diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 4135d1d0f2..e6fa6d7203 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -11,30 +11,63 @@ defaults: jobs: run-checks: - name: Run checks - runs-on: ubuntu-22.04 + name: Run checks on ${{matrix.cfg.name}} + runs-on: ${{matrix.cfg.os}} + + strategy: + matrix: + cfg: + - { name: 'Linux', os: 'ubuntu-24.04' } + - { name: 'MacOS', os: 'macos-15' } steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 + + - name: install GNU tools + if: matrix.cfg.os == 'macos-15' + run: | + brew install gnu-sed + 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-15' + run: brew update + - name: update-apt-cache + if: matrix.cfg.os == 'ubuntu-24.04' run: sudo apt-get update - - name: install + - name: install (Linux) + if: matrix.cfg.os == 'ubuntu-24.04' run: sudo apt-get install latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended lmodern - - name: make + - name: install (MacOS) + 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 environ layouts enumitem l3packages l3kernel imakeidx splitindex xstring + + - name: make (Linux) + if: matrix.cfg.os == 'ubuntu-24.04' run: make quiet + - name: make (MacOS) + if: matrix.cfg.os == 'macos-15' + run: make full + - name: check-output.sh run: ../tools/check-output.sh - name: upload PDF - uses: actions/upload-artifact@v2 + if: matrix.cfg.os == 'ubuntu-24.04' + uses: actions/upload-artifact@v4 with: name: draft-snapshot path: source/std.pdf 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 f8d179c44e..4ab1c20b2d 100644 --- a/README.rst +++ b/README.rst @@ -24,7 +24,7 @@ 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: - sudo tlmgr install latexmk isodate substr relsize ulem fixme rsfs extract layouts enumitem l3packages l3kernel imakeidx splitindex + sudo tlmgr install latexmk isodate substr relsize ulem fixme rsfs extract layouts enumitem l3packages l3kernel imakeidx splitindex xstring --------------------------------------- Getting Started on Debian-based Systems @@ -48,7 +48,7 @@ Getting Started on Arch Linux Install the following packages: - pacman -S texlive-latexextra + pacman -S make texlive-latexextra texlive-binextra texlive-plaingeneric texlive-fontsrecommended ----------------------------- Getting Started on Microsoft Windows diff --git a/papers/n4929.html b/papers/n4929.html new file mode 100644 index 0000000000..9d0ae5c6b6 --- /dev/null +++ b/papers/n4929.html @@ -0,0 +1,1017 @@ + + + + + +N4929 + + +

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

+ +

Date: 2022-12-18

+ +

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. +Thank you also to Dan Raviv and Robert Leahy for drafting motion applications, +and special thanks to Johel Ernesto Guerrero Peña for providing in-depth review +of many of the draft motion applications.

+ +

New papers

+ + + +

National body comments on the Committee Draft

+ +

N4919 is the C++23 Committee Draft. It received 137 comments from national bodies. +The working group's responses to the issues so far is noted below.

+ +

Editorial comments

+ +

The following 11 national body comments are editorial in nature, and fixes for +them have been applied.

+ + + +

Non-editorial comments

+ + + +

Motions incorporated into working draft

+ +

Notes

+ + + +

Core working group polls

+ +

CWG poll 1: Accept as Defect Reports all issues except 2635 and 2602 in P2709R0 (Core Language Working Group "ready" Issues for the November, 2022 meeting) and apply their proposed resolutions to the C++ Working Paper.

+ +

CWG poll 2: Accept as a Defect Report issue 2635 (Constrained structured bindings) in P2709R0 (Core Language Working Group "ready" Issues for the November, 2022 meeting) and apply its proposed resolution to the C++ Working Paper.

+ +

CWG poll 3: Accept as Defect Reports all issues except 2615, 2639, 2640, 2652, 2653, 2654, and 2538 in P2710R0 (Core Language Working Group NB comment resolutions for the November, 2022 meeting) and apply their proposed resolution to the C++ Working Paper, resolving the NB comments as indicated.

+ +

CWG poll 4: Apply the proposed resolutions of issues 2615, 2639, 2640, 2652, and 2653 in P2710R0 (Core Language Working Group NB comment resolutions for the November, 2022 meeting) to the C++ Working Paper, resolving the NB comments as indicated.

+ +

CWG poll 5: Accept as a Defect Report issue 2654 (Un-deprecation of compound volatile assignments) in P2710R0 (Core Language Working Group NB comment resolutions for the November, 2022 meeting) and apply its proposed resolution to the C++ Working Paper, resolving NB comment US 16-045.

+ +

CWG poll 6: Accept as a Defect Report issue 2538 (Can standard attributes be syntactically ignored?) in P2710R0 (Core Language Working Group NB comment resolutions for the November, 2022 meeting) and apply its proposed resolution to the C++ Working Paper, resolving NB comment GB-055.

+ +

CWG poll 7: Apply the changes in P2589R1 (static operator[]) to the C++ Working Paper, resolving NB comment CA-065.

+ +

CWG poll 8: Accept as a Defect Report and apply the changes in P2647R1 (Permitting static constexpr variables in constexpr functions) to the C++ Working Paper, resolving NB comment GB-048.

+ +

CWG poll 9: Accept as a Defect Report and apply the changes in P2564R3 (consteval needs to propagate up) to the C++ Working Paper, resolving NB comment DE-046.

+ +

CWG poll 10: Accept as a Defect Report and apply the changes in P2706R0 (Redundant specification for defaulted functions) to the C++ Working Paper, resolving NB comment US 26-061.

+ +

CWG poll 11: Accept as a Defect Report and apply the changes in P2615R1 (Meaningful exports) to the C++ Working Paper, resolving NB comment GB-059.

+ +

CWG poll 12: Apply the changes in P2718R0 (Wording for P2644R1 Fix for Range-based for Loop) to the C++ Working Paper, resolving NB comment DE-038.

+ +

Library working group polls

+ +

Polls 1–6 do not concern the C++ Working Paper.

+ +

LWG poll 7: Apply the changes for all Ready and Tentatively Ready issues in P2703R0 (C++ Standard Library Ready Issues to be moved in Kona, Nov. 2022) to the C++ working paper.

+ +

LWG poll 8: Apply the changes for all Immediate issues in P2704R0 (C++ Standard Library Immediate Issues to be moved in Kona, Nov. 2022) to the C++ working paper.

+ +

LWG poll 9: Apply the changes in P2602R2 (Poison Pills are Too Toxic) to the C++ working paper. This addresses ballot comment US 49-111.

+ +

LWG poll 10: Apply the changes in P2167R3 (Improved Proposed Wording for LWG 2114 (contextually convertible to bool)) to the C++ working paper. This addresses ballot comment US 32-073.

+ +

LWG poll 11: Apply the changes in P2539R4 (Should the output of std::print to a terminal be synchronized with the underlying stream?) to the C++ working paper. This addresses ballot comment US 58-123 (and duplicates US 59-124 and FR-001-019).

+ +

LWG poll 12: Apply the changes in P1264R2 (Revising the wording of stream input operations) to the C++ working paper. This partially addresses ballot comment FR-018-004.

+ +

LWG poll 13: Apply the changes in P2505R5 (Monadic Functions for std::expected) to the C++ working paper. This addresses ballot comments GB-093, US 36-091, US 35-092, and FR-011-009.

+ +

LWG poll 14: Apply the changes in P2696R0 (Introduce Cpp17Swappable as additional convenience requirements) to the C++ working paper.

+ +

Noteworthy editorial changes

+ + + +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4917 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 7772de4408db8122431169156ea230803cb6bf56
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Sep 6 19:47:21 2022 +0100
+
+    [headers] Reflow table after header additions
+
+commit 3231e8115e93a24806694c36f1eb2d709fe78f4f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Jun 12 15:49:22 2022 +0200
+
+    [basic.align] Recommend alignment-specifier instead of deprecated library facility
+
+commit 37d46b0d41d014febacd9ffe684eb0cf11a5c364
+Author: Chuanqi Xu <yedeng.yd@linux.alibaba.com>
+Date:   Tue Jun 7 16:19:08 2022 +0800
+
+    [module.reach] Remove redundant module implementation unit declaration
+
+commit 4e2297b8d2543062edf347ec13341a8356f59605
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Fri Sep 9 04:12:51 2022 +0800
+
+    [thread.stoptoken.syn] "class template", not just "class"; fix spacing (#5799)
+
+commit 20452e91b30d0a299a03d937f443a81537dc03f2
+Author: xmh0511 <970252187@qq.com>
+Date:   Fri Sep 9 04:54:01 2022 +0800
+
+    [basic.def.odr] A variable is "named by" an expression (#5534)
+
+    The previous wording, a variable "whose name appears
+    as [an] expression", is less precise and not well-defined.
+
+commit 7260f30c74eaf670b3f3d33a7571f6c055930cd7
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Jan 21 23:27:34 2022 +0100
+
+    [basic.life] Add cross-reference for union member lifetime
+
+commit ba51a5375fa3099e4a85594f2e67d48bc11ec448
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Mon Mar 20 11:58:33 2017 +0000
+
+    [rand.req.seedseq] Rephrase in terms of const types not values
+
+commit 88e574edc674e85911ea1a5b4e87c07457d97bf1
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Mon Mar 20 12:23:12 2017 +0000
+
+    [container.requirements] Rephrase in terms of const types not values
+
+commit 547987d9d203bb7f1f18297ca438ccb18d8fe612
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Wed Sep 14 14:39:16 2022 +0800
+
+    [range.chunk.view.input, range.slide.view] Remove unused name in the deduction guide
+
+commit c774ac4a072efd41e478d72ad57a3dae8b0946ff
+Author: Mathias Stearn <redbeard0531@gmail.com>
+Date:   Fri Sep 16 17:46:10 2022 +0200
+
+    [basic.life] Change "complete const object" to "const, complete object" (#5818)
+
+    "Complete object" is a defined term (https://eel.is/c++draft/basic#def:complete_object).
+    Putting "const" in the middle of that leaves it ambiguous whether we are referring to
+    a const-qualified "complete object", or to a complete const object with some other meaning
+    of "complete" (such as "with a complete type").
+
+commit 787ea7683982ed58b1a8bf7bbfb7c77f8d227dce
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Sep 16 21:24:15 2022 +0200
+
+    [diagnostics] Remove 'shall', use 'recommended practice'
+
+commit 9a005c04b91ffa9b92e6a57a03419091f365bc9b
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Sep 16 21:57:46 2022 +0200
+
+    [func.bind.isplace] Add cross-reference to [func.bind.place]
+
+commit 7bd72a7671d9bee0eed11578e325460bcf7fa5a1
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Sep 16 22:09:23 2022 +0200
+
+    [vector.bool.pspc] Index vector<bool>::reference
+
+commit f68d6428f27d5cd722e713262d8986489484ae02
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Sep 16 22:18:36 2022 +0200
+
+    [over.best.ics.general] Split long paragraph
+
+commit 1383e97e21d6d10ac210344d66ab715cfc0f747a
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Sep 15 15:38:58 2022 +0100
+
+    [ranges.syn] Make get overloads freestanding
+
+    These were moved to the synopsis after the P1642 changes to mark nearly
+    everything in the synopsis freestanding, so they were not marked.
+
+commit c70087afe980f9ec339f088babde575e04e185d7
+Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com>
+Date:   Sat Sep 17 02:29:45 2022 +0500
+
+    [expr.add] Move note, add example (#4778)
+
+    The original note wasn't quite in the right place.
+    It is moved and made more concrete.
+
+    In the original place of the note we now put
+    a more immediately relevant example.
+
+commit 6000c29e5b9547bf457f4461fd538670144ad88c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Sep 17 10:05:19 2022 +0200
+
+    [format.string.std] Clarify location of 0x prefix for pointers
+
+commit 718873b512d0687143bbfa00e18edfb0a8b164ce
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Sep 17 08:56:36 2022 +0200
+
+    [expr.prim.lambda.capture] Cross-reference [basic.def.odr] for 'odr-usable'
+
+commit 6a98fd8c1f9ea79961b78f731637ba9fe9d52218
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Sep 17 09:05:57 2022 +0200
+
+    [thread.thread.this] Clarify this_thread::get_id
+
+commit 90c4ba5624a655af5c5d8b11c1137d552f3e0a60
+Author: Casey Carter <Casey@Carter.net>
+Date:   Sun Sep 18 14:55:55 2022 -0700
+
+    [headers] Order `<type_traits>` before `<typeindex>` in the header table
+
+    Fixes #5853.
+
+commit 16f92154ce99a5fef26c53c464e8b14ad5b78d79
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Sep 20 05:37:31 2022 +0800
+
+    [c.math.hypot3] Fix mis-transcribed parameter type (#5852)
+
+    The paper P1467R9 says that the third parameter of `hypot` should be
+    `_floating-point-type_`, but it was erroneously transcribed as `double`.
+
+commit db26a63222f10cec871656958b3e296e529df67e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Sep 21 22:18:51 2022 +0100
+
+    [support, etc.] New subclause "Arithmetic types". (#5851)
+
+    The new subclause contains both "integer types" (<cstdint>)
+    and "extended floating-point types" (<stdfloat>).
+
+    Previously, the newly added <stdfloat> synopsis was somewhat
+    disconnected and out of context.
+
+    This change removes the stable labels [cstdint] and [cstdint.general].
+
+commit d462173b5afdc8506d85e5395f2be19311895f2d
+Author: Casey Carter <Casey@Carter.net>
+Date:   Mon Sep 19 20:42:44 2022 -0700
+
+    [mdspan.extents.cons] Correct spelling of "dynamic-extents"
+
+commit 14a10ef0948f4709cd1114c489b8e4b919ba7cbc
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Thu Sep 22 05:20:44 2022 +0800
+
+    [unord.general, container.adaptors.general] Fix list of exposition-only alias templates (#5840)
+
+commit aab149233f76df37979d777ffd2b3151c52d48a9
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Sep 22 10:51:46 2022 +0100
+
+    [template.bitset] reorder synopsis and member descriptions
+
+    Group shifts together and use same order for synopsis and detailed
+    descriptions.
+
+    Also remove the unnecessary "for b[i];" comments explaining what
+    operator[] does, and add a comment introducing the group containing
+    count(), size() etc.
+
+commit 63e4a76f780c925a13efeb06955252d7c37ed4ef
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Thu Sep 22 09:30:14 2022 +0800
+
+    [range.as.const.overview] Remove unnecessary ranges namespace qualification
+
+commit 179436adbe60c277fa6512352ee27e26f192bf2b
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Fri Sep 23 12:45:09 2022 -0400
+
+    [utility.arg.requirements] Present identifiers as itemization (#5856)
+
+    Lists providing the key for names used throughout a subclause are difficult
+    to follow when buried as a single sentence in a paragraph. This change updates
+    the key to tables 29-36 in [utility.arg.requirements] to a bulleted list
+    following the examples set elsewhere.
+
+    Each key is now consistently introduced with the word "denotes", following
+    the precedent set by similar bullet lists.
+
+    It is not at all coincidental that this also resolves pagination issues
+    at the end of the page, so that the floating tables to not float into the
+    middle of a sentence in the following section.
+
+commit 24d54e30506a62ef41cf4bd0132fbdba45bb6dda
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Sep 27 11:56:32 2022 +0100
+
+    [futures.task.members] Add missing explicit to packaged_task ctor
+
+commit 842424bd228b79876437a1a9393f20f00033476a
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Wed Sep 28 16:39:59 2022 +0800
+
+    [futures.task.members] Correct capitalization
+
+commit d3ddc0906638bb30b5a3ce0f4033148e9a8ed1ff
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Thu Sep 29 15:49:06 2022 +0800
+
+    [container.rev.reqmts] Correct capitalization
+
+commit a7f17181ef5b59ad728b421a83975209406fa037
+Author: Daniel Krügler <daniel.kruegler@gmail.com>
+Date:   Mon Oct 3 17:59:20 2022 +0200
+
+    [sequence.reqmts] Use "lvalues of type T are swappable" (#5878)
+
+commit dd6c7f4012489325bdd65a40cd121b3d25008b0e
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Tue Oct 4 04:41:26 2022 +0800
+
+    [associative.reqmts.general] Fix typo in namespace name (#5881)
+
+commit 42c7b3fb3a3cb11bc1af418cfdd395ecf314aa43
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Oct 4 13:08:17 2022 +0100
+
+    [intro.defs] Update hyperlink according to SC22 requirements
+
+commit 05019b35890b79374fac180a9a9ff9e7cf8d7595
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Oct 4 15:19:01 2022 +0100
+
+    Foreword placeholder
+
+commit b0fab58d4f2b12defdaf7c3ddfb2ddcd1f30e1b5
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed Oct 5 11:27:23 2022 +0100
+
+    [temp.local] Fix typo in "inject-class-name" (#5889)
+
+commit f6c5d4512d4b32d63d66669555ab976b315d439c
+Author: mordante <koraq@xs4all.nl>
+Date:   Mon Oct 10 17:50:51 2022 +0200
+
+    [format.string.escaped] Fix example of invalid code unit (#5890)
+
+    Example 5 should only have one invalid code unit. The second code unit is a valid code point.
+
+    This issue was already in the paper P2286R8 "Formatting Ranges".
+
+commit 5f26c516a659cdf3f0ea007cf6c90c690cccc3b6
+Author: Eelis van der Weegen <eelis@eelis.net>
+Date:   Tue Oct 11 04:36:08 2022 +0200
+
+    [bibliography] Remove stray closing parenthesis.
+
+commit 6c51392a3d1c3c928ef1c20c19e8efe6efed7dc1
+Author: Corentin Jabot <corentinjabot@gmail.com>
+Date:   Wed Oct 19 22:29:09 2022 +0200
+
+    [intro.defs] Move the definition of "multibyte character" to library
+
+    This address the US-2 NB comment as per the direction voted on
+    by SG-16.
+
+    No use of "multibyte character" remains before [multibyte.strings].
+
+commit 33e56641d63c5993d288082cf264a733464ff75c
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Tue Oct 25 17:48:03 2022 -0400
+
+    [stack.syn, queue.syn] Add xref comments to class synopses (#5913)
+
+commit 90aa7729b9a926622581354284ecf294a56e410b
+Author: Will Hawkins <8715530+hawkinsw@users.noreply.github.com>
+Date:   Tue Nov 1 04:37:52 2022 -0400
+
+    [range.dangling] Replace "tag type" with just "type" (#5922)
+
+    The extra word "tag" was not adding any value and was potentially,
+    confusing; e.g. the "dangling" type is not like, say, an iterator tag
+    that would be used for overload resolution.
+
+commit fd998c52af2dc6b9c73098fdbd5a22444a358448
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Tue Nov 1 10:45:53 2022 -0400
+
+    [flat.set] [flat.multiset] Use value_type, not key_type
+
+    For consistency with the other `set`, `unordered_set` containers.
+    `key_type` is a synonym for `value_type`, and there's no reason
+    the flat containers need to depart from existing practice here.
+
+commit 48ecaaec300de4a8176c116408cac915142166ce
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Mon Nov 7 14:02:40 2022 -0500
+
+    [flat.multiset.modifiers] Fix typo in "multiset" (#5927)
+
+commit 45d9a5ba5aee1e3c4da8938e12376b36a7147d63
+Author: Eric41293 <eric41293@comcast.net>
+Date:   Mon Nov 7 11:11:58 2022 -0800
+
+    [climits.syn] Correct note about types of macros (#5926)
+
+    This note was added apparently as a response to LWG 416. However, there may have been a misunderstanding of the C standard, and in fact only the macros for `{signed,unsigned,} char` and `{signed,unsigned} int` have a different type.
+
+commit f41cd00273e6ee7ff1a29446b21f230c28bf1a9f
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Mon Nov 7 20:59:54 2022 +0000
+
+    [time.clock.system.nonmembers, time.zone.zonedtime.nonmembers] Add <charT> to STATICALLY-WIDEN (#5934)
+
+commit ef7d0e234722d2ef8b4ec069b6f929dc083d8dc7
+Author: Ed Catmur <edward.catmur@mavensecurities.com>
+Date:   Tue Sep 20 18:12:45 2022 +0100
+
+    [meta, thread] Add or amend references to func.{require,invoke}
+
+commit 0d5c9b9310b2f6c6c4259665e1e680936babdc3d
+Author: Eric41293 <eric41293@comcast.net>
+Date:   Mon Nov 7 15:54:55 2022 -0800
+
+    [meta.type.synop] Capitalize NTTP name (#5921)
+
+commit 0959b5c200a6f2b543e2d656850917b8d788767c
+Author: Hui <65944694+huixie90@users.noreply.github.com>
+Date:   Tue Nov 8 00:49:15 2022 +0000
+
+    [range.drop.while.overview] Use string_view rather than string literal (#5897)
+
+    The string literal would have been treated as a `const char*`, which is not a range.
+
+commit 720c3ae24a68fda02a6372eda13ec3f9c6a1a39b
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Nov 8 02:01:34 2022 +0000
+
+    [time.format] Use basic_ostringstream<charT> instead of ostringstream (#5932)
+
+commit 8739d316f2a55c633963b26b748681ff16498887
+Author: Marc Mutz <94039187+marcmutz@users.noreply.github.com>
+Date:   Tue Nov 8 03:05:45 2022 +0100
+
+    [meta.const.eval] Add is_constant_evaluated to index of library names (#5898)
+
+    Previously, only its feature-test macro was listed there.
+
+commit 4c442cf93f03a44ec1f6a93875043a3aca7c5b9b
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Mon Nov 7 23:38:36 2022 -0400
+
+    [class.union.general] Attach example to its note (#5882)
+
+commit 65c494b9a4a5a4fab500733441c04e50a787d318
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Tue Nov 8 15:51:21 2022 +0800
+
+    [mdspan.extents.expo] Remove redundant "// exposition only" (#5907)
+
+commit b766881dda1d0201d98710b11efda3491a84b4f2
+Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com>
+Date:   Tue Nov 8 13:15:07 2022 +0500
+
+    [dcl.init.list] Specify the type of the prvalue (#5919)
+
+commit 6e035b52e28e95211a39ffb552851499432b2c6e
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Tue Nov 8 15:30:29 2022 -0400
+
+    [ratio.ratio] Use symbol "sgn" for the signum function (#5925)
+
+commit 89269f8e548b993b239f2c0f5ecc071ee7f54c9a
+Author: Blackteahamburger <blackteahamburger@outlook.com>
+Date:   Wed Nov 9 04:12:59 2022 +0800
+
+    [dcl.link] Add missing restriction to language linkage application (#5892)
+
+    A language linkage specification should only apply to entities that do in fact have language linkage.
+
+commit ea77b2fa83ddac0c52c1b505ff666328a2a8f558
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Nov 9 00:34:26 2022 +0100
+
+    [temp.deduct.general] Fix typo in comment in example
+
+commit 0c196ec375993000547e8913abb4c4ce703144cb
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Nov 10 15:32:56 2022 +0100
+
+    [temp.deduct.conv] Remove misleading paragraph break
+
+commit 0cd0c33f648d1304160e6dcb1856affd71b3ebbb
+Author: Casey Carter <Casey@Carter.net>
+Date:   Fri Nov 11 18:35:53 2022 -0800
+
+    [mdspan.extents.cons] "constexpr" should precede "explicit"
+
+    In library function declarations, the `constexpr` specifier always precedes the `explicit` specifier per our standing style guide.
+
+commit 608c152dbae69d335d7238cdd5d178e048e2a1fd
+Author: Casey Carter <Casey@Carter.net>
+Date:   Mon Nov 14 10:48:18 2022 -0800
+
+    [vector.bool.pspc] Replace `constexpr static` with `static constexpr`
+
+    As preferred by our style guide.
+
+commit d829eac310981e688a15b28622a2f048d23eed65
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Nov 10 07:43:32 2022 +0000
+
+    [class.inhctor.init] Fix explanation of "error:" in example
+
+    The correct explanation is that classes `B1` and `D1` do not have
+    default constructors, not that they have deleted default constructors.
+
+    Fixes NB CA 062 (C++23 CD).
+
+commit 6a1c5050c21ac26fcb2b5b187a0de867713568dc
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Nov 8 23:35:00 2022 +0000
+
+    [diff.cpp20.library] Add missing new headers
+
+    Fixes NB FR 008 (C++23 CD).
+
+commit b2fa70faa783827cd38b819409e94da2523333f2
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Nov 9 18:50:56 2022 +0000
+
+    [views] Subclauses for contiguous and multidimensional access
+
+    This organises the material for <span> and <mdspan> into separate
+    subclauses, rather than having all constituent parts being siblings in
+    the same subclause. Even though we now have some subclauses six levels
+    deep, this seems like an improvement. As a drive-by, this allows us to
+    move a subclause on a non-member span helper function up one level,
+    where it is more appropriate.
+
+    Fixes NB FR 027 (C++23 CD).
+
+commit e0bab4b7f2d8afe5d3939aa49fe6de4fd5e638c6
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Nov 10 02:16:11 2022 +0000
+
+    [concepts index] Describe exposition-only concepts
+
+    Fixes NB GB 136 (C++23 CD).
+
+commit 9512e41e30cf24a8e93e8c8568ff1b5c14398cc6
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Nov 11 19:31:11 2022 +0000
+
+    [general, library index] Describe exposition-only entities
+
+    Partially fixes NB GB 137 (C++23 CD).
+
+commit 0783dde32073b02b369c7c3893f4f496a83e3658
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Nov 11 19:33:33 2022 +0000
+
+    [func.wrap.move.ctor] Move private expos member to general index
+
+    The private, exposition-only data member is not useful in the library
+    index. However, there seems no reason to not show it in the general
+    index, so we move the index entry from the library index to the
+    general index.
+
+    Partially fixes NB GB 137 (C++23 CD).
+
+commit 3e825f144f2aa8668c9a1a94066b43799e08a6e7
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Nov 8 21:31:30 2022 +0000
+
+    [basic.scope.scope] Fix indentation in example
+
+    Fixes NB US 034 (C++23 CD).
+
+commit 92de5996625efcb070f99681acd2e39efc206ee2
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Nov 8 23:24:35 2022 +0000
+
+    [unord.req.general] Fix garbled end of sentence
+
+    This was an editorial mistake introduced by the transformation of the
+    requirement tables into regular paragraphs.
+
+    Fixes NB US 100 (C++23 CD).
+
+commit 24e046896029a11f2cb78fd6db21482fb0d4be66
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Nov 8 21:02:31 2022 +0000
+
+    [coro.generator.promise] Use "equivalent to `throw`, ..."
+
+    Our style guide says that "equivalent to <expression>" is the
+    appropriate style for an expression of type `void`, which is the case
+    for `throw`. This avoids the awkward situation of having "equivalent
+    to: `throws;`" appear in the middle of a paragraph without proper
+    terminal punctuation.
+
+    Fixes NB US 119 (C++23 CD).
+
+commit 3f47d2565f26a9144e8076641ee55bf7be79f896
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Nov 8 21:27:56 2022 +0000
+
+    [coro.generator.promise] Remove unused name "x"
+
+    Fixes NB US 120 (C++23 CD).
+
+commit fb0df97e7d7c2c75bbdf7164c33b0796024ff6d3
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Nov 17 08:44:05 2022 +0000
+
+    [atomics] Replace integral and floating-point placeholders (#5939)
+
+    Fixes NB GB 129 (C++23 CD).
+
+commit 0bb57d5ebffa7170fbc80724f55a6ac2a82f2e83
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Fri Nov 25 14:56:24 2022 +0800
+
+    [format.arg] Add std:: for forward
+
+commit c88fb46327d87d78d571b7e1076e1916eaf7e310
+Author: Dawn Perchik <dawn@brightsidecomputing.com>
+Date:   Tue Nov 15 07:46:41 2022 -0800
+
+    [expr.unary.op] Say "the ~ operator" consistently, remove "unary"
+
+    We are currently using the term "unary complement operator" to refer
+    to the "~" operator without ever giving it that name. This change
+    removes the use of that undefined term.
+
+commit bef02b89464fe6f4be3926d62defc92986ae4532
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Nov 22 16:28:42 2022 +0000
+
+    [expr.unary.op] Notes naming unary ops as {ones',two's} complement
+
+    The terms "one's complement" and "two's complement" are well-known,
+    and it is useful to associate them with these operators.
+
+commit 020a312b2aa513a992e488d82db55fd0cd4fa025
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Nov 16 17:48:12 2022 +0000
+
+    [fs.rec.dir.itr.nonmembers] "for" is a keyword in "range-based for"
+
+commit cee095e75a97fb88a7053e360b3bc06d36a6b687
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Fri Dec 16 06:51:26 2022 +0700
+
+    [depr.conversions.string] remove redundent respecification (#6004)
+
+    There are several typedef names defined precisely in the deprecated code conversion
+    facets classes that are redundantly respecified in text. Nowhere else in the library
+    does this; any specified typedef names are _see below_ definitions, not repeats of
+    the class definition. Needless redundancy is always a risk of divergence, however
+    small, so remove the respecification in text form.
+
+commit 1bb52db31be002f04ea5977f9900ba4174c7155e
+Author: Anoop Rana <93918384+ranaanoop@users.noreply.github.com>
+Date:   Fri Dec 16 05:23:57 2022 +0530
+
+    [concepts.object] Change "built-in" to "fundamental" types (#6012)
+
+commit ce1cc3b011099b6228b18dad937911c6ea67d309
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Sun Dec 11 17:03:41 2022 -0400
+
+    [expr.const] Remove redundant "ill-formed" in "error" comment
+
+commit 5d43f0137776fa112d0ffd6ba0e34df34a4cb820
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Dec 13 12:52:00 2022 +0000
+
+    [time.zone.leap.members] update note about leap seconds
+
+commit fd20d4ea9f3ea8653b17169aad61eec843b71718
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed Nov 23 14:45:43 2022 +0000
+
+    [time.zone.zonedtime.overview] Rename parameters to match later definitions
+
+commit 137728f0830824c6058648a846376eec80e5cab3
+Author: Michael Florian Hava <mfh@live.at>
+Date:   Fri Dec 16 02:10:55 2022 +0100
+
+    [coro.generator.promise] Fix template parameters (#6009)
+
+    Some of the template parameters of `yield_value` were inconsistent,
+    and the synopsis contained an outright typo. This change uses `R2`
+    consistently since the parameter is a reference.
+
+commit 5d6099c3df78922ee5b5f1d1c42a5c762d246df0
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Dec 15 23:31:26 2022 +0000
+
+    [formatter.requirements] Remove one level of list nesting
+
+commit 9e41a1c27de2f676badacbe0c1aac783063b7cd6
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Nov 16 19:43:58 2022 +0000
+
+    [time.clock.req] Make list item end with comma, not full stop.
+
+    Also reformat the itemization source to be more edit-friendly.
+
+commit 5ef31f3fc1531d9e6e923cb57bf6e5ecec59ed4e
+Author: languagelawyer <language.lawyer@gmail.com>
+Date:   Thu Jun 25 10:54:17 2020 +0300
+
+    [expr.unary.op] Fix usage of "result"
+
+commit 8c60752c7eb28e1ff1cc9e088d7836957356f559
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Apr 26 10:18:11 2022 +0100
+
+    [optional.ctor], [expected.object.ctor] Add converts-from-any-cvref
+
+commit 405b46f50ce6c7458e94db7b4528fc267e2b67c3
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Sat Dec 17 00:14:51 2022 +0800
+
+    [mdspan.mdspan.overview] Add default template arguments for mdspan (#6018)
+
+    We usually restate the default template arguments in the class synopsis,
+    so that the information is in one place and one does not need to also refer
+    to the header synopsis.
+
+commit ae88bb581d32f1939987c0a834fe3f6011a9d003
+Author: frederick-vs-ja <de34@live.cn>
+Date:   Fri Dec 16 21:25:31 2022 +0800
+
+    [range.repeat] Change `W`/`WArgs` to `T`/`TArgs`
+
+commit 0a1f1e147c75ce9220de3488103ca880b6b8e49f
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Dec 16 17:19:08 2022 +0000
+
+    [concept.copyconstructible] Avoid "possibly \tcode{const}"
+
+    A small rewrite avoids the phrase "possibly \tcode{const}",
+    which we would like to remove entirely in favour of just
+    "possibly const".
+
+commit f058decdf9c7dea0461f723df72f5093f5e92b11
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Dec 16 17:31:47 2022 +0000
+
+    Replace "possibly \tcode{const}" with "possibly const"
+
+    The "const" here is not syntax, but just normal text.
+    This is similar to "inline" and "public", which have
+    previously been cleaned up similarly.
+
+commit 9ac55553459e15c84db6d8072c93787d41ef7ccf
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Jun 4 00:29:30 2021 +0200
+
+    [lib] Drop 'inline' from 'inline constexpr' variable templates.
+
+    Since CWG2387, constexpr variable templates have external linkage.
+
+ + diff --git a/papers/n4929.md b/papers/n4929.md new file mode 100644 index 0000000000..36adf1e8d4 --- /dev/null +++ b/papers/n4929.md @@ -0,0 +1,868 @@ +# N4929 Editors' Report -- Programming Languages -- C++ + +Date: 2022-12-18 + +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. +Thank you also to Dan Raviv and Robert Leahy for drafting motion applications, +and special thanks to Johel Ernesto Guerrero Peña for providing in-depth review +of many of the draft motion applications. + +## New papers + + * [N4928](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4928.pdf) is the + current working draft for C++23. It replaces + [N4917](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4917.pdf). + * N4929 is this Editors' Report. + +## National body comments on the Committee Draft + +N4919 is the C++23 Committee Draft. It received 137 comments from national bodies. +The working group's responses to the issues so far is noted below. + +### Editorial comments + +The following 11 national body comments are editorial in nature, and fixes for +them have been applied. + + * **FR 008:** Accepted; fixed by 6a1c5050c21ac26fcb2b5b187a0de867713568dc. + * **FR 027:** Accepted; fixed by b2fa70faa783827cd38b819409e94da2523333f2. + New subclauses "contiguous access" and "mulitidimensional access" have been added + to organize the content for `span` and `mdspan`. + * **US 029:** Accepted with modifications; fixed by 6c51392a3d1c3c928ef1c20c19e8efe6efed7dc1. + This issue had already been fixed editorially prior to the NB comments. + * **US 034:** Accepted; fixed by 3e825f144f2aa8668c9a1a94066b43799e08a6e7. + * **CA 062:** Accepted with modifications; fixed by d829eac310981e688a15b28622a2f048d23eed65. + A second erroneous comment with the same problem has also been corrected in the same way. + * **US 100:** Accepted; fixed by 92de5996625efcb070f99681acd2e39efc206ee2. + * **US 119:** Accepted with modifications; fixed by 24e046896029a11f2cb78fd6db21482fb0d4be66. + We removed the colon after "equivalent to" and the semicolon after "throw", + and connected the next sentence with a comma. + * **US 120:** Accepted; fixed by 3f47d2565f26a9144e8076641ee55bf7be79f896. + * **GB 129:** Accepted with modifications; fixed by fb0df97e7d7c2c75bbdf7164c33b0796024ff6d3. + Reviewed by LWG and considered editorial. + * **GB 136:** Accepted; fixed by e0bab4b7f2d8afe5d3939aa49fe6de4fd5e638c6. + * **GB 137:** Accepted; fixed by 9512e41e30cf24a8e93e8c8568ff1b5c14398cc6 and 0783dde32073b02b369c7c3893f4f496a83e3658. + +### Non-editorial comments + +* **FR 004:** Partially fixed by [P1264R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1264r2.pdf) (LWG poll 12). +* **FR 005:** Fixed by [CWG2631](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2631) (CWG poll 4). +* **FR 009:** Duplicate of GB 093 +* **FR 019:** Duplicate of US 123 +* **US 028:** Fixed by [CWG2640](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2640) (CWG poll 4). +* **US 030:** Fixed by [CWG2639](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2639) (CWG poll 4). +* **US 033:** Fixed by [CWG2242](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2242) (CWG poll 3). +* **DE 038:** Fixed by [P2718R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2718r0.html) (CWG poll 12). +* **US 039:** Fixed by [CWG2643](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2643) (CWG poll 3). +* **US 042:** Fixed by [CWG2644](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2644) (CWG poll 3). +* **US 044:** Fixed by [CWG2645](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2645) (CWG poll 3). +* **US 045:** Fixed by [CWG2654](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2654) (CWG poll 5). +* **US 045:** Fixed by [CWG2654](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2654) (CWG poll 5). +* **DE 046:** Fixed by [P2564R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2564r3.html) (CWG poll 9). +* **US 047:** Fixed by [CWG2647](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2647) (CWG poll 3). +* **GB 048:** Fixed by [P2647R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2647r1.html) (CWG poll 8). +* **GB 051:** Fixed by [CWG2653](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2653) (CWG poll 4). +* **US 052:** Fixed by [CWG2646](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2646) (CWG poll 3). +* **CA 054:** Fixed by [CWG2621](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2621) (CWG poll 3). +* **GB 055:** Fixed by [CWG2538](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2538) (CWG poll 6). +* **GB 059:** Fixed by [P2615R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2615r1.html) (CWG poll 11). +* **US 061:** Fixed by [P2706R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2706r0.html) (CWG poll 10). +* **CA 063:** Fixed by [CWG2648](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2648) (CWG poll 3). +* **CA 064:** Fixed by [CWG2649](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2649) (CWG poll 3). +* **CA 065:** Fixed by [P2589R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2589r1.pdf) (CWG poll 7). +* **US 068:** Fixed by [CWG2650](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2650) (CWG poll 3). +* **US 069:** Fixed by [CWG2651](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2651) (CWG poll 3). +* **GB 070:** Fixed by [CWG2615](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2615) (CWG poll 4). +* **US 071:** Fixed by [CWG2652](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2652) (CWG poll 4). +* **US 073:** Fixed by [P2167R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2167r3.html) (LWG poll 10). +* **GB 074:** Fixed by [LWG3818](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3818) (LWG poll 8). +* **GB 075:** Fixed by [LWG3753](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3753) (LWG poll 8). +* **GB 085:** Fixed by [LWG3814](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3814) (LWG poll 8). +* **GB 090:** Fixed by [LWG3823](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3823) (LWG poll 8). +* **US 091:** Duplicate of GB 093 +* **US 092:** Duplicate of GB 093 +* **GB 093:** Fixed by [P2505R5](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2505r5.html) (LWG poll 13). +* **GB 095:** Fixed by [LWG3824](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3824) (LWG poll 8). +* **GB 101:** Fixed by [LWG3817](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3817) (LWG poll 8). +* **US 103:** Fixed by [LWG3816](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3816) (LWG poll 8). +* **US 109:** Partially fixed by [LWG3717](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3717) + and [LWG3737](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3737) (LWG poll 8). +* **GB 110:** Fixed by [LWG3814](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3814) (LWG poll 8). +* **US 111:** Fixed by [P2602R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2602r2.html) (LWG poll 9). +* **US 118:** Fixed by [LWG3826](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3826) (LWG poll 8). +* **US 123:** Fixed by [P2539R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2539r4.html) (LWG poll 11). +* **US 124:** Duplicate of US 123 +* **US 125:** Fixed by [LWG3822](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3822) (LWG poll 8). +* **GB 130:** Partially fixed by [LWG3814](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html#3814) (LWG poll 8). +* **US 132:** Fixed by [CWG2636](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2636) (CWG poll 3). + +## Motions incorporated into working draft + +### Notes + + * CWG issue 2602 was withdrawn from the motions. Even though it is part of + [P2709R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2709r0.html), + it has not been applied. + * CWG issue 2642 (in + [P2710R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html#2642), + polled in CWG poll 3) was discovered to be incorrect after the WG21 meeting; + CWG has requested that the issue not be applied and reverted to the working + group for further discussion. It has not been applied. + +### Core working group polls + +CWG poll 1: Accept as Defect Reports all issues except 2635 and 2602 in [P2709R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2709r0.html) (Core Language Working Group "ready" Issues for the November, 2022 meeting) and apply their proposed resolutions to the C++ Working Paper. + +CWG poll 2: Accept as a Defect Report issue 2635 (Constrained structured bindings) in [P2709R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2709r0.html) (Core Language Working Group "ready" Issues for the November, 2022 meeting) and apply its proposed resolution to the C++ Working Paper. + +CWG poll 3: Accept as Defect Reports all issues except 2615, 2639, 2640, 2652, 2653, 2654, and 2538 in [P2710R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html) (Core Language Working Group NB comment resolutions for the November, 2022 meeting) and apply their proposed resolution to the C++ Working Paper, resolving the NB comments as indicated. + +CWG poll 4: Apply the proposed resolutions of issues 2615, 2639, 2640, 2652, and 2653 in [P2710R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html) (Core Language Working Group NB comment resolutions for the November, 2022 meeting) to the C++ Working Paper, resolving the NB comments as indicated. + +CWG poll 5: Accept as a Defect Report issue 2654 (Un-deprecation of compound volatile assignments) in [P2710R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html) (Core Language Working Group NB comment resolutions for the November, 2022 meeting) and apply its proposed resolution to the C++ Working Paper, resolving NB comment US 16-045. + +CWG poll 6: Accept as a Defect Report issue 2538 (Can standard attributes be syntactically ignored?) in [P2710R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2710r0.html) (Core Language Working Group NB comment resolutions for the November, 2022 meeting) and apply its proposed resolution to the C++ Working Paper, resolving NB comment GB-055. + +CWG poll 7: Apply the changes in [P2589R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2589r1.pdf) (`static operator[]`) to the C++ Working Paper, resolving NB comment CA-065. + +CWG poll 8: Accept as a Defect Report and apply the changes in [P2647R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2647r1.html) (Permitting static constexpr variables in constexpr functions) to the C++ Working Paper, resolving NB comment GB-048. + +CWG poll 9: Accept as a Defect Report and apply the changes in [P2564R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2564r3.html) (`consteval` needs to propagate up) to the C++ Working Paper, resolving NB comment DE-046. + +CWG poll 10: Accept as a Defect Report and apply the changes in [P2706R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2706r0.html) (Redundant specification for defaulted functions) to the C++ Working Paper, resolving NB comment US 26-061. + +CWG poll 11: Accept as a Defect Report and apply the changes in [P2615R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2615r1.html) (Meaningful exports) to the C++ Working Paper, resolving NB comment GB-059. + +CWG poll 12: Apply the changes in [P2718R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2718r0.html) (Wording for P2644R1 Fix for Range-based `for` Loop) to the C++ Working Paper, resolving NB comment DE-038. + +### Library working group polls + +Polls 1–6 do not concern the C++ Working Paper. + +LWG poll 7: Apply the changes for all Ready and Tentatively Ready issues in [P2703R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2703r0.html) (C++ Standard Library Ready Issues to be moved in Kona, Nov. 2022) to the C++ working paper. + +LWG poll 8: Apply the changes for all Immediate issues in [P2704R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2704r0.html) (C++ Standard Library Immediate Issues to be moved in Kona, Nov. 2022) to the C++ working paper. + +LWG poll 9: Apply the changes in [P2602R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2602r2.html) (Poison Pills are Too Toxic) to the C++ working paper. This addresses ballot comment US 49-111. + +LWG poll 10: Apply the changes in [P2167R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2167r3.html) (Improved Proposed Wording for LWG 2114 (contextually convertible to `bool`)) to the C++ working paper. This addresses ballot comment US 32-073. + +LWG poll 11: Apply the changes in [P2539R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2539r4.html) (Should the output of `std::print` to a terminal be synchronized with the underlying stream?) to the C++ working paper. This addresses ballot comment US 58-123 (and duplicates US 59-124 and FR-001-019). + +LWG poll 12: Apply the changes in [P1264R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1264r2.pdf) (Revising the wording of stream input operations) to the C++ working paper. This partially addresses ballot comment FR-018-004. + +LWG poll 13: Apply the changes in [P2505R5](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2505r5.html) (Monadic Functions for `std::expected`) to the C++ working paper. This addresses ballot comments GB-093, US 36-091, US 35-092, and FR-011-009. + +LWG poll 14: Apply the changes in [P2696R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2696r0.html) (Introduce _Cpp17Swappable_ as additional convenience requirements) to the C++ working paper. + +### Noteworthy editorial changes + +* There were no noteworthy changes to the wording of the approved papers. +* A new subclause "Arithmetic types" was added. The new subclause contains + both "integer types" (``) and the new "extended floating-point + types" (``). Previously, the newly added `` synopsis + was somewhat disconnected and out of context. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4917 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/n4917...n4928). + + commit 7772de4408db8122431169156ea230803cb6bf56 + Author: Thomas Köppe + Date: Tue Sep 6 19:47:21 2022 +0100 + + [headers] Reflow table after header additions + + commit 3231e8115e93a24806694c36f1eb2d709fe78f4f + Author: Jens Maurer + Date: Sun Jun 12 15:49:22 2022 +0200 + + [basic.align] Recommend alignment-specifier instead of deprecated library facility + + commit 37d46b0d41d014febacd9ffe684eb0cf11a5c364 + Author: Chuanqi Xu + Date: Tue Jun 7 16:19:08 2022 +0800 + + [module.reach] Remove redundant module implementation unit declaration + + commit 4e2297b8d2543062edf347ec13341a8356f59605 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Fri Sep 9 04:12:51 2022 +0800 + + [thread.stoptoken.syn] "class template", not just "class"; fix spacing (#5799) + + commit 20452e91b30d0a299a03d937f443a81537dc03f2 + Author: xmh0511 <970252187@qq.com> + Date: Fri Sep 9 04:54:01 2022 +0800 + + [basic.def.odr] A variable is "named by" an expression (#5534) + + The previous wording, a variable "whose name appears + as [an] expression", is less precise and not well-defined. + + commit 7260f30c74eaf670b3f3d33a7571f6c055930cd7 + Author: Jens Maurer + Date: Fri Jan 21 23:27:34 2022 +0100 + + [basic.life] Add cross-reference for union member lifetime + + commit ba51a5375fa3099e4a85594f2e67d48bc11ec448 + Author: Jonathan Wakely + Date: Mon Mar 20 11:58:33 2017 +0000 + + [rand.req.seedseq] Rephrase in terms of const types not values + + commit 88e574edc674e85911ea1a5b4e87c07457d97bf1 + Author: Jonathan Wakely + Date: Mon Mar 20 12:23:12 2017 +0000 + + [container.requirements] Rephrase in terms of const types not values + + commit 547987d9d203bb7f1f18297ca438ccb18d8fe612 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Wed Sep 14 14:39:16 2022 +0800 + + [range.chunk.view.input, range.slide.view] Remove unused name in the deduction guide + + commit c774ac4a072efd41e478d72ad57a3dae8b0946ff + Author: Mathias Stearn + Date: Fri Sep 16 17:46:10 2022 +0200 + + [basic.life] Change "complete const object" to "const, complete object" (#5818) + + "Complete object" is a defined term (https://eel.is/c++draft/basic#def:complete_object). + Putting "const" in the middle of that leaves it ambiguous whether we are referring to + a const-qualified "complete object", or to a complete const object with some other meaning + of "complete" (such as "with a complete type"). + + commit 787ea7683982ed58b1a8bf7bbfb7c77f8d227dce + Author: Jens Maurer + Date: Fri Sep 16 21:24:15 2022 +0200 + + [diagnostics] Remove 'shall', use 'recommended practice' + + commit 9a005c04b91ffa9b92e6a57a03419091f365bc9b + Author: Jens Maurer + Date: Fri Sep 16 21:57:46 2022 +0200 + + [func.bind.isplace] Add cross-reference to [func.bind.place] + + commit 7bd72a7671d9bee0eed11578e325460bcf7fa5a1 + Author: Jens Maurer + Date: Fri Sep 16 22:09:23 2022 +0200 + + [vector.bool.pspc] Index vector::reference + + commit f68d6428f27d5cd722e713262d8986489484ae02 + Author: Jens Maurer + Date: Fri Sep 16 22:18:36 2022 +0200 + + [over.best.ics.general] Split long paragraph + + commit 1383e97e21d6d10ac210344d66ab715cfc0f747a + Author: Jonathan Wakely + Date: Thu Sep 15 15:38:58 2022 +0100 + + [ranges.syn] Make get overloads freestanding + + These were moved to the synopsis after the P1642 changes to mark nearly + everything in the synopsis freestanding, so they were not marked. + + commit c70087afe980f9ec339f088babde575e04e185d7 + Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com> + Date: Sat Sep 17 02:29:45 2022 +0500 + + [expr.add] Move note, add example (#4778) + + The original note wasn't quite in the right place. + It is moved and made more concrete. + + In the original place of the note we now put + a more immediately relevant example. + + commit 6000c29e5b9547bf457f4461fd538670144ad88c + Author: Jens Maurer + Date: Sat Sep 17 10:05:19 2022 +0200 + + [format.string.std] Clarify location of 0x prefix for pointers + + commit 718873b512d0687143bbfa00e18edfb0a8b164ce + Author: Jens Maurer + Date: Sat Sep 17 08:56:36 2022 +0200 + + [expr.prim.lambda.capture] Cross-reference [basic.def.odr] for 'odr-usable' + + commit 6a98fd8c1f9ea79961b78f731637ba9fe9d52218 + Author: Jens Maurer + Date: Sat Sep 17 09:05:57 2022 +0200 + + [thread.thread.this] Clarify this_thread::get_id + + commit 90c4ba5624a655af5c5d8b11c1137d552f3e0a60 + Author: Casey Carter + Date: Sun Sep 18 14:55:55 2022 -0700 + + [headers] Order `` before `` in the header table + + Fixes #5853. + + commit 16f92154ce99a5fef26c53c464e8b14ad5b78d79 + Author: A. Jiang + Date: Tue Sep 20 05:37:31 2022 +0800 + + [c.math.hypot3] Fix mis-transcribed parameter type (#5852) + + The paper P1467R9 says that the third parameter of `hypot` should be + `_floating-point-type_`, but it was erroneously transcribed as `double`. + + commit db26a63222f10cec871656958b3e296e529df67e + Author: Thomas Köppe + Date: Wed Sep 21 22:18:51 2022 +0100 + + [support, etc.] New subclause "Arithmetic types". (#5851) + + The new subclause contains both "integer types" () + and "extended floating-point types" (). + + Previously, the newly added synopsis was somewhat + disconnected and out of context. + + This change removes the stable labels [cstdint] and [cstdint.general]. + + commit d462173b5afdc8506d85e5395f2be19311895f2d + Author: Casey Carter + Date: Mon Sep 19 20:42:44 2022 -0700 + + [mdspan.extents.cons] Correct spelling of "dynamic-extents" + + commit 14a10ef0948f4709cd1114c489b8e4b919ba7cbc + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Thu Sep 22 05:20:44 2022 +0800 + + [unord.general, container.adaptors.general] Fix list of exposition-only alias templates (#5840) + + commit aab149233f76df37979d777ffd2b3151c52d48a9 + Author: Jonathan Wakely + Date: Thu Sep 22 10:51:46 2022 +0100 + + [template.bitset] reorder synopsis and member descriptions + + Group shifts together and use same order for synopsis and detailed + descriptions. + + Also remove the unnecessary "for b[i];" comments explaining what + operator[] does, and add a comment introducing the group containing + count(), size() etc. + + commit 63e4a76f780c925a13efeb06955252d7c37ed4ef + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Thu Sep 22 09:30:14 2022 +0800 + + [range.as.const.overview] Remove unnecessary ranges namespace qualification + + commit 179436adbe60c277fa6512352ee27e26f192bf2b + Author: Alisdair Meredith + Date: Fri Sep 23 12:45:09 2022 -0400 + + [utility.arg.requirements] Present identifiers as itemization (#5856) + + Lists providing the key for names used throughout a subclause are difficult + to follow when buried as a single sentence in a paragraph. This change updates + the key to tables 29-36 in [utility.arg.requirements] to a bulleted list + following the examples set elsewhere. + + Each key is now consistently introduced with the word "denotes", following + the precedent set by similar bullet lists. + + It is not at all coincidental that this also resolves pagination issues + at the end of the page, so that the floating tables to not float into the + middle of a sentence in the following section. + + commit 24d54e30506a62ef41cf4bd0132fbdba45bb6dda + Author: Jonathan Wakely + Date: Tue Sep 27 11:56:32 2022 +0100 + + [futures.task.members] Add missing explicit to packaged_task ctor + + commit 842424bd228b79876437a1a9393f20f00033476a + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Wed Sep 28 16:39:59 2022 +0800 + + [futures.task.members] Correct capitalization + + commit d3ddc0906638bb30b5a3ce0f4033148e9a8ed1ff + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Thu Sep 29 15:49:06 2022 +0800 + + [container.rev.reqmts] Correct capitalization + + commit a7f17181ef5b59ad728b421a83975209406fa037 + Author: Daniel Krügler + Date: Mon Oct 3 17:59:20 2022 +0200 + + [sequence.reqmts] Use "lvalues of type T are swappable" (#5878) + + commit dd6c7f4012489325bdd65a40cd121b3d25008b0e + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Tue Oct 4 04:41:26 2022 +0800 + + [associative.reqmts.general] Fix typo in namespace name (#5881) + + commit 42c7b3fb3a3cb11bc1af418cfdd395ecf314aa43 + Author: Thomas Köppe + Date: Tue Oct 4 13:08:17 2022 +0100 + + [intro.defs] Update hyperlink according to SC22 requirements + + commit 05019b35890b79374fac180a9a9ff9e7cf8d7595 + Author: Thomas Köppe + Date: Tue Oct 4 15:19:01 2022 +0100 + + Foreword placeholder + + commit b0fab58d4f2b12defdaf7c3ddfb2ddcd1f30e1b5 + Author: Jonathan Wakely + Date: Wed Oct 5 11:27:23 2022 +0100 + + [temp.local] Fix typo in "inject-class-name" (#5889) + + commit f6c5d4512d4b32d63d66669555ab976b315d439c + Author: mordante + Date: Mon Oct 10 17:50:51 2022 +0200 + + [format.string.escaped] Fix example of invalid code unit (#5890) + + Example 5 should only have one invalid code unit. The second code unit is a valid code point. + + This issue was already in the paper P2286R8 "Formatting Ranges". + + commit 5f26c516a659cdf3f0ea007cf6c90c690cccc3b6 + Author: Eelis van der Weegen + Date: Tue Oct 11 04:36:08 2022 +0200 + + [bibliography] Remove stray closing parenthesis. + + commit 6c51392a3d1c3c928ef1c20c19e8efe6efed7dc1 + Author: Corentin Jabot + Date: Wed Oct 19 22:29:09 2022 +0200 + + [intro.defs] Move the definition of "multibyte character" to library + + This address the US-2 NB comment as per the direction voted on + by SG-16. + + No use of "multibyte character" remains before [multibyte.strings]. + + commit 33e56641d63c5993d288082cf264a733464ff75c + Author: Arthur O'Dwyer + Date: Tue Oct 25 17:48:03 2022 -0400 + + [stack.syn, queue.syn] Add xref comments to class synopses (#5913) + + commit 90aa7729b9a926622581354284ecf294a56e410b + Author: Will Hawkins <8715530+hawkinsw@users.noreply.github.com> + Date: Tue Nov 1 04:37:52 2022 -0400 + + [range.dangling] Replace "tag type" with just "type" (#5922) + + The extra word "tag" was not adding any value and was potentially, + confusing; e.g. the "dangling" type is not like, say, an iterator tag + that would be used for overload resolution. + + commit fd998c52af2dc6b9c73098fdbd5a22444a358448 + Author: Arthur O'Dwyer + Date: Tue Nov 1 10:45:53 2022 -0400 + + [flat.set] [flat.multiset] Use value_type, not key_type + + For consistency with the other `set`, `unordered_set` containers. + `key_type` is a synonym for `value_type`, and there's no reason + the flat containers need to depart from existing practice here. + + commit 48ecaaec300de4a8176c116408cac915142166ce + Author: Arthur O'Dwyer + Date: Mon Nov 7 14:02:40 2022 -0500 + + [flat.multiset.modifiers] Fix typo in "multiset" (#5927) + + commit 45d9a5ba5aee1e3c4da8938e12376b36a7147d63 + Author: Eric41293 + Date: Mon Nov 7 11:11:58 2022 -0800 + + [climits.syn] Correct note about types of macros (#5926) + + This note was added apparently as a response to LWG 416. However, there may have been a misunderstanding of the C standard, and in fact only the macros for `{signed,unsigned,} char` and `{signed,unsigned} int` have a different type. + + commit f41cd00273e6ee7ff1a29446b21f230c28bf1a9f + Author: Jonathan Wakely + Date: Mon Nov 7 20:59:54 2022 +0000 + + [time.clock.system.nonmembers, time.zone.zonedtime.nonmembers] Add to STATICALLY-WIDEN (#5934) + + commit ef7d0e234722d2ef8b4ec069b6f929dc083d8dc7 + Author: Ed Catmur + Date: Tue Sep 20 18:12:45 2022 +0100 + + [meta, thread] Add or amend references to func.{require,invoke} + + commit 0d5c9b9310b2f6c6c4259665e1e680936babdc3d + Author: Eric41293 + Date: Mon Nov 7 15:54:55 2022 -0800 + + [meta.type.synop] Capitalize NTTP name (#5921) + + commit 0959b5c200a6f2b543e2d656850917b8d788767c + Author: Hui <65944694+huixie90@users.noreply.github.com> + Date: Tue Nov 8 00:49:15 2022 +0000 + + [range.drop.while.overview] Use string_view rather than string literal (#5897) + + The string literal would have been treated as a `const char*`, which is not a range. + + commit 720c3ae24a68fda02a6372eda13ec3f9c6a1a39b + Author: Jonathan Wakely + Date: Tue Nov 8 02:01:34 2022 +0000 + + [time.format] Use basic_ostringstream instead of ostringstream (#5932) + + commit 8739d316f2a55c633963b26b748681ff16498887 + Author: Marc Mutz <94039187+marcmutz@users.noreply.github.com> + Date: Tue Nov 8 03:05:45 2022 +0100 + + [meta.const.eval] Add is_constant_evaluated to index of library names (#5898) + + Previously, only its feature-test macro was listed there. + + commit 4c442cf93f03a44ec1f6a93875043a3aca7c5b9b + Author: Johel Ernesto Guerrero Peña + Date: Mon Nov 7 23:38:36 2022 -0400 + + [class.union.general] Attach example to its note (#5882) + + commit 65c494b9a4a5a4fab500733441c04e50a787d318 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Tue Nov 8 15:51:21 2022 +0800 + + [mdspan.extents.expo] Remove redundant "// exposition only" (#5907) + + commit b766881dda1d0201d98710b11efda3491a84b4f2 + Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com> + Date: Tue Nov 8 13:15:07 2022 +0500 + + [dcl.init.list] Specify the type of the prvalue (#5919) + + commit 6e035b52e28e95211a39ffb552851499432b2c6e + Author: Johel Ernesto Guerrero Peña + Date: Tue Nov 8 15:30:29 2022 -0400 + + [ratio.ratio] Use symbol "sgn" for the signum function (#5925) + + commit 89269f8e548b993b239f2c0f5ecc071ee7f54c9a + Author: Blackteahamburger + Date: Wed Nov 9 04:12:59 2022 +0800 + + [dcl.link] Add missing restriction to language linkage application (#5892) + + A language linkage specification should only apply to entities that do in fact have language linkage. + + commit ea77b2fa83ddac0c52c1b505ff666328a2a8f558 + Author: Jens Maurer + Date: Wed Nov 9 00:34:26 2022 +0100 + + [temp.deduct.general] Fix typo in comment in example + + commit 0c196ec375993000547e8913abb4c4ce703144cb + Author: Jens Maurer + Date: Thu Nov 10 15:32:56 2022 +0100 + + [temp.deduct.conv] Remove misleading paragraph break + + commit 0cd0c33f648d1304160e6dcb1856affd71b3ebbb + Author: Casey Carter + Date: Fri Nov 11 18:35:53 2022 -0800 + + [mdspan.extents.cons] "constexpr" should precede "explicit" + + In library function declarations, the `constexpr` specifier always precedes the `explicit` specifier per our standing style guide. + + commit 608c152dbae69d335d7238cdd5d178e048e2a1fd + Author: Casey Carter + Date: Mon Nov 14 10:48:18 2022 -0800 + + [vector.bool.pspc] Replace `constexpr static` with `static constexpr` + + As preferred by our style guide. + + commit d829eac310981e688a15b28622a2f048d23eed65 + Author: Thomas Köppe + Date: Thu Nov 10 07:43:32 2022 +0000 + + [class.inhctor.init] Fix explanation of "error:" in example + + The correct explanation is that classes `B1` and `D1` do not have + default constructors, not that they have deleted default constructors. + + Fixes NB CA 062 (C++23 CD). + + commit 6a1c5050c21ac26fcb2b5b187a0de867713568dc + Author: Thomas Köppe + Date: Tue Nov 8 23:35:00 2022 +0000 + + [diff.cpp20.library] Add missing new headers + + Fixes NB FR 008 (C++23 CD). + + commit b2fa70faa783827cd38b819409e94da2523333f2 + Author: Thomas Köppe + Date: Wed Nov 9 18:50:56 2022 +0000 + + [views] Subclauses for contiguous and multidimensional access + + This organises the material for and into separate + subclauses, rather than having all constituent parts being siblings in + the same subclause. Even though we now have some subclauses six levels + deep, this seems like an improvement. As a drive-by, this allows us to + move a subclause on a non-member span helper function up one level, + where it is more appropriate. + + Fixes NB FR 027 (C++23 CD). + + commit e0bab4b7f2d8afe5d3939aa49fe6de4fd5e638c6 + Author: Thomas Köppe + Date: Thu Nov 10 02:16:11 2022 +0000 + + [concepts index] Describe exposition-only concepts + + Fixes NB GB 136 (C++23 CD). + + commit 9512e41e30cf24a8e93e8c8568ff1b5c14398cc6 + Author: Thomas Köppe + Date: Fri Nov 11 19:31:11 2022 +0000 + + [general, library index] Describe exposition-only entities + + Partially fixes NB GB 137 (C++23 CD). + + commit 0783dde32073b02b369c7c3893f4f496a83e3658 + Author: Thomas Köppe + Date: Fri Nov 11 19:33:33 2022 +0000 + + [func.wrap.move.ctor] Move private expos member to general index + + The private, exposition-only data member is not useful in the library + index. However, there seems no reason to not show it in the general + index, so we move the index entry from the library index to the + general index. + + Partially fixes NB GB 137 (C++23 CD). + + commit 3e825f144f2aa8668c9a1a94066b43799e08a6e7 + Author: Thomas Köppe + Date: Tue Nov 8 21:31:30 2022 +0000 + + [basic.scope.scope] Fix indentation in example + + Fixes NB US 034 (C++23 CD). + + commit 92de5996625efcb070f99681acd2e39efc206ee2 + Author: Thomas Köppe + Date: Tue Nov 8 23:24:35 2022 +0000 + + [unord.req.general] Fix garbled end of sentence + + This was an editorial mistake introduced by the transformation of the + requirement tables into regular paragraphs. + + Fixes NB US 100 (C++23 CD). + + commit 24e046896029a11f2cb78fd6db21482fb0d4be66 + Author: Thomas Köppe + Date: Tue Nov 8 21:02:31 2022 +0000 + + [coro.generator.promise] Use "equivalent to `throw`, ..." + + Our style guide says that "equivalent to " is the + appropriate style for an expression of type `void`, which is the case + for `throw`. This avoids the awkward situation of having "equivalent + to: `throws;`" appear in the middle of a paragraph without proper + terminal punctuation. + + Fixes NB US 119 (C++23 CD). + + commit 3f47d2565f26a9144e8076641ee55bf7be79f896 + Author: Thomas Köppe + Date: Tue Nov 8 21:27:56 2022 +0000 + + [coro.generator.promise] Remove unused name "x" + + Fixes NB US 120 (C++23 CD). + + commit fb0df97e7d7c2c75bbdf7164c33b0796024ff6d3 + Author: Jonathan Wakely + Date: Thu Nov 17 08:44:05 2022 +0000 + + [atomics] Replace integral and floating-point placeholders (#5939) + + Fixes NB GB 129 (C++23 CD). + + commit 0bb57d5ebffa7170fbc80724f55a6ac2a82f2e83 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Fri Nov 25 14:56:24 2022 +0800 + + [format.arg] Add std:: for forward + + commit c88fb46327d87d78d571b7e1076e1916eaf7e310 + Author: Dawn Perchik + Date: Tue Nov 15 07:46:41 2022 -0800 + + [expr.unary.op] Say "the ~ operator" consistently, remove "unary" + + We are currently using the term "unary complement operator" to refer + to the "~" operator without ever giving it that name. This change + removes the use of that undefined term. + + commit bef02b89464fe6f4be3926d62defc92986ae4532 + Author: Thomas Köppe + Date: Tue Nov 22 16:28:42 2022 +0000 + + [expr.unary.op] Notes naming unary ops as {ones',two's} complement + + The terms "one's complement" and "two's complement" are well-known, + and it is useful to associate them with these operators. + + commit 020a312b2aa513a992e488d82db55fd0cd4fa025 + Author: Thomas Köppe + Date: Wed Nov 16 17:48:12 2022 +0000 + + [fs.rec.dir.itr.nonmembers] "for" is a keyword in "range-based for" + + commit cee095e75a97fb88a7053e360b3bc06d36a6b687 + Author: Alisdair Meredith + Date: Fri Dec 16 06:51:26 2022 +0700 + + [depr.conversions.string] remove redundent respecification (#6004) + + There are several typedef names defined precisely in the deprecated code conversion + facets classes that are redundantly respecified in text. Nowhere else in the library + does this; any specified typedef names are _see below_ definitions, not repeats of + the class definition. Needless redundancy is always a risk of divergence, however + small, so remove the respecification in text form. + + commit 1bb52db31be002f04ea5977f9900ba4174c7155e + Author: Anoop Rana <93918384+ranaanoop@users.noreply.github.com> + Date: Fri Dec 16 05:23:57 2022 +0530 + + [concepts.object] Change "built-in" to "fundamental" types (#6012) + + commit ce1cc3b011099b6228b18dad937911c6ea67d309 + Author: Johel Ernesto Guerrero Peña + Date: Sun Dec 11 17:03:41 2022 -0400 + + [expr.const] Remove redundant "ill-formed" in "error" comment + + commit 5d43f0137776fa112d0ffd6ba0e34df34a4cb820 + Author: Jonathan Wakely + Date: Tue Dec 13 12:52:00 2022 +0000 + + [time.zone.leap.members] update note about leap seconds + + commit fd20d4ea9f3ea8653b17169aad61eec843b71718 + Author: Jonathan Wakely + Date: Wed Nov 23 14:45:43 2022 +0000 + + [time.zone.zonedtime.overview] Rename parameters to match later definitions + + commit 137728f0830824c6058648a846376eec80e5cab3 + Author: Michael Florian Hava + Date: Fri Dec 16 02:10:55 2022 +0100 + + [coro.generator.promise] Fix template parameters (#6009) + + Some of the template parameters of `yield_value` were inconsistent, + and the synopsis contained an outright typo. This change uses `R2` + consistently since the parameter is a reference. + + commit 5d6099c3df78922ee5b5f1d1c42a5c762d246df0 + Author: Thomas Köppe + Date: Thu Dec 15 23:31:26 2022 +0000 + + [formatter.requirements] Remove one level of list nesting + + commit 9e41a1c27de2f676badacbe0c1aac783063b7cd6 + Author: Thomas Köppe + Date: Wed Nov 16 19:43:58 2022 +0000 + + [time.clock.req] Make list item end with comma, not full stop. + + Also reformat the itemization source to be more edit-friendly. + + commit 5ef31f3fc1531d9e6e923cb57bf6e5ecec59ed4e + Author: languagelawyer + Date: Thu Jun 25 10:54:17 2020 +0300 + + [expr.unary.op] Fix usage of "result" + + commit 8c60752c7eb28e1ff1cc9e088d7836957356f559 + Author: Jonathan Wakely + Date: Tue Apr 26 10:18:11 2022 +0100 + + [optional.ctor], [expected.object.ctor] Add converts-from-any-cvref + + commit 405b46f50ce6c7458e94db7b4528fc267e2b67c3 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Sat Dec 17 00:14:51 2022 +0800 + + [mdspan.mdspan.overview] Add default template arguments for mdspan (#6018) + + We usually restate the default template arguments in the class synopsis, + so that the information is in one place and one does not need to also refer + to the header synopsis. + + commit ae88bb581d32f1939987c0a834fe3f6011a9d003 + Author: frederick-vs-ja + Date: Fri Dec 16 21:25:31 2022 +0800 + + [range.repeat] Change `W`/`WArgs` to `T`/`TArgs` + + commit 0a1f1e147c75ce9220de3488103ca880b6b8e49f + Author: Thomas Köppe + Date: Fri Dec 16 17:19:08 2022 +0000 + + [concept.copyconstructible] Avoid "possibly \tcode{const}" + + A small rewrite avoids the phrase "possibly \tcode{const}", + which we would like to remove entirely in favour of just + "possibly const". + + commit f058decdf9c7dea0461f723df72f5093f5e92b11 + Author: Thomas Köppe + Date: Fri Dec 16 17:31:47 2022 +0000 + + Replace "possibly \tcode{const}" with "possibly const" + + The "const" here is not syntax, but just normal text. + This is similar to "inline" and "public", which have + previously been cleaned up similarly. + + commit 9ac55553459e15c84db6d8072c93787d41ef7ccf + Author: Jens Maurer + Date: Fri Jun 4 00:29:30 2021 +0200 + + [lib] Drop 'inline' from 'inline constexpr' variable templates. + + Since CWG2387, constexpr variable templates have external linkage. diff --git a/papers/n4945.html b/papers/n4945.html new file mode 100644 index 0000000000..7ead1e9a9d --- /dev/null +++ b/papers/n4945.html @@ -0,0 +1,635 @@ + + + + + +N4945 + + +

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

+ +

Date: 2023-03-22

+ +

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. +Thank you also to Robert Leahy for drafting motion applications, +and special thanks to Johel Ernesto Guerrero Peña for providing in-depth review +of many of the draft motion applications.

+ +

New papers

+ +
    +
  • N4944 is the +current working draft for C++23. It replaces +N4928.
  • +
  • N4945 is this Editors' Report.
  • +
+ +

National body comments on the Committee Draft

+ +

N4919 is the C++23 Committee Draft. It received 137 comments from national bodies. +The first set of responses to all 11 editorial comments and to 49 non-editorial comments +was incorporated into the previous working draft, N4928; see the +previous Editors' Report +for details. The present working draft contains the final set of responses, +to 26 non-editorial comments, as noted below.

+ +

Non-editorial comments

+ +
    +
  • FR 012: Fixed by P2675R1 (LWG poll 10)
  • +
  • FR 013: Fixed by P2736R2 (CWG poll 8)
  • +
  • FR 021: Fixed by P2164R9 (LWG poll 6)
  • +
  • FR 023: Fixed by P2693R1 (LWG poll 12)
  • +
  • US 035: Fixed by CWG2642 (CWG poll 1)
  • +
  • US 036: Fixed by P2788R0 (CWG poll 9)
  • +
  • DE 038: Fixed by CWG2659 (CWG poll 6)
  • +
  • CA 076: Fixed by LWG3871 (LWG poll 3)
  • +
  • US 077: Fixed by P2652R2 (LWG poll 16)
  • +
  • DE 079: Fixed by P2614R2 (LWG poll 18)
  • +
  • GB 080: Fixed by LWG3828 (LWG poll 3)
  • +
  • GB 081: Fixed by LWG3827 (LWG poll 3)
  • +
  • GB 082: Fixed by LWG3827 (LWG poll 3)
  • +
  • GB 084: Fixed by LWG3869 (LWG poll 3)
  • +
  • CA 086: Fixed by P2679R2 (LWG poll 13)
  • +
  • GB 089: Fixed by P2674R1 (LWG poll 14)
  • +
  • US 098: Fixed by P2713R1 (LWG poll 9)
  • +
  • US 099: Fixed by P2609R3 (LWG poll 8)
  • +
  • US 108: Duplicate of FR 021
  • +
  • US 116: Fixed by P2787R1 (LWG poll 17)
  • +
  • GB 121: Fixed by LWG3870 (LWG poll 3)
  • +
  • US 126: Fixed by P2770R0 (LWG poll 5)
  • +
  • US 131: Fixed by P2588R3 (LWG poll 19)
  • +
  • FR 133: Duplicate of FR 013
  • +
  • FR 134: Duplicate of US 098
  • +
  • DE 135: Duplicate of US 131
  • +
+ +

Motions incorporated into working draft

+ +

Notes on motions

+ +
    +
  • CWG Poll 7 does not modify the C++ Working Paper.
  • +
  • For CWG Poll 4, the proposed wording of CWG 2521 +erroneously used the non-existing grammar production pp-token, +which was fixed to preprocessing-token.
  • +
  • For CWG Poll 8, a change of "character classes" to "character properties" +missing from P2736R2 +was applied.
  • +
  • CWG Poll 8, LWG Polls 9 and 11 all affect Unicode-related wording. While the +wording for the latter two was given relative to the status quo ante, the +actual wording has been adjusted to incorporate the changes from the CWG poll. +Moreover, we now always use the phrase "UAX #N of the Unicode Standard".
  • +
  • For LWG Poll 2, issue LWG 3821, +the new overload was marked as "freestanding" to match the surrounding interface; +this was not in the proposed wording.
  • +
  • For LWG Poll 6, an unused and erroneous default argument "pos = 0" was removed.
  • +
  • For LWG Poll 16, the wording has been reconciled with the changes from issue +LWG 3775 +that was applied after the previous meeting.
  • +
+ +

Core working group polls

+ +

CWG Poll 1: Accept as a Defect Report and apply the proposed resolution of all issues +except issues 2518, 2521, 2659, 2674, 2678, and 2691 in P2796R0 +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper.

+ +

CWG Poll 2: Apply the proposed resolution of issues 2674 and 2691 +in P2796R0 +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper.

+ +

CWG Poll 3: Accept as a Defect Report and apply the proposed resolution of issue 2518 (Conformance requirements and #error/#warning) +in P2796R0 +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper.

+ +

CWG Poll 4: Accept as a Defect Report and apply the proposed resolution of issue 2521 (User-defined literals and reserved identifiers) +in P2796R0 +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper.

+ +

CWG Poll 5: Accept as a Defect Report and apply the proposed resolution of issue 2678 +(std::source_location::current is unimplementable) in P2796R0 +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper.

+ +

CWG Poll 6: Apply the proposed resolution of issue 2659 (Missing feature-test macro for lifetime extension in range-for loop) +in P2796R0 +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper, resolving NB comment DE 038.

+ +

CWG Poll 7: Specify that P2647R1 +(Permitting static constexpr variables in constexpr functions) (applied in November, 2022) is no longer a Defect Report.

+ +

CWG Poll 8: Apply the changes in P2736R2 (Referencing The Unicode Standard) +to the C++ Working Paper, resolving NB comments FR 133 and FR 013.

+ +

CWG Poll 9: Accept as a Defect Report and apply the changes in P2788R0 +(Linkage for modular constants) to the C++ Working Paper, resolving NB comment US 036.

+ +

CWG Poll 10: Apply the changes in P2797R0 +(Proposed resolution for CWG2692 Static and explicit object member functions with the same parameter-type-lists) to the C++ Working Paper.

+ +

Library working group polls

+ +

Poll 1 does not concern the C++ Working Paper.

+ +

LWG Poll 2: Apply the changes for all Ready and Tentatively Ready issues in P2789R0 +(C++ Standard Library Issues to be moved in Issaquah, Feb. 2023) to the C++ working paper.

+ +

LWG Poll 3: Apply the changes for all Immediate issues except 3441 in P2790R0 +(C++ Standard Library Immediate Issues to be moved in Issaquah, Feb. 2023) to the C++ working paper.

+ +

LWG Poll 4: Apply the changes for the Immediate issue 3441 in P2790R0 +(C++ Standard Library Immediate Issues to be moved in Issaquah, Feb. 2023) to the C++ working paper.

+ +

LWG Poll 5: Apply the changes in P2770R0 +(Stashing stashing iterators for proper flattening) to the C++ working paper. This addresses ballot comment US 126.

+ +

LWG Poll 6: Apply the changes in P2164R9 +(views::enumerate) to the C++ working paper. This addresses ballot comments FR 021 and US 108.

+ +

LWG Poll 7: Apply the changes in P2711R1 +(Making multi-param constructors of views explicit) to the C++ working paper.

+ +

LWG Poll 8: Apply the changes in P2609R3 +(Relaxing Ranges Just A Smidge) to the C++ working paper. This addresses ballot comment US 099.

+ +

LWG Poll 9: Apply the changes in P2713R1 +(Escaping improvements in std::format) to the C++ working paper. This addresses ballot comments US 098 and FR 134.

+ +

LWG Poll 10: Apply the changes in P2675R1 +(format's width estimation is too approximate and not forward compatible) to the C++ working paper. This addresses ballot comment FR 012.

+ +

LWG Poll 11: Apply the changes in P2572R1 +(std::format fill character allowances) to the C++ working paper.

+ +

LWG Poll 12: Apply the changes in P2693R1 +(Formatting thread::id and stacktrace) to the C++ working paper. This addresses ballot comment FR 023.

+ +

LWG Poll 13: Apply the changes in P2679R2 +(Fixing std::start_lifetime_as for arrays) to the C++ working paper. This addresses ballot comment CA 086.

+ +

LWG Poll 14: Apply the changes in P2674R1 +(A trait for implicit lifetime types) to the C++ working paper. This addresses ballot comment GB 089.

+ +

LWG Poll 15: Apply the changes in P2655R3 +(common_reference_t of reference_wrapper Should Be a Reference Type) to the C++ working paper.

+ +

LWG Poll 16: Apply the changes in P2652R2 +(Disallow User Specialization of allocator_traits) to the C++ working paper. This addresses ballot comment US 077.

+ +

LWG Poll 17: Apply the changes in P2787R1 +(pmr::generator - Promise Types are not Values) to the C++ working paper. This addresses ballot comment US 116.

+ +

LWG Poll 18: Apply the changes in P2614R2 +(Deprecate numeric_limits::has_denorm) to the C++ working paper. This addresses ballot comment DE 079.

+ +

LWG Poll 19: Apply the changes in P2588R3 +(barrier's phase completion guarantees) to the C++ working paper. This addresses ballot comment DE 135 and US 131.

+ +

LWG Poll 20: Apply the changes in P2763R1 +(layout_stride static extents default constructor fix) to the C++ working paper.

+ +

Noteworthy editorial changes

+ +
    +
  • In the container requirements, the presentation of "contiguous container" has +been reordered for a better logical progression, which was made possible by +the earlier dissolution of the requirements tables.
  • +
+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4928 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 538ed7470087a1304ec9c04db8b00de1d4f40d03
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Dec 18 21:19:08 2022 +0000
+
+    [lex.ccon] Add xref to lex.charset, where encodings are defined
+
+commit ffd3141ffd278f86209845282548e6e5d9ed21eb
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Dec 19 00:02:24 2022 +0000
+
+    [lex.string] Add xref to lex.charset, where encodings are defined
+
+commit 13fa11859e144ecba44807746cd376c0b33f571f
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Thu Dec 29 02:01:37 2022 +0800
+
+    [range.single.view] Remove duplicate semicolon (#6040)
+
+commit b98b620ec72c67423169782aa197dd0008900154
+Author: Eric41293 <eric41293@comcast.net>
+Date:   Wed Dec 28 11:07:01 2022 -0700
+
+    [format.string.std] Fixing grammatical error (#6037)
+
+commit c8e334d0632b5e49e7333002ebeb04c58754f2d1
+Author: zhihaoy <43971430+zhihaoy@users.noreply.github.com>
+Date:   Thu Jan 5 02:40:02 2023 -0800
+
+    [bitwise.operations.not] missing parameter name
+
+commit 0c9dd96bbfc421a0feabcbc2b6850cd369ed181f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Jan 17 23:16:33 2023 +0100
+
+    [over.over] Missed edit for P0847R7
+
+    P0847R7 (Deducing this) was approved at the October, 2021 meeting
+    and applied with commit ee5117e100bbe9b7adb3510b2d7bb6d4d150f810,
+    missing this change.
+
+commit 2228f1c619fcd19c61ae6a4378f03f6ee938e55a
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Mon Jan 16 12:11:47 2023 +0000
+
+    [unord.map.overview] Remove stray template-head on non-template
+
+commit b9d35e813c007f3514015017e1ce09d936b5e2cc
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Mon Jan 23 01:43:54 2023 +0800
+
+    [reverse.iter.conv] Remove unclear explicit comments
+
+    I don't know what explicit refers to here, it seems to be more appropriate to remove.
+    People who disagree with me are also welcome.
+
+commit b5d9d4f5c5a14a059a8af75428707a0fc14b4c12
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Tue Jan 24 17:20:59 2023 +0800
+
+    [move.sentinel] Use "std::move" in example for correctness (#6043)
+
+commit a009995257307b1ed8894718b70c917f4c25094b
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Thu Jan 26 02:06:35 2023 +0800
+
+    [iterator.synopsis] Fix inconsistent template constraint
+
+commit 388eff69768d3ba97c095de98e9972685f2e3579
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Jan 27 14:30:39 2023 +0100
+
+    [version.syn] Fix value of __cpp_lib_constexpr_bitset
+
+    Paper P2417R2 was approved in July 2022, but commit
+    75518ffdc476cbc239918466588d963fc97a8013 did not set
+    the feature-test to the approriate value.
+
+commit 9020f7480b2cd0f3c0857b93cab4dbcf44a24edc
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Sun Feb 5 23:30:36 2023 +0800
+
+    [format.range.fmtmap] Fix undefined type name
+
+commit a096b08e6a2ee5544fd753aefd9469673e4864dd
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Tue Jan 31 10:53:18 2023 +0800
+
+    [const.iterators.iterator] Add \expos comment for concept
+
+commit 9ce105b48e34c0e08947ac073694faa6600716ec
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Fri Feb 10 14:52:42 2023 +0800
+
+    [iostream.cons] Add std:: qualified for move
+
+commit 6d836080a380d0f828de30e6449985b5b503d874
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Mar 6 18:28:32 2023 +0000
+
+    [dcl.pre] Add missing markup that makes "fails" a definition.
+
+    This change was missed from the application of CWG2518.
+
+    Also fixes the indexing of "static_assert" (which is a keyword, not a
+    grammar production).
+
+commit 9357ba63abeb27152ac7d03db4ba9a274cf2f922
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Sun Feb 26 19:52:46 2023 -0600
+
+    [expected.object.eq] Fix typo
+
+commit 586f4ed7fbafeee5b91fcb6c2950008dfffbeec0
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Mar 7 10:34:50 2023 -0500
+
+    [cpp.pre] Fix grammar for #elifdef
+
+    This fix is editorial as it corrects a mis-application of the original
+    paper, https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2334r1.pdf.
+
+    Note that the corresponding use of this grammar in [cpp.cond]p13
+    assumes the correct grammar, making the intent equally clear.
+
+commit 64ef8b32a5b3ac60e8ac1f28ccb008c704cc25f4
+Author: Barry Revzin <barry.revzin@gmail.com>
+Date:   Sun Mar 12 10:11:24 2023 -0500
+
+    [expr.prim.req.compound] Move compound requirement example from inner to outer bullet (#6159)
+
+    Example 1 from [expr.prim.req.compound] is currently attached to the
+    inner bullet point, but should be attached to the outer one.
+
+commit 5a974f72f43928258a6264155f8932bebb3fea30
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Sun Mar 12 23:17:02 2023 +0800
+
+    [util.smartptr.atomic.general] Simplify example code (#6077)
+
+    Removes the redundant explicit construction of the return value,
+    and uses an explicit return type instead of "auto" for clarity.
+
+commit 1912644b1bf60e0c8fc8d53ccbee0488244b1fd3
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Mar 13 00:02:02 2023 +0800
+
+    [specialized.algorithms.general] Remove possibly wrong note (#6157)
+
+commit 40cfc37319ae4e6204a2237ad6e143fac6911df6
+Author: Blackteahamburger <blackteahamburger@outlook.com>
+Date:   Mon Mar 13 02:23:01 2023 +0800
+
+    [allocator.requirements.general] Fix SimpleAllocator example (#6152)
+
+    The example now meets the requirements and is minimal.
+    Previously, some == comparisons that should work were ambiguous.
+
+commit f131b37fbf412bf2b69690914c2030b3ad702e55
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Sun Mar 12 14:27:09 2023 -0400
+
+    [library.general,tab:thread.summary] Update references to renamed Clause (#6149)
+
+commit 71c72b23250d4e3f8c960c345721ba5e6a52f3c1
+Author: Giuseppe D'Angelo <dangelog@users.noreply.github.com>
+Date:   Sun Mar 12 23:29:23 2023 +0100
+
+    [range.split] Fix invalid conversion in example (#6041)
+
+    Replaces an illegal implicit conversion from a range to string_view
+    in the example with an explicit one.
+
+    After P2499R0, it is no longer possible to implicitly construct a
+    string_view from a range (like the ones produced by views::split).
+
+commit b1f3246af2a6af4f2b81be9b296feb08ad40962b
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Mar 2 12:58:40 2023 +0000
+
+    Consistent comma after e.g. and i.e. (again)
+
+commit 29c0c3d61be7875e9be08a19d7612a7a2c628ef6
+Author: Alex Riegler <53669754+alexriegler@users.noreply.github.com>
+Date:   Sun Mar 12 19:59:06 2023 -0500
+
+    [tab:iostreams.summary] Add missing header in summary table (#6079)
+
+    Also reorder the headers into order of appearance,
+    which is how the "C library files" headers are ordered.
+
+commit 16dfc43257e15582d7461280b2c896c471e6e431
+Author: Mark de Wever <koraq@xs4all.nl>
+Date:   Mon Mar 13 02:06:04 2023 +0100
+
+    [time.syn] Use "ymwd" parameter name consistently (#6029)
+
+commit 6298c4b6ad03946ea5a547d375762d5f029cf195
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Mar 7 22:23:05 2023 -0500
+
+    [depr.template.template] Add cross-ref to core language
+
+    Add a cross reference to the core language paragraph that
+    contains the deprecation notice, [temp.names] (p6).
+
+commit d9f8705de8aaa61112250d211e7891e91b411dbe
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Sat Dec 31 00:57:08 2022 +0800
+
+    [range.take.overview, range.drop.overview] Remove redundant ranges:: qualifier
+
+commit dcac5eaf993a190a1bb1335217779bd9ef13a38e
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Mar 14 10:46:30 2023 -0400
+
+    [span.iterators] Fix cross-reference to container iterators (#6183)
+
+    The current cross-reference is to [containers.requirements], which
+    is the whole containers requirements clause, including not just
+    general containers, but also allocator-aware, reversible, sequence,
+    associative, and unodered associative containers.  It seems very
+    unlikely that the cross-reference expects to be the intersection
+    of all of those.
+
+    Rather, the reference seems to intend just the [containers.reqmts]
+    subclause, which adds just two useful constraints: random access
+    iterators should support the 3-way comparison operator, and the
+    interoperabiity of container iterators and const_iterators.
+
+commit 39c1510d443b647c46de3e84d49a21d442154795
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Mar 14 16:12:22 2023 +0100
+
+    [stmt] Fix cross-references for condition
+
+commit 22a3b44cd6d5b0017cb57d8767d9dfc2094735c8
+Author: morinmorin <mimomorin@gmail.com>
+Date:   Wed Mar 15 01:45:28 2023 +0900
+
+    [projected, alg.req.ind.{move, copy}, range.as.rvalue.overview] Article "an", not "a" (#6186)
+
+    The subsequent identifier is naturally pronounced with a leading vowel.
+
+commit ae8ec6f016e0efcb37104a96f0b0677b850fdd0f
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Mar 16 11:13:43 2023 -0400
+
+    [container.reqmts] Fix cross-references to contiguous container
+
+    This edit deserves describing in detail, to establish that it
+    is purely editorial.
+
+    As part of the mission to clean up tables in the standard,
+    the general container requirements were split into 5 more
+    focused leaf nodes.  Due to its location in the original
+    text, the definition for a contiguous container fell into
+    the subclause for reversible containers, to which it is
+    entirely unrelated.  There is no requirement that a
+    contiguous container be reversible, only that it has the
+    correct category for its iterators.
+
+    Meanwhile, all 3 of the existing cross-references point
+    to the wrong leaf node, that simply provides a key to
+    the identifiers used throughout the specification of this
+    clause.
+
+    The fix has two parts.  First move the definition of
+    contiguous container, and a container with special
+    iterators, into the [container.reqmts] clause where it
+    best belongs.  This move is appended to the end so that
+    there can be no ambiguity that any existing text could
+    be confused with requirements only on contiguous
+    containers after the edit.  The other part is to fix up
+    the three cross-references to point to [container.reqmts]
+    rather than its sibling that has no information on
+    contiguous containers.
+
+    A grep of the .tex source files confirms that these
+    three references (array,basic_string, and vector) are
+    the only current uses of contiguous container, even
+    though basic_stacktrace would also meet the requirements.
+
+commit f24d86dcb1d597dc65cd10e56e80d23e331a9f1b
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Sat Mar 18 20:41:27 2023 -0400
+
+    [range.subrange.general, range.adaptors] Use "present only if" (#6146)
+
+ + diff --git a/papers/n4945.md b/papers/n4945.md new file mode 100644 index 0000000000..2be432983d --- /dev/null +++ b/papers/n4945.md @@ -0,0 +1,488 @@ +# N4945 Editors' Report -- Programming Languages -- C++ + +Date: 2023-03-22 + +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. +Thank you also to Robert Leahy for drafting motion applications, +and special thanks to Johel Ernesto Guerrero Peña for providing in-depth review +of many of the draft motion applications. + +## New papers + + * [N4944](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4944.pdf) is the + current working draft for C++23. It replaces + [N4928](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4928.pdf). + * N4945 is this Editors' Report. + +## National body comments on the Committee Draft + +N4919 is the C++23 Committee Draft. It received 137 comments from national bodies. +The first set of responses to all 11 editorial comments and to 49 non-editorial comments +was incorporated into the previous working draft, N4928; see the +[previous Editors' Report](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4929.html) +for details. The present working draft contains the final set of responses, +to 26 non-editorial comments, as noted below. + +### Non-editorial comments + +* **FR 012:** Fixed by [P2675R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2675r1.pdf) (LWG poll 10) +* **FR 013:** Fixed by [P2736R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2736r2.pdf) (CWG poll 8) +* **FR 021:** Fixed by [P2164R9](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2164r9.pdf) (LWG poll 6) +* **FR 023:** Fixed by [P2693R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2693r1.pdf) (LWG poll 12) +* **US 035:** Fixed by [CWG2642](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2796r0.html#2642) (CWG poll 1) +* **US 036:** Fixed by [P2788R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2788r0.html) (CWG poll 9) +* **DE 038:** Fixed by [CWG2659](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2796r0.html#2659) (CWG poll 6) +* **CA 076**: Fixed by [LWG3871](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2790r0.html#3871) (LWG poll 3) +* **US 077:** Fixed by [P2652R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2652r2.html) (LWG poll 16) +* **DE 079:** Fixed by [P2614R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2614r2.pdf) (LWG poll 18) +* **GB 080**: Fixed by [LWG3828](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2790r0.html#3828) (LWG poll 3) +* **GB 081**: Fixed by [LWG3827](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2790r0.html#3827) (LWG poll 3) +* **GB 082**: Fixed by [LWG3827](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2790r0.html#3827) (LWG poll 3) +* **GB 084**: Fixed by [LWG3869](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2790r0.html#3869) (LWG poll 3) +* **CA 086:** Fixed by [P2679R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2679r2.html) (LWG poll 13) +* **GB 089:** Fixed by [P2674R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2674r1.pdf) (LWG poll 14) +* **US 098:** Fixed by [P2713R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2713r1.html) (LWG poll 9) +* **US 099:** Fixed by [P2609R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2609r3.html) (LWG poll 8) +* **US 108:** Duplicate of FR 021 +* **US 116:** Fixed by [P2787R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2787r1.pdf) (LWG poll 17) +* **GB 121**: Fixed by [LWG3870](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2790r0.html#3870) (LWG poll 3) +* **US 126:** Fixed by [P2770R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2770r0.html) (LWG poll 5) +* **US 131:** Fixed by [P2588R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2588r3.html) (LWG poll 19) +* **FR 133:** Duplicate of FR 013 +* **FR 134:** Duplicate of US 098 +* **DE 135:** Duplicate of US 131 + +## Motions incorporated into working draft + +### Notes on motions + +* CWG Poll 7 does not modify the C++ Working Paper. +* For CWG Poll 4, the proposed wording of [CWG 2521](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2796r0.html#2521) + erroneously used the non-existing grammar production *pp-token*, + which was fixed to *preprocessing-token*. +* For CWG Poll 8, a change of "character classes" to "character properties" + missing from [P2736R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2736r2.pdf) + was applied. +* CWG Poll 8, LWG Polls 9 and 11 all affect Unicode-related wording. While the + wording for the latter two was given relative to the status quo ante, the + actual wording has been adjusted to incorporate the changes from the CWG poll. + Moreover, we now always use the phrase "UAX #N of the Unicode Standard". +* For LWG Poll 2, issue [LWG 3821](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2789r0.html#3821), + the new overload was marked as "freestanding" to match the surrounding interface; + this was not in the proposed wording. +* For LWG Poll 6, an unused and erroneous default argument "`pos = 0`" was removed. +* For LWG Poll 16, the wording has been reconciled with the changes from issue + [LWG 3775](https://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2703r0.html#3775) + that was applied after the previous meeting. + +### Core working group polls + +CWG Poll 1: Accept as a Defect Report and apply the proposed resolution of all issues +except issues 2518, 2521, 2659, 2674, 2678, and 2691 in [P2796R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2796r0.html) +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper. + +CWG Poll 2: Apply the proposed resolution of issues 2674 and 2691 +in [P2796R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2796r0.html) +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper. + +CWG Poll 3: Accept as a Defect Report and apply the proposed resolution of issue 2518 (Conformance requirements and `#error`/`#warning`) +in [P2796R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2796r0.html) +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper. + +CWG Poll 4: Accept as a Defect Report and apply the proposed resolution of issue 2521 (User-defined literals and reserved identifiers) +in [P2796R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2796r0.html) +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper. + +CWG Poll 5: Accept as a Defect Report and apply the proposed resolution of issue 2678 +(`std::source_location::current` is unimplementable) in [P2796R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2796r0.html) +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper. + +CWG Poll 6: Apply the proposed resolution of issue 2659 (Missing feature-test macro for lifetime extension in range-for loop) +in [P2796R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2796r0.html) +(Core Language Working Group "ready" Issues for the February, 2023 meeting) to the C++ Working Paper, resolving NB comment DE 038. + +CWG Poll 7: Specify that [P2647R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2647r1.html) +(Permitting static constexpr variables in constexpr functions) (applied in November, 2022) is no longer a Defect Report. + +CWG Poll 8: Apply the changes in [P2736R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2736r2.pdf) (Referencing The Unicode Standard) +to the C++ Working Paper, resolving NB comments FR 133 and FR 013. + +CWG Poll 9: Accept as a Defect Report and apply the changes in [P2788R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2788r0.html) +(Linkage for modular constants) to the C++ Working Paper, resolving NB comment US 036. + +CWG Poll 10: Apply the changes in [P2797R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2797r0.html) +(Proposed resolution for CWG2692 Static and explicit object member functions with the same parameter-type-lists) to the C++ Working Paper. + +### Library working group polls + +Poll 1 does not concern the C++ Working Paper. + +LWG Poll 2: Apply the changes for all Ready and Tentatively Ready issues in [P2789R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2789r0.html) +(C++ Standard Library Issues to be moved in Issaquah, Feb. 2023) to the C++ working paper. + +LWG Poll 3: Apply the changes for all Immediate issues except 3441 in [P2790R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2790r0.html) +(C++ Standard Library Immediate Issues to be moved in Issaquah, Feb. 2023) to the C++ working paper. + +LWG Poll 4: Apply the changes for the Immediate issue 3441 in [P2790R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2790r0.html) +(C++ Standard Library Immediate Issues to be moved in Issaquah, Feb. 2023) to the C++ working paper. + +LWG Poll 5: Apply the changes in [P2770R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2770r0.html) +(Stashing stashing iterators for proper flattening) to the C++ working paper. This addresses ballot comment US 126. + +LWG Poll 6: Apply the changes in [P2164R9](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2164r9.pdf) +(`views::enumerate`) to the C++ working paper. This addresses ballot comments FR 021 and US 108. + +LWG Poll 7: Apply the changes in [P2711R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2711r1.html) +(Making multi-param constructors of views explicit) to the C++ working paper. + +LWG Poll 8: Apply the changes in [P2609R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2609r3.html) +(Relaxing Ranges Just A Smidge) to the C++ working paper. This addresses ballot comment US 099. + +LWG Poll 9: Apply the changes in [P2713R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2713r1.html) +(Escaping improvements in `std::format`) to the C++ working paper. This addresses ballot comments US 098 and FR 134. + +LWG Poll 10: Apply the changes in [P2675R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2675r1.pdf) +(`format`'s width estimation is too approximate and not forward compatible) to the C++ working paper. This addresses ballot comment FR 012. + +LWG Poll 11: Apply the changes in [P2572R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2572r1.html) +(`std::format` fill character allowances) to the C++ working paper. + +LWG Poll 12: Apply the changes in [P2693R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2693r1.pdf) +(Formatting `thread::id` and `stacktrace`) to the C++ working paper. This addresses ballot comment FR 023. + +LWG Poll 13: Apply the changes in [P2679R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2679r2.html) +(Fixing `std::start_lifetime_as` for arrays) to the C++ working paper. This addresses ballot comment CA 086. + +LWG Poll 14: Apply the changes in [P2674R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2674r1.pdf) +(A trait for implicit lifetime types) to the C++ working paper. This addresses ballot comment GB 089. + +LWG Poll 15: Apply the changes in [P2655R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2655r3.html) +(`common_reference_t` of `reference_wrapper` Should Be a Reference Type) to the C++ working paper. + +LWG Poll 16: Apply the changes in [P2652R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2652r2.html) +(Disallow User Specialization of `allocator_traits`) to the C++ working paper. This addresses ballot comment US 077. + +LWG Poll 17: Apply the changes in [P2787R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2787r1.pdf) +(`pmr::generator` - Promise Types are not Values) to the C++ working paper. This addresses ballot comment US 116. + +LWG Poll 18: Apply the changes in [P2614R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2614r2.pdf) +(Deprecate `numeric_limits::has_denorm`) to the C++ working paper. This addresses ballot comment DE 079. + +LWG Poll 19: Apply the changes in [P2588R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2588r3.html) +(`barrier`'s phase completion guarantees) to the C++ working paper. This addresses ballot comment DE 135 and US 131. + +LWG Poll 20: Apply the changes in [P2763R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2763r1.html) +(`layout_stride` static extents default constructor fix) to the C++ working paper. + +### Noteworthy editorial changes + +* In the container requirements, the presentation of "contiguous container" has + been reordered for a better logical progression, which was made possible by + the earlier dissolution of the requirements tables. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4928 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/n4928...n4944). + + commit 538ed7470087a1304ec9c04db8b00de1d4f40d03 + Author: Thomas Köppe + Date: Sun Dec 18 21:19:08 2022 +0000 + + [lex.ccon] Add xref to lex.charset, where encodings are defined + + commit ffd3141ffd278f86209845282548e6e5d9ed21eb + Author: Thomas Köppe + Date: Mon Dec 19 00:02:24 2022 +0000 + + [lex.string] Add xref to lex.charset, where encodings are defined + + commit 13fa11859e144ecba44807746cd376c0b33f571f + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Thu Dec 29 02:01:37 2022 +0800 + + [range.single.view] Remove duplicate semicolon (#6040) + + commit b98b620ec72c67423169782aa197dd0008900154 + Author: Eric41293 + Date: Wed Dec 28 11:07:01 2022 -0700 + + [format.string.std] Fixing grammatical error (#6037) + + commit c8e334d0632b5e49e7333002ebeb04c58754f2d1 + Author: zhihaoy <43971430+zhihaoy@users.noreply.github.com> + Date: Thu Jan 5 02:40:02 2023 -0800 + + [bitwise.operations.not] missing parameter name + + commit 0c9dd96bbfc421a0feabcbc2b6850cd369ed181f + Author: Jens Maurer + Date: Tue Jan 17 23:16:33 2023 +0100 + + [over.over] Missed edit for P0847R7 + + P0847R7 (Deducing this) was approved at the October, 2021 meeting + and applied with commit ee5117e100bbe9b7adb3510b2d7bb6d4d150f810, + missing this change. + + commit 2228f1c619fcd19c61ae6a4378f03f6ee938e55a + Author: Jonathan Wakely + Date: Mon Jan 16 12:11:47 2023 +0000 + + [unord.map.overview] Remove stray template-head on non-template + + commit b9d35e813c007f3514015017e1ce09d936b5e2cc + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Mon Jan 23 01:43:54 2023 +0800 + + [reverse.iter.conv] Remove unclear explicit comments + + I don't know what explicit refers to here, it seems to be more appropriate to remove. + People who disagree with me are also welcome. + + commit b5d9d4f5c5a14a059a8af75428707a0fc14b4c12 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Tue Jan 24 17:20:59 2023 +0800 + + [move.sentinel] Use "std::move" in example for correctness (#6043) + + commit a009995257307b1ed8894718b70c917f4c25094b + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Thu Jan 26 02:06:35 2023 +0800 + + [iterator.synopsis] Fix inconsistent template constraint + + commit 388eff69768d3ba97c095de98e9972685f2e3579 + Author: Jens Maurer + Date: Fri Jan 27 14:30:39 2023 +0100 + + [version.syn] Fix value of __cpp_lib_constexpr_bitset + + Paper P2417R2 was approved in July 2022, but commit + 75518ffdc476cbc239918466588d963fc97a8013 did not set + the feature-test to the approriate value. + + commit 9020f7480b2cd0f3c0857b93cab4dbcf44a24edc + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Sun Feb 5 23:30:36 2023 +0800 + + [format.range.fmtmap] Fix undefined type name + + commit a096b08e6a2ee5544fd753aefd9469673e4864dd + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Tue Jan 31 10:53:18 2023 +0800 + + [const.iterators.iterator] Add \expos comment for concept + + commit 9ce105b48e34c0e08947ac073694faa6600716ec + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Fri Feb 10 14:52:42 2023 +0800 + + [iostream.cons] Add std:: qualified for move + + commit 6d836080a380d0f828de30e6449985b5b503d874 + Author: Thomas Köppe + Date: Mon Mar 6 18:28:32 2023 +0000 + + [dcl.pre] Add missing markup that makes "fails" a definition. + + This change was missed from the application of CWG2518. + + Also fixes the indexing of "static_assert" (which is a keyword, not a + grammar production). + + commit 9357ba63abeb27152ac7d03db4ba9a274cf2f922 + Author: timsong-cpp + Date: Sun Feb 26 19:52:46 2023 -0600 + + [expected.object.eq] Fix typo + + commit 586f4ed7fbafeee5b91fcb6c2950008dfffbeec0 + Author: Alisdair Meredith + Date: Tue Mar 7 10:34:50 2023 -0500 + + [cpp.pre] Fix grammar for #elifdef + + This fix is editorial as it corrects a mis-application of the original + paper, https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2334r1.pdf. + + Note that the corresponding use of this grammar in [cpp.cond]p13 + assumes the correct grammar, making the intent equally clear. + + commit 64ef8b32a5b3ac60e8ac1f28ccb008c704cc25f4 + Author: Barry Revzin + Date: Sun Mar 12 10:11:24 2023 -0500 + + [expr.prim.req.compound] Move compound requirement example from inner to outer bullet (#6159) + + Example 1 from [expr.prim.req.compound] is currently attached to the + inner bullet point, but should be attached to the outer one. + + commit 5a974f72f43928258a6264155f8932bebb3fea30 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Sun Mar 12 23:17:02 2023 +0800 + + [util.smartptr.atomic.general] Simplify example code (#6077) + + Removes the redundant explicit construction of the return value, + and uses an explicit return type instead of "auto" for clarity. + + commit 1912644b1bf60e0c8fc8d53ccbee0488244b1fd3 + Author: A. Jiang + Date: Mon Mar 13 00:02:02 2023 +0800 + + [specialized.algorithms.general] Remove possibly wrong note (#6157) + + commit 40cfc37319ae4e6204a2237ad6e143fac6911df6 + Author: Blackteahamburger + Date: Mon Mar 13 02:23:01 2023 +0800 + + [allocator.requirements.general] Fix SimpleAllocator example (#6152) + + The example now meets the requirements and is minimal. + Previously, some == comparisons that should work were ambiguous. + + commit f131b37fbf412bf2b69690914c2030b3ad702e55 + Author: Johel Ernesto Guerrero Peña + Date: Sun Mar 12 14:27:09 2023 -0400 + + [library.general,tab:thread.summary] Update references to renamed Clause (#6149) + + commit 71c72b23250d4e3f8c960c345721ba5e6a52f3c1 + Author: Giuseppe D'Angelo + Date: Sun Mar 12 23:29:23 2023 +0100 + + [range.split] Fix invalid conversion in example (#6041) + + Replaces an illegal implicit conversion from a range to string_view + in the example with an explicit one. + + After P2499R0, it is no longer possible to implicitly construct a + string_view from a range (like the ones produced by views::split). + + commit b1f3246af2a6af4f2b81be9b296feb08ad40962b + Author: Jonathan Wakely + Date: Thu Mar 2 12:58:40 2023 +0000 + + Consistent comma after e.g. and i.e. (again) + + commit 29c0c3d61be7875e9be08a19d7612a7a2c628ef6 + Author: Alex Riegler <53669754+alexriegler@users.noreply.github.com> + Date: Sun Mar 12 19:59:06 2023 -0500 + + [tab:iostreams.summary] Add missing header in summary table (#6079) + + Also reorder the headers into order of appearance, + which is how the "C library files" headers are ordered. + + commit 16dfc43257e15582d7461280b2c896c471e6e431 + Author: Mark de Wever + Date: Mon Mar 13 02:06:04 2023 +0100 + + [time.syn] Use "ymwd" parameter name consistently (#6029) + + commit 6298c4b6ad03946ea5a547d375762d5f029cf195 + Author: Alisdair Meredith + Date: Tue Mar 7 22:23:05 2023 -0500 + + [depr.template.template] Add cross-ref to core language + + Add a cross reference to the core language paragraph that + contains the deprecation notice, [temp.names] (p6). + + commit d9f8705de8aaa61112250d211e7891e91b411dbe + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Sat Dec 31 00:57:08 2022 +0800 + + [range.take.overview, range.drop.overview] Remove redundant ranges:: qualifier + + commit dcac5eaf993a190a1bb1335217779bd9ef13a38e + Author: Alisdair Meredith + Date: Tue Mar 14 10:46:30 2023 -0400 + + [span.iterators] Fix cross-reference to container iterators (#6183) + + The current cross-reference is to [containers.requirements], which + is the whole containers requirements clause, including not just + general containers, but also allocator-aware, reversible, sequence, + associative, and unodered associative containers. It seems very + unlikely that the cross-reference expects to be the intersection + of all of those. + + Rather, the reference seems to intend just the [containers.reqmts] + subclause, which adds just two useful constraints: random access + iterators should support the 3-way comparison operator, and the + interoperabiity of container iterators and const_iterators. + + commit 39c1510d443b647c46de3e84d49a21d442154795 + Author: Jens Maurer + Date: Tue Mar 14 16:12:22 2023 +0100 + + [stmt] Fix cross-references for condition + + commit 22a3b44cd6d5b0017cb57d8767d9dfc2094735c8 + Author: morinmorin + Date: Wed Mar 15 01:45:28 2023 +0900 + + [projected, alg.req.ind.{move, copy}, range.as.rvalue.overview] Article "an", not "a" (#6186) + + The subsequent identifier is naturally pronounced with a leading vowel. + + commit ae8ec6f016e0efcb37104a96f0b0677b850fdd0f + Author: Alisdair Meredith + Date: Thu Mar 16 11:13:43 2023 -0400 + + [container.reqmts] Fix cross-references to contiguous container + + This edit deserves describing in detail, to establish that it + is purely editorial. + + As part of the mission to clean up tables in the standard, + the general container requirements were split into 5 more + focused leaf nodes. Due to its location in the original + text, the definition for a contiguous container fell into + the subclause for reversible containers, to which it is + entirely unrelated. There is no requirement that a + contiguous container be reversible, only that it has the + correct category for its iterators. + + Meanwhile, all 3 of the existing cross-references point + to the wrong leaf node, that simply provides a key to + the identifiers used throughout the specification of this + clause. + + The fix has two parts. First move the definition of + contiguous container, and a container with special + iterators, into the [container.reqmts] clause where it + best belongs. This move is appended to the end so that + there can be no ambiguity that any existing text could + be confused with requirements only on contiguous + containers after the edit. The other part is to fix up + the three cross-references to point to [container.reqmts] + rather than its sibling that has no information on + contiguous containers. + + A grep of the .tex source files confirms that these + three references (array,basic_string, and vector) are + the only current uses of contiguous container, even + though basic_stacktrace would also meet the requirements. + + commit f24d86dcb1d597dc65cd10e56e80d23e331a9f1b + Author: Johel Ernesto Guerrero Peña + Date: Sat Mar 18 20:41:27 2023 -0400 + + [range.subrange.general, range.adaptors] Use "present only if" (#6146) diff --git a/papers/n4951.html b/papers/n4951.html new file mode 100644 index 0000000000..ab5636e4d9 --- /dev/null +++ b/papers/n4951.html @@ -0,0 +1,447 @@ + + + + + +N4951 + + +

N4951 Editors’ Report:
Programming Languages — C++

+ +

Date: 2023-05-10

+ +

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

+ +
    +
  • N4950 is the +current and final working draft for C++23. It replaces +N4944, and it +forms the basis of the Draft International Standard for C++23.
  • +
  • N4951 is this Editors' Report.
  • +
  • The next working draft will be for C++26.
  • +
+ +

Editorial changes

+ +

There have not been any motions from WG21 since the last working draft. This +revision incorporates all the changes requested by the editorial review +committee in preparation of the Draft International Standard (DIS) ballot, +as well as other editorial changes.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4944 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 b8512a1c292adee71c1145d3c61e32d48dcb8daa
+Author: morinmorin <mimomorin@gmail.com>
+Date:   Wed Mar 15 01:45:28 2023 +0900
+
+    [container.requirements.general] Move exposition-only concept
+
+    The exposition-only concept container-compatible-range is defined
+    in the subclause for allocator-aware containers, that does not
+    actually use it.  This requirement is used throughout the subclause
+    for a variety of contains, so relocate the definition into the
+    leading subclause that provides a key to definitions used throughout
+    the containers subclauses.
+
+commit 6e7fd98b684a92405934de981abf01414a67ddbd
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Mar 23 14:21:22 2023 +0000
+
+    [version.syn] bump value of __cpp_lib_allocate_at_least
+
+    This is requested for the Tentatively Ready LWG issue 3887.
+
+    Fixes #6202
+
+commit a0403a9407e6520b6bbf0e818d9db8ac1282f4e1
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sat Mar 11 20:40:30 2023 +0000
+
+    [module.interface] Fix outdated example
+
+commit 2c7e87d447d65684c74890074999c60bb45712ab
+Author: Christian Trott <crtrott@sandia.gov>
+Date:   Fri Mar 24 09:32:22 2023 -0700
+
+    [mdspan.layout.left.cons] extents() should be other.extents() (#6069)
+
+    The precondition was erroneously referring to the not yet
+    constructed extents instead of other.extents().
+
+    Note that the extents of the to be constructed layout will be
+    initialized with other.extents - i.e. after construction they will
+    return the same value for the fwd-prod-of-extents etc.
+
+commit 1b0fe66324f2d5e7861397d7f537243833418cde
+Author: Jakub Mazurkiewicz <mazkuba3@gmail.com>
+Date:   Fri Mar 24 17:33:09 2023 +0100
+
+    [range.cartesian.view] Add missing views:: qualifier (#6059)
+
+commit 562af663363337848bcb34a8f5ba37641fb0560e
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Mar 27 17:06:50 2023 -0400
+
+    [over.literal] Cross-reference deprecated grammar (#6209)
+
+    The core convention is to retain deprecated wording in the
+    core clauses, but always make a reference to Annex D
+    where a feature, or parts of a feature, are deprecated.
+
+commit ac47f9cb768760f0abd7a57cbf3074ad5eebf011
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Mar 27 17:09:44 2023 -0400
+
+    [container.reqmts] Move requirements to the right place (#6199)
+
+    As part of the replacement of the container requirements tables with text,
+    several paragraphs of general container requirements were buried
+    in the new subsections for more specific requirements such as
+    reversible containers or allocator-aware containers.
+
+    This seems to have happened when general container requirements
+    followed one of the container requirements tables that are now expressed
+    as text. This change carefully restores text to the general container requirements
+    clause, in the original order they appeared in C++20.
+
+commit bb65fc8e22b8e056cfbeb45ba65c6f37bf355182
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Mar 28 21:04:20 2023 +0200
+
+    [dcl.decl.general] Fix cross-references
+
+    "templated function" is defined in [temp.pre], but avoid having
+    two cross-references to the same place in the same paragraph by
+    dropping the cross-reference for the definition of the grammar
+    non-terminal "requires-clause".
+
+commit 8c99598b60f0a059b37c7e1fd82480aaf32169a5
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Mar 29 10:47:27 2023 +0100
+
+    [class.member.lookup] Also change "N" to "M" in note.
+
+    This change should have been part of the resolution of CWG2642 (via
+    CWG Motion 1), but was accidentally omitted there.
+
+commit 8e2d6ee92f372d9526c01a8fb601da9921c94b2a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Mar 29 16:08:57 2023 +0100
+
+    [stacktrace.format] Use full typename "basic_stacktrace<Allocator>".
+
+commit 70b2f7b6bf0d7fe3d87d9438459f766fdd83b08c
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Mar 29 17:31:24 2023 +0100
+
+    [indirectcallable.indirectinvocable] Remove stray "&".
+
+    This was an error in the application of P2609R3.
+
+commit 08581e85636794384029de729a641975bb13260c
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Sun Apr 16 05:18:24 2023 -0400
+
+    [alg.unique] fix typo: namepace -> namespace
+
+commit 1a2e97de0517bb9ee1715a9664fa2861fa025cda
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Mon Apr 17 14:31:05 2023 +0800
+
+    [range.repeat.iterator] Remove redundant period (#6234)
+
+commit 44ff7aa92ba7f716abe96c29876b2ea145a22c66
+Author: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
+Date:   Fri Apr 21 18:56:31 2023 +0330
+
+    [check.yml] update version of "upload" action (#6231)
+
+    Update the `actions/upload-artifact` action to version 3.
+
+commit 413b147b0f48ea87606e0b7fbc107c8316b98fc3
+Author: Detlef Riekenberg <wine.dev@web.de>
+Date:   Thu Apr 27 04:00:32 2023 +0200
+
+    [compliance, headers.cpp.fs] Fix subclause name for cstddef (#6227)
+
+commit 82ecf4355a016847ffcf778abfcf1fe96d02fc79
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Sun Apr 30 07:56:10 2023 -0400
+
+    [flat.map.modifiers] Fix erroneous "try_emplace_hint" (#6238)
+
+    The hint-taking operation is instead an overload of try_emplace.
+
+commit 9568c66abd12eadd696b9f16bb4884908e2aad66
+Author: Daniel Krügler <daniel.kruegler@gmail.com>
+Date:   Sun Apr 30 13:57:23 2023 +0200
+
+    [ranges] Remove "inline" from variable templates (#6218)
+
+commit bdd25a63a8a84a1183ebc125dac132d0572f67fd
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sun Apr 30 08:02:42 2023 -0400
+
+    [iterator.concept.winc] Improve implementation-defined text (#6228)
+
+commit 057da6c79e35cc4cdebaa5a6096738f273c6c2e8
+Author: tocic <tocic@protonmail.ch>
+Date:   Wed Sep 28 13:14:14 2022 +0300
+
+    [back, macros] Fix inconsistent hyphenation of "cross-reference"
+
+commit d1e109e43d7625f4a4ebb6a045fc68a275fca611
+Author: tocic <tocic@protonmail.ch>
+Date:   Wed Sep 28 13:19:36 2022 +0300
+
+    [std] Fix inconsistent hyphenation of "multidimensional"
+
+commit bf9edb92183b34421dd6e02474f2ac943fd7cea3
+Author: tocic <tocic@protonmail.ch>
+Date:   Fri Apr 7 13:56:59 2023 +0300
+
+    [diff.cpp17.temp] Fix inconsistent hyphenation of "well-formed"
+
+commit 62cd54aedecb8bf152e80b1aced64d80e0b8bff6
+Author: tocic <tocic@protonmail.ch>
+Date:   Fri Apr 7 13:57:28 2023 +0300
+
+    [diff.cpp17.depr] Fix inconsistent hyphenation of "well-defined"
+
+commit 57ad77984fd2e07c90b1bb8ca34125452688031a
+Author: tocic <tocic@protonmail.ch>
+Date:   Fri Apr 7 13:51:09 2023 +0300
+
+    [fs.path.type.cvt] Fix inconsistent hyphenation of "error-prone"
+
+commit e16a651b7d6f490e9ffe003c9ca382970c478c1d
+Author: tocic <tocic@protonmail.ch>
+Date:   Fri Apr 7 13:45:39 2023 +0300
+
+    [filesystems] Fix inconsistent hyphenation of "subdirectory"
+
+commit f52423c2a4d60d0ad653a3c8e2895037df016db0
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 30 14:07:51 2023 +0100
+
+    [format.string.std] Clarify how an integer is interpreted
+
+commit 62d7d5a2e51d63d676cc93bfe69d4d55ea635983
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 30 14:15:35 2023 +0100
+
+    [class.{default,copy}.ctor] Use new term "constexpr-suitable".
+
+    As of CWG2602 (ce7d8b0360e1509de6f7fd073d0a091238b1326f), the term
+    "constexpr-suitable" replaces the previous phrase "satisfy the
+    requirements for a constexpr function".
+
+commit 696ddeb2b28b48efaffa93b881ff667d85d0a457
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 30 14:22:32 2023 +0100
+
+    [time.duration.general] Use new term "constexpr-suitable".
+
+commit 79aef51943810dcf14654490fb6101bbc9e4a0f9
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 30 14:23:05 2023 +0100
+
+    [pairs.pair, variant.ctor, tuple.cnstr] Use new term "constexpr-suitable".
+
+commit b6903b6fe23d06e23191e672ae287f0de0de472c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon May 1 09:47:08 2023 +0200
+
+    [cpp.predefined] Add __cpp_auto_cast
+
+commit 8f946881355fbbe031a325168078b2925e029bba
+Author: xmh0511 <970252187@qq.com>
+Date:   Tue May 2 01:31:02 2023 +0800
+
+    [temp.variadic] Change "init-capture pack" to "init-capture pack declaration"
+
+commit b81e4be37c5f7a4d374546a72bfc82c96601aee2
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri May 5 12:01:05 2023 +0100
+
+    [container.alloc.reqmts] Fix incorrect change of \mandates to \expects
+
+    This was incorrectly changed from a \mandates to an \expects when
+    93ff092d1cd2b335f372b9546365b3d495caf2d8 replaced the requirements
+    tables.
+
+commit 7003252f4db8b388dd097790b374ffed3be1ff56
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Sun May 7 16:27:19 2023 -0400
+
+    [flat.map.cons] Close an angle bracket (#6245)
+
+commit e7492cef7f930089e009913bff6ac30f41d6165e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 6 02:47:07 2023 +0100
+
+    [format] Fix presentation of whitespace; use \caret
+
+commit f8f5b8b564a785297a43b6b823b521e5adc79fb9
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Mon May 8 14:30:31 2023 -0400
+
+    [flat.map.modifiers] "Arg..." should be "Args..." (#6249)
+
+commit 02545c761c7f6c9e336c6badf8660b2baf4ac627
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Tue May 9 13:25:42 2023 -0400
+
+    [flat.set.modifiers] `(first, last)` should be `rg` (#6246)
+
+    Restore consistency with [flat.map.modifiers]/13, which already uses `ranges::distance(rg)`.
+
+ + diff --git a/papers/n4951.md b/papers/n4951.md new file mode 100644 index 0000000000..01e7a0651d --- /dev/null +++ b/papers/n4951.md @@ -0,0 +1,306 @@ +# N4951 Editors' Report -- Programming Languages -- C++ + +Date: 2023-05-10 + +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 + + * [N4950](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf) is the + current and final working draft for C++23. It replaces + [N4944](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4944.pdf), and it + forms the basis of the Draft International Standard for C++23. + * N4951 is this Editors' Report. + * The next working draft will be for C++26. + +### Editorial changes + +There have not been any motions from WG21 since the last working draft. This +revision incorporates all the changes requested by the editorial review +committee in preparation of the Draft International Standard (DIS) ballot, +as well as other editorial changes. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4944 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/n4944...n4950). + + commit b8512a1c292adee71c1145d3c61e32d48dcb8daa + Author: morinmorin + Date: Wed Mar 15 01:45:28 2023 +0900 + + [container.requirements.general] Move exposition-only concept + + The exposition-only concept container-compatible-range is defined + in the subclause for allocator-aware containers, that does not + actually use it. This requirement is used throughout the subclause + for a variety of contains, so relocate the definition into the + leading subclause that provides a key to definitions used throughout + the containers subclauses. + + commit 6e7fd98b684a92405934de981abf01414a67ddbd + Author: Jonathan Wakely + Date: Thu Mar 23 14:21:22 2023 +0000 + + [version.syn] bump value of __cpp_lib_allocate_at_least + + This is requested for the Tentatively Ready LWG issue 3887. + + Fixes #6202 + + commit a0403a9407e6520b6bbf0e818d9db8ac1282f4e1 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sat Mar 11 20:40:30 2023 +0000 + + [module.interface] Fix outdated example + + commit 2c7e87d447d65684c74890074999c60bb45712ab + Author: Christian Trott + Date: Fri Mar 24 09:32:22 2023 -0700 + + [mdspan.layout.left.cons] extents() should be other.extents() (#6069) + + The precondition was erroneously referring to the not yet + constructed extents instead of other.extents(). + + Note that the extents of the to be constructed layout will be + initialized with other.extents - i.e. after construction they will + return the same value for the fwd-prod-of-extents etc. + + commit 1b0fe66324f2d5e7861397d7f537243833418cde + Author: Jakub Mazurkiewicz + Date: Fri Mar 24 17:33:09 2023 +0100 + + [range.cartesian.view] Add missing views:: qualifier (#6059) + + commit 562af663363337848bcb34a8f5ba37641fb0560e + Author: Alisdair Meredith + Date: Mon Mar 27 17:06:50 2023 -0400 + + [over.literal] Cross-reference deprecated grammar (#6209) + + The core convention is to retain deprecated wording in the + core clauses, but always make a reference to Annex D + where a feature, or parts of a feature, are deprecated. + + commit ac47f9cb768760f0abd7a57cbf3074ad5eebf011 + Author: Alisdair Meredith + Date: Mon Mar 27 17:09:44 2023 -0400 + + [container.reqmts] Move requirements to the right place (#6199) + + As part of the replacement of the container requirements tables with text, + several paragraphs of general container requirements were buried + in the new subsections for more specific requirements such as + reversible containers or allocator-aware containers. + + This seems to have happened when general container requirements + followed one of the container requirements tables that are now expressed + as text. This change carefully restores text to the general container requirements + clause, in the original order they appeared in C++20. + + commit bb65fc8e22b8e056cfbeb45ba65c6f37bf355182 + Author: Jens Maurer + Date: Tue Mar 28 21:04:20 2023 +0200 + + [dcl.decl.general] Fix cross-references + + "templated function" is defined in [temp.pre], but avoid having + two cross-references to the same place in the same paragraph by + dropping the cross-reference for the definition of the grammar + non-terminal "requires-clause". + + commit 8c99598b60f0a059b37c7e1fd82480aaf32169a5 + Author: Thomas Köppe + Date: Wed Mar 29 10:47:27 2023 +0100 + + [class.member.lookup] Also change "N" to "M" in note. + + This change should have been part of the resolution of CWG2642 (via + CWG Motion 1), but was accidentally omitted there. + + commit 8e2d6ee92f372d9526c01a8fb601da9921c94b2a + Author: Thomas Köppe + Date: Wed Mar 29 16:08:57 2023 +0100 + + [stacktrace.format] Use full typename "basic_stacktrace". + + commit 70b2f7b6bf0d7fe3d87d9438459f766fdd83b08c + Author: Thomas Köppe + Date: Wed Mar 29 17:31:24 2023 +0100 + + [indirectcallable.indirectinvocable] Remove stray "&". + + This was an error in the application of P2609R3. + + commit 08581e85636794384029de729a641975bb13260c + Author: Arthur O'Dwyer + Date: Sun Apr 16 05:18:24 2023 -0400 + + [alg.unique] fix typo: namepace -> namespace + + commit 1a2e97de0517bb9ee1715a9664fa2861fa025cda + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Mon Apr 17 14:31:05 2023 +0800 + + [range.repeat.iterator] Remove redundant period (#6234) + + commit 44ff7aa92ba7f716abe96c29876b2ea145a22c66 + Author: Mohammed Keyvanzadeh + Date: Fri Apr 21 18:56:31 2023 +0330 + + [check.yml] update version of "upload" action (#6231) + + Update the `actions/upload-artifact` action to version 3. + + commit 413b147b0f48ea87606e0b7fbc107c8316b98fc3 + Author: Detlef Riekenberg + Date: Thu Apr 27 04:00:32 2023 +0200 + + [compliance, headers.cpp.fs] Fix subclause name for cstddef (#6227) + + commit 82ecf4355a016847ffcf778abfcf1fe96d02fc79 + Author: Arthur O'Dwyer + Date: Sun Apr 30 07:56:10 2023 -0400 + + [flat.map.modifiers] Fix erroneous "try_emplace_hint" (#6238) + + The hint-taking operation is instead an overload of try_emplace. + + commit 9568c66abd12eadd696b9f16bb4884908e2aad66 + Author: Daniel Krügler + Date: Sun Apr 30 13:57:23 2023 +0200 + + [ranges] Remove "inline" from variable templates (#6218) + + commit bdd25a63a8a84a1183ebc125dac132d0572f67fd + Author: Alisdair Meredith + Date: Sun Apr 30 08:02:42 2023 -0400 + + [iterator.concept.winc] Improve implementation-defined text (#6228) + + commit 057da6c79e35cc4cdebaa5a6096738f273c6c2e8 + Author: tocic + Date: Wed Sep 28 13:14:14 2022 +0300 + + [back, macros] Fix inconsistent hyphenation of "cross-reference" + + commit d1e109e43d7625f4a4ebb6a045fc68a275fca611 + Author: tocic + Date: Wed Sep 28 13:19:36 2022 +0300 + + [std] Fix inconsistent hyphenation of "multidimensional" + + commit bf9edb92183b34421dd6e02474f2ac943fd7cea3 + Author: tocic + Date: Fri Apr 7 13:56:59 2023 +0300 + + [diff.cpp17.temp] Fix inconsistent hyphenation of "well-formed" + + commit 62cd54aedecb8bf152e80b1aced64d80e0b8bff6 + Author: tocic + Date: Fri Apr 7 13:57:28 2023 +0300 + + [diff.cpp17.depr] Fix inconsistent hyphenation of "well-defined" + + commit 57ad77984fd2e07c90b1bb8ca34125452688031a + Author: tocic + Date: Fri Apr 7 13:51:09 2023 +0300 + + [fs.path.type.cvt] Fix inconsistent hyphenation of "error-prone" + + commit e16a651b7d6f490e9ffe003c9ca382970c478c1d + Author: tocic + Date: Fri Apr 7 13:45:39 2023 +0300 + + [filesystems] Fix inconsistent hyphenation of "subdirectory" + + commit f52423c2a4d60d0ad653a3c8e2895037df016db0 + Author: Thomas Köppe + Date: Sun Apr 30 14:07:51 2023 +0100 + + [format.string.std] Clarify how an integer is interpreted + + commit 62d7d5a2e51d63d676cc93bfe69d4d55ea635983 + Author: Thomas Köppe + Date: Sun Apr 30 14:15:35 2023 +0100 + + [class.{default,copy}.ctor] Use new term "constexpr-suitable". + + As of CWG2602 (ce7d8b0360e1509de6f7fd073d0a091238b1326f), the term + "constexpr-suitable" replaces the previous phrase "satisfy the + requirements for a constexpr function". + + commit 696ddeb2b28b48efaffa93b881ff667d85d0a457 + Author: Thomas Köppe + Date: Sun Apr 30 14:22:32 2023 +0100 + + [time.duration.general] Use new term "constexpr-suitable". + + commit 79aef51943810dcf14654490fb6101bbc9e4a0f9 + Author: Thomas Köppe + Date: Sun Apr 30 14:23:05 2023 +0100 + + [pairs.pair, variant.ctor, tuple.cnstr] Use new term "constexpr-suitable". + + commit b6903b6fe23d06e23191e672ae287f0de0de472c + Author: Jens Maurer + Date: Mon May 1 09:47:08 2023 +0200 + + [cpp.predefined] Add __cpp_auto_cast + + commit 8f946881355fbbe031a325168078b2925e029bba + Author: xmh0511 <970252187@qq.com> + Date: Tue May 2 01:31:02 2023 +0800 + + [temp.variadic] Change "init-capture pack" to "init-capture pack declaration" + + commit b81e4be37c5f7a4d374546a72bfc82c96601aee2 + Author: Jonathan Wakely + Date: Fri May 5 12:01:05 2023 +0100 + + [container.alloc.reqmts] Fix incorrect change of \mandates to \expects + + This was incorrectly changed from a \mandates to an \expects when + 93ff092d1cd2b335f372b9546365b3d495caf2d8 replaced the requirements + tables. + + commit 7003252f4db8b388dd097790b374ffed3be1ff56 + Author: Arthur O'Dwyer + Date: Sun May 7 16:27:19 2023 -0400 + + [flat.map.cons] Close an angle bracket (#6245) + + commit e7492cef7f930089e009913bff6ac30f41d6165e + Author: Thomas Köppe + Date: Sat May 6 02:47:07 2023 +0100 + + [format] Fix presentation of whitespace; use \caret + + commit f8f5b8b564a785297a43b6b823b521e5adc79fb9 + Author: Arthur O'Dwyer + Date: Mon May 8 14:30:31 2023 -0400 + + [flat.map.modifiers] "Arg..." should be "Args..." (#6249) + + commit 02545c761c7f6c9e336c6badf8660b2baf4ac627 + Author: Arthur O'Dwyer + Date: Tue May 9 13:25:42 2023 -0400 + + [flat.set.modifiers] `(first, last)` should be `rg` (#6246) + + Restore consistency with [flat.map.modifiers]/13, which already uses `ranges::distance(rg)`. diff --git a/papers/n4959.html b/papers/n4959.html new file mode 100644 index 0000000000..958923da9f --- /dev/null +++ b/papers/n4959.html @@ -0,0 +1,698 @@ + + + + + +N4959 + + +

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

+ +

Date: 2023-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 +and to those who have provided pull requests with fixes, +and special thanks to Johel Ernesto Guerrero Peña for providing in-depth review +of many of the draft motion applications.

+ +

New papers

+ +
    +
  • N4958 is the +current working draft for C++26. It replaces +N4950.
  • +
  • N4959 is this Editors' Report.
  • +
+ +

Motions incorporated into working draft

+ +

Notes on motions

+ +

All motions were applied cleanly. In a small number of cases, the approved +wording was based on an older draft and needed reconciliation with intervening +changes, but it was clear how to do this.

+ +
    +
  • The wording for P1854R4 +("Making non-encodable string literals ill-formed", CWG Poll 3) +has been reconciled with previous changes from +P2314R4 +("Character sets and encodings").
  • +
  • For P0792R14 +("function_ref: a type-erased callable reference", LWG Poll 18), +among some minor fixes for correctness and consistency, +exposition-only members have been added explicitly to the class synopsis, +which had only been mentioned in the descriptive text in the approved wording.
  • +
  • The feature test macro __cpp_lib_format has been modified three times, as follows: +
      +
    • 202304L by +P2510R3 +("Formatting pointers", LWG Poll 10)
    • +
    • 202305L by +P2757R3 +("Type checking format args", LWG Poll 20)
    • +
    • 202306L by +P2637R3 +("Member visit", LWG Poll 21)
    • +
  • +
  • The feature test macro for +P2641R4 +("Checking if a union alternative is active", LWG Poll 22) +has been renamed from __cpp_lib_within_lifetime to __cpp_lib_is_within_lifetime, +which seems more appropriate and follows existing practice.
  • +
  • For P2630R4 +(submdspan, LWG Poll 29), numerous minor editorial corrections and improvements +have been applied; see the full commit log for details.
  • +
+ +

Core working group polls

+ +

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

+ +

CWG Poll 2: Accept as a Defect Report and apply the changes in +P2621R2 +(UB? In my Lexer?) to the C++26 Working Paper.

+ +

CWG Poll 3: Accept as a Defect Report and apply the changes in +P1854R4 +(Making non-encodable string literals ill-formed) to the C++26 Working Paper.

+ +

CWG Poll 4: Apply the changes in P2361R6 +(Unevaluated strings) to the C++26 Working Paper.

+ +

CWG Poll 5: Apply the changes in P2558R2 +(Add @, $, and ` to the basic character set) to the C++26 Working Paper.

+ +

CWG Poll 6: Apply the changes in P2738R1 +(constexpr cast from void*: towards constexpr type-erasure) to the C++26 Working Paper.

+ +

CWG Poll 7: Accept as a Defect Report and apply the changes in +P2915R0 +(Proposed resolution for CWG1223) to the C++26 Working Paper.

+ +

CWG Poll 8: Accept as a Defect Report and apply the changes in +P2552R3 +(On the ignorability of standard attributes) to the C++26 Working Paper.

+ +

CWG Poll 9: Accept as a Defect Report and apply the changes in +P2752R3 +(Static storage for braced initializers) to the C++26 Working Paper.

+ +

CWG Poll 10: Apply the changes in P2741R3 +(User-generated static_assert messages) to the C++26 Working Paper.

+ +

CWG Poll 11: Apply the changes in P2169R4 +(A nice placeholder with no name) to the C++26 Working Paper.

+ +

Library working group polls

+ +

LWG Poll 1: Apply the changes for all Tentatively Ready issues in +P2910R0 +(C++ Standard Library Issues to be moved in Varna, Jun. 2023) to the C++ working paper.

+ +

LWG Poll 2: Apply the changes in P2497R0 +(Testing for success or failure of <charconv> functions) to the C++ working paper.

+ +

LWG Poll 3: Apply the changes in P2592R3 +(Hashing support for std::chrono value classes) to the C++ working paper.

+ +

LWG Poll 4: Apply the changes in P2587R3 +(to_string or not to_string) to the C++ working paper.

+ +

LWG Poll 5: Apply the changes in P2562R1 +(constexpr Stable Sorting) to the C++ working paper.

+ +

LWG Poll 6: Apply the changes in P2545R4 +(Read-Copy Update (RCU)) to the C++ working paper.

+ +

LWG Poll 7: Apply the changes in P2530R3 +(Hazard Pointers for C++26) to the C++ working paper.

+ +

LWG Poll 8: Apply the changes in P2538R1 +(ADL-proof std::projected) to the C++ working paper.

+ +

LWG Poll 9: Apply the changes in P2495R3 +(Interfacing stringstreams with string_view) to the C++ working paper.

+ +

LWG Poll 10: Apply the changes in P2510R3 +(Formatting pointers) to the C++ working paper.

+ +

LWG Poll 11: Apply the changes in P2198R7 +(Freestanding Feature-Test Macros and Implementation-Defined Extensions) to the C++ working paper.

+ +

LWG Poll 12: Apply the changes in P2338R4 +(Freestanding Library: Character primitives and the C library) to the C++ working paper.

+ +

LWG Poll 13: Apply the changes in P2013R5 +(Freestanding Language: Optional ::operator new) to the C++ working paper.

+ +

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

+ +

LWG Poll 15: Apply the changes in P2363R5 +(Extending associative containers with the remaining heterogeneous overloads) to the C++ working paper.

+ +

LWG Poll 16: Apply the changes in P1901R2 +(Enabling the Use of weak_ptr as Keys in Unordered Associative Containers) to the C++ working paper.

+ +

LWG Poll 17: Apply the changes in P1885R12 +(Naming Text Encodings to Demystify Them) to the C++ working paper.

+ +

LWG Poll 18: Apply the changes in P0792R14 +(function_ref: a type-erased callable reference) to the C++ working paper.

+ +

LWG Poll 19: Apply the changes in P2874R2 +(Mandating Annex D) to the C++ working paper.

+ +

LWG Poll 20: Apply the changes in P2757R3 +(Type checking format args) to the C++ working paper.

+ +

LWG Poll 21: Apply the changes in P2637R3 +(Member visit) to the C++ working paper.

+ +

LWG Poll 22: Apply the changes in P2641R4 +(Checking if a union alternative is active) to the C++ working paper.

+ +

LWG Poll 23: Apply the changes in P1759R6 +(Native handles and file streams) to the C++ working paper.

+ +

LWG Poll 24: Apply the changes in P2697R1 +(Interfacing bitset with string_view) to the C++ working paper.

+ +

LWG Poll 25: Apply the changes in P1383R2 +(More constexpr for <cmath> and <complex>) to the C++ working paper.

+ +

LWG Poll 26: Apply the changes in P2734R0 +(Adding the new 2022 SI prefixes) to the C++ working paper.

+ +

LWG Poll 27: Apply the changes in P2548R6 +(copyable_function) to the C++ working paper.

+ +

LWG Poll 28: Apply the changes in P2714R1 +(Bind front and back to NTTP callables) to the C++ working paper.

+ +

LWG Poll 29: Apply the changes in P2630R4 +(submdspan) to the C++ working paper.

+ +

Editorial changes

+ +

Noteworthy changes

+ +

Some Unicode examples of the new formatting facilities had been missing from the +last few working drafts (but are present in the C++23 DIS) because they needed +some bespoke handling. This has now been integrated into the main branch, and +the examples now appear correctly in the working draft. (The examples are +generated with LuaTeX. As a side effect, the typeface used in existing diagrams +has been changed to match the one used for the main body text. We have also +explored switching the typesetting engine for the main document from eTeX to +LuaTeX. This is possible in principle, but results in slightly lower typographic +quality at the moment, so we are holding off on this and will revisit this +change in the future.)

+ +

The title of the working draft has been changed to "Working Draft, Programming +Languages — C++", to match the official title of the standard more closely.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4950 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 abb81facf56f82a7487b3f64ae337ce2802c4bf3
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri May 12 09:38:16 2023 +0200
+
+    [intro.execution] Fix bad function call in example
+
+commit 42f21d84fb374b11d44c0b367bda649636128b6a
+Author: Andrew Rogers <adr26__github@nunsway.co.uk>
+Date:   Wed Apr 19 01:03:57 2023 +0100
+
+    [dcl.init.aggr] Add missing apostrophe
+
+commit 4514233a48954d0fd0669236cc986640e33feb04
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Fri May 12 23:14:43 2023 +0200
+
+    [basic.compound] Fix cross-reference for 'incomplete type' (#6210)
+
+commit 4fac9f97a2c25d39a01f75cf198d0783bfa8deda
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue May 16 17:01:51 2023 +0100
+
+    [strings], [unord.req.general], [stringbuf.members]: Fix xrefs to [container.requirements.general]
+
+    All the references for "qualifies as an input iterator" and "qualifies
+    as an allocator" are supposed to be to [container.reqmts] p69 which
+    begins:
+
+    > The behavior of certain container member functions and deduction
+    > guides depends on whether types qualify as input iterators or
+    > allocators.
+
+    The reference in [string.require] for obtaining an allocator should be
+    to [container.reqmts] p64.
+
+    The reference in [string.require] Note 2 should be to
+    [container.requirements.pre] p3.
+
+    Fixes #6184
+
+commit 1be4801ac1f90aca9a8f5804a48e8bcd082f5bb9
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Jun 1 20:57:05 2023 +0200
+
+    [lib] Refer to exposition-only function templates as templates, not functions (#6265)
+
+     * [tuple.apply]/1, /4
+     * [expected.object.assign]/1
+     * [iterator.cust.swap]/2
+     * [specialized.algorithms.general]/3
+
+commit c0685a584ea51d3e47381478a750729da3202b37
+Author: Géry Ogam <gery.ogam@gmail.com>
+Date:   Tue Jun 13 18:21:59 2023 +0200
+
+    [basic.lval] Reword the misused term ‘classifications’ (#4913)
+
+commit ae4cba4dc8ee2437f39a451268ad6bc924076da0
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jun 20 13:29:38 2023 +0100
+
+    [cover-wd] A more appropriate title, and better line spacing
+
+commit 7e7afe0965e4e16ff651167212ea05ed9c0ef788
+Author: Eisenwave <me@eisenwave.net>
+Date:   Thu Jul 6 12:45:54 2023 +0200
+
+    [expr.mul] Add missing commas (#6366)
+
+commit 384d36a0d30e6a8050e23f7193db40fb56ff4f06
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Jul 6 20:45:10 2023 +0100
+
+    [filebuf.virtuals] fix "if width if less than zero" typo
+
+commit 964015779245341d64d93bbd0d1e11f050b32e70
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Mon Jul 10 18:53:10 2023 +0800
+
+    [time.duration.cons] Fix duplicate definition in example (#6372)
+
+commit e6c2f8fb0d5ad6cda3e2d3da63bd5d5e434635b4
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 18 23:16:59 2023 +0100
+
+    [diff.cpp23.expr] Fix environment ("example" should be "codeblock")
+
+commit 2109f579cc6749d19ddf9cf892e8aec4762ba344
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 21 16:21:54 2023 +0100
+
+    [locale.general] Add cross-references to class synopsis
+
+commit c2e05a4080e8c79bcc9971054ca6fb6ae9b3e722
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 21 17:05:10 2023 +0100
+
+    [functional.syn] Tweak cross-references in class synopsis
+
+commit 8334cc876d29595f0f2796a6de42acae937d8377
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 21 23:29:54 2023 +0100
+
+    [functional.syn, func.wrap.move] Hyphenate "move-only wrapper"
+
+commit 7fb62d5f50bfbfc159df4ca0af932ee82d26bc41
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 21 18:13:28 2023 +0100
+
+    [version.syn] Rename smart_pointer_owner_equality to smart_ptr_owner_equality
+
+    For consistency: the use of "ptr" is already prevailing.
+
+commit 56a6b7fe068726ace9196366c968cc679653cc04
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Wed May 17 23:27:22 2023 +0800
+
+    <ranges> Add missing colon for the Effects: Equivalent to return format
+
+commit a34d2e08bda9b1314ecec1b608745a88a678d664
+Author: vasama <git@vasama.org>
+Date:   Wed Jun 7 11:01:02 2023 +0300
+
+    [expr.pre] Clarify note on pointer subtraction
+
+commit 96f695aea7589a62e5ebb55a18a40f985f7d89ce
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jun 13 09:18:01 2023 +0300
+
+    [basic.def.odr] Restructure requirements in p14-p15
+
+commit ebba9f316ddd8c120608447b00ea32bf3926a18d
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Sun Jul 23 02:29:17 2023 +0100
+
+    [func.wrap.func.general, func.wrap.move.class] Remove redundant declaration (#6273)
+
+    We don't need to repeat the declarations of the incomplete primary
+    template, they are already present in the <functional> synopsis.
+
+commit e6bd946d953b76e908a8e853d93834572c125d59
+Author: Richard Smith <richard@metafoo.co.uk>
+Date:   Fri Jul 14 13:31:47 2023 -0700
+
+    [basic.scope.scope] Avoid hard-to-read except...unless construction.
+
+    Factor out a name for the "unless" condition to avoid the double-negative.
+
+commit 3769c701daf9ae38f8db054670106abca7c03d32
+Author: Roger Orr <rogero@howzatt.co.uk>
+Date:   Tue Jul 18 23:54:34 2023 +0100
+
+    [dcl.ambig.res] fix double declaration of 'y' in example
+
+commit 0bf51a3bc5c24b070265412c32e53a0060d73eef
+Author: Christian Trott <crtrott@sandia.gov>
+Date:   Sat Jul 22 19:33:41 2023 -0600
+
+    [mdspan.layout.stride.cons] Fix missed rename of template parameter (#6385)
+
+    "LayoutStrideMapping" should say "StridedLayoutMapping".
+
+commit f8feaa6e5bc8e6d28e00c06a3de305f80f395913
+Author: Eelis van der Weegen <eelis@eelis.net>
+Date:   Fri Jul 21 11:43:39 2023 +0200
+
+    [version.syn] Fix header references.
+
+commit 872bda08678d1aeecfc555f26920cec28a2ad497
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Jun 1 14:59:00 2023 +0000
+
+    [basic.stc.dynamic.allocation] Remove redundant 'address of' from a note
+
+commit 880531fad125c4b806300151ddcb961a7f44a181
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Sat Jul 22 21:49:38 2023 -0400
+
+    [flat.{,multi}{map,set}.cons]: zip_view should be views::zip (#6373)
+
+    We don't expect to use CTAD on `ranges::zip_view(args...)`;
+    what we expect is `views::zip`.
+
+commit a417ade53722d944481baac575292874c1bcc79a
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Sat Jul 22 21:50:37 2023 -0400
+
+    [range.enumerate.overview] Add cross reference to [range.adaptor.object] (#6219)
+
+commit 7f100cc67b0bb263e2f438238e87555347ae45c0
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Sun Jul 23 17:50:27 2023 +0800
+
+    [input.output] Fix the "Effects: Equivalent to" format (#6402)
+
+commit 9334219bd95a85e86b20c8a712397f9f23f0f7a8
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Jul 23 06:59:28 2023 +0200
+
+    [class.copy.assign] Remove note obsoleted by CWG2586
+
+commit 503b4b261061bdd2481e1e4f1153481a0a75ecee
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Jul 23 08:29:10 2023 +0200
+
+    [dcl.fct.def.default] Highlight different references in defaulted assignments
+
+commit a567088b0ab8ca62f0ff5a7b4746337ac3f6df9b
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 24 12:45:57 2023 +0100
+
+    [assets] Move separate assets into "assets" subdirectory
+
+commit 7e2cc3ba6a30a693a96bbc37c4d8428d92ce1fa8
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Aug 19 17:03:37 2022 +0100
+
+    [assets] Unicode examples
+
+commit 589af92ce99b91444a3e6155cb64f8009918e885
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Aug 28 02:09:47 2022 +0100
+
+    [format.string.{std,escaped}, macros] Add missing examples
+
+commit f61a2c8a847e846ba1167c876b0fc1532ab433d7
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 24 21:27:00 2023 +0100
+
+    [format.string.escape] Fix mis{sing,escaped} braces
+
+    This was an oversight in the application of
+    https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2713r0.html
+    in e38ea31d46ca2964c4f9169f049e2f15e2cd5957.
+
+commit 3b2a8ee11725eb485df89dec40a7e0fc965debb2
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Fri Jul 21 12:46:48 2023 -0400
+
+    [func.wrap.ref.class] change deduction guide to match its detailed specifications
+
+commit d5160c6ff6c09fc0c52b5b11676c03ff179f4554
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Jul 23 02:51:25 2023 +0100
+
+    [mdspan.submdspan.extents] Factor out common result expression
+
+commit 84cf8ef63a479a3fda05a219dd26ab4b8c6a8e32
+Author: Jakub Mazurkiewicz <mazkuba3@gmail.com>
+Date:   Tue Jul 25 01:06:49 2023 +0200
+
+    [mdspan.mdspan.cons] `OtherIndexType` is not a parameter pack; missing _v (#6263)
+
+commit a636f553369825bc37ac0d95c171a00c526af499
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Jul 24 16:16:14 2023 +0000
+
+    [intro.object] Fix cross-references for library implicit object creation
+
+commit d09a77e09a5210c50994b89d999f3cbdfcc9a436
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed May 17 18:51:00 2023 +0100
+
+    [re.results.general, string.cons] Fix references to container reqmts
+
+    [re.results.general] should refer to [container.alloc.reqmts] for an
+    allocator-aware container, [strings.cons] should refer to sequence
+    container requirements.
+
+commit dd32b7eeb21e0ca8be7aae1996814a2ffda0ed83
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu May 18 12:54:12 2023 +0100
+
+    [container.gen.reqmts] Adjust subclause names and stable tags
+
+    There are no more cross-references to [container.gen.reqmts] or
+    [container.requirements.general], so this doesn't affect anything else.
+
+commit a0e6740cda724c192ea14979e2fa92e9f38cf242
+Author: Janet Cobb <git@randomcat.org>
+Date:   Mon Jul 24 12:09:44 2023 -0400
+
+    [basic.fundamental] Clarify that table of minimum integral type widths applies only to standard integral types
+
+commit 3a2586ccb4112f32f08643f7fcafab0b6b7956e2
+Author: Joshua Berne <berne@notadragon.com>
+Date:   Fri Jul 28 15:31:51 2023 -0400
+
+    [dcl.attr.grammar] Fix typo "appeartain" -> "appertain" (#6420)
+
+commit 00b4bb25e7b881cc53dca91dd44ef87c9696b19c
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Aug 13 22:35:57 2023 +0200
+
+    [over.ics.list] Fix missing std:: in example (#6453)
+
+commit cf7d5820d2ab8352d96462c647b735dc575cc1cb
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Aug 15 00:12:21 2023 +0200
+
+    [depr.static.constexpr] Cross-reference core clauses for deprecated feature (#6448)
+
+commit 1353359777de653346dd05ed117bba3627b6c7ca
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Jan 24 18:51:02 2023 +0100
+
+    [class.mem.general] Clarify class completeness
+
+commit 77d1b66193d5324b121979474d0e35645bbcfb1c
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Aug 1 13:39:55 2023 +0800
+
+    [memory.syn] Remove redundant freestanding mark for members
+
+    Making `allocator_arg_t` shown like `from_range_t` in [ranges.syn].
+
+commit bf304328b603d96b9da5dc38dfeb04057c67cc53
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Aug 1 13:42:07 2023 +0800
+
+    [ranges.syn] Remove redundant freestanding mark for members
+
+commit d347b328e058bb4b357a2b7b4733c923fca6fd98
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Tue Aug 15 00:42:54 2023 +0200
+
+    [temp.over] itemize parts of long paragraph (#6443)
+
+commit e34a8e15e1de7eab0980af328765957c6118fc04
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Tue Aug 15 00:45:43 2023 +0200
+
+    [meta.unary.prop] itemize long sentence (#6436)
+
+ + diff --git a/papers/n4959.md b/papers/n4959.md new file mode 100644 index 0000000000..a1f6effec6 --- /dev/null +++ b/papers/n4959.md @@ -0,0 +1,553 @@ +# N4959 Editors' Report -- Programming Languages -- C++ + +Date: 2023-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) +and to those who have provided pull requests with fixes, +and special thanks to Johel Ernesto Guerrero Peña for providing in-depth review +of many of the draft motion applications. + +## New papers + + * [N4958](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4958.pdf) is the + current working draft for C++26. It replaces + [N4950](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf). + * N4959 is this Editors' Report. + +## Motions incorporated into working draft + +### Notes on motions + +All motions were applied cleanly. In a small number of cases, the approved +wording was based on an older draft and needed reconciliation with intervening +changes, but it was clear how to do this. + +* The wording for [P1854R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1854r4.pdf) + ("Making non-encodable string literals ill-formed", CWG Poll 3) + has been reconciled with previous changes from + [P2314R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2314r4.html) + ("Character sets and encodings"). +* For [P0792R14](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0792r14.html) + ("`function_ref`: a type-erased callable reference", LWG Poll 18), + among some minor fixes for correctness and consistency, + exposition-only members have been added explicitly to the class synopsis, + which had only been mentioned in the descriptive text in the approved wording. +* The feature test macro `__cpp_lib_format` has been modified three times, as follows: + * `202304L` by + [P2510R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2510r3.pdf) + ("Formatting pointers", LWG Poll 10) + * `202305L` by + [P2757R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2757r3.html) + ("Type checking format args", LWG Poll 20) + * `202306L` by + [P2637R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2637r3.html) + ("Member `visit`", LWG Poll 21) +* The feature test macro for + [P2641R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2641r4.html) + ("Checking if a union alternative is active", LWG Poll 22) + has been renamed from `__cpp_lib_within_lifetime` to `__cpp_lib_is_within_lifetime`, + which seems more appropriate and follows existing practice. +* For [P2630R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2630r4.html) + (`submdspan`, LWG Poll 29), numerous minor editorial corrections and improvements + have been applied; see the full commit log for details. + +### Core working group polls + +CWG Poll 1: Accept as Defect Reports and apply the proposed resolutions of all issues in +[P2922R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2922r0.html) +(Core Language Working Group "ready" Issues for the June, 2023 meeting) to the C++ Working Paper. + +CWG Poll 2: Accept as a Defect Report and apply the changes in +[P2621R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2621r2.pdf) +(UB? In my Lexer?) to the C++26 Working Paper. + +CWG Poll 3: Accept as a Defect Report and apply the changes in +[P1854R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1854r4.pdf) +(Making non-encodable string literals ill-formed) to the C++26 Working Paper. + +CWG Poll 4: Apply the changes in [P2361R6](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2361r6.pdf) +(Unevaluated strings) to the C++26 Working Paper. + +CWG Poll 5: Apply the changes in [P2558R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2558r2.html) +(Add `@`, `$`, and ` to the basic character set) to the C++26 Working Paper. + +CWG Poll 6: Apply the changes in [P2738R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2738r1.pdf) +(constexpr cast from `void*`: towards constexpr type-erasure) to the C++26 Working Paper. + +CWG Poll 7: Accept as a Defect Report and apply the changes in +[P2915R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2915r0.pdf) +(Proposed resolution for CWG1223) to the C++26 Working Paper. + +CWG Poll 8: Accept as a Defect Report and apply the changes in +[P2552R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2552r3.pdf) +(On the ignorability of standard attributes) to the C++26 Working Paper. + +CWG Poll 9: Accept as a Defect Report and apply the changes in +[P2752R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2752r3.html) +(Static storage for braced initializers) to the C++26 Working Paper. + +CWG Poll 10: Apply the changes in [P2741R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2741r3.pdf) +(User-generated `static_assert` messages) to the C++26 Working Paper. + +CWG Poll 11: Apply the changes in [P2169R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2169r4.pdf) +(A nice placeholder with no name) to the C++26 Working Paper. + +### Library working group polls + +LWG Poll 1: Apply the changes for all Tentatively Ready issues in +[P2910R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2910r0.html) +(C++ Standard Library Issues to be moved in Varna, Jun. 2023) to the C++ working paper. + +LWG Poll 2: Apply the changes in [P2497R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2497r0.html) +(Testing for success or failure of `` functions) to the C++ working paper. + +LWG Poll 3: Apply the changes in [P2592R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2592r3.html) +(Hashing support for `std::chrono` value classes) to the C++ working paper. + +LWG Poll 4: Apply the changes in [P2587R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2587r3.html) +(`to_string` or not `to_string`) to the C++ working paper. + +LWG Poll 5: Apply the changes in [P2562R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2562r1.pdf) +(`constexpr` Stable Sorting) to the C++ working paper. + +LWG Poll 6: Apply the changes in [P2545R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2545r4.pdf) +(Read-Copy Update (RCU)) to the C++ working paper. + +LWG Poll 7: Apply the changes in [P2530R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2530r3.pdf) +(Hazard Pointers for C++26) to the C++ working paper. + +LWG Poll 8: Apply the changes in [P2538R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2538r1.html) +(ADL-proof `std::projected`) to the C++ working paper. + +LWG Poll 9: Apply the changes in [P2495R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2495r3.pdf) +(Interfacing stringstreams with `string_view`) to the C++ working paper. + +LWG Poll 10: Apply the changes in [P2510R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2510r3.pdf) +(Formatting pointers) to the C++ working paper. + +LWG Poll 11: Apply the changes in [P2198R7](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2198r7.html) +(Freestanding Feature-Test Macros and Implementation-Defined Extensions) to the C++ working paper. + +LWG Poll 12: Apply the changes in [P2338R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2338r4.html) +(Freestanding Library: Character primitives and the C library) to the C++ working paper. + +LWG Poll 13: Apply the changes in [P2013R5](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2013r5.html) +(Freestanding Language: Optional `::operator new`) to the C++ working paper. + +LWG Poll 14: Apply the changes in [P0493R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0493r4.pdf) +(Atomic maximum/minimum) to the C++ working paper. + +LWG Poll 15: Apply the changes in [P2363R5](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2363r5.html) +(Extending associative containers with the remaining heterogeneous overloads) to the C++ working paper. + +LWG Poll 16: Apply the changes in [P1901R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1901r2.html) +(Enabling the Use of `weak_ptr` as Keys in Unordered Associative Containers) to the C++ working paper. + +LWG Poll 17: Apply the changes in [P1885R12](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1885r12.pdf) +(Naming Text Encodings to Demystify Them) to the C++ working paper. + +LWG Poll 18: Apply the changes in [P0792R14](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0792r14.html) +(`function_ref`: a type-erased callable reference) to the C++ working paper. + +LWG Poll 19: Apply the changes in [P2874R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2874r2.pdf) +(Mandating Annex D) to the C++ working paper. + +LWG Poll 20: Apply the changes in [P2757R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2757r3.html) +(Type checking format args) to the C++ working paper. + +LWG Poll 21: Apply the changes in [P2637R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2637r3.html) +(Member `visit`) to the C++ working paper. + +LWG Poll 22: Apply the changes in [P2641R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2641r4.html) +(Checking if a union alternative is active) to the C++ working paper. + +LWG Poll 23: Apply the changes in [P1759R6](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1759r6.html) +(Native handles and file streams) to the C++ working paper. + +LWG Poll 24: Apply the changes in [P2697R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2697r1.pdf) +(Interfacing `bitset` with `string_view`) to the C++ working paper. + +LWG Poll 25: Apply the changes in [P1383R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1383r2.pdf) +(More `constexpr` for `` and ``) to the C++ working paper. + +LWG Poll 26: Apply the changes in [P2734R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2734r0.pdf) +(Adding the new 2022 SI prefixes) to the C++ working paper. + +LWG Poll 27: Apply the changes in [P2548R6](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2548r6.pdf) +(`copyable_function`) to the C++ working paper. + +LWG Poll 28: Apply the changes in [P2714R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2714r1.html) +(Bind front and back to NTTP callables) to the C++ working paper. + +LWG Poll 29: Apply the changes in [P2630R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2630r4.html) +(`submdspan`) to the C++ working paper. + +## Editorial changes + +### Noteworthy changes + +Some Unicode examples of the new formatting facilities had been missing from the +last few working drafts (but are present in the C++23 DIS) because they needed +some bespoke handling. This has now been integrated into the main branch, and +the examples now appear correctly in the working draft. (The examples are +generated with LuaTeX. As a side effect, the typeface used in existing diagrams +has been changed to match the one used for the main body text. We have also +explored switching the typesetting engine for the main document from eTeX to +LuaTeX. This is possible in principle, but results in slightly lower typographic +quality at the moment, so we are holding off on this and will revisit this +change in the future.) + +The title of the working draft has been changed to "Working Draft, Programming +Languages — C++", to match the official title of the standard more closely. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4950 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/n4950...n4958). + + commit abb81facf56f82a7487b3f64ae337ce2802c4bf3 + Author: Jens Maurer + Date: Fri May 12 09:38:16 2023 +0200 + + [intro.execution] Fix bad function call in example + + commit 42f21d84fb374b11d44c0b367bda649636128b6a + Author: Andrew Rogers + Date: Wed Apr 19 01:03:57 2023 +0100 + + [dcl.init.aggr] Add missing apostrophe + + commit 4514233a48954d0fd0669236cc986640e33feb04 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Fri May 12 23:14:43 2023 +0200 + + [basic.compound] Fix cross-reference for 'incomplete type' (#6210) + + commit 4fac9f97a2c25d39a01f75cf198d0783bfa8deda + Author: Jonathan Wakely + Date: Tue May 16 17:01:51 2023 +0100 + + [strings], [unord.req.general], [stringbuf.members]: Fix xrefs to [container.requirements.general] + + All the references for "qualifies as an input iterator" and "qualifies + as an allocator" are supposed to be to [container.reqmts] p69 which + begins: + + > The behavior of certain container member functions and deduction + > guides depends on whether types qualify as input iterators or + > allocators. + + The reference in [string.require] for obtaining an allocator should be + to [container.reqmts] p64. + + The reference in [string.require] Note 2 should be to + [container.requirements.pre] p3. + + Fixes #6184 + + commit 1be4801ac1f90aca9a8f5804a48e8bcd082f5bb9 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Jun 1 20:57:05 2023 +0200 + + [lib] Refer to exposition-only function templates as templates, not functions (#6265) + + * [tuple.apply]/1, /4 + * [expected.object.assign]/1 + * [iterator.cust.swap]/2 + * [specialized.algorithms.general]/3 + + commit c0685a584ea51d3e47381478a750729da3202b37 + Author: Géry Ogam + Date: Tue Jun 13 18:21:59 2023 +0200 + + [basic.lval] Reword the misused term ‘classifications’ (#4913) + + commit ae4cba4dc8ee2437f39a451268ad6bc924076da0 + Author: Thomas Köppe + Date: Tue Jun 20 13:29:38 2023 +0100 + + [cover-wd] A more appropriate title, and better line spacing + + commit 7e7afe0965e4e16ff651167212ea05ed9c0ef788 + Author: Eisenwave + Date: Thu Jul 6 12:45:54 2023 +0200 + + [expr.mul] Add missing commas (#6366) + + commit 384d36a0d30e6a8050e23f7193db40fb56ff4f06 + Author: Jonathan Wakely + Date: Thu Jul 6 20:45:10 2023 +0100 + + [filebuf.virtuals] fix "if width if less than zero" typo + + commit 964015779245341d64d93bbd0d1e11f050b32e70 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Mon Jul 10 18:53:10 2023 +0800 + + [time.duration.cons] Fix duplicate definition in example (#6372) + + commit e6c2f8fb0d5ad6cda3e2d3da63bd5d5e434635b4 + Author: Thomas Köppe + Date: Tue Jul 18 23:16:59 2023 +0100 + + [diff.cpp23.expr] Fix environment ("example" should be "codeblock") + + commit 2109f579cc6749d19ddf9cf892e8aec4762ba344 + Author: Thomas Köppe + Date: Fri Jul 21 16:21:54 2023 +0100 + + [locale.general] Add cross-references to class synopsis + + commit c2e05a4080e8c79bcc9971054ca6fb6ae9b3e722 + Author: Thomas Köppe + Date: Fri Jul 21 17:05:10 2023 +0100 + + [functional.syn] Tweak cross-references in class synopsis + + commit 8334cc876d29595f0f2796a6de42acae937d8377 + Author: Thomas Köppe + Date: Fri Jul 21 23:29:54 2023 +0100 + + [functional.syn, func.wrap.move] Hyphenate "move-only wrapper" + + commit 7fb62d5f50bfbfc159df4ca0af932ee82d26bc41 + Author: Thomas Köppe + Date: Fri Jul 21 18:13:28 2023 +0100 + + [version.syn] Rename smart_pointer_owner_equality to smart_ptr_owner_equality + + For consistency: the use of "ptr" is already prevailing. + + commit 56a6b7fe068726ace9196366c968cc679653cc04 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Wed May 17 23:27:22 2023 +0800 + + Add missing colon for the Effects: Equivalent to return format + + commit a34d2e08bda9b1314ecec1b608745a88a678d664 + Author: vasama + Date: Wed Jun 7 11:01:02 2023 +0300 + + [expr.pre] Clarify note on pointer subtraction + + commit 96f695aea7589a62e5ebb55a18a40f985f7d89ce + Author: Thomas Köppe + Date: Tue Jun 13 09:18:01 2023 +0300 + + [basic.def.odr] Restructure requirements in p14-p15 + + commit ebba9f316ddd8c120608447b00ea32bf3926a18d + Author: Jonathan Wakely + Date: Sun Jul 23 02:29:17 2023 +0100 + + [func.wrap.func.general, func.wrap.move.class] Remove redundant declaration (#6273) + + We don't need to repeat the declarations of the incomplete primary + template, they are already present in the synopsis. + + commit e6bd946d953b76e908a8e853d93834572c125d59 + Author: Richard Smith + Date: Fri Jul 14 13:31:47 2023 -0700 + + [basic.scope.scope] Avoid hard-to-read except...unless construction. + + Factor out a name for the "unless" condition to avoid the double-negative. + + commit 3769c701daf9ae38f8db054670106abca7c03d32 + Author: Roger Orr + Date: Tue Jul 18 23:54:34 2023 +0100 + + [dcl.ambig.res] fix double declaration of 'y' in example + + commit 0bf51a3bc5c24b070265412c32e53a0060d73eef + Author: Christian Trott + Date: Sat Jul 22 19:33:41 2023 -0600 + + [mdspan.layout.stride.cons] Fix missed rename of template parameter (#6385) + + "LayoutStrideMapping" should say "StridedLayoutMapping". + + commit f8feaa6e5bc8e6d28e00c06a3de305f80f395913 + Author: Eelis van der Weegen + Date: Fri Jul 21 11:43:39 2023 +0200 + + [version.syn] Fix header references. + + commit 872bda08678d1aeecfc555f26920cec28a2ad497 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Jun 1 14:59:00 2023 +0000 + + [basic.stc.dynamic.allocation] Remove redundant 'address of' from a note + + commit 880531fad125c4b806300151ddcb961a7f44a181 + Author: Arthur O'Dwyer + Date: Sat Jul 22 21:49:38 2023 -0400 + + [flat.{,multi}{map,set}.cons]: zip_view should be views::zip (#6373) + + We don't expect to use CTAD on `ranges::zip_view(args...)`; + what we expect is `views::zip`. + + commit a417ade53722d944481baac575292874c1bcc79a + Author: Johel Ernesto Guerrero Peña + Date: Sat Jul 22 21:50:37 2023 -0400 + + [range.enumerate.overview] Add cross reference to [range.adaptor.object] (#6219) + + commit 7f100cc67b0bb263e2f438238e87555347ae45c0 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Sun Jul 23 17:50:27 2023 +0800 + + [input.output] Fix the "Effects: Equivalent to" format (#6402) + + commit 9334219bd95a85e86b20c8a712397f9f23f0f7a8 + Author: Jens Maurer + Date: Sun Jul 23 06:59:28 2023 +0200 + + [class.copy.assign] Remove note obsoleted by CWG2586 + + commit 503b4b261061bdd2481e1e4f1153481a0a75ecee + Author: Jens Maurer + Date: Sun Jul 23 08:29:10 2023 +0200 + + [dcl.fct.def.default] Highlight different references in defaulted assignments + + commit a567088b0ab8ca62f0ff5a7b4746337ac3f6df9b + Author: Thomas Köppe + Date: Mon Jul 24 12:45:57 2023 +0100 + + [assets] Move separate assets into "assets" subdirectory + + commit 7e2cc3ba6a30a693a96bbc37c4d8428d92ce1fa8 + Author: Thomas Köppe + Date: Fri Aug 19 17:03:37 2022 +0100 + + [assets] Unicode examples + + commit 589af92ce99b91444a3e6155cb64f8009918e885 + Author: Thomas Köppe + Date: Sun Aug 28 02:09:47 2022 +0100 + + [format.string.{std,escaped}, macros] Add missing examples + + commit f61a2c8a847e846ba1167c876b0fc1532ab433d7 + Author: Thomas Köppe + Date: Mon Jul 24 21:27:00 2023 +0100 + + [format.string.escape] Fix mis{sing,escaped} braces + + This was an oversight in the application of + https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2713r0.html + in e38ea31d46ca2964c4f9169f049e2f15e2cd5957. + + commit 3b2a8ee11725eb485df89dec40a7e0fc965debb2 + Author: Johel Ernesto Guerrero Peña + Date: Fri Jul 21 12:46:48 2023 -0400 + + [func.wrap.ref.class] change deduction guide to match its detailed specifications + + commit d5160c6ff6c09fc0c52b5b11676c03ff179f4554 + Author: Thomas Köppe + Date: Sun Jul 23 02:51:25 2023 +0100 + + [mdspan.submdspan.extents] Factor out common result expression + + commit 84cf8ef63a479a3fda05a219dd26ab4b8c6a8e32 + Author: Jakub Mazurkiewicz + Date: Tue Jul 25 01:06:49 2023 +0200 + + [mdspan.mdspan.cons] `OtherIndexType` is not a parameter pack; missing _v (#6263) + + commit a636f553369825bc37ac0d95c171a00c526af499 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Jul 24 16:16:14 2023 +0000 + + [intro.object] Fix cross-references for library implicit object creation + + commit d09a77e09a5210c50994b89d999f3cbdfcc9a436 + Author: Jonathan Wakely + Date: Wed May 17 18:51:00 2023 +0100 + + [re.results.general, string.cons] Fix references to container reqmts + + [re.results.general] should refer to [container.alloc.reqmts] for an + allocator-aware container, [strings.cons] should refer to sequence + container requirements. + + commit dd32b7eeb21e0ca8be7aae1996814a2ffda0ed83 + Author: Jonathan Wakely + Date: Thu May 18 12:54:12 2023 +0100 + + [container.gen.reqmts] Adjust subclause names and stable tags + + There are no more cross-references to [container.gen.reqmts] or + [container.requirements.general], so this doesn't affect anything else. + + commit a0e6740cda724c192ea14979e2fa92e9f38cf242 + Author: Janet Cobb + Date: Mon Jul 24 12:09:44 2023 -0400 + + [basic.fundamental] Clarify that table of minimum integral type widths applies only to standard integral types + + commit 3a2586ccb4112f32f08643f7fcafab0b6b7956e2 + Author: Joshua Berne + Date: Fri Jul 28 15:31:51 2023 -0400 + + [dcl.attr.grammar] Fix typo "appeartain" -> "appertain" (#6420) + + commit 00b4bb25e7b881cc53dca91dd44ef87c9696b19c + Author: Jan Schultke + Date: Sun Aug 13 22:35:57 2023 +0200 + + [over.ics.list] Fix missing std:: in example (#6453) + + commit cf7d5820d2ab8352d96462c647b735dc575cc1cb + Author: Alisdair Meredith + Date: Tue Aug 15 00:12:21 2023 +0200 + + [depr.static.constexpr] Cross-reference core clauses for deprecated feature (#6448) + + commit 1353359777de653346dd05ed117bba3627b6c7ca + Author: Jens Maurer + Date: Tue Jan 24 18:51:02 2023 +0100 + + [class.mem.general] Clarify class completeness + + commit 77d1b66193d5324b121979474d0e35645bbcfb1c + Author: A. Jiang + Date: Tue Aug 1 13:39:55 2023 +0800 + + [memory.syn] Remove redundant freestanding mark for members + + Making `allocator_arg_t` shown like `from_range_t` in [ranges.syn]. + + commit bf304328b603d96b9da5dc38dfeb04057c67cc53 + Author: A. Jiang + Date: Tue Aug 1 13:42:07 2023 +0800 + + [ranges.syn] Remove redundant freestanding mark for members + + commit d347b328e058bb4b357a2b7b4733c923fca6fd98 + Author: Jan Schultke + Date: Tue Aug 15 00:42:54 2023 +0200 + + [temp.over] itemize parts of long paragraph (#6443) + + commit e34a8e15e1de7eab0980af328765957c6118fc04 + Author: Jan Schultke + Date: Tue Aug 15 00:45:43 2023 +0200 + + [meta.unary.prop] itemize long sentence (#6436) diff --git a/papers/n4965.html b/papers/n4965.html new file mode 100644 index 0000000000..de693b4372 --- /dev/null +++ b/papers/n4965.html @@ -0,0 +1,658 @@ + + + + + +N4965 + + +

N4965 Editors’ Report — Programming Languages — C++

+ +

Date: 2023-10-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 + and to those who have provided pull requests with fixes.

+ +

New papers

+ +
    +
  • N4964 is the +current working draft for C++26. It replaces +N4958.
  • +
  • N4965 is this Editors' Report.
  • +
+ +

Comments on the Draft International Standard

+ +

This report includes a snapshot of our dispositions on the Draft International Standard (DIS) +ballot comments for C++23 from national bodies and the ISO secretariat. Some of them only apply +to the published standard document and not the working draft, and the corresponding edits do not +appear in the working draft commit history. All comments on the ballot were editorial.

+ +
    +
  • ISO/CS 01: Accepted. We added references to the tables.
  • +
  • ISO/CS 02: in progress
  • +
  • ISO/CS 03: Accepted. We are now referring to a specific element, and keeping the dated reference.
  • +
  • ISO/CS 04: Accepted.
  • +
  • ISO/CS 05: Rejected: We do not understand the justification "Since there is no specific element referenced this reference shall be undated." The Drafting Directives seem to make a clear case for when undated (10.4) and dated (10.5) references are appropriate, and we firmly fall into the case where an undated reference is inappropriate ("if it will be possible to use all future changes of the referenced document" is defintely not the case). Reference to a specific element does not seem to be required in order to permit the use of a dated reference. Even the House Style seems to permit dated references when necessary: "When referring to the whole document, use an undated document number unless it is necessary that the user refers to a specific edition".
  • +
  • ISO/CS 06: Rejected: Moot by comment 05.
  • +
  • ISO/CS 07: Rejected: Moot by comment 05.
  • +
  • ISO/CS 08: Accepted. We reworded the reference to the Unicode standard to make the normative nature more obvious.
  • +
  • ISO/CS 09: Accepted.
  • +
  • ISO/CS 10: Rejected: We find domains valuable here, since the terms often sound like plain English words, but have rather domain-specific meaning, and the domain establishes important context to aid understandability.
  • +
  • ISO/CS 11: Accepted with modifications: four unused definitions are removed. The remaining term, "unspecified behavior" is retained, since it captures a variety of patterns which are not lexically spelled "behavior" but are neatly covered by this umbrella term.
  • +
  • ISO/CS 12: Accepted with modifications: we have italicized the cross-references. However, for the formal grammar terms that we display in italic sans font, please see the discussion on comment 32.
  • +
  • ISO/CS 13: Rejected: The token "CE" is not an acronym, but a meta variable (like "x" or "y". It is typeset distinctly. The name is evocative of its use.
  • +
  • ISO/CS 14: Accepted.
  • +
  • ISO/CS 15: Accepted.
  • +
  • ISO/CS 16: Rejected: The wording is correct as written. However, this is also mooted by comment 11, which deletes the wording in question.
  • +
  • ISO/CS 17: Accepted.
  • +
  • ISO/CS 18: Accepted.
  • +
  • ISO/CS 19: Accepted.
  • +
  • CA 20: n/a, comment was filed erroneously
  • +
  • JP 21: Accepted. We added an example.
  • +
  • JP 22: Rejected: No consensus for change; any attributes of a lambda-declarator are considered to be attached to the synthesized function call operator or operator template (i.e. the member function of the closure type), not the closure type itself.
  • +
  • JP 23: Accepted with modifications: The example is written as intended. The comments in the example have been amended to clarify the exposition.
  • +
  • JP 24: Accepted.
  • +
  • JP 25: Accepted.
  • +
  • JP 26: Rejected: No concensus for change; the example deliberately introduces a facility to aid comprehension.
  • +
  • JP 27: Rejected: No concensus for change; the example deliberately introduces a facility to aid comprehension.
  • +
  • JP 28: Rejected: No concensus for change; the example deliberately introduces a facility to aid comprehension.
  • +
  • ISO/CS 29: Accepted.
  • +
  • ISO/CS 30: Accepted. We added a note that refers to the annex.
  • +
  • ISO/CS 31: Accepted. We had previously used foreword wording from an older document.
  • +
  • ISO/CS 32: Rejected (to be discussed), along with comment 12.
  • +
  • ISO/CS 33: Rejected: We have an approved SC22 ballot to permit the use of paragraph numbers. (We also have a proposal for the JDMT to add such a permission to the Drafting Directives.)
  • +
  • ISO/CS 34: Accepted. Reworded to clarify.
  • +
  • ISO/CS 35: Accepted.
  • +
  • ISO/CS 36: Accepted the notes and tables captioning changes. Rejected the UK English spelling: The document defines many terms that must be spelled the same way by conforming implementations and by users of those implementations, and these terms use US English spelling. It would be confusing for the document text to use UK English spelling when describing these terms. (This is the same disposition as for a similar comment on the DIS ballot of 14882:2017.)
  • +
  • ISO/CS 37: in progress
  • +
  • ISO/CS 38: Accepted with modifications: We will review the presentation of cross-references in Clause 3. However, the use of italics in Clause 3 is not a regular "emphasis/definition" in body font, but rather a grammar production, which we typeset distinctly. Please also see the discussion regarding comment 32.
  • +
  • ISO/CS 39: in progress
  • +
  • ISO/CS 40: Accepted. The logic that processed the notes was erroneous and failed to handle subclauses with more than 9 notes; this has been fixed.
  • +
+ +

Editorial changes

+ +

There have not been any motions from WG21 since the last working draft. This +revision incorporates all the changes resulting from the DIS ballot comments for +C++23, in as far as they apply to the current working draft, as well as other +editorial changes.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4958 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 a4b1ffd9e65188ae19c29dffd2db42cb1558cee2
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Tue Aug 15 01:18:00 2023 +0200
+
+    [except.terminate] add comma after introductory phrase (#6446)
+
+commit aa8a5315136feb1af9084a2a914ba19cd8758a74
+Author: Salvage <29021710+Saalvage@users.noreply.github.com>
+Date:   Sun May 28 18:59:26 2023 +0200
+
+    [flat.multiset.defn] Fix minor errors and inconsistencies
+
+    [flat.set.defn] and [flat.multiset.defn] are now formatted identically.
+    Additionally removed erroenous template parameters in two deduction guides.
+
+commit d3ac7d4c1c74df5d5b375f4c0260345be18b0b0b
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Wed Aug 16 16:21:40 2023 +0200
+
+    [conv.ptr, conv.mem] Remove redundant text on null pointer comparisons (#6411)
+
+commit b55ad4cb65b53bb6b6e60064938537f07d63bfb3
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Aug 17 00:32:21 2023 +0200
+
+    [algorithms.parallel.defns] New paragraph for example (#6447)
+
+    Making the example a sibling to the preceding paragraph
+    rather than part of it resets its list numbering, which is less
+    confusing than continuing numbering.
+
+commit be07cd4e87c693fb9749c1e5e7c07ee0cf9e0084
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Aug 2 01:28:29 2023 +0800
+
+    [diagnostics] Exposition-only formatting for members
+
+commit 7b7dedba78c8ae860db78feb3149acdf34ebb551
+Author: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+Date:   Thu Aug 17 21:04:37 2023 +0200
+
+    [time.general] Add a reference to time.hash in the summary
+
+    [time.general] has a library summary with references to the various
+    subclauses; [time.hash] was missing, add it.
+
+commit 1e9e54ef536870ea01e6b016e4219e57df0c099b
+Author: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+Date:   Thu Aug 17 21:07:27 2023 +0200
+
+    [time.hash] Fix a typo in the code for zoned_time
+
+    The `m` was supposed to be a `,` to separate the template arguments.
+
+commit a272b7cd04dc0be488250a0c6aaead160e778774
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Fri Aug 18 12:11:24 2023 +0800
+
+    [iterator.concept.readable] Add missing \expos for indirectly-readable-impl
+
+    Also adjust horizontal whitespace in related comments.
+
+commit 846dc84ac222e5f4a26373899a2cbd683f83991c
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Aug 20 16:56:55 2023 +0200
+
+    [diff.cpp20.utilities] Hyphenate bit-fields (#6481)
+
+commit 433baff775b00c2b72d0d81d792c24617c2ace06
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Aug 20 20:56:34 2023 +0200
+
+    [tuple.swap] Improve 'call x with y' wording (#6478)
+
+commit 1c22d62180901069128b21daa2773d40566bd983
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Mon Aug 21 08:31:10 2023 +0200
+
+    [lex.phases] Add cross-reference to [cpp.include] (#6485)
+
+commit a54e71ed55a590214f2f33f4b1b900263a5f0b0d
+Author: Eelis van der Weegen <eelis@eelis.net>
+Date:   Fri Aug 25 18:05:32 2023 +0200
+
+    [rand.device] Remove stray \textit.
+
+    Fixes #6513.
+
+commit 9a0b5d767ed6ef038adc129856c0c0623f552abe
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Mon Aug 28 14:51:28 2023 +0200
+
+    [vector.data],[array.members] Clarify boolean condition (#6526)
+
+commit 8845a3778dbbd078c83a66ac09ae07e6357ec3e5
+Author: Eisenwave <me@eisenwave.net>
+Date:   Mon Aug 28 15:33:11 2023 +0200
+
+    [expr.call] add further forward references
+
+commit 837d6c979124200f1e06bc582079a60767c2756b
+Author: Daniel Krügler <daniel.kruegler@gmail.com>
+Date:   Sat Aug 26 18:35:55 2023 +0200
+
+    [atomics] Reword preconditions on memory_order values in a positive form
+
+commit 55b87300ce414fc5aa761838f217a957c797e9bf
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Aug 29 13:12:09 2023 +0100
+
+    [format.string.std] Fix example
+
+commit 61c089e934c1df406580eeb488dd5cee0900a7b1
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Jul 29 01:36:15 2023 +0800
+
+    [intro.object] Fix alignment in example
+
+    Makes the storage in the example properly aligned,
+    and explicitly states size assumption.
+
+commit 90d56dbe810e707d90322a3d16256e122e915eca
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Aug 19 15:51:27 2023 +0200
+
+    [expr.sizeof] turn identifier into a grammarterm
+
+commit f52ffc9054913f3f9a4c5dc6973f6c5c3e7f1096
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Aug 30 08:56:33 2023 +0200
+
+    [class.access.general] Fix improper \keyword{private} (#6532)
+
+commit d02a12a70c53974442f3e3ca4a75227783ea39d7
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Aug 30 19:54:36 2023 +0200
+
+    [lex.string] Mark "narrow string literal" as a definition (#6533)
+
+commit 31154dccdbe33aadb91d43cc03884f2d1aa5dbc0
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sat Sep 2 09:08:17 2023 +0200
+
+    [class.local] Add comma after introductory phrase (#6545)
+
+commit f9d08b09ffd8f68a32cbb480d54ab517e425d519
+Author: Joshua Berne <berne@notadragon.com>
+Date:   Sat Sep 2 12:56:57 2023 -0400
+
+    [diff.cpp20.thread] Add hyphen for "ill-formed" (#6550)
+
+commit 9130806ceb4a9476153eb7544b4509b713cce3e0
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Aug 30 14:01:06 2023 +0200
+
+    [fs.path.member] fix empty() == true
+
+commit ae4ae54b293c28d782902b955af8abae5229fc6d
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Aug 30 14:01:49 2023 +0200
+
+    [fs.path.modifiers] fix empty() == true
+
+commit ab4185710a64b303e6d302ac43c543849d79c5a8
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Aug 30 14:06:30 2023 +0200
+
+    [fs.filesystem.error.members] fix missing 'is true'
+
+commit 86b18720b37dadefe6c753ac2aec478b8f87593d
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Sep 5 16:19:25 2023 -0400
+
+    [basic.types.general] Apply Oxford comma consistently (#6554)
+
+commit 16c8ce5db2173a098a91e552dcfa3544c67e544f
+Author: Eelis <github.com@contacts.eelis.net>
+Date:   Fri Sep 8 08:05:36 2023 +0200
+
+    [mdspan.submdspan.extents] Format equations as math (#6530)
+
+commit 3bdb5e7b2b947ecd9fbb42029899ec098b51c51c
+Author: Casey Carter <Casey@Carter.net>
+Date:   Wed Sep 13 00:24:17 2023 -0700
+
+    [mdspan.layout.stride.cons] Fix cross-reference (#6565)
+
+commit 536653b854e293af569156864ea6aa407c90e011
+Author: Casey Carter <Casey@Carter.net>
+Date:   Mon Sep 11 10:36:39 2023 -0700
+
+    [mdspan.extents.cons] require conversions to index_type to be nonnegative
+
+    "nonnegative" is meaningless for a value of some arbitrary type which we've only required to be convertible to the integral type `index_type`, so this wording clearly intends to constrain the result of the conversion.
+
+commit 5c7841b1530dc02dbf7feacd5e154b777632dc36
+Author: Casey Carter <Casey@Carter.net>
+Date:   Mon Sep 11 16:56:47 2023 -0700
+
+    [mdspan.layout.stride.cons] Convert to integral type before comparing to 0
+
+    `s[i]` is an lvalue of a type that we can only convert to `index_type`; clearly the wording intends that the result of the conversion should be `> 0`.
+
+commit 24659bd716808538fb7066103a396e785e4f0099
+Author: Casey Carter <Casey@Carter.net>
+Date:   Mon Sep 11 16:59:56 2023 -0700
+
+    [mdspan.layout.stride.expo] Convert to integral type to perform math
+
+    [mdspan.layout.stride.cons] uses either a span or array of a type which we can only convert to `index_type` as the second argument to the exposition-only `REQUIRED-SPAN-SIZE`. We must perform that conversion before doing math with the result.
+
+commit 81c3897d34ccd32d4ccdbe3c74091ba1db458533
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Wed Oct 4 00:22:33 2023 +0800
+
+    [const.iterators.ops] Add missing \pnum and replace returns with effects (#6581)
+
+commit 34cf81ebc821377eb3969002e4669bf5e08f479f
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Wed Oct 4 02:59:42 2023 +0800
+
+    [common.iter.const] Add missing period for Returns (#6584)
+
+commit 22537613dd844670ee9fb9d5afcf19f89c26fd26
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Sep 26 07:21:52 2023 +0200
+
+    [temp.over.link] Fix phrasing and cross-reference introduced by P1787R6
+
+commit 1398617dfd99dd3383e801abee6ce58629439f3a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Oct 4 17:48:32 2023 +0200
+
+    [tab:headers.cpp] Add <hazard_pointer> (#6586)
+
+commit 78635c91ac910e9c0953e1784eec648a214eb5ad
+Author: Casey Carter <Casey@Carter.net>
+Date:   Wed Oct 4 14:44:18 2023 -0700
+
+    [string.cons] Remove erroneous paragraph break (#6587)
+
+commit a2e820424e089806191a40d43df2360906902d86
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Sep 19 13:36:52 2023 +0100
+
+    [range.utility.conv.to] Add terminating condition for first bullet
+
+    We currently fail to say what happens if the first bullet is true, but
+    then none of its sub-bullets is true.
+
+commit 9369ba13509cd5d2c9e862b7ad02f109c204a585
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Sep 19 16:19:50 2023 +0100
+
+    [version.syn] Put feature test macros in alphabetical order
+
+commit 1430209dbf6edda0827207166770c4d964cf0598
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Oct 6 15:53:39 2023 +0200
+
+    [time.format] Make reference to ISO 8601 more precise
+
+    Fixes ISO/CS 003 (C++23 DIS).
+
+commit 7ed9cbfef44d15b798af83223f5d3b62927652a5
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Oct 6 15:14:44 2023 +0200
+
+    [intro.refs] Fix title of ISO/IEC 9899:2018
+
+    Fixes ISO/CS 004 (C++23 DIS).
+
+commit 258290ecc9d6e4d615b29173fd520df1f66a3292
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Oct 6 01:21:01 2023 +0200
+
+    [annex] Fix table numbering in annexes
+
+    Fixes ISO/CS 029 (C++23 DIS).
+
+commit c39f5b014540820b4ea2061805a92c417e43ca0d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Oct 6 14:59:03 2023 +0200
+
+    [lex.name] Add cross-reference to Annex E
+
+    Fixes ISO/CS 030 (C++23 DIS).
+
+commit b5d6409bf5132d653bc13a3ce8f76c556d5d6fc9
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 7 22:50:53 2023 +0200
+
+    [defns.component] Remove unwarranted italics
+
+    Fixes ISO/CS 018 (C++23 DIS).
+
+commit 722bd4f167badc5bb5dddde9b0d00f91c2ef1644
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Oct 6 13:24:16 2023 +0200
+
+    [util.smartptr.shared.cmp] Fix missing right parenthesis
+
+    Fixes NB JP 025 (C++23 DIS).
+
+commit 24b090f5c63bf99d4cdcea8989d885f2d23c00e7
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Oct 6 13:20:03 2023 +0200
+
+    [unique.ptr.runtime.modifiers] Fix placement of 'constexpr'
+
+    Fixes NB JP 024 (C++23 DIS).
+
+commit 400521547f60196f6dfa7857bdcc907698991df8
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 7 11:11:15 2023 +0200
+
+    [expr.const] Amend comments in example
+
+    Fixes NB JP 023 (C++23 DIS).
+
+commit 812e64a65699bb01203fbedcc7d9d5ea004a5007
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 7 22:32:16 2023 +0200
+
+    [expr.prim.lambda.general] Add example for parsing ambiguity
+
+    Fixes NB JP 021 (C++23 DIS).
+
+commit bd7f9a9e640bfcd204cabecf1cc4953b7138554e
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 7 10:38:29 2023 +0200
+
+    [intro.scope] Clarify 'they'
+
+    Fixes ISO/CS 034 (C++23 DIS).
+
+commit dc597fa561a795c100a36f46376d6ddd0cf93a31
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Oct 9 12:02:19 2023 -0400
+
+    [expr.prim.lambda.closure] Insert an extra \pnum (#6594)
+
+commit d81c17120e5a527f779b965ba8fd1ce66cfc24ef
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Oct 9 12:03:25 2023 -0400
+
+    [obj.lifetime] Dehyphenate trivially-copyable (#6592)
+
+commit d29b1fc1c22018b1a83cee910ebdbb4520d2c960
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 8 09:52:42 2023 +0200
+
+    [lex.charset] Add reference to the Unicode Standard
+
+commit e128de19470877fbf8f0335b8c0e2a1700f2e320
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 8 11:52:06 2023 +0200
+
+    [lex.charset] Clarify normative reference to Unicode for UTF-x
+
+    Fixes ISO/CS 008 (C++23 DIS).
+
+commit 4d603c640dd47c71f84bbce55416302efab8b298
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Oct 10 23:55:22 2023 +0100
+
+    [intro.defs] Remove inappropriate paragraph.
+
+    Only specific, fixed wording is allowed in Clause 3.
+
+    Fixes ISO/CS 009 (C++23 DIS).
+
+commit 7d4fa2432b58a2ef6a2062812ec00ccde4443acf
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Oct 11 01:04:35 2023 +0200
+
+    [intro.defs] Remove unused definitions
+
+    The terms "arbitrary-positional stream", "repositional stream",
+    and "iostream class templates" are removed.
+
+    Fixes ISO/CS 011 and ISO/CS 16 (C++23 DIS).
+
+commit 4c76193e3d310ea5a18679ab86a54074fe1635e9
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 11 00:14:53 2023 +0100
+
+    [defns.impl.limits] Use singular
+
+    Fixes ISO/CS 015 (C++23 DIS).
+
+commit f672ecf38d2aec6ccf184d1a36bc4e83809afab0
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 11 00:46:29 2023 +0100
+
+    [std] Replace "C Standard" with "ISO/IEC 9899:2018".
+
+    Fixes ISO/CS 035 (C++23 DIS).
+
+commit 2d6182932954732f71a28d90ec1f1b23838ccc67
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 11 01:13:46 2023 +0100
+
+    [intro.{r,d}efs] Make "C standard library" a defined term
+
+    Partially fixes ISO/CS-002 (C++23 DIS).
+
+commit 4676f765f696774807688c3adfdc2eb03905a827
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 8 12:30:18 2023 +0200
+
+    [type.traits] Add references to tables
+
+    Fixes ISO/CS 001 (C++23 DIS).
+
+commit 583391e28f34d6e0a17f67f77e04ba4f924c1d13
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Oct 14 20:42:50 2023 +0100
+
+    [intro.defs, dcl.init.list] Move definition of direct-non-list-init
+
+    Partially fixes ISO/CS-11 (C++23 DIS).
+
+commit 4a8e84ede8a927a7ebe7fa16a086041db437d57c
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Oct 14 20:58:52 2023 +0100
+
+    [xrefdelta] Remove mention of removals that are now already in C++23
+
+ + diff --git a/papers/n4965.md b/papers/n4965.md new file mode 100644 index 0000000000..fabff56da6 --- /dev/null +++ b/papers/n4965.md @@ -0,0 +1,515 @@ +# N4965 Editors' Report -- Programming Languages -- C++ + +Date: 2023-10-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) +and to those who have provided pull requests with fixes. + +## New papers + + * [N4964](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4964.pdf) is the + current working draft for C++26. It replaces + [N4958](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4958.pdf). + * N4965 is this Editors' Report. + +## Comments on the Draft International Standard + +This report includes a snapshot of our dispositions on the Draft International Standard (DIS) +ballot comments for C++23 from national bodies and the ISO secretariat. Some of them only apply +to the published standard document and not the working draft, and the corresponding edits do not +appear in the working draft commit history. All comments on the ballot were editorial. + +* **ISO/CS 01:** Accepted. We added references to the tables. +* **ISO/CS 02:** _in progress_ +* **ISO/CS 03:** Accepted. We are now referring to a specific element, and keeping the dated reference. +* **ISO/CS 04:** Accepted. +* **ISO/CS 05:** Rejected: We do not understand the justification "Since there is no specific element referenced this reference shall be undated." The Drafting Directives seem to make a clear case for when undated (10.4) and dated (10.5) references are appropriate, and we firmly fall into the case where an undated reference is inappropriate ("if it will be possible to use all future changes of the referenced document" is defintely not the case). Reference to a specific element does not seem to be required in order to permit the use of a dated reference. Even the House Style seems to permit dated references when necessary: "When referring to the whole document, use an undated document number unless it is necessary that the user refers to a specific edition". +* **ISO/CS 06:** Rejected: Moot by comment 05. +* **ISO/CS 07:** Rejected: Moot by comment 05. +* **ISO/CS 08:** Accepted. We reworded the reference to the Unicode standard to make the normative nature more obvious. +* **ISO/CS 09:** Accepted. +* **ISO/CS 10:** Rejected: We find domains valuable here, since the terms often sound like plain English words, but have rather domain-specific meaning, and the domain establishes important context to aid understandability. +* **ISO/CS 11:** Accepted with modifications: four unused definitions are removed. The remaining term, "unspecified behavior" is retained, since it captures a variety of patterns which are not lexically spelled "behavior" but are neatly covered by this umbrella term. +* **ISO/CS 12:** Accepted with modifications: we have italicized the cross-references. However, for the formal grammar terms that we display in italic sans font, please see the discussion on comment 32. +* **ISO/CS 13:** Rejected: The token "CE" is not an acronym, but a meta variable (like "x" or "y". It is typeset distinctly. The name is evocative of its use. +* **ISO/CS 14:** Accepted. +* **ISO/CS 15:** Accepted. +* **ISO/CS 16:** Rejected: The wording is correct as written. However, this is also mooted by comment 11, which deletes the wording in question. +* **ISO/CS 17:** Accepted. +* **ISO/CS 18:** Accepted. +* **ISO/CS 19:** Accepted. +* **CA 20:** n/a, comment was filed erroneously +* **JP 21:** Accepted. We added an example. +* **JP 22:** Rejected: No consensus for change; any attributes of a lambda-declarator are considered to be attached to the synthesized function call operator or operator template (i.e. the member function of the closure type), not the closure type itself. +* **JP 23:** Accepted with modifications: The example is written as intended. The comments in the example have been amended to clarify the exposition. +* **JP 24:** Accepted. +* **JP 25:** Accepted. +* **JP 26:** Rejected: No concensus for change; the example deliberately introduces a facility to aid comprehension. +* **JP 27:** Rejected: No concensus for change; the example deliberately introduces a facility to aid comprehension. +* **JP 28:** Rejected: No concensus for change; the example deliberately introduces a facility to aid comprehension. +* **ISO/CS 29:** Accepted. +* **ISO/CS 30:** Accepted. We added a note that refers to the annex. +* **ISO/CS 31:** Accepted. We had previously used foreword wording from an older document. +* **ISO/CS 32:** Rejected (to be discussed), along with comment 12. +* **ISO/CS 33:** Rejected: We have an approved SC22 ballot to permit the use of paragraph numbers. (We also have a proposal for the JDMT to add such a permission to the Drafting Directives.) +* **ISO/CS 34:** Accepted. Reworded to clarify. +* **ISO/CS 35:** Accepted. +* **ISO/CS 36:** Accepted the notes and tables captioning changes. Rejected the UK English spelling: The document defines many terms that must be spelled the same way by conforming implementations and by users of those implementations, and these terms use US English spelling. It would be confusing for the document text to use UK English spelling when describing these terms. (This is the same disposition as for a similar comment on the DIS ballot of 14882:2017.) +* **ISO/CS 37:** _in progress_ +* **ISO/CS 38:** Accepted with modifications: We will review the presentation of cross-references in Clause 3. However, the use of italics in Clause 3 is not a regular "emphasis/definition" in body font, but rather a grammar production, which we typeset distinctly. Please also see the discussion regarding comment 32. +* **ISO/CS 39:** _in progress_ +* **ISO/CS 40:** Accepted. The logic that processed the notes was erroneous and failed to handle subclauses with more than 9 notes; this has been fixed. + +## Editorial changes + +There have not been any motions from WG21 since the last working draft. This +revision incorporates all the changes resulting from the DIS ballot comments for +C++23, in as far as they apply to the current working draft, as well as other +editorial changes. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4958 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/n4958...n4964). + + commit a4b1ffd9e65188ae19c29dffd2db42cb1558cee2 + Author: Jan Schultke + Date: Tue Aug 15 01:18:00 2023 +0200 + + [except.terminate] add comma after introductory phrase (#6446) + + commit aa8a5315136feb1af9084a2a914ba19cd8758a74 + Author: Salvage <29021710+Saalvage@users.noreply.github.com> + Date: Sun May 28 18:59:26 2023 +0200 + + [flat.multiset.defn] Fix minor errors and inconsistencies + + [flat.set.defn] and [flat.multiset.defn] are now formatted identically. + Additionally removed erroenous template parameters in two deduction guides. + + commit d3ac7d4c1c74df5d5b375f4c0260345be18b0b0b + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Wed Aug 16 16:21:40 2023 +0200 + + [conv.ptr, conv.mem] Remove redundant text on null pointer comparisons (#6411) + + commit b55ad4cb65b53bb6b6e60064938537f07d63bfb3 + Author: Alisdair Meredith + Date: Thu Aug 17 00:32:21 2023 +0200 + + [algorithms.parallel.defns] New paragraph for example (#6447) + + Making the example a sibling to the preceding paragraph + rather than part of it resets its list numbering, which is less + confusing than continuing numbering. + + commit be07cd4e87c693fb9749c1e5e7c07ee0cf9e0084 + Author: A. Jiang + Date: Wed Aug 2 01:28:29 2023 +0800 + + [diagnostics] Exposition-only formatting for members + + commit 7b7dedba78c8ae860db78feb3149acdf34ebb551 + Author: Giuseppe D'Angelo + Date: Thu Aug 17 21:04:37 2023 +0200 + + [time.general] Add a reference to time.hash in the summary + + [time.general] has a library summary with references to the various + subclauses; [time.hash] was missing, add it. + + commit 1e9e54ef536870ea01e6b016e4219e57df0c099b + Author: Giuseppe D'Angelo + Date: Thu Aug 17 21:07:27 2023 +0200 + + [time.hash] Fix a typo in the code for zoned_time + + The `m` was supposed to be a `,` to separate the template arguments. + + commit a272b7cd04dc0be488250a0c6aaead160e778774 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Fri Aug 18 12:11:24 2023 +0800 + + [iterator.concept.readable] Add missing \expos for indirectly-readable-impl + + Also adjust horizontal whitespace in related comments. + + commit 846dc84ac222e5f4a26373899a2cbd683f83991c + Author: Jan Schultke + Date: Sun Aug 20 16:56:55 2023 +0200 + + [diff.cpp20.utilities] Hyphenate bit-fields (#6481) + + commit 433baff775b00c2b72d0d81d792c24617c2ace06 + Author: Jan Schultke + Date: Sun Aug 20 20:56:34 2023 +0200 + + [tuple.swap] Improve 'call x with y' wording (#6478) + + commit 1c22d62180901069128b21daa2773d40566bd983 + Author: Jan Schultke + Date: Mon Aug 21 08:31:10 2023 +0200 + + [lex.phases] Add cross-reference to [cpp.include] (#6485) + + commit a54e71ed55a590214f2f33f4b1b900263a5f0b0d + Author: Eelis van der Weegen + Date: Fri Aug 25 18:05:32 2023 +0200 + + [rand.device] Remove stray \textit. + + Fixes #6513. + + commit 9a0b5d767ed6ef038adc129856c0c0623f552abe + Author: Jan Schultke + Date: Mon Aug 28 14:51:28 2023 +0200 + + [vector.data],[array.members] Clarify boolean condition (#6526) + + commit 8845a3778dbbd078c83a66ac09ae07e6357ec3e5 + Author: Eisenwave + Date: Mon Aug 28 15:33:11 2023 +0200 + + [expr.call] add further forward references + + commit 837d6c979124200f1e06bc582079a60767c2756b + Author: Daniel Krügler + Date: Sat Aug 26 18:35:55 2023 +0200 + + [atomics] Reword preconditions on memory_order values in a positive form + + commit 55b87300ce414fc5aa761838f217a957c797e9bf + Author: Thomas Köppe + Date: Tue Aug 29 13:12:09 2023 +0100 + + [format.string.std] Fix example + + commit 61c089e934c1df406580eeb488dd5cee0900a7b1 + Author: A. Jiang + Date: Sat Jul 29 01:36:15 2023 +0800 + + [intro.object] Fix alignment in example + + Makes the storage in the example properly aligned, + and explicitly states size assumption. + + commit 90d56dbe810e707d90322a3d16256e122e915eca + Author: Eisenwave + Date: Sat Aug 19 15:51:27 2023 +0200 + + [expr.sizeof] turn identifier into a grammarterm + + commit f52ffc9054913f3f9a4c5dc6973f6c5c3e7f1096 + Author: Jan Schultke + Date: Wed Aug 30 08:56:33 2023 +0200 + + [class.access.general] Fix improper \keyword{private} (#6532) + + commit d02a12a70c53974442f3e3ca4a75227783ea39d7 + Author: Jan Schultke + Date: Wed Aug 30 19:54:36 2023 +0200 + + [lex.string] Mark "narrow string literal" as a definition (#6533) + + commit 31154dccdbe33aadb91d43cc03884f2d1aa5dbc0 + Author: Jan Schultke + Date: Sat Sep 2 09:08:17 2023 +0200 + + [class.local] Add comma after introductory phrase (#6545) + + commit f9d08b09ffd8f68a32cbb480d54ab517e425d519 + Author: Joshua Berne + Date: Sat Sep 2 12:56:57 2023 -0400 + + [diff.cpp20.thread] Add hyphen for "ill-formed" (#6550) + + commit 9130806ceb4a9476153eb7544b4509b713cce3e0 + Author: Eisenwave + Date: Wed Aug 30 14:01:06 2023 +0200 + + [fs.path.member] fix empty() == true + + commit ae4ae54b293c28d782902b955af8abae5229fc6d + Author: Eisenwave + Date: Wed Aug 30 14:01:49 2023 +0200 + + [fs.path.modifiers] fix empty() == true + + commit ab4185710a64b303e6d302ac43c543849d79c5a8 + Author: Eisenwave + Date: Wed Aug 30 14:06:30 2023 +0200 + + [fs.filesystem.error.members] fix missing 'is true' + + commit 86b18720b37dadefe6c753ac2aec478b8f87593d + Author: Alisdair Meredith + Date: Tue Sep 5 16:19:25 2023 -0400 + + [basic.types.general] Apply Oxford comma consistently (#6554) + + commit 16c8ce5db2173a098a91e552dcfa3544c67e544f + Author: Eelis + Date: Fri Sep 8 08:05:36 2023 +0200 + + [mdspan.submdspan.extents] Format equations as math (#6530) + + commit 3bdb5e7b2b947ecd9fbb42029899ec098b51c51c + Author: Casey Carter + Date: Wed Sep 13 00:24:17 2023 -0700 + + [mdspan.layout.stride.cons] Fix cross-reference (#6565) + + commit 536653b854e293af569156864ea6aa407c90e011 + Author: Casey Carter + Date: Mon Sep 11 10:36:39 2023 -0700 + + [mdspan.extents.cons] require conversions to index_type to be nonnegative + + "nonnegative" is meaningless for a value of some arbitrary type which we've only required to be convertible to the integral type `index_type`, so this wording clearly intends to constrain the result of the conversion. + + commit 5c7841b1530dc02dbf7feacd5e154b777632dc36 + Author: Casey Carter + Date: Mon Sep 11 16:56:47 2023 -0700 + + [mdspan.layout.stride.cons] Convert to integral type before comparing to 0 + + `s[i]` is an lvalue of a type that we can only convert to `index_type`; clearly the wording intends that the result of the conversion should be `> 0`. + + commit 24659bd716808538fb7066103a396e785e4f0099 + Author: Casey Carter + Date: Mon Sep 11 16:59:56 2023 -0700 + + [mdspan.layout.stride.expo] Convert to integral type to perform math + + [mdspan.layout.stride.cons] uses either a span or array of a type which we can only convert to `index_type` as the second argument to the exposition-only `REQUIRED-SPAN-SIZE`. We must perform that conversion before doing math with the result. + + commit 81c3897d34ccd32d4ccdbe3c74091ba1db458533 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Wed Oct 4 00:22:33 2023 +0800 + + [const.iterators.ops] Add missing \pnum and replace returns with effects (#6581) + + commit 34cf81ebc821377eb3969002e4669bf5e08f479f + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Wed Oct 4 02:59:42 2023 +0800 + + [common.iter.const] Add missing period for Returns (#6584) + + commit 22537613dd844670ee9fb9d5afcf19f89c26fd26 + Author: Jens Maurer + Date: Tue Sep 26 07:21:52 2023 +0200 + + [temp.over.link] Fix phrasing and cross-reference introduced by P1787R6 + + commit 1398617dfd99dd3383e801abee6ce58629439f3a + Author: Jens Maurer + Date: Wed Oct 4 17:48:32 2023 +0200 + + [tab:headers.cpp] Add (#6586) + + commit 78635c91ac910e9c0953e1784eec648a214eb5ad + Author: Casey Carter + Date: Wed Oct 4 14:44:18 2023 -0700 + + [string.cons] Remove erroneous paragraph break (#6587) + + commit a2e820424e089806191a40d43df2360906902d86 + Author: Jonathan Wakely + Date: Tue Sep 19 13:36:52 2023 +0100 + + [range.utility.conv.to] Add terminating condition for first bullet + + We currently fail to say what happens if the first bullet is true, but + then none of its sub-bullets is true. + + commit 9369ba13509cd5d2c9e862b7ad02f109c204a585 + Author: Jonathan Wakely + Date: Tue Sep 19 16:19:50 2023 +0100 + + [version.syn] Put feature test macros in alphabetical order + + commit 1430209dbf6edda0827207166770c4d964cf0598 + Author: Jens Maurer + Date: Fri Oct 6 15:53:39 2023 +0200 + + [time.format] Make reference to ISO 8601 more precise + + Fixes ISO/CS 003 (C++23 DIS). + + commit 7ed9cbfef44d15b798af83223f5d3b62927652a5 + Author: Jens Maurer + Date: Fri Oct 6 15:14:44 2023 +0200 + + [intro.refs] Fix title of ISO/IEC 9899:2018 + + Fixes ISO/CS 004 (C++23 DIS). + + commit 258290ecc9d6e4d615b29173fd520df1f66a3292 + Author: Jens Maurer + Date: Fri Oct 6 01:21:01 2023 +0200 + + [annex] Fix table numbering in annexes + + Fixes ISO/CS 029 (C++23 DIS). + + commit c39f5b014540820b4ea2061805a92c417e43ca0d + Author: Jens Maurer + Date: Fri Oct 6 14:59:03 2023 +0200 + + [lex.name] Add cross-reference to Annex E + + Fixes ISO/CS 030 (C++23 DIS). + + commit b5d6409bf5132d653bc13a3ce8f76c556d5d6fc9 + Author: Jens Maurer + Date: Sat Oct 7 22:50:53 2023 +0200 + + [defns.component] Remove unwarranted italics + + Fixes ISO/CS 018 (C++23 DIS). + + commit 722bd4f167badc5bb5dddde9b0d00f91c2ef1644 + Author: Jens Maurer + Date: Fri Oct 6 13:24:16 2023 +0200 + + [util.smartptr.shared.cmp] Fix missing right parenthesis + + Fixes NB JP 025 (C++23 DIS). + + commit 24b090f5c63bf99d4cdcea8989d885f2d23c00e7 + Author: Jens Maurer + Date: Fri Oct 6 13:20:03 2023 +0200 + + [unique.ptr.runtime.modifiers] Fix placement of 'constexpr' + + Fixes NB JP 024 (C++23 DIS). + + commit 400521547f60196f6dfa7857bdcc907698991df8 + Author: Jens Maurer + Date: Sat Oct 7 11:11:15 2023 +0200 + + [expr.const] Amend comments in example + + Fixes NB JP 023 (C++23 DIS). + + commit 812e64a65699bb01203fbedcc7d9d5ea004a5007 + Author: Jens Maurer + Date: Sat Oct 7 22:32:16 2023 +0200 + + [expr.prim.lambda.general] Add example for parsing ambiguity + + Fixes NB JP 021 (C++23 DIS). + + commit bd7f9a9e640bfcd204cabecf1cc4953b7138554e + Author: Jens Maurer + Date: Sat Oct 7 10:38:29 2023 +0200 + + [intro.scope] Clarify 'they' + + Fixes ISO/CS 034 (C++23 DIS). + + commit dc597fa561a795c100a36f46376d6ddd0cf93a31 + Author: Alisdair Meredith + Date: Mon Oct 9 12:02:19 2023 -0400 + + [expr.prim.lambda.closure] Insert an extra \pnum (#6594) + + commit d81c17120e5a527f779b965ba8fd1ce66cfc24ef + Author: Alisdair Meredith + Date: Mon Oct 9 12:03:25 2023 -0400 + + [obj.lifetime] Dehyphenate trivially-copyable (#6592) + + commit d29b1fc1c22018b1a83cee910ebdbb4520d2c960 + Author: Jens Maurer + Date: Sun Oct 8 09:52:42 2023 +0200 + + [lex.charset] Add reference to the Unicode Standard + + commit e128de19470877fbf8f0335b8c0e2a1700f2e320 + Author: Jens Maurer + Date: Sun Oct 8 11:52:06 2023 +0200 + + [lex.charset] Clarify normative reference to Unicode for UTF-x + + Fixes ISO/CS 008 (C++23 DIS). + + commit 4d603c640dd47c71f84bbce55416302efab8b298 + Author: Thomas Köppe + Date: Tue Oct 10 23:55:22 2023 +0100 + + [intro.defs] Remove inappropriate paragraph. + + Only specific, fixed wording is allowed in Clause 3. + + Fixes ISO/CS 009 (C++23 DIS). + + commit 7d4fa2432b58a2ef6a2062812ec00ccde4443acf + Author: Jens Maurer + Date: Wed Oct 11 01:04:35 2023 +0200 + + [intro.defs] Remove unused definitions + + The terms "arbitrary-positional stream", "repositional stream", + and "iostream class templates" are removed. + + Fixes ISO/CS 011 and ISO/CS 16 (C++23 DIS). + + commit 4c76193e3d310ea5a18679ab86a54074fe1635e9 + Author: Thomas Köppe + Date: Wed Oct 11 00:14:53 2023 +0100 + + [defns.impl.limits] Use singular + + Fixes ISO/CS 015 (C++23 DIS). + + commit f672ecf38d2aec6ccf184d1a36bc4e83809afab0 + Author: Thomas Köppe + Date: Wed Oct 11 00:46:29 2023 +0100 + + [std] Replace "C Standard" with "ISO/IEC 9899:2018". + + Fixes ISO/CS 035 (C++23 DIS). + + commit 2d6182932954732f71a28d90ec1f1b23838ccc67 + Author: Thomas Köppe + Date: Wed Oct 11 01:13:46 2023 +0100 + + [intro.{r,d}efs] Make "C standard library" a defined term + + Partially fixes ISO/CS-002 (C++23 DIS). + + commit 4676f765f696774807688c3adfdc2eb03905a827 + Author: Jens Maurer + Date: Sun Oct 8 12:30:18 2023 +0200 + + [type.traits] Add references to tables + + Fixes ISO/CS 001 (C++23 DIS). + + commit 583391e28f34d6e0a17f67f77e04ba4f924c1d13 + Author: Thomas Köppe + Date: Sat Oct 14 20:42:50 2023 +0100 + + [intro.defs, dcl.init.list] Move definition of direct-non-list-init + + Partially fixes ISO/CS-11 (C++23 DIS). + + commit 4a8e84ede8a927a7ebe7fa16a086041db437d57c + Author: Thomas Köppe + Date: Sat Oct 14 20:58:52 2023 +0100 + + [xrefdelta] Remove mention of removals that are now already in C++23 diff --git a/papers/n4972.html b/papers/n4972.html new file mode 100644 index 0000000000..61df993043 --- /dev/null +++ b/papers/n4972.html @@ -0,0 +1,846 @@ + + + + + +N4972 + + +

N4972 Editors’ Report:
Programming Languages — C++

+ +

Date: 2023-12-18

+ +

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

+ +

Email: cxxeditor@gmail.com

+ +

Acknowledgements

+ +

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

+ +

New papers

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

Motions incorporated into working draft

+ +

Notes on motions

+ +

All motions were applied cleanly, and the following additional changes applied +for the sake of integration:

+ +
    +
  • LWG Polls 1 and 3 both modified [optional.monadic]: +LWG-3973 +changed **this to *val, and +P2407R5 +changed value() to **this. This has been reconciled by changing the +latter to *val, too.
  • +
  • LWG Poll 2 created a freestanding facility (saturation arithmetic) but did +not define a freestanding feature test macro. We added the macro +__cpp_lib_freestanding_numeric, also defined in the <numeric> header.
  • +
+ +

The feature test macro __cpp_lib_span has been modified both LWG Poll 3 and +LWG Poll 10, and is now set to a common, updated value (202311L).

+ +

The linear algebra paper P1673R13 moved by LWG Poll 19 adds a substantial amount +of material, and numerous minor issues were discovered during application, many +of which have been fixed immediately, and some will be addressed in future +editorial work. One particular issue, which is not new and also affects the +random number and special maths functions, is how to relate variables in code +and mathematical variables in a mathematical expression.

+ +

Core working group polls

+ +

CWG Poll 1: Accept as a Defect Report and apply the proposed resolution of all issues in +P3046R0 +(Core Language Working Group "ready" Issues for the November, 2023 meeting) to the C++ Working Paper.

+ +

CWG Poll 2: Accept as a Defect Report and apply the changes in +P2308R1 +(Template parameter initialization) to the C++ Working Paper.

+ +

CWG Poll 3: Apply the changes in +P2662R3 +(Pack Indexing) to the C++ Working Paper.

+ +

CWG Poll 4: Apply the changes in +P2864R2 +(Remove Deprecated Arithmetic Conversion on Enumerations From C++26) to the C++ Working Paper.

+ +

CWG Poll 5 was withdrawn.

+ +

Library working group polls

+ +

LWG Poll 1: Apply the changes for all Ready and Tentatively Ready issues in +P3040R0 +(C++ Standard Library Issues to be moved in Kona, Nov. 2023) to the C++ working paper.

+ +

LWG Poll 2: Apply the changes in +P0543R3 +(Saturation arithmetic) to the C++ working paper.

+ +

LWG Poll 3: Apply the changes in +P2407R5 +(Freestanding Library: Partial Classes) to the C++ working paper.

+ +

LWG Poll 4: Apply the changes in +P2546R5 +(Debugging Support) to the C++ working paper.

+ +

LWG Poll 5: Accept as a Defect Report and apply the changes in +P2905R2 +(Runtime format strings) to the C++ working paper.

+ +

LWG Poll 6: Apply the changes in +P2918R2 +(Runtime format strings II) to the C++ working paper.

+ +

LWG Poll 7: Accept as a Defect Report and apply the changes in +P2909R4 +(Fix formatting of code units as integers (Dude, where's my char?)) to the C++ working paper.

+ +

LWG Poll 8: Apply the changes in +P0952R2 +(A new specification for std::generate_canonical) to the C++ working paper.

+ +

LWG Poll 9: Apply the changes in +P2447R6 +(std::span over an initializer list) to the C++ working paper.

+ +

LWG Poll 10: Apply the changes in +P2821R5 +(span.at()) to the C++ working paper.

+ +

LWG Poll 11: Apply the changes in +P2868R3 +(Remove Deprecated std::allocator Typedef From C++26) to the C++ working paper.

+ +

LWG Poll 12: Apply the changes in +P2870R3 +(Remove basic_string::reserve() From C++26) to the C++ working paper.

+ +

LWG Poll 13: Apply the changes in +P2871R3 +(Remove Deprecated Unicode Conversion Facets from C++26) to the C++ working paper.

+ +

LWG Poll 14: Apply the changes in +P2819R2 +(Add tuple protocol to complex) to the C++ working paper.

+ +

LWG Poll 15: Apply the changes in +P2937R0 +(Freestanding: Remove strtok) to the C++ working paper.

+ +

LWG Poll 16: Apply the changes in +P2833R2 +(Freestanding Library: inout expected span) to the C++ working paper.

+ +

LWG Poll 17: Accept as a Defect Report and apply the changes in +P2836R1 +(std::basic_const_iterator should follow its underlying type's convertibility) to the C++ working paper.

+ +

LWG Poll 18: Apply the changes in +P2264R7 +(Make assert() macro user friendly for C and C++) to the C++ working paper.

+ +

LWG Poll 19: Apply the changes in +P1673R13 +(A free function linear algebra interface based on the BLAS) to the C++ working paper.

+ +

Comments on the Draft International Standard

+ +

This report includes our final dispositions on the Draft International Standard (DIS) +ballot comments for C++23 from national bodies and the ISO secretariat. Some of them only apply +to the published standard document and not the working draft, and the corresponding edits do not +appear in the working draft commit history. All comments on the ballot were editorial.

+ +
    +
  • ISO/CS 01: Accepted. We added references to the tables.
  • +
  • ISO/CS 02: Accepted. We moved the explanations close to their point of use.
  • +
  • ISO/CS 03: Accepted. We are now referring to a specific element, and keeping the dated reference.
  • +
  • ISO/CS 04: Accepted.
  • +
  • ISO/CS 05: Rejected: We do not understand the justification "Since there is no specific element referenced this reference shall be undated." The Drafting Directives seem to make a clear case for when undated (10.4) and dated (10.5) references are appropriate, and we firmly fall into the case where an undated reference is inappropriate ("if it will be possible to use all future changes of the referenced document" is definitely not the case). Reference to a specific element does not seem to be required in order to permit the use of a dated reference. Even the House Style seems to permit dated references when necessary: "When referring to the whole document, use an undated document number unless it is necessary that the user refers to a specific edition".
  • +
  • ISO/CS 06: Rejected: Moot by comment 05.
  • +
  • ISO/CS 07: Rejected: Moot by comment 05.
  • +
  • ISO/CS 08: Accepted. We reworded the reference to the Unicode standard to make the normative nature more obvious.
  • +
  • ISO/CS 09: Accepted.
  • +
  • ISO/CS 10: Rejected: We find domains valuable here, since the terms often sound like plain English words, but have rather domain-specific meaning, and the domain establishes important context to aid understandability.
  • +
  • ISO/CS 11: Accepted with modifications: four unused definitions are removed. The remaining term, "unspecified behavior" is retained, since it captures a variety of patterns which are not lexically spelled "behavior" but are neatly covered by this umbrella term.
  • +
  • ISO/CS 12: Accepted with modifications: we have italicized the cross-references. However, for the formal grammar terms that we display in italic sans font, please see the discussion on comment 32.
  • +
  • ISO/CS 13: Rejected: The token "CE" is not an acronym, but a meta variable (like "x" or "y". It is typeset distinctly. The name is evocative of its use.
  • +
  • ISO/CS 14: Accepted.
  • +
  • ISO/CS 15: Accepted.
  • +
  • ISO/CS 16: Rejected: The wording is correct as written. However, this is also mooted by comment 11, which deletes the wording in question.
  • +
  • ISO/CS 17: Accepted.
  • +
  • ISO/CS 18: Accepted.
  • +
  • ISO/CS 19: Accepted.
  • +
  • CA 20: n/a, comment was filed erroneously
  • +
  • JP 21: Accepted. We added an example.
  • +
  • JP 22: Rejected: No consensus for change; any attributes of a lambda-declarator are considered to be attached to the synthesized function call operator or operator template (i.e. the member function of the closure type), not the closure type itself.
  • +
  • JP 23: Accepted with modifications: The example is written as intended. The comments in the example have been amended to clarify the exposition.
  • +
  • JP 24: Accepted.
  • +
  • JP 25: Accepted.
  • +
  • JP 26: Rejected: No consensus for change; the example deliberately introduces a facility to aid comprehension.
  • +
  • JP 27: Rejected: No consensus for change; the example deliberately introduces a facility to aid comprehension.
  • +
  • JP 28: Rejected: No consensus for change; the example deliberately introduces a facility to aid comprehension.
  • +
  • ISO/CS 29: Accepted.
  • +
  • ISO/CS 30: Accepted. We added a note that refers to the annex.
  • +
  • ISO/CS 31: Accepted. We had previously used foreword wording from an older document.
  • +
  • ISO/CS 32: Rejected, along with comment 12: our document has complex typographic requirements, and we have carefully selected a harmonizing family of typefaces in our document processing system that meets our needs. For example, certain parts of a formal grammar (some of which appear in Clause 3; see comment 12) require typographic distinction to avoid ambiguity. We have discussed this with the ISO secretariat.
  • +
  • ISO/CS 33: Rejected: We have an approved SC22 ballot to permit the use of paragraph numbers. (We also have a proposal for the JDMT to add such a permission to the Drafting Directives.)
  • +
  • ISO/CS 34: Accepted. Reworded to clarify.
  • +
  • ISO/CS 35: Accepted.
  • +
  • ISO/CS 36: Accepted the notes and tables captioning changes. Rejected the UK English spelling: The document defines many terms that must be spelled the same way by conforming implementations and by users of those implementations, and these terms use US English spelling. It would be confusing for the document text to use UK English spelling when describing these terms. (This is the same disposition as for a similar comment on the DIS ballot of 14882:2017.)
  • +
  • ISO/CS 37: Rejected, please see comment 39.
  • +
  • ISO/CS 38: Accepted with modifications: We will review the presentation of cross-references in Clause 3. However, the use of italics in Clause 3 is not a regular "emphasis/definition" in body font, but rather a grammar production, which we typeset distinctly. Please also see the discussion regarding comment 32.
  • +
  • ISO/CS 39: Rejected: For this comment and for comment 37, we have carefully reviewed the permitted verbal constructions. We believe that the notes are the best place for this explanatory, optional information, and the wording as-is accurately describes the consequences of normative requirements for illustrative purposes. We would like to not move this explanatory material into the main text, since that text already contains a complex range of requirements on the C++ language, its implementations, and its users, and our community has been finding our established boundary for what is explanatory note material helpful.
  • +
  • ISO/CS 40: Accepted. The logic that processed the notes was erroneous and failed to handle subclauses with more than 9 notes; this has been fixed.
  • +
+ +

Editorial changes

+ +

Major editorial changes

+ +

A number of editorial changes were made in response to requests from the ISO +secretariat during the publication of C++23. We list just a few noteworthy ones.

+ +
    +
  • There is now a new "Introduction" subclause, which explains our use of +stable labels and some typographic choices. In the future, we would like to +expand the introduction to explain more comprehensively how the Standard is +structured, phrased, and intended to be read.
  • +
  • Table captions are now formatted in bold, and the table number is separated +from the caption by a dash.
  • +
  • Inadmissible text has been removed from Clauses 2 (Normative references) and +3 (Terms and definitions), as those clauses must only contain specific, +fixed wording. The removed text has been moved nearer to the places in the +main text where it is needed.
  • +
  • Definitions in Clause 3 (Terms and definitions) now contain cross references +to one another as appropriate.
  • +
+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4964 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 a27ede64fef7fda551d480e5a1cf1b9a73832574
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Tue Oct 24 20:55:27 2023 +0800
+
+    [span.cons] Add `std::` for `data(arr)` (#6632)
+
+commit 84c526ebbda74553bf935f35f5594b8d5591bce5
+Author: Casey Carter <Casey@Carter.net>
+Date:   Mon Oct 30 14:22:57 2023 -0700
+
+    [format.formatter.spec] Add missing include to example (#6636)
+
+    The example code refers to `std::string` directly so it should `#include<string>`.
+
+commit 4a6f2e3f4791c44b8c8f32a75d0bebac4a7b6a9e
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Nov 2 00:53:04 2023 +0100
+
+    [intro.refs] Move nicknames for standards to relevant subclauses
+
+commit dc6eed02986d9c3c6827c710adb577ba0809f939
+Author: Krystian Stasiowski <sdkrystian@gmail.com>
+Date:   Tue Nov 7 04:32:19 2023 -0500
+
+    [dcl.dcl, over.best.ics, temp.param, class.union.anon] Remove mentions of "storage class" (#3906)
+
+commit 17c09925b2423c596196d3f88a61ff7b4052ef7a
+Author: Krystian Stasiowski <sdkrystian@gmail.com>
+Date:   Tue Nov 7 01:16:28 2023 -0500
+
+    [class.conv.fct] Fix reference to 'ref-qualifier-seq'
+
+commit 90720a35b0c3d65488d9dc9ecea682c271f43d52
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Oct 30 09:34:01 2023 +0800
+
+    [queue.syn] Show `formatter` specializations in the synopsis
+
+commit e43aa89a4882f8080fb10c843cdb25c9740b65c7
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Oct 30 09:36:24 2023 +0800
+
+    [stack.syn] Show the `formatter` specialization in the synopsis
+
+commit 80a8748fd401cfceee804bc96d2bfc518726d2e7
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Thu Oct 12 18:24:21 2023 -0400
+
+    [class.copy.assign] Remove a superfluous note.
+
+    Alternatively we could have added the word "non-object"; or changed
+    it to say "An overloaded assignment operator must be a member function";
+    but it doesn't seem like it needs to be here at all.
+
+commit c9c69dc54052badeb9b80458027371438d886763
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Thu Oct 12 18:58:39 2023 -0400
+
+    [class.copy.assign] Add some missing "non-object"s
+
+commit 2b5fc2936f12f73e975dbb9f34d3790fe0aa708f
+Author: Matt Bentley <mattreecebentley@gmail.com>
+Date:   Wed Nov 8 14:56:22 2023 +1300
+
+    [sequence.reqmts] Remove misleading, oversimplified informative text
+
+commit 11334c71244a046f0c29b01dfd79b35f6fea8cc4
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Sep 1 09:29:01 2023 +0200
+
+    [class.copy.elision] improve reference and replace informal term
+
+commit 4feefb62e0419bb52c678389163729959785d44a
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Nov 8 02:59:01 2023 +0100
+
+    [mem.res.pool.options] Change "field" to "member" (#6479)
+
+commit a700e3b87b00d2673b3cded0a61201d09dfc051a
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Wed Nov 8 10:01:46 2023 +0800
+
+     [version.syn] Bump value of __cpp_lib_constexpr_complex (#6421)
+
+    P1383R2 "More constexpr for <cmath> and <complex>" modifies two headers;
+    both __cpp_lib_constexpr_cmath and __cpp_lib_constexpr_complex should be updated.
+
+    This aligns with existing practice in SD6.
+
+commit e9fb04e1c1e67bfb07bf3c61145b9d63a0f0adcf
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Tue Sep 27 15:36:08 2022 -0400
+
+    [dcl.enum] Enumerators don't have "initializers"
+
+commit bc3cb41a36dfff0d2358f4e294be9636590e680e
+Author: Krystian Stasiowski <sdkrystian@gmail.com>
+Date:   Tue Nov 7 21:08:15 2023 -0500
+
+    [dcl.name] Turn informative wording into note (#3964)
+
+commit 82b2ba6f6245e717cb002a9a836117a918aab36a
+Author: Patrick Johnston <gcupcakekid@gmail.com>
+Date:   Wed Nov 8 02:10:58 2023 +0000
+
+    [streambuf.general] Remove incorrect "abstract"
+
+    The referenced class template `basic_streambuf` is not abstract.
+
+commit bbaa4a497e03d944fc38279db4d8c47eed7831d9
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Oct 12 20:51:57 2023 +0200
+
+    [basic.lval] turn reference paragraph into note
+
+commit a03b8b70d6666b67d27c801b68d41683e987e929
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Oct 5 15:27:29 2023 -0400
+
+    [temp.param] Introduce term to xref structural type
+
+    The current cross-references to [temp.param] appear confusing,
+    as the structural type definition is buried a couple of pages
+    below.  Also, this change looks clearer in the source.
+
+commit 71ee18ab8cd9efca0d8afa1f6e639cb02610a52b
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Nov 7 16:18:40 2023 -1000
+
+    [basic.types.general] Introduce term to xref implicit-lifetime type (#6591)
+
+commit 21454c7ebf67a1a723b61c32901a842c684e6b94
+Author: Language Lawyer <language.lawyer@gmail.com>
+Date:   Wed Aug 23 01:35:22 2023 +0500
+
+    [intro.races] Make reading atomic objects nondeterministic
+
+commit df26017a6bfd74d794345ea9313eae1efacbf7c9
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Nov 8 03:31:10 2023 +0100
+
+    [diff.dcl] Replace 'field initializers' with 'member initializers' (#6482)
+
+commit cc69fc0dd6b1a2fdc834bade578acb84cc7d2cfa
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Nov 8 10:54:52 2023 +0800
+
+    [intro.races] Remove inappropriate uses of "shall" (#6457)
+
+commit 60e280391a06b8d27f778a56310b0827109623aa
+Author: Eisenwave <me@eisenwave.net>
+Date:   Thu Aug 31 00:19:24 2023 +0200
+
+    [cmath.syn] fix misaligned parameter lists
+
+commit 646bfb2a060e3c7f490f6c4672ee93a0cbaf6d0d
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Nov 8 05:59:28 2023 -1000
+
+    [container.alloc.reqmts] Better xrefs for allocator-aware containers
+
+    There are now more allocator-aware containers in the standard
+    than when this subclause was first written, so ensure we have
+    call outs to all relevent subclauses.
+
+    The current wording for 'basic_stacktrace' also shows how
+    containers can properly call out the allocator-aware container
+    requirements, now that they have their own, titled subclause.
+
+commit 62e33ca8a0a55764227e6a67c1f554783ffefe40
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Thu Nov 9 00:01:38 2023 +0800
+
+    [time.zone.leap.overview] Fix example (#6383)
+
+commit 07ae51af31587ac533b1b39c95777ecb725dcab0
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Jan 25 18:22:53 2023 +0800
+
+    [expr.prim.req.general] Correct the IFNDR example
+
+commit f3059744c84f561f8ead4c5d117bc1160c43b7e2
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed Nov 8 23:52:44 2023 +0000
+
+    [defns.character.container] Improve note to entry (#6644)
+
+commit 8b38857b22f6518a41e506e4c9b2e9a1792a0fbd
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Oct 10 09:40:20 2023 +0800
+
+    [iterator.requirements.general] Clarify non-forward iterator
+
+commit fbb1a6ebbd1f78e644df2dbcb3ce31250410779e
+Author: onihusube <44743040+onihusube@users.noreply.github.com>
+Date:   Fri Nov 10 08:36:12 2023 +0900
+
+    [execpol.unseq] Fix missing \itemdescr (#5931)
+
+commit 10e2799f5d524dd941d424dfd08927c77a6b87f1
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Fri Feb 17 10:47:28 2023 -0500
+
+    [pairs.pair] Consistent wording for assignment
+
+    Apply a consistent pattern to how we specify assigning members in assignment operators.
+
+commit 78300aa38c23f1356dca8e786205e5aaf7769d01
+Author: Barry Revzin <barry.revzin@gmail.com>
+Date:   Thu Nov 9 14:45:17 2023 -1000
+
+    [class.compare] Don't introduce `V` for the return value (#6035)
+
+    In both cases, I'm not sure introducing `V` helps much - just requires name lookup for `V`. If we just say "the return value" in every case, I think that's clearer.
+
+commit 838cb0649b1f4061e960772aee3563cedb20b108
+Author: Michael Florian Hava <mfh@live.at>
+Date:   Thu Nov 9 13:51:58 2023 -1000
+
+    [basic.extended.fp] Replaced usage of 'mantissa' with 'significand'
+    according to SO/IEC/IEEE 60559:2008
+
+commit ce5ef1b5334f1fc756d40e40ec300257b0ff99d9
+Author: Michael Florian Hava <mfh@live.at>
+Date:   Thu Nov 9 13:57:32 2023 -1000
+
+    [numeric.limits.members] Replaced usage of 'mantissa' with 'significand' according to
+    SO/IEC/IEEE 60559:2008
+
+commit 3e1f377a9dc3bece7acd2dddb7237065504db65c
+Author: Brian Bi <bbi5291@gmail.com>
+Date:   Thu Nov 9 16:00:22 2023 -1000
+
+    [macros, styles] Add \hypertarget to headings (#6516)
+
+    This allows forming URLs with a stable label as a fragment and
+    have PDF viewers jump to the corresponding (sub)clause.
+
+    For example: std.pdf#basic.life
+
+commit 60f7bb72cdd36e9d359fa7aea84a5b836079a0ed
+Author: Eisenwave <me@eisenwave.net>
+Date:   Thu Jul 6 13:41:56 2023 +0200
+
+    [namespace.std] convert (a) and (b) notation to items
+
+commit f48f316c42c6cb67058d9f9106852154497b4516
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Nov 10 06:57:17 2023 +0100
+
+    [atomics.order] Use "recommended practice" (#6380)
+
+commit 1ec1d9e6fa98734b3edf20f6c2217a4482f78103
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Fri Nov 10 16:59:21 2023 +0800
+
+    [meta.{unary.prop.query,trans.arr] Use `static_assert` instead of `assert` in example
+
+commit bd8f4540720e52dab9187a62c5598e735aeacfdd
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Aug 19 15:57:39 2023 +0200
+
+    [expr.sizeof] use constexpr member in example
+
+commit b1f922a126dcda78acb4bae055843e7a7321fe1d
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Aug 23 13:42:39 2023 +0200
+
+    [basic.def.odr] Fix hyphenation of "{copy,move} assignment"
+
+commit 54e465a17adfcba56a57ff2fefe43ec898725efb
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Aug 23 13:43:46 2023 +0200
+
+    [res.on.arguments] Fix hyphenation of "move assignment"
+
+commit 3c5b5b0c58d0440233d992e1a0791a449936f203
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Aug 23 13:44:40 2023 +0200
+
+    [futures.{unique,shared}.future] Fix hyphenation of "{copy,move} assignment"
+
+commit 9483cb7cf6973689ad563d30778d8da2dff42a8d
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed Nov 8 22:57:57 2023 +0000
+
+    [string.capacity] Remove parentheses from "reserve()"
+
+    It's very confusing to talk about `reserve()` when describing a call to
+    `reserve(size_type)`, given that the overload `reserve()` also exists.
+
+commit 2a9f28670a0df6e239d9b335bdb014f20f577732
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Jul 24 16:19:01 2023 +0000
+
+    [dcl.meaning.general] Use 'declarator-id' instead of 'name'
+
+commit d8b72f0ceb36b3537ef576ab216d588642e332ab
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Jul 25 18:26:03 2023 +0000
+
+    [module.global.frag] Simplify wording
+
+    Also make variable order consistent across bullets.
+
+commit f0c172c5604b47c3ecc7b64669aad660df403624
+Author: Oliver Rosten <oliver.rosten@gmail.com>
+Date:   Fri Nov 10 18:12:06 2023 +0000
+
+    [algorithms] Change stable label "mismatch" to "alg.mismatch" (#6653)
+
+commit d97603a90d2fcfeec2caf4371ca9e6c8f562842a
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Nov 11 03:21:17 2023 +0800
+
+    [forward.iterators] Use "Cpp17" requirement (#6612)
+
+commit f474227b69d10350999a5fc63503725421a89954
+Author: Geng Cheng <xmcgcg@qq.com>
+Date:   Sat Nov 11 10:25:39 2023 +0800
+
+    [stringstream.general] Add missing template argument "Allocator" (#6560)
+
+commit f5fdfe453e5a1e0370f2cb28bfc2dfeecab6370e
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Nov 8 15:12:16 2023 -1000
+
+    [diff.cpp20.library] Add missing new headers for C++23
+
+commit 38dfe3db0f08bd09a2b445ba82e83f7caae28d94
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Nov 9 11:00:44 2023 +0800
+
+    [dcl.init.ref] Clarify "related type"
+
+    "Related type" is not a term, "reference-related type" is clearer.
+
+commit 979983929bb592c02c9ae3e52f1c676dd5ae06fe
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Tue Nov 14 02:27:01 2023 +0800
+
+    [range.cartesian.view] Don't name unused template parameter (#6177)
+
+commit ecbeb5ad4e4c0ac1d0cdb5e8dd01daab8df8d62e
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Nov 14 14:27:27 2023 -0500
+
+    [diff.cpp23.library] Entry for new headers in C++26 (#6648)
+
+commit eb7f0bcbff2af109643089ef36dfe67040a27f4a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Nov 13 01:12:50 2023 -1000
+
+    [intro.defs, macros] Add cross-references among definitions
+
+    Fixes ISO/CS 017 (C++23 DIS).
+
+commit 706880e4ed855ae76d503c70adfb0015bbfb3df0
+Author: Lewis Baker <lewissbaker@users.noreply.github.com>
+Date:   Thu Nov 16 10:36:25 2023 +1030
+
+    [allocator.requirements.general] Fix missing ellipsis (#6695)
+
+commit 5c0103c0a656cbcd725780388b0879e992a1b21a
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Nov 16 15:38:47 2023 +0000
+
+    [stacktrace.format], [stacktrace.basic.hash] change rSec3 to rSec2
+
+    These should not be nested below std::basic_stacktrace because they
+    apply to both std::stacktrace_entry and std::basic_stacktrace.
+
+commit a6ad6083ab75901cb41b5bc8d034c0b322433457
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Dec 5 23:42:23 2023 +0000
+
+    [std, styles] Adjust table captions as per ISO request
+
+    ISO has asked for captions to be bold and table numbers to be
+    separated by a dash.
+
+commit f519ea4aa97592703ba5bbe9164242d946723721
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 7 01:00:53 2023 +0100
+
+    [intro.refs, time.format] Update references from ISO 8601:2004 to ISO 8601-1:2019 (#6720)
+
+commit 37956fb3685c2c279bd6b4b701964b20913d0c79
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Dec 6 19:01:29 2023 +0000
+
+    [syntax] Change "italic" to "italic, sans-serif"
+
+    We changed the grammar non-terminal font to sans-serif,
+    so we should update the description.
+
+commit 4eed7a0f1e44c45554f8a210af34fd6e1ea19596
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 7 22:13:35 2023 +0100
+
+    [intro.abstract] Actually use the phrase 'unspecified/undefined behavior'
+
+    Fixes ISO/CS 011 (C++23 DIS).
+
+commit f8a6138da1e431779ac43a893faa32f3f0cad7d0
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Dec 7 12:45:11 2023 +0000
+
+    [intro.defs] Fix introductory text according to ISO rules.
+
+    In principle, "symbols and abbreviated terms" can be listed in a
+    standard, and can be listed in a separate clause or in a combined
+    clause 3 "Terms, definitions, symbols and abbreviated terms", we do
+    not actually need symbol definitions. In any case, the introductory
+    text would never mention "symbols".
+
+commit 9961cd4f16aca645c77d6927526ea71f635a2932
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Dec 7 00:01:48 2023 +0000
+
+    [introduction] A minimal "Introduction" clause
+
+    This clause explains our conventions regarding stable labels and
+    choice of fonts.
+
+commit 9041b27206388fecd03073bb913185ac738c6dca
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Dec 18 00:57:45 2023 +0000
+
+    [optional.monaic] Restore wording effected by LWG3973.
+
+    Both LWG3973 (Motion 1) and P2407R5 (Motion 3) modified this wording:
+    LWG3973 changes "value()" to "*val" to address ADL concerns, and
+    P2407R5 changed "value()" to "**this" to be freestanding. In light of
+    the former, the latter should also use "*val".
+
+    Independently, additional problems have been discovered with LWG3973,
+    but those will be addressed by a future LWG issue.
+
+commit 2b1867a3404562c4261722e0a913cbcbf5a0a476
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Dec 17 23:10:44 2023 +0000
+
+    [version.syn] New feature test macro __cpp_lib_freestanding_numeric
+
+    This macro indicates that freestanding support for "saturation
+    arithmetic" is available, which was added in motion LWG-2 (via
+    P0543R3). This reverts the previous change
+    148e03a16d53ff8cffd219384df37efad5fd386d, which I had made subsequent
+    to motion LWG-3 (P2407R5), on advice of LWG. A separate macro is
+    preferable to mixing both headers under "algorithm".
+
+commit fa54f9e7306b3d0abb21a82b5cc951711c96161f
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed Dec 13 11:03:18 2023 +0000
+
+    [range.access.general] Use consistent "In addition to being available ..." form
+
+    Elsewhere we say "the header" or "any of the headers", e.g. [meta.trans.other],
+    [tuple.helper], etc.
+
+commit 8c611593555b93a45a13543ad265d8cfaf646932
+Author: Cassio Neri <cassio.neri@gmail.com>
+Date:   Mon Nov 27 19:47:29 2023 +0000
+
+    [expected.general] Fix description of expected<T, E> (issue #6714.)
+
+commit 12565ed5ea083761b25df3c8325989f95fa04898
+Author: Po-yao Chang <poyaoc97@gmail.com>
+Date:   Wed Nov 22 23:02:49 2023 +0800
+
+    [class.eq] Fix the return value of a defaulted == operator function
+
+ + diff --git a/papers/n4972.md b/papers/n4972.md new file mode 100644 index 0000000000..ed66878372 --- /dev/null +++ b/papers/n4972.md @@ -0,0 +1,699 @@ +# N4972 Editors' Report -- Programming Languages -- C++ + +Date: 2023-12-18 + +Thomas Köppe (editor, Google DeepMind) +Jens Maurer (co-editor) +Dawn Perchik (co-editor, Bright Side Computing, LLC) +Richard Smith (co-editor, Google Inc) + +Email: `cxxeditor@gmail.com` + +## Acknowledgements + +Thanks to all those who have [submitted editorial +issues](https://github.com/cplusplus/draft/wiki/How-to-submit-an-editorial-issue) +and to those who have provided pull requests with fixes, +and special thanks to Johel Ernesto Guerrero Peña for providing in-depth review +of many of the draft motion applications. + +## New papers + + * [N4971](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4971.pdf) is the + current working draft for C++26. It replaces + [N4964](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4964.pdf). + * N4972 is this Editors' Report. + +## Motions incorporated into working draft + +### Notes on motions + +All motions were applied cleanly, and the following additional changes applied +for the sake of integration: + +* LWG Polls 1 and 3 both modified [optional.monadic]: + [LWG-3973](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p3040r0.html#3973) + changed `**this` to `*val`, and + [P2407R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2407r5.html) + changed `value()` to `**this`. This has been reconciled by changing the + latter to `*val`, too. +* LWG Poll 2 created a freestanding facility (saturation arithmetic) but did + not define a freestanding feature test macro. We added the macro + `__cpp_lib_freestanding_numeric`, also defined in the `` header. + +The feature test macro `__cpp_lib_span` has been modified both LWG Poll 3 and +LWG Poll 10, and is now set to a common, updated value (`202311L`). + +The linear algebra paper P1673R13 moved by LWG Poll 19 adds a substantial amount +of material, and numerous minor issues were discovered during application, many +of which have been fixed immediately, and some will be addressed in future +editorial work. One particular issue, which is not new and also affects the +random number and special maths functions, is how to relate variables in code +and mathematical variables in a mathematical expression. + +### Core working group polls + +CWG Poll 1: Accept as a Defect Report and apply the proposed resolution of all issues in +[P3046R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p3046r0.html) +(Core Language Working Group "ready" Issues for the November, 2023 meeting) to the C++ Working Paper. + +CWG Poll 2: Accept as a Defect Report and apply the changes in +[P2308R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2308r1.html) +(Template parameter initialization) to the C++ Working Paper. + +CWG Poll 3: Apply the changes in +[P2662R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2662r3.pdf) +(Pack Indexing) to the C++ Working Paper. + +CWG Poll 4: Apply the changes in +[P2864R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2864r2.pdf) +(Remove Deprecated Arithmetic Conversion on Enumerations From C++26) to the C++ Working Paper. + +CWG Poll 5 was withdrawn. + +### Library working group polls + +LWG Poll 1: Apply the changes for all Ready and Tentatively Ready issues in +[P3040R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p3040r0.html) +(C++ Standard Library Issues to be moved in Kona, Nov. 2023) to the C++ working paper. + +LWG Poll 2: Apply the changes in +[P0543R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0543r3.html) +(Saturation arithmetic) to the C++ working paper. + +LWG Poll 3: Apply the changes in +[P2407R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2407r5.html) +(Freestanding Library: Partial Classes) to the C++ working paper. + +LWG Poll 4: Apply the changes in +[P2546R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2546r5.html) +(Debugging Support) to the C++ working paper. + +LWG Poll 5: Accept as a Defect Report and apply the changes in +[P2905R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2905r2.html) +(Runtime format strings) to the C++ working paper. + +LWG Poll 6: Apply the changes in +[P2918R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2918r2.html) +(Runtime format strings II) to the C++ working paper. + +LWG Poll 7: Accept as a Defect Report and apply the changes in +[P2909R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2909r4.html) +(Fix formatting of code units as integers (Dude, where's my char?)) to the C++ working paper. + +LWG Poll 8: Apply the changes in +[P0952R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0952r2.html) +(A new specification for `std::generate_canonical`) to the C++ working paper. + +LWG Poll 9: Apply the changes in +[P2447R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2447r6.html) +(`std::span` over an initializer list) to the C++ working paper. + +LWG Poll 10: Apply the changes in +[P2821R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2821r5.html) +(`span.at()`) to the C++ working paper. + +LWG Poll 11: Apply the changes in +[P2868R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2868r3.pdf) +(Remove Deprecated `std::allocator` Typedef From C++26) to the C++ working paper. + +LWG Poll 12: Apply the changes in +[P2870R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2870r3.pdf) +(Remove `basic_string::reserve()` From C++26) to the C++ working paper. + +LWG Poll 13: Apply the changes in +[P2871R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2871r3.pdf) +(Remove Deprecated Unicode Conversion Facets from C++26) to the C++ working paper. + +LWG Poll 14: Apply the changes in +[P2819R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2819r2.pdf) +(Add tuple protocol to `complex`) to the C++ working paper. + +LWG Poll 15: Apply the changes in +[P2937R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2937r0.html) +(Freestanding: Remove `strtok`) to the C++ working paper. + +LWG Poll 16: Apply the changes in +[P2833R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2833r2.html) +(Freestanding Library: `inout` `expected` `span`) to the C++ working paper. + +LWG Poll 17: Accept as a Defect Report and apply the changes in +[P2836R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2836r1.html) +(`std::basic_const_iterator` should follow its underlying type's convertibility) to the C++ working paper. + +LWG Poll 18: Apply the changes in +[P2264R7](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2264r7.html) +(Make `assert()` macro user friendly for C and C++) to the C++ working paper. + +LWG Poll 19: Apply the changes in +[P1673R13](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1673r13.html) +(A free function linear algebra interface based on the BLAS) to the C++ working paper. + +## Comments on the Draft International Standard + +This report includes our final dispositions on the Draft International Standard (DIS) +ballot comments for C++23 from national bodies and the ISO secretariat. Some of them only apply +to the published standard document and not the working draft, and the corresponding edits do not +appear in the working draft commit history. All comments on the ballot were editorial. + +* **ISO/CS 01:** Accepted. We added references to the tables. +* **ISO/CS 02:** Accepted. We moved the explanations close to their point of use. +* **ISO/CS 03:** Accepted. We are now referring to a specific element, and keeping the dated reference. +* **ISO/CS 04:** Accepted. +* **ISO/CS 05:** Rejected: We do not understand the justification "Since there is no specific element referenced this reference shall be undated." The Drafting Directives seem to make a clear case for when undated (10.4) and dated (10.5) references are appropriate, and we firmly fall into the case where an undated reference is inappropriate ("if it will be possible to use all future changes of the referenced document" is definitely not the case). Reference to a specific element does not seem to be required in order to permit the use of a dated reference. Even the House Style seems to permit dated references when necessary: "When referring to the whole document, use an undated document number unless it is necessary that the user refers to a specific edition". +* **ISO/CS 06:** Rejected: Moot by comment 05. +* **ISO/CS 07:** Rejected: Moot by comment 05. +* **ISO/CS 08:** Accepted. We reworded the reference to the Unicode standard to make the normative nature more obvious. +* **ISO/CS 09:** Accepted. +* **ISO/CS 10:** Rejected: We find domains valuable here, since the terms often sound like plain English words, but have rather domain-specific meaning, and the domain establishes important context to aid understandability. +* **ISO/CS 11:** Accepted with modifications: four unused definitions are removed. The remaining term, "unspecified behavior" is retained, since it captures a variety of patterns which are not lexically spelled "behavior" but are neatly covered by this umbrella term. +* **ISO/CS 12:** Accepted with modifications: we have italicized the cross-references. However, for the formal grammar terms that we display in italic sans font, please see the discussion on comment 32. +* **ISO/CS 13:** Rejected: The token "CE" is not an acronym, but a meta variable (like "x" or "y". It is typeset distinctly. The name is evocative of its use. +* **ISO/CS 14:** Accepted. +* **ISO/CS 15:** Accepted. +* **ISO/CS 16:** Rejected: The wording is correct as written. However, this is also mooted by comment 11, which deletes the wording in question. +* **ISO/CS 17:** Accepted. +* **ISO/CS 18:** Accepted. +* **ISO/CS 19:** Accepted. +* **CA 20:** n/a, comment was filed erroneously +* **JP 21:** Accepted. We added an example. +* **JP 22:** Rejected: No consensus for change; any attributes of a lambda-declarator are considered to be attached to the synthesized function call operator or operator template (i.e. the member function of the closure type), not the closure type itself. +* **JP 23:** Accepted with modifications: The example is written as intended. The comments in the example have been amended to clarify the exposition. +* **JP 24:** Accepted. +* **JP 25:** Accepted. +* **JP 26:** Rejected: No consensus for change; the example deliberately introduces a facility to aid comprehension. +* **JP 27:** Rejected: No consensus for change; the example deliberately introduces a facility to aid comprehension. +* **JP 28:** Rejected: No consensus for change; the example deliberately introduces a facility to aid comprehension. +* **ISO/CS 29:** Accepted. +* **ISO/CS 30:** Accepted. We added a note that refers to the annex. +* **ISO/CS 31:** Accepted. We had previously used foreword wording from an older document. +* **ISO/CS 32:** Rejected, along with comment 12: our document has complex typographic requirements, and we have carefully selected a harmonizing family of typefaces in our document processing system that meets our needs. For example, certain parts of a formal grammar (some of which appear in Clause 3; see comment 12) require typographic distinction to avoid ambiguity. We have discussed this with the ISO secretariat. +* **ISO/CS 33:** Rejected: We have an approved SC22 ballot to permit the use of paragraph numbers. (We also have a proposal for the JDMT to add such a permission to the Drafting Directives.) +* **ISO/CS 34:** Accepted. Reworded to clarify. +* **ISO/CS 35:** Accepted. +* **ISO/CS 36:** Accepted the notes and tables captioning changes. Rejected the UK English spelling: The document defines many terms that must be spelled the same way by conforming implementations and by users of those implementations, and these terms use US English spelling. It would be confusing for the document text to use UK English spelling when describing these terms. (This is the same disposition as for a similar comment on the DIS ballot of 14882:2017.) +* **ISO/CS 37:** Rejected, please see comment 39. +* **ISO/CS 38:** Accepted with modifications: We will review the presentation of cross-references in Clause 3. However, the use of italics in Clause 3 is not a regular "emphasis/definition" in body font, but rather a grammar production, which we typeset distinctly. Please also see the discussion regarding comment 32. +* **ISO/CS 39:** Rejected: For this comment and for comment 37, we have carefully reviewed the permitted verbal constructions. We believe that the notes are the best place for this explanatory, optional information, and the wording as-is accurately describes the consequences of normative requirements for illustrative purposes. We would like to not move this explanatory material into the main text, since that text already contains a complex range of requirements on the C++ language, its implementations, and its users, and our community has been finding our established boundary for what is explanatory note material helpful. +* **ISO/CS 40:** Accepted. The logic that processed the notes was erroneous and failed to handle subclauses with more than 9 notes; this has been fixed. + +## Editorial changes + +### Major editorial changes + +A number of editorial changes were made in response to requests from the ISO +secretariat during the publication of C++23. We list just a few noteworthy ones. + +* There is now a new "Introduction" subclause, which explains our use of + stable labels and some typographic choices. In the future, we would like to + expand the introduction to explain more comprehensively how the Standard is + structured, phrased, and intended to be read. +* Table captions are now formatted in bold, and the table number is separated + from the caption by a dash. +* Inadmissible text has been removed from Clauses 2 (Normative references) and + 3 (Terms and definitions), as those clauses must only contain specific, + fixed wording. The removed text has been moved nearer to the places in the + main text where it is needed. +* Definitions in Clause 3 (Terms and definitions) now contain cross references + to one another as appropriate. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4964 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/n4964...n4971). + + commit a27ede64fef7fda551d480e5a1cf1b9a73832574 + Author: S. B. Tam + Date: Tue Oct 24 20:55:27 2023 +0800 + + [span.cons] Add `std::` for `data(arr)` (#6632) + + commit 84c526ebbda74553bf935f35f5594b8d5591bce5 + Author: Casey Carter + Date: Mon Oct 30 14:22:57 2023 -0700 + + [format.formatter.spec] Add missing include to example (#6636) + + The example code refers to `std::string` directly so it should `#include`. + + commit 4a6f2e3f4791c44b8c8f32a75d0bebac4a7b6a9e + Author: Jens Maurer + Date: Thu Nov 2 00:53:04 2023 +0100 + + [intro.refs] Move nicknames for standards to relevant subclauses + + commit dc6eed02986d9c3c6827c710adb577ba0809f939 + Author: Krystian Stasiowski + Date: Tue Nov 7 04:32:19 2023 -0500 + + [dcl.dcl, over.best.ics, temp.param, class.union.anon] Remove mentions of "storage class" (#3906) + + commit 17c09925b2423c596196d3f88a61ff7b4052ef7a + Author: Krystian Stasiowski + Date: Tue Nov 7 01:16:28 2023 -0500 + + [class.conv.fct] Fix reference to 'ref-qualifier-seq' + + commit 90720a35b0c3d65488d9dc9ecea682c271f43d52 + Author: A. Jiang + Date: Mon Oct 30 09:34:01 2023 +0800 + + [queue.syn] Show `formatter` specializations in the synopsis + + commit e43aa89a4882f8080fb10c843cdb25c9740b65c7 + Author: A. Jiang + Date: Mon Oct 30 09:36:24 2023 +0800 + + [stack.syn] Show the `formatter` specialization in the synopsis + + commit 80a8748fd401cfceee804bc96d2bfc518726d2e7 + Author: Arthur O'Dwyer + Date: Thu Oct 12 18:24:21 2023 -0400 + + [class.copy.assign] Remove a superfluous note. + + Alternatively we could have added the word "non-object"; or changed + it to say "An overloaded assignment operator must be a member function"; + but it doesn't seem like it needs to be here at all. + + commit c9c69dc54052badeb9b80458027371438d886763 + Author: Arthur O'Dwyer + Date: Thu Oct 12 18:58:39 2023 -0400 + + [class.copy.assign] Add some missing "non-object"s + + commit 2b5fc2936f12f73e975dbb9f34d3790fe0aa708f + Author: Matt Bentley + Date: Wed Nov 8 14:56:22 2023 +1300 + + [sequence.reqmts] Remove misleading, oversimplified informative text + + commit 11334c71244a046f0c29b01dfd79b35f6fea8cc4 + Author: Eisenwave + Date: Fri Sep 1 09:29:01 2023 +0200 + + [class.copy.elision] improve reference and replace informal term + + commit 4feefb62e0419bb52c678389163729959785d44a + Author: Jan Schultke + Date: Wed Nov 8 02:59:01 2023 +0100 + + [mem.res.pool.options] Change "field" to "member" (#6479) + + commit a700e3b87b00d2673b3cded0a61201d09dfc051a + Author: S. B. Tam + Date: Wed Nov 8 10:01:46 2023 +0800 + + [version.syn] Bump value of __cpp_lib_constexpr_complex (#6421) + + P1383R2 "More constexpr for and " modifies two headers; + both __cpp_lib_constexpr_cmath and __cpp_lib_constexpr_complex should be updated. + + This aligns with existing practice in SD6. + + commit e9fb04e1c1e67bfb07bf3c61145b9d63a0f0adcf + Author: Arthur O'Dwyer + Date: Tue Sep 27 15:36:08 2022 -0400 + + [dcl.enum] Enumerators don't have "initializers" + + commit bc3cb41a36dfff0d2358f4e294be9636590e680e + Author: Krystian Stasiowski + Date: Tue Nov 7 21:08:15 2023 -0500 + + [dcl.name] Turn informative wording into note (#3964) + + commit 82b2ba6f6245e717cb002a9a836117a918aab36a + Author: Patrick Johnston + Date: Wed Nov 8 02:10:58 2023 +0000 + + [streambuf.general] Remove incorrect "abstract" + + The referenced class template `basic_streambuf` is not abstract. + + commit bbaa4a497e03d944fc38279db4d8c47eed7831d9 + Author: Jan Schultke + Date: Thu Oct 12 20:51:57 2023 +0200 + + [basic.lval] turn reference paragraph into note + + commit a03b8b70d6666b67d27c801b68d41683e987e929 + Author: Alisdair Meredith + Date: Thu Oct 5 15:27:29 2023 -0400 + + [temp.param] Introduce term to xref structural type + + The current cross-references to [temp.param] appear confusing, + as the structural type definition is buried a couple of pages + below. Also, this change looks clearer in the source. + + commit 71ee18ab8cd9efca0d8afa1f6e639cb02610a52b + Author: Alisdair Meredith + Date: Tue Nov 7 16:18:40 2023 -1000 + + [basic.types.general] Introduce term to xref implicit-lifetime type (#6591) + + commit 21454c7ebf67a1a723b61c32901a842c684e6b94 + Author: Language Lawyer + Date: Wed Aug 23 01:35:22 2023 +0500 + + [intro.races] Make reading atomic objects nondeterministic + + commit df26017a6bfd74d794345ea9313eae1efacbf7c9 + Author: Jan Schultke + Date: Wed Nov 8 03:31:10 2023 +0100 + + [diff.dcl] Replace 'field initializers' with 'member initializers' (#6482) + + commit cc69fc0dd6b1a2fdc834bade578acb84cc7d2cfa + Author: A. Jiang + Date: Wed Nov 8 10:54:52 2023 +0800 + + [intro.races] Remove inappropriate uses of "shall" (#6457) + + commit 60e280391a06b8d27f778a56310b0827109623aa + Author: Eisenwave + Date: Thu Aug 31 00:19:24 2023 +0200 + + [cmath.syn] fix misaligned parameter lists + + commit 646bfb2a060e3c7f490f6c4672ee93a0cbaf6d0d + Author: Alisdair Meredith + Date: Wed Nov 8 05:59:28 2023 -1000 + + [container.alloc.reqmts] Better xrefs for allocator-aware containers + + There are now more allocator-aware containers in the standard + than when this subclause was first written, so ensure we have + call outs to all relevent subclauses. + + The current wording for 'basic_stacktrace' also shows how + containers can properly call out the allocator-aware container + requirements, now that they have their own, titled subclause. + + commit 62e33ca8a0a55764227e6a67c1f554783ffefe40 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Thu Nov 9 00:01:38 2023 +0800 + + [time.zone.leap.overview] Fix example (#6383) + + commit 07ae51af31587ac533b1b39c95777ecb725dcab0 + Author: A. Jiang + Date: Wed Jan 25 18:22:53 2023 +0800 + + [expr.prim.req.general] Correct the IFNDR example + + commit f3059744c84f561f8ead4c5d117bc1160c43b7e2 + Author: Jonathan Wakely + Date: Wed Nov 8 23:52:44 2023 +0000 + + [defns.character.container] Improve note to entry (#6644) + + commit 8b38857b22f6518a41e506e4c9b2e9a1792a0fbd + Author: A. Jiang + Date: Tue Oct 10 09:40:20 2023 +0800 + + [iterator.requirements.general] Clarify non-forward iterator + + commit fbb1a6ebbd1f78e644df2dbcb3ce31250410779e + Author: onihusube <44743040+onihusube@users.noreply.github.com> + Date: Fri Nov 10 08:36:12 2023 +0900 + + [execpol.unseq] Fix missing \itemdescr (#5931) + + commit 10e2799f5d524dd941d424dfd08927c77a6b87f1 + Author: Alisdair Meredith + Date: Fri Feb 17 10:47:28 2023 -0500 + + [pairs.pair] Consistent wording for assignment + + Apply a consistent pattern to how we specify assigning members in assignment operators. + + commit 78300aa38c23f1356dca8e786205e5aaf7769d01 + Author: Barry Revzin + Date: Thu Nov 9 14:45:17 2023 -1000 + + [class.compare] Don't introduce `V` for the return value (#6035) + + In both cases, I'm not sure introducing `V` helps much - just requires name lookup for `V`. If we just say "the return value" in every case, I think that's clearer. + + commit 838cb0649b1f4061e960772aee3563cedb20b108 + Author: Michael Florian Hava + Date: Thu Nov 9 13:51:58 2023 -1000 + + [basic.extended.fp] Replaced usage of 'mantissa' with 'significand' + according to SO/IEC/IEEE 60559:2008 + + commit ce5ef1b5334f1fc756d40e40ec300257b0ff99d9 + Author: Michael Florian Hava + Date: Thu Nov 9 13:57:32 2023 -1000 + + [numeric.limits.members] Replaced usage of 'mantissa' with 'significand' according to + SO/IEC/IEEE 60559:2008 + + commit 3e1f377a9dc3bece7acd2dddb7237065504db65c + Author: Brian Bi + Date: Thu Nov 9 16:00:22 2023 -1000 + + [macros, styles] Add \hypertarget to headings (#6516) + + This allows forming URLs with a stable label as a fragment and + have PDF viewers jump to the corresponding (sub)clause. + + For example: std.pdf#basic.life + + commit 60f7bb72cdd36e9d359fa7aea84a5b836079a0ed + Author: Eisenwave + Date: Thu Jul 6 13:41:56 2023 +0200 + + [namespace.std] convert (a) and (b) notation to items + + commit f48f316c42c6cb67058d9f9106852154497b4516 + Author: Jan Schultke + Date: Fri Nov 10 06:57:17 2023 +0100 + + [atomics.order] Use "recommended practice" (#6380) + + commit 1ec1d9e6fa98734b3edf20f6c2217a4482f78103 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Fri Nov 10 16:59:21 2023 +0800 + + [meta.{unary.prop.query,trans.arr] Use `static_assert` instead of `assert` in example + + commit bd8f4540720e52dab9187a62c5598e735aeacfdd + Author: Eisenwave + Date: Sat Aug 19 15:57:39 2023 +0200 + + [expr.sizeof] use constexpr member in example + + commit b1f922a126dcda78acb4bae055843e7a7321fe1d + Author: Eisenwave + Date: Wed Aug 23 13:42:39 2023 +0200 + + [basic.def.odr] Fix hyphenation of "{copy,move} assignment" + + commit 54e465a17adfcba56a57ff2fefe43ec898725efb + Author: Eisenwave + Date: Wed Aug 23 13:43:46 2023 +0200 + + [res.on.arguments] Fix hyphenation of "move assignment" + + commit 3c5b5b0c58d0440233d992e1a0791a449936f203 + Author: Eisenwave + Date: Wed Aug 23 13:44:40 2023 +0200 + + [futures.{unique,shared}.future] Fix hyphenation of "{copy,move} assignment" + + commit 9483cb7cf6973689ad563d30778d8da2dff42a8d + Author: Jonathan Wakely + Date: Wed Nov 8 22:57:57 2023 +0000 + + [string.capacity] Remove parentheses from "reserve()" + + It's very confusing to talk about `reserve()` when describing a call to + `reserve(size_type)`, given that the overload `reserve()` also exists. + + commit 2a9f28670a0df6e239d9b335bdb014f20f577732 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Jul 24 16:19:01 2023 +0000 + + [dcl.meaning.general] Use 'declarator-id' instead of 'name' + + commit d8b72f0ceb36b3537ef576ab216d588642e332ab + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Jul 25 18:26:03 2023 +0000 + + [module.global.frag] Simplify wording + + Also make variable order consistent across bullets. + + commit f0c172c5604b47c3ecc7b64669aad660df403624 + Author: Oliver Rosten + Date: Fri Nov 10 18:12:06 2023 +0000 + + [algorithms] Change stable label "mismatch" to "alg.mismatch" (#6653) + + commit d97603a90d2fcfeec2caf4371ca9e6c8f562842a + Author: A. Jiang + Date: Sat Nov 11 03:21:17 2023 +0800 + + [forward.iterators] Use "Cpp17" requirement (#6612) + + commit f474227b69d10350999a5fc63503725421a89954 + Author: Geng Cheng + Date: Sat Nov 11 10:25:39 2023 +0800 + + [stringstream.general] Add missing template argument "Allocator" (#6560) + + commit f5fdfe453e5a1e0370f2cb28bfc2dfeecab6370e + Author: Alisdair Meredith + Date: Wed Nov 8 15:12:16 2023 -1000 + + [diff.cpp20.library] Add missing new headers for C++23 + + commit 38dfe3db0f08bd09a2b445ba82e83f7caae28d94 + Author: A. Jiang + Date: Thu Nov 9 11:00:44 2023 +0800 + + [dcl.init.ref] Clarify "related type" + + "Related type" is not a term, "reference-related type" is clearer. + + commit 979983929bb592c02c9ae3e52f1c676dd5ae06fe + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Tue Nov 14 02:27:01 2023 +0800 + + [range.cartesian.view] Don't name unused template parameter (#6177) + + commit ecbeb5ad4e4c0ac1d0cdb5e8dd01daab8df8d62e + Author: Alisdair Meredith + Date: Tue Nov 14 14:27:27 2023 -0500 + + [diff.cpp23.library] Entry for new headers in C++26 (#6648) + + commit eb7f0bcbff2af109643089ef36dfe67040a27f4a + Author: Thomas Köppe + Date: Mon Nov 13 01:12:50 2023 -1000 + + [intro.defs, macros] Add cross-references among definitions + + Fixes ISO/CS 017 (C++23 DIS). + + commit 706880e4ed855ae76d503c70adfb0015bbfb3df0 + Author: Lewis Baker + Date: Thu Nov 16 10:36:25 2023 +1030 + + [allocator.requirements.general] Fix missing ellipsis (#6695) + + commit 5c0103c0a656cbcd725780388b0879e992a1b21a + Author: Jonathan Wakely + Date: Thu Nov 16 15:38:47 2023 +0000 + + [stacktrace.format], [stacktrace.basic.hash] change rSec3 to rSec2 + + These should not be nested below std::basic_stacktrace because they + apply to both std::stacktrace_entry and std::basic_stacktrace. + + commit a6ad6083ab75901cb41b5bc8d034c0b322433457 + Author: Thomas Köppe + Date: Tue Dec 5 23:42:23 2023 +0000 + + [std, styles] Adjust table captions as per ISO request + + ISO has asked for captions to be bold and table numbers to be + separated by a dash. + + commit f519ea4aa97592703ba5bbe9164242d946723721 + Author: Jens Maurer + Date: Thu Dec 7 01:00:53 2023 +0100 + + [intro.refs, time.format] Update references from ISO 8601:2004 to ISO 8601-1:2019 (#6720) + + commit 37956fb3685c2c279bd6b4b701964b20913d0c79 + Author: Thomas Köppe + Date: Wed Dec 6 19:01:29 2023 +0000 + + [syntax] Change "italic" to "italic, sans-serif" + + We changed the grammar non-terminal font to sans-serif, + so we should update the description. + + commit 4eed7a0f1e44c45554f8a210af34fd6e1ea19596 + Author: Jens Maurer + Date: Thu Dec 7 22:13:35 2023 +0100 + + [intro.abstract] Actually use the phrase 'unspecified/undefined behavior' + + Fixes ISO/CS 011 (C++23 DIS). + + commit f8a6138da1e431779ac43a893faa32f3f0cad7d0 + Author: Thomas Köppe + Date: Thu Dec 7 12:45:11 2023 +0000 + + [intro.defs] Fix introductory text according to ISO rules. + + In principle, "symbols and abbreviated terms" can be listed in a + standard, and can be listed in a separate clause or in a combined + clause 3 "Terms, definitions, symbols and abbreviated terms", we do + not actually need symbol definitions. In any case, the introductory + text would never mention "symbols". + + commit 9961cd4f16aca645c77d6927526ea71f635a2932 + Author: Thomas Köppe + Date: Thu Dec 7 00:01:48 2023 +0000 + + [introduction] A minimal "Introduction" clause + + This clause explains our conventions regarding stable labels and + choice of fonts. + + commit 9041b27206388fecd03073bb913185ac738c6dca + Author: Thomas Köppe + Date: Mon Dec 18 00:57:45 2023 +0000 + + [optional.monaic] Restore wording effected by LWG3973. + + Both LWG3973 (Motion 1) and P2407R5 (Motion 3) modified this wording: + LWG3973 changes "value()" to "*val" to address ADL concerns, and + P2407R5 changed "value()" to "**this" to be freestanding. In light of + the former, the latter should also use "*val". + + Independently, additional problems have been discovered with LWG3973, + but those will be addressed by a future LWG issue. + + commit 2b1867a3404562c4261722e0a913cbcbf5a0a476 + Author: Thomas Köppe + Date: Sun Dec 17 23:10:44 2023 +0000 + + [version.syn] New feature test macro __cpp_lib_freestanding_numeric + + This macro indicates that freestanding support for "saturation + arithmetic" is available, which was added in motion LWG-2 (via + P0543R3). This reverts the previous change + 148e03a16d53ff8cffd219384df37efad5fd386d, which I had made subsequent + to motion LWG-3 (P2407R5), on advice of LWG. A separate macro is + preferable to mixing both headers under "algorithm". + + commit fa54f9e7306b3d0abb21a82b5cc951711c96161f + Author: Jonathan Wakely + Date: Wed Dec 13 11:03:18 2023 +0000 + + [range.access.general] Use consistent "In addition to being available ..." form + + Elsewhere we say "the header" or "any of the headers", e.g. [meta.trans.other], + [tuple.helper], etc. + + commit 8c611593555b93a45a13543ad265d8cfaf646932 + Author: Cassio Neri + Date: Mon Nov 27 19:47:29 2023 +0000 + + [expected.general] Fix description of expected (issue #6714.) + + commit 12565ed5ea083761b25df3c8325989f95fa04898 + Author: Po-yao Chang + Date: Wed Nov 22 23:02:49 2023 +0800 + + [class.eq] Fix the return value of a defaulted == operator function 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/wd-index.md b/papers/wd-index.md index 5d6a4f75a1..92100a86b8 100644 --- a/papers/wd-index.md +++ b/papers/wd-index.md @@ -41,4 +41,16 @@ * [N4892](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4892.pdf) 2021-06 C++ Working Draft * [N4901](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4901.pdf) 2021-10 C++ Working Draft * [N4910](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4910.pdf) 2022-03 C++ Working Draft - * [N4910](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4917.pdf) 2022-07 C++ Working Draft + * [N4917](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4917.pdf) 2022-07 C++ Working Draft + * [N4928](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4928.pdf) 2022-11 C++ Working Draft + * [N4944](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4944.pdf) 2023-02 C++ Working Draft + * [N4950](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf) 2023-05 C++ Working Draft + * [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 02f990cd01..d4a2ff4064 100644 --- a/source/Makefile +++ b/source/Makefile @@ -1,4 +1,5 @@ -FIGURES=$(patsubst %.dot,%.pdf,$(wildcard *.dot)) +FIGURES=$(patsubst %.dot,%.pdf,$(wildcard assets/*.dot)) +EXAMPLES=$(patsubst %.tex,%.pdf,$(wildcard assets/*.tex)) default: full @@ -15,9 +16,17 @@ quiet: latexmk -pdf std -e '$$max_repeat = 1;' -silent || ( rm std.pdf; latexmk -pdf std -e '$$max_repeat = 4;' ) %.pdf: %.dot - dot -o $@ -Tpdf $< + dot -o $@ -Tpdf $< -Nfontname=NewComputerModernSans10 clean-figures: rm -f $(FIGURES) figures: $(FIGURES) + +%.pdf: %.tex + lualatex -output-directory assets $< + +clean-examples: + rm -f $(EXAMPLES) + +examples: $(EXAMPLES) diff --git a/source/algorithms.tex b/source/algorithms.tex index 1a4d627698..4c85cac4da 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, @@ -151,14 +133,14 @@ whenever an algorithm expects a function object\iref{function.objects} that, when applied to the result of dereferencing the corresponding iterator, returns a value testable as \tcode{true}. -In other words, -if an algorithm takes \tcode{Predicate pred} as its argument and +If an algorithm takes \tcode{Predicate pred} as its argument and \tcode{first} as its iterator argument with value type \tcode{T}, -it should work correctly in the construct -\tcode{pred(*first)} contextually converted to \tcode{bool}\iref{conv}. +the expression \tcode{pred(*first)} shall be well-formed and +the type \tcode{decltype(pred(*first))} shall model +\exposconcept{boolean-testable}\iref{concept.booleantestable}. The function object \tcode{pred} shall not apply any non-constant function -through the dereferenced iterator. -Given a glvalue \tcode{u} of type (possibly \keyword{const}) \tcode{T} +through its argument. +Given a glvalue \tcode{u} of type (possibly const) \tcode{T} that designates the same object as \tcode{*first}, \tcode{pred(u)} shall be a valid expression that is equal to \tcode{pred(*first)}. @@ -170,22 +152,24 @@ to dereferencing an iterator and type \tcode{T} when \tcode{T} is part of the signature, returns a value testable as \tcode{true}. -In other words, -if an algorithm takes \tcode{BinaryPredicate binary_pred} as its argument and +If an algorithm takes \tcode{BinaryPredicate binary_pred} as its argument and \tcode{first1} and \tcode{first2} as its iterator arguments with respective value types \tcode{T1} and \tcode{T2}, -it should work correctly in the construct -\tcode{binary_pred(*first1, *first2)} contextually converted to \tcode{bool}\iref{conv}. +the expression \tcode{binary_pred(*first1, *first2)} shall be well-formed and +the type \tcode{decltype(binary_pred(*first1, *first2))} shall model +\exposconcept{boolean-testable}. Unless otherwise specified, \tcode{BinaryPredicate} always takes the first iterator's \tcode{value_type} as its first argument, that is, in those cases when \tcode{T value} -is part of the signature, it should work correctly in the construct -\tcode{binary_pred(*first1, value)} contextually converted to \tcode{bool}\iref{conv}. +is part of the signature, +the expression \tcode{binary_pred(*first1, value)} shall be well-formed and +the type \tcode{decltype(binary_pred(*first1, value))} shall model +\exposconcept{boolean-testable}. \tcode{binary_pred} shall not apply any non-constant function -through the dereferenced iterators. -Given a glvalue \tcode{u} of type (possibly \keyword{const}) \tcode{T1} +through any of its arguments. +Given a glvalue \tcode{u} of type (possibly const) \tcode{T1} that designates the same object as \tcode{*first1}, and -a glvalue \tcode{v} of type (possibly \keyword{const}) \tcode{T2} +a glvalue \tcode{v} of type (possibly const) \tcode{T2} that designates the same object as \tcode{*first2}, \tcode{binary_pred(u, *first2)}, \tcode{binary_pred(*first1, v)}, and @@ -295,7 +279,7 @@ by invoking the following functions: \begin{itemize} \item - All operations of the categories of the iterators + All operations of the categories of the iterators or \tcode{mdspan} types that the algorithm is instantiated with. \item Operations on those sequence elements that are required by its specification. @@ -310,6 +294,8 @@ \end{note} \end{itemize} These functions are herein called \defn{element access functions}. + +\pnum \begin{example} The \tcode{sort} function may invoke the following element access functions: \begin{itemize} @@ -344,7 +330,7 @@ int a[] = {1,2}; std::for_each(std::execution::par_unseq, std::begin(a), std::end(a), [&](int) { std::lock_guard guard(m); // incorrect: \tcode{lock_guard} constructor calls \tcode{m.lock()} - ++x; + ++x; }); } \end{codeblock} @@ -365,7 +351,8 @@ \tcode{UnaryOperation}, \tcode{BinaryOperation}, \tcode{BinaryOperation1}, -\tcode{BinaryOperation2}, and +\tcode{BinaryOperation2}, +\tcode{BinaryDivideOp}, 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) @@ -434,7 +421,7 @@ The behavior of a program is undefined if it invokes a vectorization-unsafe standard library function from user code -called from a \tcode{execution::unsequenced_policy} algorithm. +called from an \tcode{execution::unsequenced_policy} algorithm. \begin{note} Because \tcode{execution::unsequenced_policy} allows the execution of element access functions @@ -521,7 +508,7 @@ The behavior of a program is undefined if it invokes a vectorization-unsafe standard library function from user code -called from a \tcode{execution::parallel_unsequenced_policy} algorithm. +called from an \tcode{execution::parallel_unsequenced_policy} algorithm. \begin{note} Because \tcode{execution::parallel_unsequenced_policy} allows the execution of element access functions @@ -614,10 +601,178 @@ Parallel algorithms shall not participate in overload resolution unless \tcode{is_execution_policy_v>} is \tcode{true}. +\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 { @\seebelow@ }; +\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 { @@ -656,7 +811,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 { @@ -672,7 +827,7 @@ 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 { @@ -688,7 +843,7 @@ 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 { @@ -702,10 +857,12 @@ // \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 = {}); @@ -727,7 +884,7 @@ 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 { @@ -747,7 +904,7 @@ 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 { @@ -761,33 +918,36 @@ } // \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 @@ -843,13 +1003,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); @@ -881,13 +1041,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); @@ -916,11 +1076,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); @@ -938,27 +1098,30 @@ } // \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 @@ -973,7 +1136,7 @@ count_if(R&& r, Pred pred, Proj proj = {}); } - // \ref{mismatch}, mismatch + // \ref{alg.mismatch}, mismatch template constexpr pair mismatch(InputIterator1 first1, InputIterator1 last1, @@ -993,24 +1156,24 @@ 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); @@ -1048,21 +1211,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); @@ -1108,7 +1271,7 @@ class Proj1 = identity, class Proj2 = identity, @\libconcept{indirect_equivalence_relation}@, Proj1>, projected, Proj2>> - Pred = ranges::equal_to> + Pred = ranges::equal_to> constexpr bool is_permutation(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } @@ -1125,13 +1288,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); @@ -1152,36 +1315,40 @@ Proj1 proj1 = {}, Proj2 proj2 = {}); } - 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, @@ -1250,11 +1417,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, @@ -1266,18 +1434,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, - @\exposconcept{indirectly-binary-right-foldable}@ F> + 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, - @\exposconcept{indirectly-binary-right-foldable}@> F> + 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> + @\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> @@ -1289,11 +1457,12 @@ template using fold_left_first_with_iter_result = in_value_result; - 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 @\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, @@ -1313,7 +1482,7 @@ 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); @@ -1336,7 +1505,7 @@ 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); @@ -1355,7 +1524,7 @@ 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); @@ -1400,7 +1569,7 @@ 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); @@ -1442,7 +1611,7 @@ 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); @@ -1477,13 +1646,13 @@ 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); @@ -1510,14 +1679,14 @@ @\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 = {}); @@ -1527,35 +1696,41 @@ 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<@\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 @@ -1567,17 +1742,18 @@ 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); @@ -1586,18 +1762,21 @@ template using 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 = {}); @@ -1605,39 +1784,44 @@ template using 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 = {}); } // \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); + 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); } @@ -1646,13 +1830,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 { @@ -1668,26 +1852,29 @@ } // \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*> @@ -1703,14 +1890,15 @@ remove_if(R&& r, Pred pred, Proj proj = {}); } - 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 @@ -1720,7 +1908,7 @@ 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); @@ -1728,13 +1916,14 @@ template using 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*> @@ -1763,10 +1952,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); @@ -1791,13 +1980,13 @@ 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); @@ -1827,7 +2016,7 @@ 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 { @@ -1845,7 +2034,7 @@ 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); @@ -1869,7 +2058,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); @@ -1888,7 +2077,7 @@ 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); @@ -1951,7 +2140,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); @@ -1969,7 +2158,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); @@ -1989,10 +2178,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); @@ -2009,15 +2198,15 @@ } template - void stable_sort(RandomAccessIterator first, RandomAccessIterator last); + constexpr void stable_sort(RandomAccessIterator first, RandomAccessIterator last); // hosted template - 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); @@ -2025,11 +2214,11 @@ template<@\libconcept{random_access_iterator}@ I, @\libconcept{sentinel_for}@ S, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@ - 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> - borrowed_iterator_t - stable_sort(R&& r, Comp comp = {}, Proj proj = {}); + constexpr borrowed_iterator_t + stable_sort(R&& r, Comp comp = {}, Proj proj = {}); // hosted } template @@ -2039,11 +2228,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); @@ -2073,14 +2262,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, @@ -2115,10 +2304,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); @@ -2140,11 +2329,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); @@ -2166,11 +2355,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); @@ -2187,83 +2376,95 @@ } // \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 = {}, @@ -2274,7 +2475,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 { @@ -2291,7 +2492,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); @@ -2309,12 +2510,12 @@ } template - BidirectionalIterator stable_partition(BidirectionalIterator first, - BidirectionalIterator last, - Predicate pred); + 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); @@ -2322,11 +2523,13 @@ template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{permutable}@ - 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}@> - 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 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); @@ -2393,14 +2596,14 @@ 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); @@ -2425,20 +2628,20 @@ } template - void inplace_merge(BidirectionalIterator first, - BidirectionalIterator middle, - BidirectionalIterator last); + constexpr void inplace_merge(BidirectionalIterator first, // hosted + BidirectionalIterator middle, + BidirectionalIterator last); template - void inplace_merge(BidirectionalIterator first, - BidirectionalIterator middle, - BidirectionalIterator last, Compare comp); + 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); @@ -2447,12 +2650,12 @@ template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@ - 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> - borrowed_iterator_t - inplace_merge(R&& r, iterator_t middle, Comp comp = {}, - Proj proj = {}); + constexpr borrowed_iterator_t + inplace_merge(R&& r, iterator_t middle, Comp comp = {}, Proj proj = {}); // hosted } // \ref{alg.set.operations}, set operations @@ -2464,12 +2667,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); @@ -2496,20 +2699,20 @@ 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); @@ -2546,14 +2749,14 @@ 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); @@ -2590,14 +2793,14 @@ 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); @@ -2634,14 +2837,14 @@ 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); @@ -2746,10 +2949,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); @@ -2771,11 +2974,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); @@ -2867,10 +3070,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); @@ -2890,10 +3093,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); @@ -2915,11 +3118,11 @@ 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 { @@ -2961,13 +3164,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); @@ -3358,10 +3561,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} @@ -3638,10 +3842,11 @@ \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); @@ -3660,10 +3865,11 @@ 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 = {}); @@ -3711,10 +3917,12 @@ \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<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @@ -3908,7 +4116,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} @@ -3977,10 +4185,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); @@ -3993,11 +4202,12 @@ 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 = {}); @@ -4040,7 +4250,7 @@ of the corresponding predicate and any projection. \end{itemdescr} -\rSec2[mismatch]{Mismatch} +\rSec2[alg.mismatch]{Mismatch} \indexlibraryglobal{mismatch}% \begin{itemdecl} @@ -4346,7 +4556,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, @@ -4399,7 +4609,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: @@ -4437,7 +4647,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 @@ -4457,23 +4667,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, @@ -4489,12 +4701,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 @@ -4504,14 +4720,15 @@ \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, @@ -4522,7 +4739,7 @@ \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)}. @@ -4622,7 +4839,8 @@ \returns \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} @@ -4630,9 +4848,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} @@ -4665,10 +4885,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} @@ -4720,10 +4940,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} @@ -4841,7 +5062,7 @@ \indexlibraryglobal{copy}% \begin{itemdecl} template - ForwardIterator2 copy(ExecutionPolicy&& policy, + ForwardIterator2 copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); \end{itemdecl} @@ -5104,7 +5325,7 @@ \indexlibrary{\idxcode{move}!algorithm}% \begin{itemdecl} template - ForwardIterator2 move(ExecutionPolicy&& policy, + ForwardIterator2 move(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); \end{itemdecl} @@ -5327,14 +5548,14 @@ @\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 = {}); @@ -5419,37 +5640,43 @@ \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<@\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 @@ -5515,30 +5742,32 @@ 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<@\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 = {}); @@ -5601,23 +5830,28 @@ \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); \end{itemdecl} @@ -5706,10 +5940,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); @@ -5722,10 +5957,12 @@ 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 @@ -5791,12 +6028,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, @@ -5813,13 +6051,14 @@ 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> @@ -5932,7 +6171,7 @@ \pnum \expects -For the overloads in namepace \tcode{std}, +For the overloads in namespace \tcode{std}, \tcode{pred} is an equivalence relation and the type of \tcode{*first} meets the \oldconcept{MoveAssignable} requirements (\tref{cpp17.moveassignable}). @@ -6024,7 +6263,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 + (last - first)} do not overlap. \item For the overloads in namespace \tcode{std}: @@ -6293,7 +6532,7 @@ \effects Equivalent to: \begin{codeblock} -return ranges::rotate_copy(ranges::begin(r), middle, ranges::end(r), result); +return ranges::rotate_copy(ranges::begin(r), middle, ranges::end(r), std::move(result)); \end{codeblock} \end{itemdescr} @@ -6525,7 +6764,7 @@ 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} @@ -6569,7 +6808,7 @@ named \tcode{BinaryPredicate}~\iref{algorithms.requirements}. The return value of the function call operation applied to an object of type \tcode{Compare}, -when contextually converted to \tcode{bool}\iref{conv}, +when converted to \tcode{bool}, yields \tcode{true} if the first argument of the call is less than the second, and \tcode{false} otherwise. @@ -6712,14 +6951,14 @@ \indexlibraryglobal{stable_sort}% \begin{itemdecl} template - void stable_sort(RandomAccessIterator first, RandomAccessIterator last); + constexpr void stable_sort(RandomAccessIterator first, RandomAccessIterator last); template void stable_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last); template - void stable_sort(RandomAccessIterator first, RandomAccessIterator last, - Compare comp); + constexpr void stable_sort(RandomAccessIterator first, RandomAccessIterator last, + Compare comp); template void stable_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, @@ -6728,10 +6967,10 @@ template<@\libconcept{random_access_iterator}@ I, @\libconcept{sentinel_for}@ S, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@ - I ranges::stable_sort(I first, S last, Comp comp = {}, Proj proj = {}); + constexpr I ranges::stable_sort(I first, S last, Comp comp = {}, Proj proj = {}); template<@\libconcept{random_access_range}@ R, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@, Comp, Proj> - borrowed_iterator_t + constexpr borrowed_iterator_t ranges::stable_sort(R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} @@ -7191,21 +7430,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 @@ -7239,20 +7481,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 @@ -7286,22 +7531,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 @@ -7320,7 +7568,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}. @@ -7351,21 +7599,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 = {}, @@ -7384,7 +7635,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}. @@ -7510,7 +7761,8 @@ \begin{itemdecl} template BidirectionalIterator - stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred); + constexpr stable_partition(BidirectionalIterator first, BidirectionalIterator last, + Predicate pred); template BidirectionalIterator stable_partition(ExecutionPolicy&& exec, @@ -7519,11 +7771,11 @@ template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{permutable}@ - subrange ranges::stable_partition(I first, S last, Pred pred, Proj proj = {}); + constexpr subrange ranges::stable_partition(I first, S last, Pred pred, Proj proj = {}); template<@\libconcept{bidirectional_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{permutable}@> - borrowed_subrange_t ranges::stable_partition(R&& r, Pred pred, Proj proj = {}); + constexpr borrowed_subrange_t ranges::stable_partition(R&& r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -7790,9 +8042,9 @@ \indexlibraryglobal{inplace_merge}% \begin{itemdecl} template - void inplace_merge(BidirectionalIterator first, - BidirectionalIterator middle, - BidirectionalIterator last); + constexpr void inplace_merge(BidirectionalIterator first, + BidirectionalIterator middle, + BidirectionalIterator last); template void inplace_merge(ExecutionPolicy&& exec, BidirectionalIterator first, @@ -7800,9 +8052,9 @@ BidirectionalIterator last); template - void inplace_merge(BidirectionalIterator first, - BidirectionalIterator middle, - BidirectionalIterator last, Compare comp); + constexpr void inplace_merge(BidirectionalIterator first, + BidirectionalIterator middle, + BidirectionalIterator last, Compare comp); template void inplace_merge(ExecutionPolicy&& exec, BidirectionalIterator first, @@ -7812,7 +8064,7 @@ template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@ - I ranges::inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); + constexpr I ranges::inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -7849,7 +8101,7 @@ \begin{itemize} \item For the overloads with no \tcode{ExecutionPolicy}, and - if enough additional memory is available, exactly $N - 1$ comparisons. + if enough additional memory is available, at most $N - 1$ comparisons. \item Otherwise, \bigoh{N \log N} comparisons. \end{itemize} @@ -7863,7 +8115,7 @@ \begin{itemdecl} template<@\libconcept{bidirectional_range}@ R, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@, Comp, Proj> - borrowed_iterator_t + constexpr borrowed_iterator_t ranges::inplace_merge(R&& r, iterator_t middle, Comp comp = {}, Proj proj = {}); \end{itemdecl} @@ -8396,6 +8648,8 @@ The range \range{first}{last - 1} is a valid heap with respect to \tcode{comp} and \tcode{proj}. For the overloads in namespace \tcode{std}, +\tcode{RandomAccessIterator} meets +the \oldconcept{ValueSwappable} requirements\iref{swappable.requirements} and the type of \tcode{*first} meets the \oldconcept{MoveConstructible} requirements (\tref{cpp17.moveconstructible}) and the \oldconcept{MoveAssignable} requirements (\tref{cpp17.moveassignable}). @@ -8503,8 +8757,10 @@ \pnum \expects For the overloads in namespace \tcode{std}, +\tcode{RandomAccessIterator} meets +the \oldconcept{ValueSwap\-pable} requirements\iref{swappable.requirements} and the type of \tcode{*first} meets -the \oldconcept{Move\-Constructible} (\tref{cpp17.moveconstructible}) and +the \oldconcept{MoveConstructible} (\tref{cpp17.moveconstructible}) and \oldconcept{MoveAssignable} (\tref{cpp17.moveassignable}) requirements. \pnum @@ -9200,7 +9456,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; } @@ -9388,6 +9644,7 @@ \indexheader{numeric}% \begin{codeblock} +// mostly freestanding namespace std { // \ref{accumulate}, accumulate template @@ -9407,13 +9664,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 @@ -9441,19 +9698,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); @@ -9478,13 +9735,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); @@ -9503,19 +9760,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); @@ -9529,7 +9786,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); @@ -9550,14 +9807,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); @@ -9573,13 +9830,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); @@ -9612,6 +9869,18 @@ constexpr T midpoint(T a, T b) noexcept; template constexpr T* midpoint(T* a, T* b); + + // \ref{numeric.sat}, saturation arithmetic + template + constexpr T add_sat(T x, T y) noexcept; + template + constexpr T sub_sat(T x, T y) noexcept; + template + constexpr T mul_sat(T x, T y) noexcept; + template + constexpr T div_sat(T x, T y) noexcept; + template + constexpr T saturate_cast(U x) noexcept; } \end{codeblock} @@ -10553,7 +10822,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 @@ -10746,6 +11015,117 @@ where the result of the division is truncated towards zero. \end{itemdescr} +\rSec2[numeric.sat]{Saturation arithmetic} + +\rSec3[numeric.sat.func]{Arithmetic functions} + +\pnum +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. + +\indexlibraryglobal{add_sat}% +\begin{itemdecl} +template + constexpr T add_sat(T x, T y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a signed or unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +If $\tcode{x} + \tcode{y}$ is representable as a value of type \tcode{T}, $\tcode{x} + \tcode{y}$; +otherwise, either the largest or smallest representable value of type \tcode{T}, +whichever is closer to the value of $\tcode{x} + \tcode{y}$. +\end{itemdescr} + +\indexlibraryglobal{sub_sat}% +\begin{itemdecl} +template + constexpr T sub_sat(T x, T y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a signed or unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +If $\tcode{x} - \tcode{y}$ is representable as a value of type \tcode{T}, $\tcode{x} - \tcode{y}$; +otherwise, either the largest or smallest representable value of type \tcode{T}, +whichever is closer to the value of $\tcode{x} - \tcode{y}$. +\end{itemdescr} + +\indexlibraryglobal{mul_sat}% +\begin{itemdecl} +template + constexpr T mul_sat(T x, T y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a signed or unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +If $\tcode{x} \times \tcode{y}$ is representable as a value of type \tcode{T}, $\tcode{x} \times \tcode{y}$; +otherwise, either the largest or smallest representable value of type \tcode{T}, +whichever is closer to the value of $\tcode{x} \times \tcode{y}$. +\end{itemdescr} + +\indexlibraryglobal{div_sat}% +\begin{itemdecl} +template + constexpr T div_sat(T x, T y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a signed or unsigned integer type\iref{basic.fundamental}. + +\pnum +\expects +\tcode{y != 0} is \tcode{true}. + +\pnum +\returns +If \tcode{T} is a signed integer type +and \tcode{x == numeric_limits::min() \&\& y == -1} is \tcode{true}, +\tcode{numeric_limits::max()}, otherwise, \tcode{x / y}. + +\pnum +\remarks +A function call expression +that violates the precondition in the \Fundescx{Preconditions} element +is not a core constant expression\iref{expr.const}. +\end{itemdescr} + +\rSec3[numeric.sat.cast]{Casting} + +\indexlibraryglobal{saturate_cast}% +\begin{itemdecl} +template + constexpr R saturate_cast(T x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{R} and \tcode{T} are signed or unsigned integer types\iref{basic.fundamental}. + +\pnum +\returns +If \tcode{x} is representable as a value of type \tcode{R}, \tcode{x}; +otherwise, either the largest or smallest representable value of type \tcode{R}, +whichever is closer to the value of \tcode{x}. +\end{itemdescr} + \rSec1[specialized.algorithms]{Specialized \tcode{} algorithms} \rSec2[specialized.algorithms.general]{General} @@ -10763,19 +11143,28 @@ \pnum \begin{note} -When invoked on ranges of -potentially-overlapping subobjects\iref{intro.object}, -the algorithms specified in \ref{specialized.algorithms} -result in undefined behavior. +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 -\tcode{\placeholdernc{voidify}}: +Some algorithms specified in \ref{specialized.algorithms} +make use of the following exposition-only function templates: \begin{codeblock} template constexpr void* @\placeholdernc{voidify}@(T& obj) noexcept { - return const_cast(static_cast(addressof(obj))); + 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} @@ -10870,7 +11259,8 @@ \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} @@ -10889,10 +11279,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} @@ -10910,7 +11300,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} @@ -10930,7 +11321,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} @@ -10949,7 +11340,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} @@ -10968,10 +11360,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} @@ -10989,7 +11381,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} @@ -11009,7 +11402,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} @@ -11028,8 +11421,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} @@ -11041,7 +11434,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} @@ -11057,11 +11450,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} @@ -11084,8 +11477,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} @@ -11097,7 +11490,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} @@ -11112,7 +11505,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} @@ -11127,7 +11520,7 @@ \effects Equivalent to: \begin{codeblock} -auto t = uninitialized_copy(counted_iterator(ifirst, n), +auto t = uninitialized_copy(counted_iterator(std::move(ifirst), n), default_sentinel, ofirst, olast); return {std::move(t.in).base(), t.out}; \end{codeblock} @@ -11138,8 +11531,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} @@ -11153,7 +11546,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} @@ -11164,11 +11557,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} @@ -11198,7 +11591,7 @@ \indexlibraryglobal{uninitialized_move_n}% \begin{itemdecl} template - pair + constexpr pair uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result); \end{itemdecl} @@ -11211,9 +11604,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} @@ -11223,7 +11616,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} @@ -11237,7 +11630,7 @@ \effects Equivalent to: \begin{codeblock} -auto t = uninitialized_move(counted_iterator(ifirst, n), +auto t = uninitialized_move(counted_iterator(std::move(ifirst), n), default_sentinel, ofirst, olast); return {std::move(t.in).base(), t.out}; \end{codeblock} @@ -11255,7 +11648,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} @@ -11274,10 +11668,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} @@ -11295,7 +11689,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} @@ -11315,7 +11710,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} @@ -11344,14 +11739,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} @@ -11448,7 +11851,145 @@ \effects Equivalent to: \begin{codeblock} -return destroy(counted_iterator(first, n), default_sentinel).base(); +return destroy(counted_iterator(std::move(first), n), default_sentinel).base(); +\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} diff --git a/source/assets/example_01.pdf b/source/assets/example_01.pdf new file mode 100644 index 0000000000..2d4c06ffe4 Binary files /dev/null and b/source/assets/example_01.pdf differ diff --git a/source/assets/example_01.tex b/source/assets/example_01.tex new file mode 100644 index 0000000000..ffda6ec746 --- /dev/null +++ b/source/assets/example_01.tex @@ -0,0 +1,14 @@ +\documentclass[9pt]{standalone} + +\usepackage{fontspec} + +\setmainfont{NewCM10-Regular} +\setmonofont{NewCMMono10-Regular} + +\newfontfamily\notoemoji{Noto Color Emoji}[Renderer=HarfBuzz] + +\newcommand{\emo}[1]{{\notoemoji\raisebox{1pt}{\scriptsize #1}}} + +\begin{document} +\texttt{Спасибо, Виктор \emo{♥}!} +\end{document} diff --git a/source/assets/example_02.pdf b/source/assets/example_02.pdf new file mode 100644 index 0000000000..65a9fb12f9 Binary files /dev/null and b/source/assets/example_02.pdf differ diff --git a/source/assets/example_02.tex b/source/assets/example_02.tex new file mode 100644 index 0000000000..0b48a5aacc --- /dev/null +++ b/source/assets/example_02.tex @@ -0,0 +1,14 @@ +\documentclass[9pt]{standalone} + +\usepackage{fontspec} + +\setmainfont{NewCM10-Regular} +\setmonofont{NewCMMono10-Regular} + +\newfontfamily\notoemoji{Noto Color Emoji}[Renderer=HarfBuzz] + +\newcommand{\emo}[1]{{\notoemoji\scriptsize #1}} + +\begin{document} +\emo{🤷🏻‍♂️} +\end{document} diff --git a/source/assets/example_03.pdf b/source/assets/example_03.pdf new file mode 100644 index 0000000000..74f7bd263c Binary files /dev/null and b/source/assets/example_03.pdf differ diff --git a/source/assets/example_03.tex b/source/assets/example_03.tex new file mode 100644 index 0000000000..17479d4b6d --- /dev/null +++ b/source/assets/example_03.tex @@ -0,0 +1,14 @@ +\documentclass[9pt]{standalone} + +\usepackage{fontspec} + +\setmainfont{NewCM10-Regular} +\setmonofont{NewCMMono10-Regular} + +\newfontfamily\notoemoji{Noto Color Emoji}[Renderer=HarfBuzz] + +\newcommand{\emo}[1]{{\notoemoji\scriptsize #1}} + +\begin{document} +\emo{🤷} +\end{document} diff --git a/source/assets/example_04.pdf b/source/assets/example_04.pdf new file mode 100644 index 0000000000..b02c6214d2 Binary files /dev/null and b/source/assets/example_04.pdf differ diff --git a/source/assets/example_04.tex b/source/assets/example_04.tex new file mode 100644 index 0000000000..414cdf0822 --- /dev/null +++ b/source/assets/example_04.tex @@ -0,0 +1,14 @@ +\documentclass[9pt]{standalone} + +\usepackage{fontspec} + +\setmainfont{NewCM10-Regular} +\setmonofont{NewCMMono10-Regular} + +\newfontfamily\notoemoji{Noto Color Emoji}[Renderer=HarfBuzz] + +\newcommand{\emo}[1]{{\notoemoji\scriptsize #1}} + +\begin{document} +\emo{♂} +\end{document} diff --git a/source/assets/example_05.pdf b/source/assets/example_05.pdf new file mode 100644 index 0000000000..047d45a9b3 Binary files /dev/null and b/source/assets/example_05.pdf differ diff --git a/source/assets/example_05.tex b/source/assets/example_05.tex new file mode 100644 index 0000000000..109eb45f3f --- /dev/null +++ b/source/assets/example_05.tex @@ -0,0 +1,14 @@ +\documentclass[9pt]{standalone} + +\usepackage{fontspec} + +\setmainfont{NewCM10-Regular} +\setmonofont{NewCMMono10-Regular} + +\newfontfamily\notoemoji{Noto Color Emoji}[Renderer=HarfBuzz] + +\newcommand{\emo}[1]{{\notoemoji\scriptsize #1}} + +\begin{document} +\emo{🤡} +\end{document} diff --git a/source/assets/example_06.pdf b/source/assets/example_06.pdf new file mode 100644 index 0000000000..5d8f5392da Binary files /dev/null and b/source/assets/example_06.pdf differ diff --git a/source/assets/example_06.tex b/source/assets/example_06.tex new file mode 100644 index 0000000000..f63b99cc89 --- /dev/null +++ b/source/assets/example_06.tex @@ -0,0 +1,10 @@ +\documentclass[9pt]{standalone} + +\usepackage{fontspec} + +\setmainfont{NewCM10-Regular} +\setmonofont{NewCMMono10-Regular} + +\begin{document} +\texttt{ẹ́} +\end{document} diff --git a/source/figdag.dot b/source/assets/figdag.dot similarity index 100% rename from source/figdag.dot rename to source/assets/figdag.dot diff --git a/source/assets/figdag.pdf b/source/assets/figdag.pdf new file mode 100644 index 0000000000..26c743ece5 Binary files /dev/null and b/source/assets/figdag.pdf differ diff --git a/source/figname.dot b/source/assets/figname.dot similarity index 100% rename from source/figname.dot rename to source/assets/figname.dot diff --git a/source/assets/figname.pdf b/source/assets/figname.pdf new file mode 100644 index 0000000000..a7f5bd30c0 Binary files /dev/null and b/source/assets/figname.pdf differ diff --git a/source/fignonvirt.dot b/source/assets/fignonvirt.dot similarity index 100% rename from source/fignonvirt.dot rename to source/assets/fignonvirt.dot diff --git a/source/assets/fignonvirt.pdf b/source/assets/fignonvirt.pdf new file mode 100644 index 0000000000..302424c78a Binary files /dev/null and b/source/assets/fignonvirt.pdf differ diff --git a/source/figvirt.dot b/source/assets/figvirt.dot similarity index 100% rename from source/figvirt.dot rename to source/assets/figvirt.dot diff --git a/source/assets/figvirt.pdf b/source/assets/figvirt.pdf new file mode 100644 index 0000000000..ddbbeb3176 Binary files /dev/null and b/source/assets/figvirt.pdf differ diff --git a/source/figvirtnonvirt.dot b/source/assets/figvirtnonvirt.dot similarity index 100% rename from source/figvirtnonvirt.dot rename to source/assets/figvirtnonvirt.dot diff --git a/source/assets/figvirtnonvirt.pdf b/source/assets/figvirtnonvirt.pdf new file mode 100644 index 0000000000..5591593dc5 Binary files /dev/null and b/source/assets/figvirtnonvirt.pdf differ 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/valuecategories.dot b/source/assets/valuecategories.dot similarity index 100% rename from source/valuecategories.dot rename to source/assets/valuecategories.dot diff --git a/source/assets/valuecategories.pdf b/source/assets/valuecategories.pdf new file mode 100644 index 0000000000..3cff95520a Binary files /dev/null and b/source/assets/valuecategories.pdf differ diff --git a/source/back.tex b/source/back.tex index dda5569dc8..7cd2714e9f 100644 --- a/source/back.tex +++ b/source/back.tex @@ -1,61 +1,96 @@ %!TEX root = std.tex -\chapter{Bibliography} +\renewcommand{\leftmark}{\bibname} -\begin{itemize} -\renewcommand{\labelitemi}{---} +\begin{thebibliography}{99} % ISO documents in numerical order. -\item +\bibitem{iso4217} ISO 4217:2015, \doccite{Codes for the representation of currencies} -\item +\bibitem{iso10967-1} ISO/IEC 10967-1:2012, \doccite{Information technology --- Language independent arithmetic --- Part 1: Integer and floating point arithmetic} -\item +\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 --- Programming languages, their environments, and system software interfaces --- Floating-point extensions for C --- Part 3: Interchange and extended types} % Other international standards. -\item - %%% Format for the following entry is based on that specified at - %%% http://www.iec.ch/standardsdev/resources/draftingpublications/directives/principles/referencing.htm - The Unicode Consortium. Unicode Standard Annex, UAX \#29, - \doccite{Unicode Text Segmentation} [online]. - Edited by Mark Davis. Revision 35; issued for Unicode 12.0.0. 2019-02-15 [viewed 2020-02-23]. - Available from: \url{http://www.unicode.org/reports/tr29/tr29-35.html} -\item - The Unicode Consortium. Unicode Standard Annex, UAX \#31, - \doccite{Unicode Identifier and Pattern Syntax} [online]. - Edited by Mark Davis. Revision 33; issued for Unicode 13.0.0. - 2020-02-13 [viewed 2021-06-08]. - Available from: \url{https://www.unicode.org/reports/tr31/tr31-33.html} -\item - The Unicode Standard Version 14.0, - \doccite{Core Specification}. - Unicode Consortium, ISBN 978-1-936213-29-0, copyright \copyright 2021 Unicode, Inc. - Available from: \url{https://www.unicode.org/versions/Unicode14.0.0/UnicodeStandard-14.0.pdf} -\item +\bibitem{iana-charset} + IANA Character Sets Database. + Available from:\newline + \url{https://www.iana.org/assignments/character-sets/}, 2021-04-01 +\bibitem{iana-tz} IANA Time Zone Database. Available from: \url{https://www.iana.org/time-zones} +\bibitem{unicode-charmap} + Unicode Character Mapping Markup Language [online]. + Edited by Mark Davis and Markus Scherer. Revision 5.0.1; 2017-05-31 + Available from: \url{https://www.unicode.org/reports/tr22/tr22-8.html} % Literature references. -\item +\bibitem{cpp-r} Bjarne Stroustrup, - \doccite{The \Cpp{} Programming Language, second edition}, Chapter R. + \doccite{The \Cpp{} Programming Language, second edition}, Chapter R\@. Addison-Wesley Publishing Company, ISBN 0-201-53992-6, copyright \copyright 1991 AT\&T -\item - Brian W. Kernighan and Dennis M. Ritchie, - \doccite{The C Programming Language}, Appendix A. +\bibitem{kr} + 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 -\item - P.J. Plauger, +\bibitem{cpp-lib} + P.\,J.\ Plauger, \doccite{The Draft Standard \Cpp{} Library}. - Prentice-Hall, ISBN 0-13-117003-1, copyright \copyright 1995 P.J. Plauger) -\end{itemize} - -The arithmetic specification described in ISO/IEC 10967-1:2012 is -called \defn{LIA-1} in this document. + 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}, + Numerische Mathematik 108 (59--91), 2007. +\bibitem{blas1} + C.\,L.\ Lawson, R.\,J.\ Hanson, D.\ Kincaid, and F.\,T.\ Krogh, + \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, + \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} + Jack J.\ Dongarra, Jeremy Du Croz, Sven Hammarling, and Iain Duff, + \doccite{A Set of Level 3 Basic Linear Algebra Subprograms}. + 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, and D.\ Sorensen, + \doccite{LAPACK Users' Guide, Third Edition}. + SIAM, Philadelphia, PA, USA, 1999. +\bibitem{blas-std} + 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, and R.\ Client Whaley, + \doccite{An Updated Set of Basic Linear Algebra Subprograms (BLAS)}. + ACM Trans.\ Math.\ Soft., Vol.\ 28, Issue 2, 2002. +\bibitem{flynn-taxonomy} + Michael J.\ Flynn, + \doccite{Very High-Speed Computing Systems}. + Proceedings of the IEEE, Vol.\ 54, Issue 12, 1966. +\end{thebibliography} % FIXME: For unknown reasons, hanging paragraphs are not indented within our % glossaries by default. @@ -63,7 +98,7 @@ \chapter{Bibliography} \renewcommand{\glossitem}[4]{\hangpara{4em}{1}\realglossitem{#1}{#2}{#3}{#4}} \clearpage -\renewcommand{\glossaryname}{Cross references} +\renewcommand{\glossaryname}{Cross-references} \renewcommand{\preglossaryhook}{Each clause and subclause label is listed below along with the corresponding clause or subclause number and page number, in alphabetical order by label.\\} \twocolglossary @@ -75,9 +110,9 @@ \chapter{Bibliography} \clearpage \input{xrefdelta} -\renewcommand{\glossaryname}{Cross references from ISO \CppXX{}} +\renewcommand{\glossaryname}{Cross-references from ISO \CppXVII{}} \renewcommand{\preglossaryhook}{All clause and subclause labels from -ISO \CppXX{} (ISO/IEC 14882:2020, \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} { @@ -87,6 +122,7 @@ \chapter{Bibliography} \clearpage \renewcommand{\leftmark}{\indexname} +\renewcommand{\preindexhook}{Constructions whose name appears in \exposid{monospaced italics} are for exposition only.\\} { \raggedright \printindex[generalindex] @@ -110,7 +146,7 @@ \chapter{Bibliography} } \clearpage -\renewcommand{\preindexhook}{} +\renewcommand{\preindexhook}{Constructions whose name appears in \exposid{italics} are for exposition only.\\} { \raggedright \printindex[libraryindex] @@ -119,7 +155,8 @@ \chapter{Bibliography} \clearpage \renewcommand{\preindexhook}{The bold page number for each entry is the page where the concept is defined. -Other page numbers refer to pages where the concept is mentioned in the general text.\\} +Other page numbers refer to pages where the concept is mentioned in the general text. +Concepts whose name appears in \exposid{italics} are for exposition only.\\} { \raggedright \printindex[conceptindex] @@ -128,7 +165,6 @@ \chapter{Bibliography} \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 f32e82975f..733d6699d0 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,28 +32,28 @@ \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 \begin{itemize} \item -\grammarterm{declaration}, +\grammarterm{name-declaration}, \grammarterm{block-declaration}, or \grammarterm{member-declaration}\iref{dcl.pre,class.mem}, \item @@ -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 @@ -85,9 +100,15 @@ 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 @@ -95,32 +116,24 @@ a reference other than a non-static data member or of an object. The variable's name, if any, denotes the reference or object. +\pnum +An \defn{entity} is a value, object, reference, +structured binding, +result binding, +function, enumerator, type, +class member, bit-field, template, template specialization, namespace, or +pack. 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 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 +148,15 @@ \indextext{declaration!definition versus}% \indextext{declaration}% \indextext{declaration!name}% -A declaration\iref{dcl.dcl} may (re)introduce +A declaration\iref{dcl} 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 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}, @@ -182,7 +196,7 @@ \item it declares a static data member outside a class definition and the variable was defined within the class with the \keyword{constexpr} -specifier (this usage is deprecated; see \ref{depr.static.constexpr}), +specifier\iref{class.static.data} (this usage is deprecated; see \ref{depr.static.constexpr}), \item \indextext{declaration!class name}% it is an \grammarterm{elaborated-type-specifier}\iref{class.name}, @@ -228,7 +242,7 @@ a \grammarterm{template-declaration}\iref{temp.pre} whose \grammarterm{template-head} is not followed by either a \grammarterm{concept-definition} or a \grammarterm{declaration} -that defines a function, a class, a variable, or a static data member. +that defines a function, a class, a variable, or a static data member, \item it is an explicit instantiation declaration\iref{temp.explicit}, or \item it is @@ -299,10 +313,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} @@ -320,7 +334,7 @@ the type of that object shall not be an incomplete type\iref{term.incomplete.type}, an abstract class type\iref{class.abstract}, or -a (possibly multi-dimensional) array thereof. +a (possibly multidimensional) array thereof. \rSec1[basic.def.odr]{One-definition rule}% \indextext{object!definition}% @@ -440,33 +454,68 @@ \label{term.odr.use}% A variable is named by an expression if the expression is an \grammarterm{id-expression} that denotes it. -A variable \tcode{x} whose name appears as a -potentially-evaluated expression $E$ -is \defnx{odr-used}{odr-use} by $E$ unless +A variable \tcode{x} that is named by a +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 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 +\tcode{x} is a non-volatile object +that is usable in constant expressions at $P$ and +has no mutable subobjects and +\begin{itemize} +\item +$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. \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 @@ -489,7 +538,7 @@ \pnum An assignment operator function in a class is odr-used by an implicitly-defined -copy-assignment or move-assignment function for another class as specified +copy assignment or move assignment function for another class as specified in~\ref{class.copy.assign}. A constructor for a class is odr-used as specified in~\ref{dcl.init}. A destructor for a class is odr-used if it is potentially @@ -497,7 +546,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 +557,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 +590,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 +660,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 +687,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 @@ -650,7 +724,7 @@ \item In each such definition, corresponding names, looked up according to~\ref{basic.lookup}, shall refer to 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 @@ -675,6 +749,16 @@ \item In each such definition, corresponding entities shall have the same language linkage. +\item In each such definition, +const objects with static or thread storage duration +shall be constant-initialized if +the object is constant-initialized in any such definition. + +\item In each such definition, +corresponding manifestly constant-evaluated expressions +that are not value-dependent +shall have the same value\iref{expr.const,temp.dep.constexpr}. + \item In each such definition, the overloaded operators referred to, the implicit calls to conversion functions, constructors, operator new functions and operator delete functions, shall refer to the same @@ -688,7 +772,12 @@ 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). +\end{itemize} + +\pnum +For the purposes of the preceding requirements: +\begin{itemize} \item If \tcode{D} is a class with an implicitly-declared constructor\iref{class.default.ctor,class.copy.ctor}, it is as if the constructor was @@ -728,14 +817,16 @@ implicitly defined in every translation unit where it is odr-used, and the implicit definition in every translation unit shall call the same comparison operators for each subobject of \tcode{D}. -\end{itemize} -\pnum +\item If \tcode{D} is a template and is defined in more than one -translation unit, then the preceding requirements -shall apply both to names from the template's enclosing scope used in the +translation unit, the requirements +apply both to names from the template's enclosing scope used in the template definition, and also to dependent names at the point of instantiation\iref{temp.dep}. +\end{itemize} + +\pnum These requirements also apply to corresponding entities defined within each definition of \tcode{D} (including the closure types of \grammarterm{lambda-expression}{s}, @@ -806,9 +897,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. @@ -849,15 +942,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}. @@ -871,19 +963,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 @@ -894,6 +987,14 @@ \item the types of their object parameters are equivalent. \end{itemize} +\indextext{template!function!corresponding signature}% +Two function templates have +\defnadjx{corresponding}{signatures}{signature} if +their \grammarterm{template-parameter-list}{s} +have the same length, +their corresponding \grammarterm{template-parameter}{s} are equivalent, +they have equivalent non-object-parameter-type-lists and return types (if any), and, +if both are non-static members, they have corresponding object parameters. \pnum Two declarations \defn{correspond} @@ -912,7 +1013,11 @@ function, or function template, or \item -each declares a function or function template, except when +each declares a function or function template +and they do not declare corresponding overloads. +\end{itemize} +Two function or function template declarations declare +\defn{corresponding overloads} if \begin{itemize} \item both declare functions with the same non-object-parameter-type-list, @@ -925,21 +1030,16 @@ if both are non-static members, they have corresponding object parameters, or \item -both declare function templates with equivalent -non-object-parameter-type-lists, -return types (if any), -\grammarterm{template-head}s, and -trailing \grammarterm{requires-clause}s (if any), and, -if both are non-static members, -they have corresponding object parameters. -\end{itemize} +both declare function templates with corresponding signatures and equivalent +\grammarterm{template-head}s and +trailing \grammarterm{requires-clause}s (if any). \end{itemize} \begin{note} Declarations can correspond even if neither binds a name. \begin{example} \begin{codeblock} struct A { -friend void f(); // \#1 + friend void f(); // \#1 }; struct B { friend void f() {} // corresponds to, and defines, \#1 @@ -972,18 +1072,50 @@ \end{codeblock} \end{example} +\pnum +A declaration is \defnx{name-independent}{declaration!name-independent} +if its name is \tcode{_} (\unicode{005f}{low line}) and it declares +\begin{itemize} +\item +a variable with automatic storage duration, +\item +a structured binding +%FIXME: "and" is strange below; maybe reword to something like: +%FIXME: "that has no \grammarterm{storage-class-specifier} and +%FIXME: that is not inhabiting a namespace scope," +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? +a non-static data member of other than an anonymous union. +\end{itemize} + +\recommended +Implementations should not emit a warning +that a name-independent declaration is used or unused. + \pnum \indextext{declaration!potentially conflict}% Two declarations \defn{potentially conflict} if they correspond and cause their shared name to denote different entities\iref{basic.link}. The program is ill-formed -if, in any scope, a name is bound to two declarations -that potentially conflict and one precedes the other\iref{basic.lookup}. +if, in any scope, a name is bound to two declarations $A$ and $B$ +that potentially conflict and $A$ precedes $B$\iref{basic.lookup}, +unless $B$ is name-independent. +\begin{note} +An \grammarterm{id-expression} that names a unique name-independent declaration +is usable until an additional declaration of the same name +is introduced in the same scope\iref{basic.lookup.general}. +\end{note} \begin{note} Overload resolution can consider potentially conflicting declarations found in multiple scopes -(e.g. via \grammarterm{using-directive}s or for operator functions), +(e.g., via \grammarterm{using-directive}s or for operator functions), in which case it is often ambiguous. \end{note} \begin{example} @@ -1000,6 +1132,18 @@ namespace B = B; // OK, no effect namespace A = B; // OK, no effect namespace B {} // error: different entity for \tcode{B} + +void g() { + int _; + _ = 0; // OK + int _; // OK, name-independent declaration + _ = 0; // error: two non-function declarations in the lookup set +} +void h () { + int _; // \#1 + _ ++; // OK + static int _; // error: conflicts with \#1 because static variables are not name-independent +} \end{codeblock} \end{example} @@ -1062,8 +1206,8 @@ the locus of the declaration that hides it. \begin{example} \begin{codeblock} -const int i = 2; -{ int i[i]; } +const int i = 2; +{ int i[i]; } \end{codeblock} declares a block-scope array of two integers. \end{example} @@ -1073,10 +1217,12 @@ The locus of a \grammarterm{class-specifier} is immediately after the \grammarterm{identifier} or \grammarterm{simple-template-id} (if any) in its \grammarterm{class-head}\iref{class.pre}. -The locus of -an \grammarterm{enum-specifier} or \grammarterm{opaque-enum-declaration} -is immediately after the \grammarterm{identifier} (if any) -in it\iref{dcl.enum}. +The locus of an \grammarterm{enum-specifier} +is immediately after +its \grammarterm{enum-head}; +the locus of an \grammarterm{opaque-enum-declaration} +is immediately after it\iref{dcl.enum}. +%FIXME: What's "it" below? What's "it" above? The locus of an \grammarterm{alias-declaration} is immediately after it. \pnum @@ -1147,9 +1293,13 @@ \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 concept-name\iref{temp.concept}. +is immediately after its \grammarterm{concept-name}\iref{temp.concept}. \begin{note} The \grammarterm{constraint-expression} cannot use the \grammarterm{concept-name}. @@ -1219,7 +1369,9 @@ \end{example} \pnum -If a declaration whose target scope is the block scope $S$ of a +If a declaration +that is not a name-independent declaration and +that binds a name in the block scope $S$ of a \begin{itemize} \item \grammarterm{compound-statement} of a \grammarterm{lambda-expression}, @@ -1280,7 +1432,7 @@ in the \grammarterm{lambda-expression}. \item If $P$ is associated with a \grammarterm{requirement-parameter-list}, -its scope extends to the end of the \grammarterm{requirement-body} of the requires-expression. +its scope extends to the end of the \grammarterm{requirement-body} of the \grammarterm{requires-expression}. \item If $P$ is associated with a \grammarterm{deduction-guide}, its scope extends to the end of the \grammarterm{deduction-guide}. @@ -1360,7 +1512,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}. @@ -1380,6 +1536,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}% @@ -1390,13 +1570,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 @@ -1502,18 +1682,18 @@ \pnum \indextext{scope!search}% -A \defn{search} in a scope $X$ for a name $N$ from a program point $P$ -is a single search in $X$ for $N$ from $P$ +A \defn{search} in a scope $X$ for a name $M$ from a program point $P$ +is a single search in $X$ for $M$ from $P$ unless $X$ is the scope of a class or class template $T$, in which case the following steps define the result of the search. \begin{note} The result differs only -if $N$ is a \grammarterm{conversion-function-id} or +if $M$ is a \grammarterm{conversion-function-id} or if the single search would find nothing. \end{note} \pnum -The \defn{lookup set} for $N$ in $C$, called $S(N,C)$, +The \defn{lookup set} for a name $N$ in a class or class template $C$, called $S(N,C)$, consists of two component sets: the \term{declaration set}, a set of members named $N$; and the \term{subobject set}, @@ -1538,10 +1718,10 @@ in each direct non-dependent\iref{temp.dep.type} base class subobject $B_i$, and merge each such lookup set $S(N,B_i)$ in turn into $S(N,C)$. \begin{note} -If $T$ is incomplete, +If $C$ is incomplete, only base classes whose \grammarterm{base-specifier} appears before $P$ are considered. -If $T$ is an instantiated class, its base classes are not dependent. +If $C$ is an instantiated class, its base classes are not dependent. \end{note} \pnum @@ -1567,9 +1747,9 @@ \end{itemize} \pnum -The result of the search is the declaration set of $S(N,T)$. +The result of the search is the declaration set of $S(M,T)$. If it is an invalid set, the program is ill-formed. -If it differs from the result of a search in $T$ for $N$ +If it differs from the result of a search in $T$ for $M$ in a complete-class context\iref{class.mem} of $T$, the program is ill-formed, no diagnostic required. \begin{example} @@ -1592,7 +1772,7 @@ \end{example} \pnum -If $N$ is a non-dependent \grammarterm{conversion-function-id}, +If $M$ is a non-dependent \grammarterm{conversion-function-id}, conversion function templates that are members of $T$ are considered. For each such template $F$, the lookup set $S(t,T)$ is constructed, considering a function template declaration to have the name $t$ @@ -1601,7 +1781,7 @@ which shall not be an invalid set, are included in the result. \begin{note} Overload resolution will discard those -that cannot convert to the type specified by $N$\iref{temp.over}. +that cannot convert to the type specified by $M$\iref{temp.over}. \end{note} \pnum @@ -1743,10 +1923,6 @@ if it precedes $P$ and inhabits either $S$ or the scope of a namespace nominated by a \grammarterm{using-directive} that is active in $S$ at $P$. -\begin{note} -A \grammarterm{using-directive} is exported if and only if -it appears in a header unit. -\end{note} \pnum An \term{unqualified search} in a scope $S$ from a program point $P$ @@ -1885,7 +2061,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} @@ -1953,7 +2129,7 @@ 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. @@ -1967,17 +2143,20 @@ 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} @@ -2008,8 +2187,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 @@ -2115,7 +2294,7 @@ 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{decltype-specifier} +If a name, \grammarterm{template-id}, or \grammarterm{computed-type-specifier} is followed by a \tcode{::}, it shall designate a namespace, class, enumeration, or dependent type, and the \tcode{::} is never interpreted as @@ -2564,6 +2743,7 @@ \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. @@ -2576,28 +2756,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 can have +\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}% @@ -2616,8 +2786,11 @@ \item a non-template variable of non-volatile const-qualified type, unless \begin{itemize} + \item it is declared in the purview of a module interface unit + (outside the \grammarterm{private-module-fragment}, if any) or + module partition, or \item it is explicitly declared \keyword{extern}, or - \item it is inline or exported, or + \item it is inline, or \item it was previously declared and the prior declaration did not have internal linkage; or \end{itemize} @@ -2632,8 +2805,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 @@ -2655,6 +2828,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 @@ -2712,6 +2903,7 @@ for linkage purposes, if any\iref{dcl.typedef,dcl.enum}, they correspond\iref{basic.scope.scope}, have the same target scope that is not a function or template parameter scope, +neither is a name-independent declaration, and either \begin{itemize} \item @@ -2994,11 +3186,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 @@ -3007,11 +3194,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} @@ -3020,7 +3206,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 @@ -3114,7 +3302,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 @@ -3131,7 +3319,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 @@ -3148,6 +3336,8 @@ \end{note} \begin{example} \begin{codeblock} +// assumes that \tcode{sizeof(int)} is equal to 4 + template struct AlignedUnion { alignas(T...) unsigned char data[max(sizeof(T)...)]; @@ -3162,7 +3352,7 @@ struct A { unsigned char a[32]; }; struct B { unsigned char b[16]; }; -A a; +alignas(int) A a; B *b = new (a.a + 8) B; // \tcode{a.a} provides storage for \tcode{*b} int *p = new (b->b + 4) int; // \tcode{b->b} provides storage for \tcode{*p} // \tcode{a.a} does not provide storage for \tcode{*p} (directly), @@ -3172,7 +3362,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 @@ -3239,6 +3429,12 @@ standard-layout type\iref{basic.types.general} shall occupy contiguous bytes of storage. +\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. + \pnum \indextext{most derived object!bit-field}% \indextext{most derived object!zero size subobject}% @@ -3247,11 +3443,13 @@ Two objects with overlapping lifetimes that are not bit-fields -may have the same address -if one is nested within the other, +may have the same address if +\begin{itemize} +\item one is nested within the other, +\item at least one is a subobject of zero size and they are not of similar types\iref{conv.qual}, or -if at least one is a subobject of zero size -and they are of different types; +\item they are both potentially non-unique objects; +\end{itemize} otherwise, they have distinct addresses and occupy disjoint bytes of storage. \begin{footnote} @@ -3265,6 +3463,14 @@ static const char test1 = 'x'; static const char test2 = 'x'; const bool b = &test1 != &test2; // always \tcode{true} + +static const char (&r) [] = "x"; +static const char *s = "x"; +static std::initializer_list il = { 'x' }; +const bool b2 = r != il.begin(); // unspecified result +const bool b3 = r != s; // unspecified result +const bool b4 = il.begin() != &test1; // always \tcode{true} +const bool b5 = r != &test1; // always \tcode{true} \end{codeblock} \end{example} The address of a non-bit-field subobject of zero size is @@ -3277,7 +3483,7 @@ within a specified region of storage. For each operation that is specified as implicitly creating objects, that operation implicitly creates and starts the lifetime of -zero or more objects of implicit-lifetime types\iref{basic.types.general} +zero or more objects of implicit-lifetime types\iref{term.implicit.lifetime.type} in its specified region of storage if doing so would result in the program having defined behavior. If no such set of objects would give the program defined behavior, @@ -3322,32 +3528,133 @@ \end{example} \pnum -An operation that begins the lifetime of -an array of \tcode{char}, \tcode{unsigned char}, or \tcode{std::byte} +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,allocator.traits.members,c.malloc,cstring.syn,bit.cast}. +\iref{obj.lifetime,c.malloc,mem.res.public,bit.cast,cstring.syn}. \end{note} \indextext{object model|)} +\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[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 and, -if it is of class type or a (possibly multi-dimensional) array thereof, -that class type has a trivial default constructor. +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 @@ -3358,7 +3665,8 @@ 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} and \ref{class.copy.ctor}, +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} @@ -3367,6 +3675,21 @@ \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}% @@ -3400,8 +3723,11 @@ A \grammarterm{delete-expression}\iref{expr.delete} invokes the destructor prior to releasing the storage. \end{note} -In this case, the destructor is not implicitly invoked and any program that -depends on the side effects produced by the destructor has undefined behavior. +In this case, the destructor is not implicitly invoked. +\begin{note} +The correct behavior of a program often depends on +the destructor being invoked for each object of class type. +\end{note} \pnum Before the lifetime of an object has started but after the storage which @@ -3422,11 +3748,10 @@ 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 object will be or was of a class type with a non-trivial destructor - and the pointer is used as the operand of a \grammarterm{delete-expression}, + the pointer is used as the operand of a \grammarterm{delete-expression}, \item the pointer is used to access a non-static data member or call a non-static member function of the object, or @@ -3486,7 +3811,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 @@ -3496,26 +3821,22 @@ \keyword{typeid}. \end{itemize} -\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: -\begin{itemize} -\item the storage that $o_2$ occupies exactly overlays +\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 +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 \item $o_1$ and $o_2$ are of the same type (ignoring the top-level cv-qualifiers), and -\item $o_1$ is not a complete const object, and +\item $o_1$ is not a const, complete object, and \item neither $o_1$ nor $o_2$ is a potentially-overlapping subobject\iref{intro.object}, and @@ -3524,6 +3845,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 { @@ -3575,18 +3907,18 @@ \begin{codeblock} class T { }; struct B { - ~B(); + ~B(); }; void h() { - B b; - new (&b) T; + B b; + new (&b) T; } // undefined behavior at block exit \end{codeblock} \end{example} \pnum -Creating a new object within the storage that a const complete +Creating a new object within the storage that a const, complete object with static, thread, or automatic storage duration occupies, or within the storage that such a const object used to occupy before its lifetime ended, results in undefined behavior. @@ -3605,37 +3937,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: @@ -3652,37 +3996,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} @@ -3702,6 +4078,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}% @@ -3709,35 +4089,25 @@ \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} \pnum -\indextext{storage duration!static}% All variables which \begin{itemize} \item @@ -3747,7 +4117,7 @@ are first declared with the \keyword{static} or \keyword{extern} keywords\iref{dcl.stc} \end{itemize} -have \defn{static storage duration}. +have \defnadj{static}{storage duration}. The storage for these entities lasts for the duration of the program\iref{basic.start.static,basic.start.term}. @@ -3791,15 +4161,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 @@ -3835,27 +4206,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; @@ -3969,7 +4335,7 @@ currently installed new-handler function\iref{new.handler}, if any. \begin{note} \indextext{\idxcode{new_handler}}% -A program-supplied allocation function can obtain the address of the +A program-supplied allocation function can obtain the currently installed \tcode{new_handler} using the \tcode{std::get_new_handler} function\iref{get.new.handler}. \end{note} @@ -3992,11 +4358,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} @@ -4066,104 +4434,6 @@ 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}. - -\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; the aligned-storage templates -in the library\iref{meta.trans.other} can be used to obtain aligned storage. -\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 @@ -4175,15 +4445,9 @@ Temporary objects are created \begin{itemize} \item -when a prvalue is converted to an xvalue\iref{conv.rval}, -\item -when needed by the implementation to pass or return an object of trivially copyable type (see below), -and +when a prvalue is converted to an xvalue\iref{conv.rval} 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}, @@ -4208,7 +4472,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 @@ -4265,34 +4531,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} @@ -4310,7 +4591,7 @@ \pnum \indextext{initializer!temporary and declarator}% \indextext{temporary!order of destruction of}% -There are three contexts in which temporaries are destroyed at a different +There are five 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}. @@ -4415,8 +4696,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. @@ -4431,14 +4710,35 @@ \end{itemize} \pnum -The destruction of a temporary whose lifetime is not extended by being -bound to a reference is sequenced before the destruction of every -temporary which is constructed earlier in the same full-expression. -If the lifetime of two or more temporaries to which references are bound ends -at the same point, +The fourth context is when a temporary object +is created in the \grammarterm{for-range-initializer} of a range-based \keyword{for} statement. +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 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 +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, these temporaries are destroyed at that point in the reverse order of the completion of their construction. -In addition, the destruction of temporaries bound to references shall +In addition, the destruction of such temporaries shall take into account the ordering of destruction of objects with static, thread, or automatic storage duration\iref{basic.stc.static,basic.stc.thread,basic.stc.auto}; that is, if @@ -4607,24 +4907,36 @@ \pnum \label{term.object.representation}% The \defnx{object representation}{representation!object} -of an object of type \tcode{T} is the +of a complete object type \tcode{T} is the sequence of \placeholder{N} \tcode{\keyword{unsigned} \keyword{char}} objects taken up -by the object of type \tcode{T}, where \placeholder{N} equals +by a non-bit-field complete object of type \tcode{T}, +where \placeholder{N} equals \tcode{\keyword{sizeof}(T)}. The \defnx{value representation}{representation!value} -of an object of type \tcode{T} is the set of bits +of a type \tcode{T} is the set of bits +in the object representation of \tcode{T} that participate in representing a value of type \tcode{T}. +The object and value representation of +a non-bit-field complete object of type \tcode{T} are +the bytes and bits, respectively, of +the object corresponding to the object and value representation of its type. +The object representation of a bit-field object is +the sequence of \placeholder{N} bits taken up by the object, +where \placeholder{N} is the width of the bit-field\iref{class.bit}. +The value representation of a bit-field object is +the set of bits in the object representation that +participate in representing its value. \label{term.padding.bits}% -Bits in the object representation that are not part of the value representation +Bits in the object representation of a type or object that are +not part of the value representation are \defn{padding bits}. For trivially copyable types, the value representation is a set of bits in the object representation that determines a \defn{value}, which is one discrete element of an \impldef{values of a trivially copyable type} set of values. \begin{footnote} -The -intent is that the memory model of \Cpp{} is compatible -with that of ISO/IEC 9899 Programming Language C. +The intent is that the memory model of \Cpp{} is compatible +with that of the C programming language. \end{footnote} \pnum @@ -4655,9 +4967,14 @@ can be an array of unknown bound and therefore be incomplete at one point in a translation unit and complete later on; the array types at those two points (``array of unknown bound of \tcode{T}'' and ``array of -\tcode{N} \tcode{T}'') are different types. The type of a pointer to array of -unknown bound, or of a type defined by a \keyword{typedef} declaration to -be an array of unknown bound, cannot be completed. +\tcode{N} \tcode{T}'') are different types. +\begin{note} +The type of a pointer or reference to array of unknown bound +permanently points to or refers to an incomplete type. +An array of unknown bound named by a \keyword{typedef} declaration +permanently refers to an incomplete type. +In either case, the array type cannot be completed. +\end{note} \begin{example} \indextext{type!example of incomplete}% \begin{codeblock} @@ -4675,7 +4992,7 @@ } struct X { int i; }; // now \tcode{X} is a complete type -int arr[10]; // now the type of \tcode{arr} is complete +int arr[10]; // now the type of \tcode{arr} is complete X x; void bar() { @@ -4714,16 +5031,20 @@ Scalar types, trivially copyable class types\iref{class.prop}, arrays of such types, and cv-qualified versions of these types are collectively called \defnadjx{trivially copyable}{types}{type}. -\label{term.trivial.type}% -Scalar types, trivial class types\iref{class.prop}, -arrays of such types and cv-qualified versions of these -types are collectively called -\defnadjx{trivial}{types}{type}. +\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{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 +types\iref{class.prop}, arrays of such types, and cv-qualified versions of these types are collectively called \defnadjx{standard-layout}{types}{type}. +\label{term.implicit.lifetime.type}% Scalar types, implicit-lifetime class types\iref{class.prop}, array types, and cv-qualified versions of these types are collectively called \defnadjx{implicit-lifetime}{types}{type}. @@ -4740,15 +5061,20 @@ has all of the following properties: \begin{itemize} \item it has a constexpr destructor\iref{dcl.constexpr}, -\item it is either a closure type\iref{expr.prim.lambda.closure}, -an aggregate type\iref{dcl.init.aggr}, or -has at least one constexpr constructor or constructor template +\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}, +\item is an aggregate union type that has either +no variant members or +at least one variant member of non-volatile literal type, +\item is a non-union aggregate type for which +each of its anonymous union members +satisfies the above requirements for an aggregate union type, or +\item has at least one constexpr constructor or constructor template (possibly inherited\iref{namespace.udecl} from a base class) -that is not a copy or move constructor, -\item if it is a union, at least one of its non-static data members is -of non-volatile literal type, and -\item if it is not a union, all of its non-static data members and base classes are -of non-volatile literal types. +that is not a copy or move constructor. +\end{itemize} \end{itemize} \end{itemize} \begin{note} @@ -4844,7 +5170,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 @@ -4856,7 +5182,7 @@ \end{floattable} \pnum -The width of each signed integer type +The width of each standard signed integer type shall not be less than the values specified in \tref{basic.fundamental.width}. The value representation of a signed or unsigned integer type comprises $N$ bits, where N is the respective width. @@ -4865,11 +5191,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 @@ -5018,6 +5344,22 @@ the object and value representations and accuracy of operations of floating-point types are \impldef{representation of floating-point types}. +\pnum +The minimum range of representable values for a floating-point type is +the most negative finite floating-point number representable +in that type through +the most positive finite floating-point number representable in that type. +In addition, if negative infinity is representable in a type, +the range of that type is extended to all negative real numbers; +likewise, if positive infinity is representable in a type, +the range of that type is extended to all positive real numbers. +\begin{note} +Since negative and positive infinity are representable +in \IsoFloatUndated{} formats, +all real numbers lie within the range of representable values of +a floating-point type adhering to \IsoFloatUndated{}. +\end{note} + \pnum Integral and floating-point types are collectively termed \defnx{arithmetic types}{type!arithmetic}. @@ -5035,20 +5377,25 @@ 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}*)}. @@ -5067,9 +5414,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}. @@ -5077,49 +5424,49 @@ \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. \pnum \begin{note} 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 mantissa, -so the storage used for the mantissa is $p-1$ bits. -ISO/IEC/IEEE 60559 does not assign a name for a type +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. +\IsoFloatUndated{} does not assign a name for a type having the parameters specified for \tcode{std::bfloat16_t}. \end{note} \begin{floattable} @@ -5129,7 +5476,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 \\ @@ -5140,11 +5487,11 @@ \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} -defined in ISO/IEC TS 18661-3 and with future versions of the C standard. +defined in ISO/IEC TS 18661-3 and with future versions of \IsoCUndated{}. \rSec2[basic.compound]{Compound types} @@ -5155,7 +5502,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}; @@ -5171,9 +5518,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 @@ -5225,7 +5571,7 @@ Except for pointers to static members, text referring to ``pointers'' does not apply to pointers to members. Pointers to incomplete types are allowed although there are restrictions on what can be done with -them\iref{basic.align}. +them\iref{basic.types.general}. \indextext{address}% Every value of pointer type is one of the following: \begin{itemize} @@ -5257,17 +5603,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 @@ -5282,7 +5624,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 @@ -5522,6 +5889,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} @@ -5569,6 +5945,10 @@ \item The constituent expression of an expression is that expression. \item +The constituent expression of a conversion is +the corresponding implicit function call, if any, or +the converted expression otherwise. +\item The constituent expressions of a \grammarterm{braced-init-list} or of a (possibly parenthesized) \grammarterm{expression-list} are the constituent expressions of the elements of the respective list. @@ -5616,6 +5996,15 @@ Expressions appearing in the \grammarterm{compound-statement} of a \grammarterm{lambda-expression} are not subexpressions of the \grammarterm{lambda-expression}. \end{note} +The \defnadjx{potentially-evaluated}{subexpressions}{subexpression} of +an expression, conversion, or \grammarterm{initializer} $E$ are +\begin{itemize} +\item +the constituent expressions of $E$ and +\item +the subexpressions thereof that +are not subexpressions of a nested unevaluated operand\iref{term.unevaluated.operand}. +\end{itemize} \pnum A \defn{full-expression} is @@ -5627,13 +6016,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. @@ -5663,7 +6055,7 @@ if (S(3).v()) // full-expression includes lvalue-to-rvalue and \tcode{int} to \tcode{bool} conversions, // performed before temporary is deleted at end of full-expression { } - bool b = noexcept(S()); // exception specification of destructor of \tcode{S} considered for \keyword{noexcept} + bool b = noexcept(S(4)); // exception specification of destructor of \tcode{S} considered for \keyword{noexcept} // full-expression is destruction of \tcode{s2} at end of block } @@ -5697,7 +6089,7 @@ 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. @@ -5759,13 +6151,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. @@ -5779,20 +6188,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} @@ -5805,6 +6229,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. @@ -5814,6 +6239,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.% @@ -5889,16 +6316,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 @@ -5954,122 +6397,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 is not permitted to end 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 is not -permitted to 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 @@ -6082,7 +6420,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 @@ -6091,7 +6429,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 @@ -6107,7 +6445,7 @@ \end{itemize} The value of a non-atomic scalar object or bit-field $M$, as determined by -evaluation $B$, shall be the value stored by the +evaluation $B$, is the value stored by the \indextext{side effects!visible}% visible side effect $A$. \begin{note} @@ -6118,15 +6456,15 @@ \begin{note} This states that operations on ordinary objects are not visibly reordered. This is not actually detectable -without data races, but it is necessary to ensure that data races, as defined +without data races, but is needed to ensure that data races, as defined below, and with suitable restrictions on the use of atomics, correspond to data races in a simple interleaved (sequentially consistent) execution. \end{note} \pnum The value of an -atomic object $M$, as determined by evaluation $B$, shall be the value -stored by some +atomic object $M$, as determined by evaluation $B$, is the value +stored by some unspecified side effect $A$ that modifies $M$, where $B$ does not happen before $A$. \begin{note} @@ -6137,7 +6475,7 @@ \pnum \indextext{coherence!write-write}% If an operation $A$ that modifies an atomic object $M$ happens before -an operation $B$ that modifies $M$, then $A$ shall be earlier +an operation $B$ that modifies $M$, then $A$ is earlier than $B$ in the modification order of $M$. \begin{note} This requirement is known as write-write coherence. @@ -6149,7 +6487,7 @@ \indextext{value computation}% value computation $A$ of an atomic object $M$ happens before a value computation $B$ of $M$, and $A$ takes its value from a side -effect $X$ on $M$, then the value computed by $B$ shall either be +effect $X$ on $M$, then the value computed by $B$ is either the value stored by $X$ or the value stored by a \indextext{side effects}% side effect $Y$ on $M$, @@ -6163,7 +6501,7 @@ If a \indextext{value computation}% value computation $A$ of an atomic object $M$ happens before an -operation $B$ that modifies $M$, then $A$ shall take its value from a side +operation $B$ that modifies $M$, then $A$ takes its value from a side effect $X$ on $M$, where $X$ precedes $B$ in the modification order of $M$. \begin{note} @@ -6176,7 +6514,7 @@ If a \indextext{side effects}% side effect $X$ on an atomic object $M$ happens before a value -computation $B$ of $M$, then the evaluation $B$ shall take its +computation $B$ of $M$, then the evaluation $B$ takes its value from $X$ or from a \indextext{side effects}% side effect $Y$ that follows $X$ in the modification order of $M$. @@ -6229,12 +6567,13 @@ However, this applies only to data-race-free programs, and data-race-free programs cannot observe most program transformations that do not change single-threaded program semantics. In fact, most single-threaded program -transformations continue to be allowed, since any program that behaves +transformations remain possible, since any program that behaves differently as a result has undefined behavior. \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 @@ -6260,8 +6599,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 @@ -6276,13 +6615,18 @@ 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 a synchronization operation or an atomic operation, 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 @@ -6366,7 +6710,7 @@ the implementation ensures that the thread will eventually make progress for as long as it has not terminated. \begin{note} -This is required regardless of whether or not other threads of execution (if any) +This applies regardless of whether or not other threads of execution (if any) have been or are making progress. To eventually fulfill this requirement means that this will happen in an unspecified but finite amount of time. \end{note} @@ -6523,7 +6867,7 @@ \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. @@ -6531,8 +6875,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 @@ -6578,9 +6921,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} @@ -6600,7 +6944,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 @@ -6912,3 +7256,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 18b57e45fa..3a80fc1528 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} @@ -63,7 +70,7 @@ a partial specialization\iref{temp.spec.partial}. A \grammarterm{class-specifier} whose \grammarterm{class-head} omits the -\grammarterm{class-head-name} defines an unnamed class. +\grammarterm{class-head-name} defines an \defnadj{unnamed}{class}. \begin{note} An unnamed class thus can't be \tcode{final}. @@ -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} -In particular, a trivially copyable or trivial class does not have -virtual functions or virtual base classes. +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} +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; }; @@ -305,7 +393,7 @@ A class \tcode{S} is an \defnadj{implicit-lifetime}{class} if \begin{itemize} \item -it is an aggregate or +it is an aggregate whose destructor is not user-provided or \item it has at least one trivial eligible constructor and a trivial, non-deleted destructor. @@ -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,6 +551,7 @@ \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 @@ -480,16 +571,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 +593,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 @@ -594,7 +720,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. @@ -605,12 +732,15 @@ \end{note} \pnum -A class is considered a completely-defined object -type\iref{term.incomplete.type} (or complete type) at the closing \tcode{\}} of -the \grammarterm{class-specifier}. -The class is regarded as complete within its complete-class contexts; -otherwise it is regarded as incomplete within its own class -\grammarterm{member-specification}. +A class \tcode{C} is complete at a program point $P$ +if the definition of \tcode{C} is reachable from $P$\iref{module.reach} +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}, @@ -660,6 +790,11 @@ shall not directly or indirectly cause the implicit definition of a defaulted default constructor for the enclosing class or the exception specification of that constructor. +An immediate invocation\iref{expr.const} that +is a potentially-evaluated subexpression\iref{intro.execution} +of a default member initializer +is neither evaluated nor checked for whether it +is a constant expression at the point where the subexpression appears. \pnum A member shall not be declared with the \keyword{extern} @@ -695,7 +830,7 @@ The type of a non-static data member shall not be an incomplete type\iref{term.incomplete.type}, an abstract class type\iref{class.abstract}, -or a (possibly multi-dimensional) array thereof. +or a (possibly multidimensional) array thereof. \begin{note} In particular, a class \tcode{C} cannot contain a non-static member of class \tcode{C}, @@ -762,7 +897,7 @@ \item every member function of class \tcode{T}; \begin{note} This restriction does not apply to constructors, which do not have -names\iref{class.ctor} +names\iref{class.ctor}. \end{note}% \item every member of class \tcode{T} that is itself a type; @@ -785,13 +920,22 @@ The \defn{common initial sequence} of two standard-layout struct\iref{class.prop} types is the longest sequence of non-static data members and bit-fields in declaration order, starting with the first -such entity in each of the structs, such that corresponding entities +such entity in each of the structs, such that +\begin{itemize} +\item +corresponding entities have layout-compatible types\iref{basic.types}, -either both entities are declared with -the \tcode{no_unique_address} attribute\iref{dcl.attr.nouniqueaddr} -or neither is, -and either both entities are bit-fields with the same width +\item +corresponding entities have the same alignment requirements\iref{basic.align}, +\item +if a \grammarterm{has-attribute-expression}\iref{cpp.cond} +is not \tcode{0} for the \tcode{no_unique_address} attribute, +then neither entity is declared with +the \tcode{no_unique_address} attribute\iref{dcl.attr.nouniqueaddr}, and +\item +either both entities are bit-fields with the same width or neither is a bit-field. +\end{itemize} \begin{example} \begin{codeblock} struct A { int a; char b; }; @@ -899,8 +1043,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; @@ -913,8 +1057,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}% @@ -931,65 +1074,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 not part of a -class member access syntax\iref{expr.ref} and not used to form a -pointer to member\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}% @@ -999,7 +1083,7 @@ \grammarterm{cv-qualifier}{s}, which affect the type of the \keyword{this} pointer\iref{expr.prim.this}, and/or a \grammarterm{ref-qualifier}\iref{dcl.fct}; -both affect overload resolution\iref{over.match.funcs} +both affect overload resolution\iref{over.match.funcs}. \end{note} \pnum @@ -1028,8 +1112,7 @@ The implementation will implicitly declare these member functions for some class types when the program does not explicitly declare them. The implementation will implicitly define them -if they are odr-used\iref{term.odr.use} or -needed for constant evaluation\iref{expr.const}. +as needed\iref{dcl.fct.def.default}. \end{note} An implicitly-declared special member function is declared at the closing \tcode{\}} of the \grammarterm{class-specifier}. @@ -1069,7 +1152,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 @@ -1084,7 +1167,9 @@ \begin{itemize} \item the function is not deleted, \item the associated constraints\iref{temp.constr}, if any, are satisfied, and -\item no special member function of the same kind is more constrained\iref{temp.constr.order}. +\item no special member function of the same kind +whose associated constraints, if any, are satisfied +is more constrained\iref{temp.constr.order}. \end{itemize} \pnum @@ -1210,6 +1295,9 @@ \pnum A constructor shall not be a coroutine. +\pnum +A constructor shall not have an explicit object parameter\iref{dcl.fct}. + \rSec3[class.default.ctor]{Default constructors} \pnum @@ -1222,7 +1310,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}. @@ -1230,60 +1318,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 \tcode{X} is a union that has a variant member -with a non-trivial default constructor and -no variant member of \tcode{X} has a default member initializer, - -\item \tcode{X} is a non-union class that has a variant member \tcode{M} -with a non-trivial default constructor and -no variant member of the anonymous union containing \tcode{M} -has a default member initializer, - \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 array -thereof) with no \grammarterm{brace-or-equal-initializer} +\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 array thereof), - -\item \tcode{X} is a non-union class and all members of any anonymous union member are -of const-qualified type (or array thereof), - -\item any potentially constructed subobject, except for a non-static data member -with a \grammarterm{brace-or-equal-initializer}, has -class type \tcode{M} (or array thereof) and either \tcode{M} -has no default constructor or overload resolution\iref{over.match} -as applied to find \tcode{M}'s corresponding -constructor results in an ambiguity or in a function that is deleted or -inaccessible from the defaulted default constructor, or - -\item any potentially constructed subobject has a type -with a destructor that is deleted or inaccessible from the defaulted default -constructor. +\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 +does not result in a usable candidate\iref{over.match.general}, or + +\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, 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} @@ -1291,23 +1369,26 @@ \defnx{non-trivial}{constructor!default!non-trivial}. \pnum -A default constructor -that is defaulted and not defined as deleted -is -\defnx{implicitly defined}{constructor!implicitly defined} -when it is odr-used\iref{term.odr.use} -to initialize an object of its class type\iref{intro.object}, -when it is needed for constant evaluation\iref{expr.const}, or -when it is explicitly defaulted after its first declaration. -The implicitly-defined default constructor performs the set of +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 \grammarterm{compound-statement}. If that user-written default constructor would be ill-formed, the program is ill-formed. -If that user-written default constructor would satisfy the requirements -of a constexpr function\iref{dcl.constexpr}, the implicitly-defined +If that user-written default constructor would be constexpr-suitable\iref{dcl.constexpr}, +the implicitly-defined default constructor is \keyword{constexpr}. Before the defaulted default constructor for a class is implicitly defined, @@ -1325,7 +1406,7 @@ \indextext{constructor!implicitly invoked}% A default constructor is implicitly invoked to initialize a class object when no initializer is specified\iref{dcl.init.general}. -Such a default constructor is required to be accessible\iref{class.access}. +Such a default constructor needs to be accessible\iref{class.access}. \end{note} \pnum @@ -1536,18 +1617,16 @@ \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 array thereof) that cannot be copied/moved because + \tcode{M} (or possibly multidimensional array thereof) for which overload resolution\iref{over.match}, as applied to find - \tcode{M}'s - corresponding constructor, results in an ambiguity or - a function that is deleted or inaccessible from the - defaulted constructor, - -\item a variant member whose corresponding constructor - as selected by overload resolution is non-trivial, - -\item any potentially constructed subobject of a type - with a destructor that is deleted or inaccessible from the defaulted + \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 multidimensional array thereof) + where \tcode{M} has + a destructor that is deleted or inaccessible from the defaulted constructor, or, \item for the copy constructor, a non-static data member of rvalue reference type. @@ -1567,7 +1646,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 @@ -1590,21 +1669,12 @@ \defnx{non-trivial}{constructor!copy!nontrivial}. \pnum -\indextext{constructor!copy!implicitly defined}% -\indextext{constructor!move!implicitly defined}% -A copy/move constructor -that is defaulted and not defined as deleted -is -\term{implicitly defined} -when it is odr-used\iref{term.odr.use}, -when it is needed for constant evaluation\iref{expr.const}, or -when it is explicitly defaulted after its first declaration. \begin{note} The copy/move constructor is implicitly defined even if the implementation elided its odr-use\iref{term.odr.use,class.temporary}. \end{note} -If the implicitly-defined constructor would satisfy the requirements of a -constexpr function\iref{dcl.constexpr}, the implicitly-defined +If an implicitly-defined\iref{dcl.fct.def.default} constructor would be constexpr-suitable\iref{dcl.constexpr}, +the implicitly-defined constructor is \keyword{constexpr}. \pnum @@ -1623,7 +1693,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}). @@ -1683,16 +1753,12 @@ copy assignment operators, and, if selected, will be used to assign an object. \end{footnote} \begin{note} -An overloaded assignment operator must be declared to have only one parameter; -see~\ref{over.ass}. -\end{note} -\begin{note} More than one form of copy assignment operator can be declared for a class. \end{note} \begin{note} If a class \tcode{X} -only has a copy assignment operator with a parameter of type +only has a copy assignment operator with a non-object parameter of type \tcode{X\&}, an expression of type const \tcode{X} @@ -1732,12 +1798,12 @@ \begin{itemize} \item each direct base class \tcode{B} of \tcode{X} -has a copy assignment operator whose parameter is of type +has a copy assignment operator whose non-object parameter is of type \tcode{const B\&}, \tcode{const volatile B\&}, or \tcode{B}, and \item for all the non-static data members of \tcode{X} that are of a class type \tcode{M} (or array thereof), -each such class type has a copy assignment operator whose parameter is of type +each such class type has a copy assignment operator whose non-object parameter is of type \tcode{const M\&}, \tcode{const volatile M\&}, or \tcode{M}. \begin{footnote} @@ -1759,11 +1825,6 @@ one non-object parameter of type \tcode{X\&\&}, \tcode{const X\&\&}, \tcode{volatile X\&\&}, or \tcode{const volatile X\&\&}. \begin{note} -An overloaded assignment operator must be -declared to have only one parameter; see~\ref{over.ass}. -\end{note} -{} -\begin{note} More than one form of move assignment operator can be declared for a class. \end{note} @@ -1825,21 +1886,19 @@ A defaulted copy/move assignment operator for class \tcode{X} is defined as deleted if \tcode{X} has: \begin{itemize} -\item a variant member with a non-trivial corresponding assignment operator and - \tcode{X} is a union-like class, or - \item a non-static data member of \keyword{const} non-class - type (or 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 array thereof) or a direct base class \tcode{M} + (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, results in an ambiguity or - a function that is deleted or inaccessible from the - defaulted assignment operator. + 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} \begin{note} @@ -1853,7 +1912,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 @@ -1871,7 +1930,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 @@ -1893,18 +1952,7 @@ \defnx{non-trivial}{assignment operator!copy!non-trivial}. \pnum -\indextext{assignment operator!copy!implicitly defined}% -\indextext{assignment operator!move!implicitly defined}% -A copy/move assignment operator for a class \tcode{X} -that is defaulted and not defined as deleted -is -\term{implicitly defined} -when it is odr-used\iref{term.odr.use} -(e.g., when it is selected by overload resolution -to assign to an object of its class type), -when it is needed for constant evaluation\iref{expr.const}, or -when it is explicitly defaulted after its first declaration. -The implicitly-defined copy/move assignment operator is \keyword{constexpr}. +An implicitly-defined\iref{dcl.fct.def.default} copy/move assignment operator is \keyword{constexpr}. \pnum Before the defaulted copy/move assignment operator for a class is @@ -1961,7 +2009,7 @@ \end{example} \pnum -The implicitly-defined copy assignment operator for a +The implicitly-defined copy/move assignment operator for a union \tcode{X} copies the object representation\iref{term.object.representation} of \tcode{X}. If the source and destination of the assignment are not the same object, then for each object nested within\iref{intro.object} @@ -2014,9 +2062,8 @@ shall be \keyword{friend}, \keyword{inline}, -\keyword{virtual}, -\keyword{constexpr}, or -\keyword{consteval}. +\keyword{virtual}, or +\keyword{constexpr}. \pnum \indextext{generated destructor|see{destructor, default}}% @@ -2081,29 +2128,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 \tcode{X} is a union-like class that has a variant - member with a non-trivial destructor, - -\item any potentially constructed subobject has class type - \tcode{M} (or array thereof) and - \tcode{M} has a deleted destructor or a destructor - that is inaccessible from the defaulted destructor, +\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, -\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} @@ -2112,15 +2172,7 @@ \pnum A defaulted destructor is a constexpr destructor -if it satisfies the requirements for a constexpr function\iref{dcl.constexpr}. - -\pnum -A destructor -that is defaulted and not defined as deleted -is -\defnx{implicitly defined}{destructor!implicitly defined} -when it is odr-used\iref{term.odr.use} -or when it is explicitly defaulted after its first declaration. +if it is constexpr-suitable\iref{dcl.constexpr}. \pnum Before a @@ -2155,7 +2207,8 @@ \tcode{X} calls the destructors for \tcode{X}'s -direct non-variant non-static data members, the destructors for +direct non-variant non-static data members other than anonymous unions, +the destructors for \tcode{X}'s non-virtual direct base classes and, if \tcode{X} @@ -2229,7 +2282,7 @@ In an explicit destructor call, the destructor is specified by a \tcode{\~{}} followed by a -\grammarterm{type-name} or \grammarterm{decltype-specifier} +\grammarterm{type-name} or \grammarterm{computed-type-specifier} that denotes the destructor's class type. The invocation of a destructor is subject to the usual rules for member functions\iref{class.mfct}; @@ -2282,7 +2335,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 { @@ -2298,6 +2351,7 @@ p->X::~X(); // cleanup } \end{codeblock} +\end{example} \end{note} \pnum @@ -2353,8 +2407,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 @@ -2385,14 +2438,12 @@ 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} struct X { X(int); - X(const char*, int =0); + X(const char*, int = 0); X(int, int); }; @@ -2437,14 +2488,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}}% @@ -2473,10 +2516,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-seq} \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 @@ -2495,6 +2537,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}. @@ -2503,24 +2546,16 @@ 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 -A conversion function is never used to convert a (possibly cv-qualified) object -to the (possibly cv-qualified) same object type (or a reference to it), -to a (possibly cv-qualified) base class of that type (or a reference to it), +\begin{note} +A conversion function is never invoked for +implicit or explicit conversions of an object +to the same object type (or a reference to it), +to a base class of that type (or a reference to it), or to \cv{}~\keyword{void}. -\begin{footnote} -These conversions are considered -as standard conversions for the purposes of overload resolution\iref{over.best.ics,over.ics.ref} and therefore initialization\iref{dcl.init} and explicit casts\iref{expr.static.cast}. A conversion to \keyword{void} does not invoke any conversion function\iref{expr.static.cast}. Even though never directly called to perform a conversion, such conversion functions can be declared and can potentially be reached through a call to a virtual conversion function in a base class. -\end{footnote} +\end{note} \begin{example} \begin{codeblock} struct X { @@ -2816,9 +2851,8 @@ \end{note} \pnum -\indextext{bit-field!unnamed}% A declaration for a bit-field that omits the \grammarterm{identifier} -declares an \defn{unnamed bit-field}. Unnamed bit-fields are not +declares an \defnadj{unnamed}{bit-field}. Unnamed bit-fields are not members and cannot be initialized. An unnamed bit-field shall not be declared with a cv-qualified type. \begin{note} @@ -2937,7 +2971,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(); @@ -2973,6 +3007,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 @@ -2981,7 +3016,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(); @@ -2999,6 +3034,7 @@ delete[] bp; // undefined behavior } \end{codeblock} +\end{example} \end{note} \pnum @@ -3114,8 +3150,7 @@ structs that share a common initial sequence\iref{class.mem}, and if a non-static data member of an object of this standard-layout union type is active and is one of the standard-layout structs, -it is permitted to inspect the common initial sequence -of any of the standard-layout struct members; +the common initial sequence of any of the standard-layout struct members can be inspected; see~\ref{class.mem}. \end{note} @@ -3140,22 +3175,18 @@ 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. -\end{note} - -\pnum \begin{example} Consider the following union: - \begin{codeblock} union U { int i; @@ -3163,14 +3194,14 @@ std::string s; }; \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} \pnum When the left operand of an assignment operator @@ -3200,9 +3231,12 @@ 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}$)$, +for each element \tcode{X} of $S($\tcode{E1}$)$ and +each anonymous union member \tcode{X}\iref{class.union.anon} that +is a member of a union and +has such an element as an immediate subobject (recursively), if modification of \tcode{X} would have undefined behavior under~\ref{basic.life}, an object of the type of \tcode{X} is implicitly created in the nominated storage; @@ -3298,11 +3332,12 @@ \pnum \indextext{\idxcode{union}!global anonymous}% \indextext{scope!anonymous \tcode{union} at namespace}% -Anonymous unions declared in the scope of a namespace with external linkage -shall be declared \keyword{static}. Anonymous unions declared at -block scope shall be declared with any storage class allowed for a -block variable, or with no storage class. A storage class is not -allowed in a declaration of an anonymous union in a class scope. +An anonymous union declared in the scope of a namespace with external linkage +shall use the \grammarterm{storage-class-specifier} \keyword{static}. +Anonymous unions declared at block scope shall not use a \grammarterm{storage-class-specifier} +that is not permitted in the declaration of a block variable. +An anonymous union declaration at class scope shall not have +a \grammarterm{storage-class-specifier}. \pnum \begin{note} @@ -3399,13 +3434,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}% @@ -3452,7 +3487,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}}% @@ -3776,13 +3811,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,9 +4305,7 @@ \indextext{access control!default}% Members of a class defined with the keyword \keyword{class} -are -\keyword{private} -by default. +are private by default. Members of a class defined with the keywords \keyword{struct} or \keyword{union} are public by default. @@ -4299,12 +4332,24 @@ access control is applied to it, not to the declarations that replace it. For an overload set, access control is applied only to the function selected by overload resolution. +\begin{example} +\begin{codeblock} +struct S { + void f(int); +private: + void f(double); +}; + +void g(S* sp) { + sp->f(2); // OK, access control applied after overload resolution +} +\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, - +\begin{example} \begin{codeblock} class A { class B { }; @@ -4317,6 +4362,7 @@ A::B y; // access error, \tcode{A::B} is private } \end{codeblock} +\end{example} \end{note} \pnum @@ -4346,8 +4392,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; @@ -4355,8 +4401,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 { }; @@ -4581,8 +4627,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: @@ -4607,6 +4652,7 @@ bp2->mi = 3; // OK, access through a pointer to \tcode{B}. } \end{codeblock} +\end{example} \end{note} \pnum @@ -4871,27 +4917,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 \keyword{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 @@ -4903,21 +4944,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} @@ -5292,7 +5337,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} @@ -5353,7 +5398,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} @@ -5473,8 +5518,8 @@ \grammarterm{class-or-decltype} that denotes the constructor's class itself. If a \grammarterm{mem-initializer-id} designates the constructor's class, it shall be the only \grammarterm{mem-initializer}; the constructor -is a \term{delegating constructor}, and the constructor selected by the -\grammarterm{mem-initializer} is the \term{target constructor}. +is a \defnadj{delegating}{constructor}, and the constructor selected by the +\grammarterm{mem-initializer} is the \defnadj{target}{constructor}. The target constructor is selected by overload resolution. Once the target constructor returns, the body of the delegating constructor is executed. If a constructor delegates to itself directly or indirectly, @@ -5589,7 +5634,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} @@ -5605,7 +5650,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} @@ -5773,18 +5818,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 { @@ -5853,9 +5907,16 @@ were used to initialize the \tcode{D} object and each base class subobject from which the constructor was inherited, except that the \tcode{B} subobject is initialized -by the invocation of the inherited constructor. +by the inherited constructor +if the base class subobject were to be initialized +as part of the \tcode{D} object\iref{class.base.init}. +The invocation of the inherited constructor, +including the evaluation of any arguments, +is omitted if the \tcode{B} subobject is not to be initialized +as part of the \tcode{D} object. The complete initialization is considered to be a single function call; -in particular, the initialization of the inherited constructor's parameters +in particular, unless omitted, +the initialization of the inherited constructor's parameters is sequenced before the initialization of any part of the \tcode{D} object. \begin{example} \begin{codeblock} @@ -5879,7 +5940,7 @@ D1 d(2, 3, 4); // OK, \tcode{B1} is initialized by calling \tcode{B1(2, 3, 4)}, // then \tcode{d.x} is default-initialized (no initialization is performed), // then \tcode{d.y} is initialized by calling \tcode{get()} - D1 e; // error: \tcode{D1} has a deleted default constructor + D1 e; // error: \tcode{D1} has no default constructor } struct D2 : B2 { @@ -5887,7 +5948,7 @@ B1 b; }; -D2 f(1.0); // error: \tcode{B1} has a deleted default constructor +D2 f(1.0); // error: \tcode{B1} has no default constructor struct W { W(int); }; struct X : virtual W { using W::W; X() = delete; }; @@ -5905,6 +5966,23 @@ whenever an object of class \tcode{Log} is destroyed. \end{example} +\begin{example} +\begin{codeblock} +struct V { V() = default; V(int); }; +struct Q { Q(); }; +struct A : virtual V, Q { + using V::V; + A() = delete; +}; +int bar() { return 42; } +struct B : A { + B() : A(bar()) {} // OK +}; +struct C : B {}; +void foo() { C c; } // \tcode{bar} is not invoked, because the \tcode{V} subobject is not initialized as part of \tcode{B} +\end{codeblock} +\end{example} + \pnum If the constructor was inherited from multiple base class subobjects of type \tcode{B}, the program is ill-formed. @@ -5976,7 +6054,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, @@ -5994,11 +6072,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; @@ -6083,6 +6162,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 @@ -6212,25 +6294,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}, @@ -6238,34 +6321,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 an -exception handler\iref{except.pre} 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 +\item when the \grammarterm{exception-declaration} of a +\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 @@ -6413,12 +6497,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 @@ -6427,18 +6514,28 @@ where the implicit object parameter (if any) is considered to be the first parameter. \end{itemize} -A comparison operator function for class \tcode{C} that -is defaulted on its first declaration and -is not defined as deleted is -\defnx{implicitly defined}{operator!comparison!implicitly defined} -when it is odr-used or needed for constant evaluation. -Name lookups in the defaulted definition +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} @@ -6543,7 +6640,7 @@ is usable\iref{class.compare.default}. \pnum -The return value \tcode{V} of a defaulted \tcode{==} operator function +The return value of a defaulted \tcode{==} operator function with parameters \tcode{x} and \tcode{y} is determined by comparing corresponding elements $\tcode{x}_i$ and $\tcode{y}_i$ in the expanded lists of subobjects for \tcode{x} and \tcode{y} @@ -6551,8 +6648,8 @@ until the first index $i$ where $\tcode{x}_i\tcode{ == }\tcode{y}_i$ yields a result value which, when contextually converted to \tcode{bool}, yields \tcode{false}. -If no such index exists, \tcode{V} is \tcode{true}. -Otherwise, \tcode{V} is \tcode{false}. +The return value is \tcode{false} if such an index exists +and \tcode{true} otherwise. \pnum \begin{example} @@ -6576,11 +6673,13 @@ \begin{itemize} \item -If \tcode{a <=> b} is usable\iref{class.compare.default}, +If \tcode{a <=> b} is usable\iref{class.compare.default} and +can be explicitly converted to \tcode{R} using \keyword{static_cast}, \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. @@ -6650,7 +6749,7 @@ \end{itemize} \pnum -The return value \tcode{V} of type \tcode{R} +The return value of type \tcode{R} of the defaulted three-way comparison operator function with parameters \tcode{x} and \tcode{y} of the same type is determined by comparing corresponding elements @@ -6661,10 +6760,10 @@ the synthesized three-way comparison of type \tcode{R} between $\tcode{x}_i$ and $\tcode{y}_i$ yields a result value $\tcode{v}_i$ where $\tcode{v}_i \mathrel{\tcode{!=}} 0$, -contextually converted to \tcode{bool}, yields \tcode{true}; -\tcode{V} is a copy of $\tcode{v}_i$. -If no such index exists, \tcode{V} is -\tcode{static_cast(std::strong_ordering::equal)}. +contextually converted to \tcode{bool}, yields \tcode{true}. +The return value is a copy of $\tcode{v}_i$ +if such an index exists and +\tcode{static_cast(std::strong_ordering::equal)} otherwise. \pnum The \defn{common comparison type} \tcode{U} @@ -6705,18 +6804,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 21cd9c51eb..2e4d0d5bb6 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -1,6 +1,392 @@ %!TEX root = std.tex \infannex{diff}{Compatibility} +\rSec1[diff.cpp23]{\Cpp{} and ISO \CppXXIII{}} + +\rSec2[diff.cpp23.general]{General} + +\pnum +\indextext{summary!compatibility with ISO \CppXXIII{}}% +Subclause \ref{diff.cpp23} lists the differences between \Cpp{} and +ISO \CppXXIII{}, +by the chapters of this document. + +\rSec2[diff.cpp23.lex]{\ref{lex}: Lexical conventions} + +\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} +\change +Operations mixing a value of an enumeration type and a value of a different +enumeration type or of a floating-point type are no longer valid. +\rationale +Reinforcing type safety. +\effect +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. +\begin{example} +\begin{codeblock} +enum E1 { e }; +enum E2 { f }; +bool b = e <= 3.7; // ill-formed; previously well-formed +int k = f - e; // ill-formed; previously well-formed +auto x = true ? e : f; // ill-formed; previously well-formed +\end{codeblock} +\end{example} + +\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 +Pointer comparisons between \tcode{initializer_list} objects' backing arrays +are unspecified. +\rationale +Permit the implementation to store backing arrays in static read-only memory. +\effect +Valid \CppXXIII{} code +that relies on the result of pointer comparison between backing arrays +may change behavior. +\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 +Previously, \tcode{T...[n]} would declare a pack of function parameters. +\tcode{T...[n]} is now a \grammarterm{pack-index-specifier}. +\rationale +Improve the handling of packs. +\effect +Valid \CppXXIII{} code that declares a pack of parameters +without specifying a \grammarterm{declarator-id} becomes ill-formed. +\begin{example} +\begin{codeblock} +template +void f(T... [1]); +template +void g(T... ptr[1]); +int main() { + f(nullptr, nullptr); // ill-formed, previously \tcode{void f(int [1], double [1])} + g(nullptr, nullptr); // 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} + +\diffref{headers} +\change +New headers. +\rationale +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}, +\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{}. + +\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{}. + +\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.containers]{\ref{containers}: containers library} + +\diffref{span.overview} +\change +\tcode{span} is constructible from \tcode{initializer_list}. +\rationale +Permit passing a braced initializer list to a function taking \tcode{span}. +\effect +Valid \CppXXIII{} code that relies on the lack of this constructor +may refuse to compile, or change behavior in this revision of \Cpp{}. +\begin{example} +\begin{codeblock} +void one(pair); // \#1 +void one(span); // \#2 +void t1() { one({1, 2}); } // ambiguous between \#1 and \#2; previously called \#1 + +void two(span); +void t2() { two({{1, 2}}); } // ill-formed; previously well-formed + +void *a[10]; +int x = span{a, 0}.size(); // \tcode{x} is \tcode{2}; previously \tcode{0} +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.depr]{\ref{depr}: compatibility features} + +\nodiffref +\change +Remove the type alias \tcode{allocator::is_always_equal}. +\rationale +Non-empty allocator classes derived from \tcode{allocator} needed to explicitly +define an \tcode{is_always_equal} member type so that \tcode{allocator_traits} +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. +\begin{example} +\begin{codeblock} +template +struct MyAlloc : allocator { + int tag; +}; + +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 +Remove the \tcode{basic_string::reserve()} overload with no parameters. +\rationale +The overload of \tcode{reserve} with no parameters is redundant. +The \tcode{shrink_to_fit} member function can be used instead. +\effect +A valid \CppXXIII{} program that calls \tcode{reserve()} +on a \tcode{basic_string} object may fail to compile. +The old functionality can be achieved by calling \tcode{shrink_to_fit()} instead, +or the function call can be safely eliminated with no side effects. + +\nodiffref +\change +Remove header \libnoheader{codecvt} and all its contents. +\rationale +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, +exercising freedoms granted by \ref{zombie.names}. +\effect +A valid \CppXXIII{} program \tcode{\#include}-ing the header or importing the +header unit may fail to compile. Code that uses any of the following names by +importing the standard library modules may fail to compile: +\begin{itemize} +\item \tcode{codecvt_mode}, +\item \tcode{codecvt_utf16}, +\item \tcode{codecvt_utf8}, +\item \tcode{codecvt_utf8_utf16}, +\item \tcode{consume_header}, +\item \tcode{generate_header}, and +\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} @@ -8,15 +394,18 @@ \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 +not present in \UAX{44} properties XID_Start or XID_Continue, or not in Normalization Form C, are now rejected. \rationale Prevent confusing characters in identifiers. @@ -34,10 +423,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} @@ -49,11 +439,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 @@ -63,13 +454,38 @@ \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.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.cpp20.stmt]{\ref{stmt}: statements} + +\diffref{stmt.ranged} +\change +The lifetime of temporary objects in the \grammarterm{for-range-initializer} +is extended until the end of the loop\iref{class.temporary}. +\rationale +Improve usability of the range-based \keyword{for} statement. +\effect +Destructors of some temporary objects are invoked later. +\begin{example} +\begin{codeblock} +void f() { + std::vector v = { 42, 17, 13 }; + std::mutex m; + + for (int x : + static_cast(std::lock_guard(m)), v) { // lock released in \CppXX + std::lock_guard guard(m); // OK in \CppXX, now deadlocks + } +} +\end{codeblock} +\end{example} + +\rSec2[diff.cpp20.dcl]{\ref{dcl}: declarations} \diffref{dcl.init.string} \change @@ -82,7 +498,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]; @@ -98,6 +514,7 @@ f({u8""}); // ambiguous } \end{codeblock} +\end{example} \rSec2[diff.cpp20.temp]{\ref{temp}: templates} @@ -108,7 +525,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)); @@ -117,6 +534,7 @@ f(g); // ill-formed; previously well-formed } \end{codeblock} +\end{example} \rSec2[diff.cpp20.library]{\ref{library}: library introduction} @@ -128,9 +546,15 @@ \effect The following \Cpp{} headers are new: \libheaderref{expected}, -\libheaderref{stdatomic.h}, -\libheaderref{spanstream}, and -\libheaderref{stacktrace}. +\libheaderrefx{flat_map}{flat.map.syn}, +\libheaderrefx{flat_set}{flat.set.syn}, +\libheaderref{generator}, +\libheaderref{mdspan}, +\libheaderref{print}, +\libheaderref{spanstream}, +\libheaderref{stacktrace}, +\libheaderref{stdatomic.h}, and +\libheaderref{stdfloat}. Valid \CppXX{} code that \tcode{\#include}{s} headers with these names may be invalid in this revision of \Cpp{}. @@ -147,7 +571,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}@ @@ -161,6 +585,21 @@ return attempted_equals(p, nullptr); // ill-formed; previously well-formed } \end{codeblock} +\end{example} + +\rSec2[diff.cpp20.memory]{\ref{mem}: memory management library} + +\diffref{allocator.traits.general} +\change +Forbid partial and explicit program-defined specializations +of \tcode{allocator_traits}. +\rationale +Allow addition of \tcode{allocate_at_least} to \tcode{allocator_traits}, +and potentially other members in the future. +\effect +Valid \CppXX{} code +that partially or explicitly specializes \tcode{allocator_traits} +is ill-formed with no diagnostic required in this revision of \Cpp{}. \rSec2[diff.cpp20.utilities]{\ref{utilities}: general utilities library} @@ -177,11 +616,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 @@ -192,9 +632,9 @@ that do not support iteration when const-qualified and that are not copyable. \effect -Valid \CppXX{} code that passes bit fields to formatting functions +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; @@ -203,6 +643,39 @@ auto t = tiny(); std::format("{}", t.bit); // ill-formed, previously returned \tcode{"0"} \end{codeblock} +\end{example} + +\diffref{format.string.std} +\change +Restrict types of formatting arguments +used as \fmtgrammarterm{width} or \fmtgrammarterm{precision} in +a \fmtgrammarterm{std-format-spec}. +\rationale +Disallow types that do not have useful or portable semantics as +a formatting width or precision. +\effect +Valid \CppXX{} code that passes a boolean or character type as +\fmtgrammarterm{arg-id} becomes invalid. +\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 +Removed the \tcode{formatter} specialization: +\begin{codeblock} +template struct formatter; +\end{codeblock} +\rationale +The specialization is inconsistent with the design of \tcode{formatter}, +which is intended to be instantiated only with cv-unqualified object types. +\effect +Valid \CppXX{} code that instantiated the removed specialization +can become ill-formed. \rSec2[diff.cpp20.strings]{\ref{strings}: strings library} @@ -218,7 +691,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); @@ -226,6 +699,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} @@ -237,7 +711,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; @@ -245,10 +719,46 @@ struct D : private B { void f(std::set>& s) { - s.erase(*this); // ill formed; previously well-formed + s.erase(*this); // ill-formed; previously well-formed } }; \end{codeblock} +\end{example} + +\rSec2[diff.cpp20.thread]{\ref{thread}: concurrency support library} + +\diffref{thread.barrier} +\change +In this revision of \Cpp{}, +it is implementation-defined whether a barrier's phase completion step runs +if no thread calls \tcode{wait}. +Previously the phase completion step was guaranteed to run on the last thread that calls \tcode{arrive} or \tcode{arrive_and_drop} during the phase. +In this revision of \Cpp{}, +it can run on any of the threads that arrived or waited at the barrier +during the phase. +\rationale +Correct contradictory wording and +improve implementation flexibility for performance. +\effect +Valid \CppXX{} code using a barrier might have +different semantics in this revision of \Cpp{} +if it depends on a completion function's side effects occurring exactly once, +on a specific thread running the phase completion step, or +on a completion function's side effects occurring +without \tcode{wait} having been called. +\begin{example} +\begin{codeblock} +auto b0 = std::barrier(1); +b0.arrive(); +b0.arrive(); // implementation-defined; previously well-defined + +int data = 0; +auto b1 = std::barrier(1, [&] { data++; }); +b1.arrive(); +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{}} @@ -257,7 +767,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} @@ -272,7 +783,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} @@ -282,6 +793,7 @@ import j1; // was variable declaration; now \grammarterm{module-import-declaration} ::import j2; // variable declaration \end{codeblock} +\end{example} \diffref{lex.header} \change @@ -292,12 +804,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 @@ -345,7 +858,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 {}; @@ -354,6 +867,7 @@ Y y; // ill-formed; previously well-formed } \end{codeblock} +\end{example} \diffref{lex.literal} \indextext{UTF-8}% @@ -368,7 +882,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 @@ -387,6 +901,7 @@ }; ct::type x; // ill-formed; previously well-formed. \end{codeblock} +\end{example} \rSec2[diff.cpp17.basic]{\ref{basic}: basics} @@ -399,7 +914,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; @@ -408,6 +923,7 @@ return a; // undefined behavior; previously returned 123 } \end{codeblock} +\end{example} \diffref{intro.races} \change @@ -436,7 +952,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 @@ -446,12 +962,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 @@ -462,7 +979,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); @@ -473,6 +990,7 @@ int g(); int main() { return g(); } // used to return 42 \end{codeblock} +\end{example} \diffref{dcl.init.aggr} \change @@ -485,7 +1003,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; @@ -518,6 +1036,7 @@ Y y{X{}}; // copy constructor call; previously aggregate-initialization \end{codeblock} +\end{example} \diffref{dcl.init.list} \change @@ -528,10 +1047,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} @@ -548,7 +1068,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 @@ -556,6 +1076,7 @@ explicit(true) (S)(int); // OK }; \end{codeblock} +\end{example} \diffref{class.ctor,class.dtor} \change @@ -566,7 +1087,7 @@ \effect Valid \CppXVII{} code may fail to compile in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} template struct A { @@ -575,6 +1096,7 @@ ~A(); // error: \grammarterm{simple-template-id} not allowed for destructor }; \end{codeblock} +\end{example} \diffref{class.copy.elision} \change @@ -588,7 +1110,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(); @@ -620,6 +1142,7 @@ char c = *s.m; // undefined behavior; previously ok } \end{codeblock} +\end{example} \rSec2[diff.cpp17.over]{\ref{over}: overloading} @@ -636,7 +1159,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; @@ -652,6 +1175,33 @@ (10 != x); // calls \#1, previously selected \#3 } \end{codeblock} +\end{example} + +\diffref{over.match.oper} +\change +Overload resolution may change for equality operators\iref{expr.eq}. +\rationale +Support calling \tcode{operator==} with reversed order of arguments. +\effect +Valid \CppXVII{} code that uses equality operators with conversion functions +may be ill-formed or have different semantics in this revision of \Cpp{}. +\begin{example} +\begin{codeblock} +struct A { + operator int() const { return 10; } +}; + +bool operator==(A, int); // \#1 +// \#2 is built-in candidate: \tcode{bool operator==(int, int);} +bool b = 10 == A(); // calls \#1 with reversed order of arguments; previously selected \#2 + +struct B { + bool operator==(const B&); // member function with no cv-qualifier +}; +B b1; +bool eq = (b1 == b1); // ambiguous; previously well-formed +\end{codeblock} +\end{example} \rSec2[diff.cpp17.temp]{\ref{temp}: templates} @@ -662,18 +1212,18 @@ and for which name lookup finds nothing or finds a function will be treated as a \grammarterm{template-name} -in order to potentially cause argument dependent lookup to be performed. +in order to potentially cause argument-dependent lookup to be performed. \rationale It was problematic to call a function template with an explicit template argument list -via argument dependent lookup +via argument-dependent lookup because of the need to have a template with the same name visible via normal lookup. \effect 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); @@ -681,9 +1231,10 @@ int main() { A a; f < a; // ill-formed; previously well-formed - (f) < a; // still well formed + (f) < a; // still well-formed } \end{codeblock} +\end{example} \rSec2[diff.cpp17.except]{\ref{except}: exception handling} @@ -813,13 +1364,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}% @@ -831,13 +1383,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 @@ -851,13 +1404,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 @@ -868,12 +1422,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} @@ -946,7 +1501,7 @@ The result of a call to this member function is not reliable in the presence of multiple threads and weak pointers. The member function \tcode{use_count} is similarly unreliable, but has a clearer contract in such cases, and remains -available for well defined use in single-threaded cases. +available for well-defined use in single-threaded cases. \effect A valid \CppXVII{} program that calls \tcode{unique} on a \tcode{shared_ptr} object may fail to compile. @@ -972,7 +1527,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. @@ -988,8 +1543,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} @@ -1003,11 +1559,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} @@ -1035,7 +1592,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}% @@ -1056,11 +1613,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 @@ -1070,13 +1628,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 @@ -1089,7 +1648,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 { @@ -1102,6 +1661,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} @@ -1116,7 +1676,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); @@ -1130,21 +1690,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; @@ -1153,6 +1714,7 @@ foo(p); // ill-formed; previously well-formed } \end{codeblock} +\end{example} \rSec2[diff.cpp14.except]{\ref{except}: exception handling} @@ -1233,12 +1795,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} @@ -1255,13 +1818,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} @@ -1274,7 +1838,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 @@ -1291,6 +1855,7 @@ s.find(0); } \end{codeblock} +\end{example} \rSec2[diff.cpp14.depr]{\ref{depr}: compatibility features} @@ -1332,7 +1897,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. @@ -1349,13 +1914,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} @@ -1391,7 +1957,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; @@ -1410,8 +1976,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 @@ -1422,7 +1989,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(); @@ -1432,6 +1999,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 @@ -1441,7 +2009,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; @@ -1454,6 +2022,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} @@ -1485,7 +2054,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. @@ -1502,11 +2071,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 @@ -1516,7 +2086,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 @@ -1525,6 +2095,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 @@ -1566,7 +2137,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 @@ -1574,6 +2145,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 @@ -1593,14 +2187,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 @@ -1622,13 +2242,36 @@ 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 +Names declared in an anonymous namespace +changed from external linkage to internal linkage; +language linkage applies to names with external linkage only. +\rationale +Alignment with user expectations. +\effect +Valid \CppIII{} code may violate the one-definition rule\iref{basic.def.odr} +in this revision of \Cpp{}. +\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 +namespace A { extern "C" int x = 42; } // \#2, external linkage and C language linkage +int main(void) { return x; } +\end{codeblock} +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} @@ -1676,7 +2319,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 { }; @@ -1685,6 +2328,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 @@ -1720,11 +2364,10 @@ \libheaderref{array}, \libheaderrefx{atomic}{atomics.syn}, \libheaderrefx{chrono}{time.syn}, -\libdeprheaderref{codecvt}, \libheaderrefx{condition_variable}{condition.variable.syn}, \libheaderrefx{forward_list}{forward.list.syn}, \libheaderref{future}, -\libheaderrefx{initializer_list}{initializer.list.syn}, +\libheaderrefxx{initializer_list}{initiali\-zer_list}{initializer.list.syn}, \libheaderref{mutex}, \libheaderrefx{random}{rand.synopsis}, \libheaderref{ratio}, @@ -1733,7 +2376,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 @@ -1748,12 +2391,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} @@ -1766,15 +2409,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}: @@ -2012,7 +2655,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 @@ -2021,14 +2664,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. @@ -2036,7 +2680,7 @@ \diffref{lex.key} \change -New Keywords\\ +New Keywords.\\ New keywords are added to \Cpp{}; see \ref{lex.key}. \rationale @@ -2044,7 +2688,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. @@ -2059,7 +2703,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 ); @@ -2068,9 +2713,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} @@ -2140,16 +2786,18 @@ \diffref{basic.def} \change \Cpp{} does not have ``tentative definitions'' as in C.\\ -E.g., at file scope, +\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; }; @@ -2157,6 +2805,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. @@ -2174,7 +2823,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; @@ -2182,6 +2831,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 @@ -2251,6 +2901,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; @@ -2259,9 +2910,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 @@ -2269,26 +2921,57 @@ \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. +\begin{example} +\begin{codeblock} +enum E1 { e }; +enum E2 { f }; +int b = e <= 3.7; // valid in C; ill-formed in \Cpp{} +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 +Well-formed C code will not compile with this International Standard. +\difficulty +Violations will be diagnosed by the \Cpp{} translator. +The original behavior can be restored with a cast or integral promotion. +\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. + \diffref{expr.post.incr,expr.pre.incr} \change Decrement operator is not allowed with \keyword{bool} operand. \rationale Feature with surprising semantics. \effect -A valid ISO C expression utilizing the decrement operator on +A 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{}. @@ -2297,11 +2980,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. @@ -2312,7 +2996,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}% @@ -2326,7 +3034,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) @@ -2336,12 +3044,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 @@ -2389,7 +3098,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 @@ -2397,12 +3106,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 @@ -2437,23 +3147,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. @@ -2480,12 +3192,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 @@ -2503,15 +3216,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. @@ -2530,11 +3244,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 @@ -2577,7 +3292,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; }; @@ -2586,10 +3301,11 @@ 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, -so field initializers must be specified in order. +so member initializers must be specified in order. Array designators conflict with \grammarterm{lambda-expression} syntax. Nested designators are seldom used. \effect @@ -2607,10 +3323,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. @@ -2629,11 +3346,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{}. @@ -2650,13 +3368,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. @@ -2677,12 +3396,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 @@ -2701,7 +3422,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() { @@ -2710,6 +3431,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 @@ -2740,7 +3462,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}; @@ -2748,6 +3471,7 @@ struct X x3; x3 = x1; // also invalid \Cpp{} \end{codeblock} +\end{example} \rationale Several alternatives were debated at length. @@ -2800,13 +3524,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. @@ -2824,13 +3549,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 @@ -2844,7 +3570,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 { @@ -2852,6 +3578,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{} @@ -2871,7 +3598,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 @@ -2965,7 +3692,6 @@ 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}, @@ -2973,7 +3699,6 @@ by \libheaderref{stdalign.h}. \rSec3[diff.header.stdbool.h]{Header \tcode{}} -\indexhdr{stdbool.h}% \pnum The tokens \keyword{bool}, \keyword{true}, and \keyword{false} diff --git a/source/concepts.tex b/source/concepts.tex index 801cb8ec57..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 @@ -620,6 +620,11 @@ exchange the values denoted by \tcode{E1} and \tcode{E2}, the program is ill-formed, no diagnostic required. + \begin{note} + This precludes calling unconstrained program-defined overloads of + \tcode{swap}. When the deleted overload is viable, program-defined overloads + need to be more specialized\iref{temp.func.order} to be selected. + \end{note} \item Otherwise, if \tcode{E1} and \tcode{E2} @@ -770,7 +775,7 @@ \begin{itemdecl} template - inline constexpr bool @\exposid{is-default-initializable}@ = @\seebelow@; // \expos + constexpr bool @\exposid{is-default-initializable}@ = @\seebelow@; // \expos template concept @\deflibconcept{default_initializable}@ = @\libconcept{constructible_from}@ && @@ -828,7 +833,7 @@ \begin{itemdescr} \pnum If \tcode{T} is an object type, then let \tcode{v} be an lvalue of type -(possibly \keyword{const}) \tcode{T} or an rvalue of type \tcode{const T}. +\tcode{T} or \tcode{\keyword{const} T} or an rvalue of type \tcode{\keyword{const} T}. \tcode{T} models \libconcept{copy_constructible} only if \begin{itemize} @@ -876,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 @@ -1019,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 @@ -1200,14 +1205,14 @@ \pnum \begin{note} The \libconcept{semiregular} concept is modeled by types that behave similarly -to built-in types like \tcode{int}, except that they need not +to fundamental types like \tcode{int}, except that they need not be comparable with \tcode{==}. \end{note} \pnum \begin{note} The \libconcept{regular} concept is modeled by types that behave similarly to -built-in types like \tcode{int} and that are comparable with +fundamental types like \tcode{int} and that are comparable with \tcode{==}. \end{note} \end{itemdescr} @@ -1217,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 f5acf7b1e1..3937ed3116 100644 --- a/source/config.tex +++ b/source/config.tex @@ -1,13 +1,16 @@ %!TEX root = std.tex %%-------------------------------------------------- %% Version numbers -\newcommand{\docno}{N4917} -\newcommand{\prevdocno}{N4910} -\newcommand{\cppver}{202002L} +\newcommand{\docno}{Dxxxx} +\newcommand{\prevdocno}{N5008} +\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 7d02506cbe..947cfee6d8 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 & @@ -69,35 +70,49 @@ aligned buffers and call \tcode{construct} to place the element into the buffer. \end{note} -\rSec2[container.gen.reqmts]{General containers} +\rSec2[container.requirements.general]{General containers} -\rSec3[container.requirements.general]{General} +\rSec3[container.intro.reqmts]{Introduction} \pnum -In subclause \ref{container.gen.reqmts}, +In \ref{container.requirements.general}, \begin{itemize} \item \tcode{X} denotes a container class containing objects of type \tcode{T}, \item -\tcode{a} and \tcode{b} denote values of type \tcode{X}, +\tcode{a} denotes a value of type \tcode{X}, +\item +\tcode{b} and \tcode{c} denote values of type (possibly const) \tcode{X}, \item \tcode{i} and \tcode{j} denote values of type (possibly const) \tcode{X::iterator}, \item \tcode{u} denotes an identifier, \item -\tcode{r} denotes a non-const value of type \tcode{X}, and +\tcode{v} denotes an lvalue of type (possibly const) \tcode{X} or +an rvalue of type \tcode{const X}, +\item +\tcode{s} and \tcode{t} denote non-const lvalues of type \tcode{X}, and \item \tcode{rv} denotes a non-const rvalue of type \tcode{X}. \end{itemize} -\rSec3[container.reqmts]{Containers} +\pnum +The following exposition-only concept is used in the definition of containers: +\begin{codeblock} +template +concept @\defexposconcept{container-compatible-range}@ = // \expos + ranges::@\libconcept{input_range}@ && @\libconcept{convertible_to}@, T>; +\end{codeblock} + +\rSec3[container.reqmts]{Container requirements} % Local command to index names as members of all containers. \newcommand{\indexcont}[1]{% -\indexlibrarymisc{#1}{containers}% +\indexlibrarymisc{\idxcode{#1}}{containers}% \indexlibrarymemberx{array}{#1}% \indexlibrarymemberx{deque}{#1}% \indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{hive}{#1}% \indexlibrarymemberx{list}{#1}% \indexlibrarymemberx{vector}{#1}% \indexlibrarymemberx{map}{#1}% @@ -108,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 @@ -219,8 +238,8 @@ \end{itemdescr} \begin{itemdecl} -X u(a); -X u = a; +X u(v); +X u = v; \end{itemdecl} \begin{itemdescr} @@ -230,7 +249,7 @@ \pnum \ensures -\tcode{u == a} +\tcode{u == v}. \pnum \complexity @@ -249,11 +268,30 @@ \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=}% \begin{itemdecl} -a = rv +t = v; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&}. + +\pnum +\ensures +\tcode{t == v}. + +\pnum +\complexity +Linear. +\end{itemdescr} + +\begin{itemdecl} +t = rv \end{itemdecl} \begin{itemdescr} @@ -263,12 +301,12 @@ \pnum \effects -All existing elements of \tcode{a} are either move assigned to or destroyed. +All existing elements of \tcode{t} are either move assigned to or destroyed. \pnum \ensures -If \tcode{a} and \tcode{rv} do not refer to the same object, -\tcode{a} is equal to the value that \tcode{rv} had before this assignment. +If \tcode{t} and \tcode{rv} do not refer to the same object, +\tcode{t} is equal to the value that \tcode{rv} had before this assignment. \pnum \complexity @@ -282,7 +320,7 @@ \begin{itemdescr} \pnum \result -\keyword{void} +\keyword{void}. \pnum \effects @@ -295,14 +333,14 @@ \indexcont{begin}% \begin{itemdecl} -a.begin() +b.begin() \end{itemdecl} \begin{itemdescr} \pnum \result \tcode{iterator}; -\tcode{const_iterator} for constant \tcode{a}. +\tcode{const_iterator} for constant \tcode{b}. \pnum \returns @@ -315,14 +353,14 @@ \indexcont{end}% \begin{itemdecl} -a.end() +b.end() \end{itemdecl} \begin{itemdescr} \pnum \result \tcode{iterator}; -\tcode{const_iterator} for constant \tcode{a}. +\tcode{const_iterator} for constant \tcode{b}. \pnum \returns @@ -335,7 +373,7 @@ \indexcont{cbegin}% \begin{itemdecl} -a.cbegin() +b.cbegin() \end{itemdecl} \begin{itemdescr} @@ -345,7 +383,7 @@ \pnum \returns -\tcode{const_cast(a).begin()} +\tcode{const_cast(b).begin()} \pnum \complexity @@ -354,7 +392,7 @@ \indexcont{cend}% \begin{itemdecl} -a.cend() +b.cend() \end{itemdecl} \begin{itemdescr} @@ -364,7 +402,7 @@ \pnum \returns -\tcode{const_cast(a).end()} +\tcode{const_cast(b).end()} \pnum \complexity @@ -389,9 +427,27 @@ 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} -a == b +c == b \end{itemdecl} \begin{itemdescr} @@ -401,11 +457,11 @@ \pnum \result -Convertible to \tcode{bool}. +\tcode{bool}. \pnum \returns -\tcode{equal(a.begin(), a.end(), b.begin(), b.end())} +\tcode{equal(c.begin(), c.end(), b.begin(), b.end())} \begin{note} The algorithm \tcode{equal} is defined in \ref{alg.equal}. @@ -413,75 +469,75 @@ \pnum \complexity -Constant if \tcode{a.size() != b.size()}, linear otherwise. +Constant if \tcode{c.size() != b.size()}, linear otherwise. \pnum \remarks \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} -a != b +c != b \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to \tcode{!(a == b)}. +Equivalent to \tcode{!(c == b)}. \end{itemdescr} \indexcont{swap}% \begin{itemdecl} -a.swap(b) +t.swap(s) \end{itemdecl} \begin{itemdescr} \pnum \result -\keyword{void} +\keyword{void}. \pnum \effects -Exchanges the contents of \tcode{a} and \tcode{b}. +Exchanges the contents of \tcode{t} and \tcode{s}. \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} -swap(a, b) +swap(t, s) \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to \tcode{a.swap(b)}. -\end{itemdescr} - -\indexcont{operator=}% -\begin{itemdecl} -r = a -\end{itemdecl} - -\begin{itemdescr} -\pnum -\result -\tcode{X\&}. - -\pnum -\ensures -\tcode{r == a}. - -\pnum -\complexity -Linear. +Equivalent to \tcode{t.swap(s)}. \end{itemdescr} \indexcont{size}% \begin{itemdecl} -a.size() +c.size() \end{itemdecl} \begin{itemdescr} @@ -491,8 +547,8 @@ \pnum \returns -\tcode{distance(a.begin(), a.end())}, -i.e. the number of elements in the container. +\tcode{distance(c.begin(), c.end())}, +i.e., the number of elements in the container. \pnum \complexity @@ -506,7 +562,7 @@ \indexcont{max_size}% \begin{itemdecl} -a.max_size() +c.max_size() \end{itemdecl} \begin{itemdescr} @@ -525,17 +581,17 @@ \indexcont{empty}% \begin{itemdecl} -a.empty() +c.empty() \end{itemdecl} \begin{itemdescr} \pnum \result -Convertible to \tcode{bool}. +\tcode{bool}. \pnum \returns -\tcode{a.begin() == a.end()} +\tcode{c.begin() == c.end()} \pnum \complexity @@ -543,7 +599,7 @@ \pnum \remarks -If the container is empty, then \tcode{a.empty()} is true. +If the container is empty, then \tcode{c.empty()} is \tcode{true}. \end{itemdescr} \pnum @@ -604,16 +660,17 @@ \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. -Lvalues of any \tcode{Compare}, \tcode{Pred}, or \tcode{Hash} types -belonging to \tcode{a} and \tcode{b} shall be swappable +Any \tcode{Compare}, \tcode{Pred}, or \tcode{Hash} types +belonging to \tcode{a} and \tcode{b} shall meet the \oldconcept{Swappable} requirements and shall be exchanged by calling \tcode{swap} as described in~\ref{swappable.requirements}. If \tcode{allocator_traits::propagate_on_container_swap::value} is \tcode{true}, then -lvalues of type \tcode{allocator_type} shall be swappable and +\tcode{allocator_type} shall meet the \oldconcept{Swap\-pable} requirements and the allocators of \tcode{a} and \tcode{b} shall also be exchanged by calling \tcode{swap} as described in~\ref{swappable.requirements}. Otherwise, the allocators shall not be swapped, and the behavior is @@ -623,13 +680,91 @@ with value \tcode{a.end()} before the swap will have value \tcode{b.end()} after the swap. +\pnum +Unless otherwise specified (see~\ref{associative.reqmts.except}, \ref{unord.req.except}, \ref{deque.modifiers}, \ref{inplace.vector.modifiers}, and +\ref{vector.modifiers}) +all container types defined in this Clause meet +the following additional requirements: + +\begin{itemize} +\item +If an exception is thrown by an +\tcode{insert()} or \tcode{emplace()} +function while inserting a single element, that +function has no effects. +\item +If an exception is thrown by a +\tcode{push_back()}, +\tcode{push_front()}, +\tcode{emplace_back()}, or \tcode{emplace_front()} +function, that function has no effects. +\item +No +\tcode{erase()}, +\tcode{clear()}, +\tcode{pop_back()} +or +\tcode{pop_front()} +function throws an exception. +\item +No copy constructor or assignment operator of a returned iterator +throws an exception. +\item +No +\tcode{swap()} +function throws an exception. +\item +No +\tcode{swap()} +function invalidates any references, +pointers, or iterators referring to the elements +of the containers being swapped. +\begin{note} +The \tcode{end()} iterator does not refer to any element, so it can be invalidated. +\end{note} +\end{itemize} + +\pnum +Unless otherwise specified (either explicitly or by defining a +function in terms of other functions), invoking a container member +function or passing a container as an argument to a library function +shall not invalidate iterators to, or change the values of, objects +within that container. + +\pnum +A \defnadj{contiguous}{container} +is a container +whose member types \tcode{iterator} and \tcode{const_iterator} +meet the +\oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators} and +model \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}. + +\pnum +The behavior of certain container member functions and deduction guides +depends on whether types qualify as input iterators or allocators. +The extent to which an implementation determines that a type cannot be an input +iterator is unspecified, except that as a minimum integral types shall not qualify +as input iterators. +Likewise, the extent to which an implementation determines that a type cannot be +an allocator is unspecified, except that as a minimum a type \tcode{A} shall not qualify +as an allocator unless it meets both of the following conditions: + +\begin{itemize} +\item The \grammarterm{qualified-id} \tcode{A::value_type} +is valid and denotes a type\iref{temp.deduct}. + +\item The expression \tcode{declval().allocate(size_t\{\})} +is well-formed when treated as an unevaluated operand. +\end{itemize} + \rSec3[container.rev.reqmts]{Reversible container requirements} % Local command to index names as members of all containers. \renewcommand{\indexcont}[1]{% -\indexlibrarymisc{#1}{reversible containers}% +\indexlibrarymisc{\idxcode{#1}}{reversible containers}% \indexlibrarymemberx{array}{#1}% \indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{hive}{#1}% \indexlibrarymemberx{list}{#1}% \indexlibrarymemberx{vector}{#1}% \indexlibrarymemberx{map}{#1}% @@ -640,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 @@ -753,64 +892,6 @@ Constant. \end{itemdescr} -\pnum -Unless otherwise specified (see~\ref{associative.reqmts.except}, \ref{unord.req.except}, \ref{deque.modifiers}, and -\ref{vector.modifiers}) -all container types defined in this Clause meet -the following additional requirements: - -\begin{itemize} -\item -if an exception is thrown by an -\tcode{insert()} or \tcode{emplace()} -function while inserting a single element, that -function has no effects. -\item -if an exception is thrown by a -\tcode{push_back()}, -\tcode{push_front()}, -\tcode{emplace_back()}, or \tcode{emplace_front()} -function, that function has no effects. -\item -no -\tcode{erase()}, -\tcode{clear()}, -\tcode{pop_back()} -or -\tcode{pop_front()} -function throws an exception. -\item -no copy constructor or assignment operator of a returned iterator -throws an exception. -\item -no -\tcode{swap()} -function throws an exception. -\item -no -\tcode{swap()} -function invalidates any references, -pointers, or iterators referring to the elements -of the containers being swapped. -\begin{note} -The \tcode{end()} iterator does not refer to any element, so it can be invalidated. -\end{note} -\end{itemize} - -\pnum -Unless otherwise specified (either explicitly or by defining a -function in terms of other functions), invoking a container member -function or passing a container as an argument to a library function -shall not invalidate iterators to, or change the values of, objects -within that container. - -\pnum -A \defnadj{contiguous}{container} -is a container -whose member types \tcode{iterator} and \tcode{const_iterator} -meet the -\oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators} and -model \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}. \rSec3[container.opt.reqmts]{Optional container requirements} @@ -824,6 +905,26 @@ then the operations described below are implemented by constexpr functions. +% Local command to index a name as a member of all containers. +\renewcommand{\indexcont}[1]{% +\indexlibrarymisc{\idxcode{#1}}{optional container requirements}% +\indexlibrarymemberx{array}{#1}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +\indexlibrarymemberx{map}{#1}% +\indexlibrarymemberx{set}{#1}% +\indexlibrarymemberx{multiset}{#1}% +\indexlibrarymemberx{multimap}{#1}% +\indexlibrarymemberx{flat_map}{#1}% +\indexlibrarymemberx{flat_set}{#1}% +\indexlibrarymemberx{flat_multiset}{#1}% +\indexlibrarymemberx{flat_multimap}{#1}% +\indexlibrarymemberx{basic_string}{#1}% +} + +\indexcont{operator<=>}% \begin{itemdecl} a <=> b \end{itemdecl} @@ -835,7 +936,7 @@ \pnum \expects -Either \tcode{<=>} is defined for values of type (possibly const) \tcode{T}, +Either \tcode{T} models \libconcept{three_way_comparable}, or \tcode{<} is defined for values of type (possibly const) \tcode{T} and \tcode{<} is a total ordering relationship. @@ -856,7 +957,9 @@ \rSec3[container.alloc.reqmts]{Allocator-aware containers} \pnum -All of the containers defined in \ref{containers} and in~\ref{basic.string} except \tcode{array} +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. @@ -866,7 +969,9 @@ and an \tcode{allocator_type} identical to \tcode{allocator_traits::rebind_alloc} and given an lvalue \tcode{m} of type \tcode{A}, a pointer \tcode{p} of type \tcode{T*}, -an expression \tcode{v} of type (possibly \keyword{const}) \tcode{T}, +an expression \tcode{v} that denotes +an lvalue of type \tcode{T} or \tcode{const T} or +an rvalue of type \tcode{const T}, and an rvalue \tcode{rv} of type \tcode{T}, the following terms are defined. If \tcode{X} is not allocator-aware or is a specialization of \tcode{basic_string}, @@ -903,7 +1008,7 @@ and its evaluation causes the following postcondition to hold: The value of \tcode{*p} is equivalent to the value of \tcode{rv} before the evaluation. \begin{note} -\tcode{rv} remains a valid object. Its state is unspecified +\tcode{rv} remains a valid object. Its state is unspecified. \end{note} \item @@ -946,14 +1051,6 @@ but specialized allocators can choose a different definition. \end{note} -\pnum -The following exposition-only concept is used in the definition of containers: -\begin{codeblock} -template -concept @\defexposconcept{container-compatible-range}@ = // \expos - ranges::@\libconcept{input_range}@ && @\libconcept{convertible_to}@, T>; -\end{codeblock} - \pnum In this subclause, \begin{itemize} @@ -976,9 +1073,10 @@ % Local command to index names as members of all containers. \renewcommand{\indexcont}[1]{% -\indexlibrarymisc{#1}{allocator-aware containers}% +\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}% @@ -1007,7 +1105,7 @@ \tcode{A} \pnum -\expects +\mandates \tcode{allocator_type::value_type} is the same as \tcode{X::value_type}. \end{itemdescr} @@ -1070,7 +1168,7 @@ \pnum \ensures -\tcode{u == t}, \tcode{u.get_allocator() == m} +\tcode{u == t}, \tcode{u.get_allocator() == m}. \pnum \complexity @@ -1187,23 +1285,6 @@ Constant. \end{itemdescr} -\pnum -The behavior of certain container member functions and deduction guides -depends on whether types qualify as input iterators or allocators. -The extent to which an implementation determines that a type cannot be an input -iterator is unspecified, except that as a minimum integral types shall not qualify -as input iterators. -Likewise, the extent to which an implementation determines that a type cannot be -an allocator is unspecified, except that as a minimum a type \tcode{A} shall not qualify -as an allocator unless it meets both of the following conditions: - -\begin{itemize} -\item The \grammarterm{qualified-id} \tcode{A::value_type} -is valid and denotes a type\iref{temp.deduct}. - -\item The expression \tcode{declval().allocate(size_t\{\})} -is well-formed when treated as an unevaluated operand. -\end{itemize} \rSec2[container.requirements.dataraces]{Container data races} @@ -1233,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, @@ -1246,24 +1332,6 @@ \tcode{flat_multiset}s, out of the basic sequence container kinds (or out of other program-defined sequence containers). -\pnum -\begin{note} -The sequence containers -offer the programmer different complexity trade-offs. -\tcode{vector} -is appropriate in most circumstances. -\tcode{array} -has a fixed size known during translation. -\tcode{list} or \tcode{forward_list} -support frequent insertions and deletions from the -middle of the sequence. -\tcode{deque} -supports efficient insertions and deletions taking place at the beginning or at the -end of the sequence. -When choosing a container, remember \tcode{vector} is best; -leave a comment to explain if you choose from the rest! -\end{note} - \pnum In this subclause, \begin{itemize} @@ -1283,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}}, @@ -1296,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 @@ -1312,7 +1380,7 @@ % Local command to index names as members of all containers. \renewcommand{\indexcont}[1]{% -\indexlibrarymisc{#1}{sequence containers}% +\indexlibrarymisc{\idxcode{#1}}{sequence containers}% \indexlibrarymemberx{deque}{#1}% \indexlibrarymemberx{forward_list}{#1}% \indexlibrarymemberx{list}{#1}% @@ -1358,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 @@ -1377,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 @@ -1385,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 any reallocation. + \pnum \ensures \tcode{distance(begin(), end()) == ranges::distance(rg)} is \tcode{true}. @@ -1437,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}. @@ -1452,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}% @@ -1469,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 @@ -1493,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 @@ -1542,17 +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 -swappable\iref{swappable.requirements}. +\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 @@ -1576,12 +1653,13 @@ \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}, -\oldconcept{MoveConstructible}, +and \tcode{T} meets the +\oldconcept{Move\-Constructible}, \oldconcept{MoveAssignable}, and -swappable\iref{swappable.requirements}. +\oldconcept{Swappable}\iref{swappable.requirements} requirements. \tcode{rg} and \tcode{a} do not overlap. \pnum @@ -1618,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 @@ -1643,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 @@ -1704,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}, @@ -1733,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. @@ -1745,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} @@ -1821,7 +1909,8 @@ \pnum The following operations are provided for some types of sequence containers but not others. -An implementation shall implement them so as to take amortized constant time. +Operations other than \tcode{prepend_range} and \tcode{append_range} +are implemented so as to take amortized constant time. \begin{itemdecl} a.front() @@ -1832,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()} @@ -1843,6 +1936,7 @@ \tcode{array}, \tcode{deque}, \tcode{forward_list}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -1856,6 +1950,10 @@ \result \tcode{reference; const_reference} for constant \tcode{a}. +\pnum +\hardexpects +\tcode{a.empty()} is \tcode{false}. + \pnum \effects Equivalent to: @@ -1871,6 +1969,7 @@ \tcode{basic_string}, \tcode{array}, \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -1933,6 +2032,7 @@ \remarks Required for \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -2000,6 +2100,12 @@ \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*ranges::begin(rg)}. +For \tcode{deque}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}, and +\tcode{T} meets the +\oldconcept{MoveConstructible}, +\oldconcept{MoveAssignable}, and +\oldconcept{Swappable}\iref{swappable.requirements} requirements. \pnum \effects @@ -2039,6 +2145,7 @@ Required for \tcode{basic_string}, \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -2065,6 +2172,7 @@ Required for \tcode{basic_string}, \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -2095,6 +2203,7 @@ \remarks Required for \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -2109,7 +2218,7 @@ \keyword{void} \pnum -\expects +\hardexpects \tcode{a.empty()} is \tcode{false}. \pnum @@ -2134,7 +2243,7 @@ \keyword{void} \pnum -\expects +\hardexpects \tcode{a.empty()} is \tcode{false}. \pnum @@ -2146,6 +2255,7 @@ Required for \tcode{basic_string}, \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -2157,18 +2267,23 @@ \begin{itemdescr} \pnum \result -\tcode{reference; const_reference} for constant \tcode{a} +\tcode{reference; const_reference} for constant \tcode{a}. \pnum -\returns -\tcode{*(a.begin() + n)} +\hardexpects +\tcode{n < a.size()} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return *(a.begin() + n);} \pnum \remarks Required for \tcode{basic_string}, \tcode{array}, -\tcode{deque}, and +\tcode{deque}, +\tcode{inplace_vector}, and \tcode{vector}. \end{itemdescr} @@ -2179,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 @@ -2194,7 +2309,8 @@ Required for \tcode{basic_string}, \tcode{array}, -\tcode{deque}, and +\tcode{deque}, +\tcode{inplace_vector}, and \tcode{vector}. \end{itemdescr} @@ -2267,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))) { + constexpr friend void swap(@\placeholdernc{node-handle}@& x, @\placeholdernc{node-handle}@& y) noexcept(noexcept(x.swap(y))) { x.swap(y); } }; @@ -2296,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} @@ -2309,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} @@ -2351,7 +2467,7 @@ \rSec3[container.node.dtor]{Destructor} \begin{itemdecl} -~@\placeholdernc{node-handle}@(); +constexpr ~@\placeholdernc{node-handle}@(); \end{itemdecl} \begin{itemdescr} @@ -2366,7 +2482,7 @@ \rSec3[container.node.observers]{Observers} \begin{itemdecl} -value_type& value() const; +constexpr value_type& value() const; \end{itemdecl} \begin{itemdescr} @@ -2409,7 +2525,7 @@ \end{itemdescr} \begin{itemdecl} -mapped_type& mapped() const; +constexpr mapped_type& mapped() const; \end{itemdecl} \begin{itemdescr} @@ -2428,9 +2544,8 @@ Nothing. \end{itemdescr} - \begin{itemdecl} -allocator_type get_allocator() const; +constexpr allocator_type get_allocator() const; \end{itemdecl} \begin{itemdescr} @@ -2448,7 +2563,7 @@ \end{itemdescr} \begin{itemdecl} -explicit operator bool() const noexcept; +constexpr explicit operator bool() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -2458,7 +2573,7 @@ \end{itemdescr} \begin{itemdecl} -[[nodiscard]] bool empty() const noexcept; +constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -2470,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} @@ -2615,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 possibly \keyword{const} value of type \tcode{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 @@ -2625,9 +2740,9 @@ \tcode{a_eq} denotes a value of type \tcode{X} when \tcode{X} supports multiple keys, \item -\tcode{a_tran} denotes a possibly \keyword{const} value of type \tcode{X} +\tcode{a_tran} denotes a value of type \tcode{X} or \tcode{const X} when the \grammarterm{qualified-id} -\tcode{X::key_compare::is_transpa\-rent} is valid +\tcode{X::key_compare::is_transparent} is valid and denotes a type\iref{temp.deduct}, \item \tcode{i} and \tcode{j} @@ -2646,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 @@ -2654,7 +2769,7 @@ \item \tcode{k} denotes a value of type \tcode{X::key_type}, and \item -\tcode{c} denotes a possibly \keyword{const} value of type \tcode{X::key_compare}; +\tcode{c} denotes a value of type \tcode{X::key_compare} or \tcode{const X::key_compare}; \item \tcode{kl} is a value such that \tcode{a} is partitioned\iref{alg.sorting} with respect to \tcode{c(x, kl)}, @@ -2689,16 +2804,16 @@ \pnum A type \tcode{X} meets the \defnadj{associative}{container} requirements if \tcode{X} meets all the requirements of an allocator-aware -container\iref{container.requirements.general} and +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} -are required to be \oldconcept{CopyAssignable} even though the associated +need to be \oldconcept{CopyAssignable} even though the associated \tcode{value_type}, \tcode{pair}, is not \oldconcept{CopyAssignable}. \end{note} @@ -2710,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}% @@ -2906,7 +3025,7 @@ \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} -from \tcode{*range::begin(rg)}. +from \tcode{*ranges::begin(rg)}. \pnum \effects @@ -3487,7 +3606,7 @@ \pnum \expects -\tcode{a.get_allocator() == a2.get_allocator()}. +\tcode{a.get_allocator() == a2.get_allocator()} is \tcode{true}. \pnum \effects @@ -3502,7 +3621,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}. @@ -3824,7 +3944,7 @@ \pnum \complexity -Logarithmic, +Logarithmic. \end{itemdescr} \indexordmem{upper_bound}% @@ -4114,7 +4234,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 possibly const value of type \tcode{X}, +\tcode{b} denotes a value of type \tcode{X} or \tcode{const X}, \item \tcode{a_uniq} denotes a value of type \tcode{X} when \tcode{X} supports unique keys, @@ -4122,7 +4242,7 @@ \tcode{a_eq} denotes a value of type \tcode{X} when \tcode{X} supports equivalent keys, \item -\tcode{a_tran} denotes a possibly const value of type \tcode{X} +\tcode{a_tran} denotes a value of type \tcode{X} or \tcode{const X} when the \grammarterm{qualified-id}s \tcode{X::key_equal::is_transparent} and \tcode{X::hasher::is_transparent} @@ -4131,7 +4251,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}}, @@ -4143,7 +4263,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 @@ -4151,15 +4271,17 @@ \item \tcode{k} denotes a value of type \tcode{key_type}, \item -\tcode{hf} denotes a possibly const value of type \tcode{hasher}, +\tcode{hf} denotes a value of type \tcode{hasher} or \tcode{const hasher}, \item -\tcode{eq} denotes a possibly const value of type \tcode{key_equal}, +\tcode{eq} denotes a value of type \tcode{key_equal} or \tcode{const key_equal}, \item \tcode{ke} is a value such that \begin{itemize} \item \tcode{eq(r1, ke) == eq(ke, r1)}, \item \tcode{hf(r1) == hf(ke)} if \tcode{eq(r1, ke)} is \tcode{true}, and - \item \tcode{(eq(r1, ke) \&\& eq(r1, r2)) == eq(r2, ke)}, + \item if any two of + \tcode{eq(r1, ke)}, \tcode{eq(r2, ke)}, and \tcode{eq(r1, r2)} + are \tcode{true}, then all three are \tcode{true}, \end{itemize} where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran}, \item @@ -4167,7 +4289,9 @@ \begin{itemize} \item \tcode{eq(r1, kx) == eq(kx, r1)}, \item \tcode{hf(r1) == hf(kx)} if \tcode{eq(r1, kx)} is \tcode{true}, - \item \tcode{(eq(r1, kx) \&\& eq(r1, r2)) == eq(r2, kx)}, and + \item if any two of + \tcode{eq(r1, kx)}, \tcode{eq(r2, kx)}, and \tcode{eq(r1, r2)} + are \tcode{true}, then all three are \tcode{true}, and \item \tcode{kx} is not convertible to either \tcode{iterator} or \tcode{const_iterator}, \end{itemize} @@ -4177,22 +4301,22 @@ \item \tcode{z} denotes a value of type \tcode{float}, and \item -\tcode{nh} denotes a non-const rvalue of type \tcode{X::node_type}. +\tcode{nh} denotes an rvalue of type \tcode{X::node_type}. \end{itemize} \pnum A type \tcode{X} meets the \defnadj{unordered associative}{container} requirements if \tcode{X} meets all the requirements of -an allocator-aware container\iref{container.requirements.general} 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} -are sometimes required to be \oldconcept{CopyAssignable} +sometimes need to be \oldconcept{CopyAssignable} even though the associated \tcode{value_type}, \tcode{pair}, is not \oldconcept{CopyAssignable}. @@ -4655,7 +4779,7 @@ \begin{itemdescr} \pnum \effects -In addition to the container requirements\iref{container.requirements.general}, +In addition to the container requirements\iref{container.reqmts}, copies the hash function, predicate, and maximum load factor. \pnum @@ -4796,7 +4920,7 @@ \pnum \effects Inserts a \tcode{value_type} object \tcode{t} -constructed with \tcode{std::forward(args)...} and +constructed with \tcode{std::forward(args)...}. \pnum \returns @@ -4951,7 +5075,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 @@ -5314,7 +5438,7 @@ \pnum \effects -Erases all elements in the range \tcode{[q1, q2)}. +Erases all elements in the range \range{q1}{q2}. \pnum \returns @@ -5550,7 +5674,36 @@ 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 +Constant. +\end{itemdescr} + +\indexunordmem{bucket}% +\begin{itemdecl} +a_tran.bucket(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\expects +\tcode{a_tran.bucket_count() > 0}. + +\pnum +\ensures +The return value is in the range \range{0}{a_tran.bucket_count()}. + +\pnum +\returns +The index of the bucket +in which elements with keys equivalent to \tcode{ke} would be found, +if any such element existed. \pnum \complexity @@ -5569,7 +5722,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 @@ -5592,7 +5745,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 @@ -5616,7 +5769,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 @@ -5639,7 +5792,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 @@ -5663,7 +5816,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 @@ -5822,7 +5975,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. @@ -5839,7 +5992,7 @@ \pnum The member function templates \tcode{find}, \tcode{count}, \tcode{equal_range}, \tcode{contains}, -\tcode{extract}, and \tcode{erase} +\tcode{extract}, \tcode{erase}, and \tcode{bucket} shall not participate in overload resolution unless the \grammarterm{qualified-id}s \tcode{Pred::is_transparent} and @@ -5898,13 +6051,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. @@ -5921,12 +6076,13 @@ \indexheader{array}% \begin{codeblock} +// mostly freestanding #include // see \ref{compare.syn} #include // see \ref{initializer.list.syn} namespace std { // \ref{array}, class template \tcode{array} - template struct array; + template struct array; // partially freestanding template constexpr bool operator==(const array& x, const array& y); @@ -5962,166 +6118,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 - inline 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}% @@ -6131,7 +6127,7 @@ \indextext{\idxcode{array}!contiguous storage}% The header \libheader{array} defines a class template for storing fixed-size sequences of objects. -An \tcode{array} is a contiguous container\iref{container.requirements.general}. +An \tcode{array} is a contiguous container\iref{container.reqmts}. An instance of \tcode{array} stores \tcode{N} elements of type \tcode{T}, so that \tcode{size() == N} is an invariant. @@ -6157,7 +6153,7 @@ for operations where there is additional semantic information. \pnum -\tcode{array} is a structural type\iref{temp.param} if +\tcode{array} is a structural type\iref{term.structural.type} if \tcode{T} is a structural type. Two values \tcode{a1} and \tcode{a2} of type \tcode{array} are template-argument-equivalent\iref{temp.type} if and only if @@ -6212,22 +6208,22 @@ 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; // 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 at(size_type n); // freestanding-deleted + constexpr const_reference at(size_type n) const; // freestanding-deleted constexpr reference front(); constexpr const_reference front() const; constexpr reference back(); constexpr const_reference back() const; - constexpr T * data() noexcept; - constexpr const T * data() const noexcept; + constexpr T* data() noexcept; + constexpr const T* data() const noexcept; }; template @@ -6240,12 +6236,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. @@ -6282,7 +6277,7 @@ \pnum \returns A pointer such that \range{data()}{data() + size()} is a valid range. For a -non-empty array, \tcode{data()} \tcode{==} \tcode{addressof(front())}. +non-empty array, \tcode{data() == addressof(front())} is \keyword{true}. \end{itemdescr} \indexlibrarymember{array}{fill}% @@ -6367,7 +6362,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 @@ -6388,7 +6383,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 @@ -6446,6 +6441,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} @@ -6472,6 +6503,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> @@ -6492,97 +6527,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; + + 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{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 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 - 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; + 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>> @@ -6599,7 +6635,7 @@ \indexlibraryctor{deque}% \begin{itemdecl} -explicit deque(const Allocator&); +constexpr explicit deque(const Allocator&); \end{itemdecl} \begin{itemdescr} @@ -6616,13 +6652,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 @@ -6636,13 +6672,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 @@ -6659,7 +6695,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} @@ -6679,7 +6715,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} @@ -6697,13 +6733,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 @@ -6714,13 +6750,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 @@ -6731,13 +6767,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 @@ -6773,27 +6809,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} @@ -6818,7 +6854,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. @@ -6829,10 +6865,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} @@ -6864,8 +6900,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} @@ -6884,7 +6920,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} @@ -6900,6 +6936,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} @@ -6918,7 +6991,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} @@ -6937,6 +7010,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> @@ -6955,105 +7032,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>> @@ -7077,7 +7157,7 @@ \indexlibraryctor{forward_list}% \begin{itemdecl} -explicit forward_list(const Allocator&); +constexpr explicit forward_list(const Allocator&); \end{itemdecl} \begin{itemdescr} @@ -7092,13 +7172,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 @@ -7112,13 +7192,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 @@ -7132,7 +7212,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} @@ -7148,7 +7228,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} @@ -7167,9 +7247,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} @@ -7192,8 +7272,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} @@ -7205,10 +7285,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 @@ -7216,7 +7299,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} @@ -7228,8 +7311,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} @@ -7241,7 +7324,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} @@ -7255,7 +7338,7 @@ \indexlibrarymember{pop}{forward_list}% \begin{itemdecl} -void pop_front(); +constexpr void pop_front(); \end{itemdecl} \begin{itemdescr} @@ -7266,13 +7349,34 @@ \indexlibrarymember{insert_after}{forward_list}% \begin{itemdecl} -iterator insert_after(const_iterator position, const T& x); -iterator insert_after(const_iterator position, T&& x); +constexpr iterator insert_after(const_iterator position, const T& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{forward_list}. +\tcode{position} is \tcode{before_begin()} or is a dereferenceable +iterator in the range \range{begin()}{end()}. + +\pnum +\effects +Inserts a copy of \tcode{x} after \tcode{position}. + +\pnum +\returns +An iterator pointing to the copy of \tcode{x}. +\end{itemdescr} + +\indexlibrarymember{insert_after}{forward_list}% +\begin{itemdecl} +constexpr iterator insert_after(const_iterator position, T&& x); \end{itemdecl} \begin{itemdescr} \pnum \expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{forward_list}. \tcode{position} is \tcode{before_begin()} or is a dereferenceable iterator in the range \range{begin()}{end()}. @@ -7287,12 +7391,13 @@ \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} \pnum \expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{forward_list}. \tcode{position} is \tcode{before_begin()} or is a dereferenceable iterator in the range \range{begin()}{end()}. @@ -7302,18 +7407,22 @@ \pnum \returns -An iterator pointing to the last inserted copy of \tcode{x} or \tcode{position} if \tcode{n == 0}. +An iterator pointing to the last inserted copy of \tcode{x}, or +\tcode{position} if \tcode{n == 0} is \tcode{true}. \end{itemdescr} \indexlibrarymember{insert_after}{forward_list}% \begin{itemdecl} template - 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} \pnum \expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{forward_list} +from \tcode{*first}. \tcode{position} is \tcode{before_begin()} or is a dereferenceable iterator in the range \range{begin()}{end()}. Neither \tcode{first} nor \tcode{last} are iterators in \tcode{*this}. @@ -7324,19 +7433,22 @@ \pnum \returns -An iterator pointing to the last inserted element or \tcode{position} if \tcode{first == last}. +An iterator pointing to the last inserted element, or +\tcode{position} if \tcode{first == last} is \tcode{true}. \end{itemdescr} \indexlibrarymember{insert_range_after}{forward_list}% \begin{itemdecl} template<@\exposconcept{container-compatible-range}@ R> - iterator insert_range_after(const_iterator position, R&& rg); + constexpr iterator insert_range_after(const_iterator position, R&& rg); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{position} is \tcode{before_begin()} or +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{forward_list} +from \tcode{*ranges::begin(rg)}. +\tcode{posi\-tion} is \tcode{before_begin()} or is a dereferenceable iterator in the range \range{begin()}{end()}. \tcode{rg} and \tcode{*this} do not overlap. @@ -7352,36 +7464,34 @@ \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} \pnum \effects -\tcode{insert_after(position, il.begin(), il.end())}. - -\pnum -\returns -An iterator pointing to the last inserted element or \tcode{position} if \tcode{il} is empty. +Equivalent to: \tcode{return insert_after(position, il.begin(), il.end());} \end{itemdescr} \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} \pnum \expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{forward_list} +from \tcode{std::forward(\linebreak args)...}. \tcode{position} is \tcode{before_begin()} or is a dereferenceable iterator in the range \range{begin()}{end()}. \pnum \effects -Inserts an object of type \tcode{value_type} constructed with -\tcode{value_type(std::forward(\brk{}args)...)} after \tcode{position}. +Inserts an object of type \tcode{value_type} direct-non-list-initialized with +\tcode{std::forward(\linebreak args)...} after \tcode{position}. \pnum \returns @@ -7390,7 +7500,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} @@ -7413,7 +7523,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} @@ -7436,13 +7546,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 @@ -7452,13 +7562,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 @@ -7470,7 +7580,7 @@ \indexlibrarymember{clear}{forward_list}% \begin{itemdecl} -void clear() noexcept; +constexpr void clear() noexcept; \end{itemdecl} \begin{itemdescr} @@ -7501,8 +7611,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} @@ -7532,8 +7642,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} @@ -7564,10 +7674,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} @@ -7595,8 +7705,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} @@ -7628,8 +7738,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} @@ -7667,10 +7777,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} @@ -7711,8 +7821,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} @@ -7733,7 +7843,7 @@ \indexlibrarymember{reverse}{forward_list}% \begin{itemdecl} -void reverse() noexcept; +constexpr void reverse() noexcept; \end{itemdecl} \begin{itemdescr} @@ -7751,21 +7861,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} @@ -7775,82 +7888,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 + hive(InputIterator first, InputIterator last, const Allocator& = Allocator()); template - list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + 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> @@ -7860,1232 +8066,911 @@ 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); +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. - -\pnum -\returns -The number of elements erased. +\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 -\throws -Nothing unless an exception is thrown by the predicate. +\complexity +If reallocation happens, linear in the size of the sequence. \pnum -\complexity -If \tcode{empty()} is \tcode{false}, -exactly \tcode{size() - 1} applications of the corresponding predicate, -otherwise no applications of 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} -\indexlibrarymember{merge}{list}% +\indexlibrarymember{trim_capacity}{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); +void trim_capacity() noexcept; +void trim_capacity(size_type n) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{comp} be \tcode{less<>{}} for the first two overloads. - -\pnum -\expects -\tcode{*this} and \tcode{x} are both sorted -with respect to the comparator \tcode{comp}, and -\tcode{get_allocator() == x.get_allocator()} is \tcode{true}. - -\pnum -\effects -If \tcode{addressof(x) == this}, there are no effects. -Otherwise, merges -the two sorted ranges \range{begin()}{end()} and \range{x.begin()}{x.end()}. -The result is a range -that is sorted with respect to the comparator \tcode{comp}. -Pointers and references to the moved elements of \tcode{x} now refer to those same elements -but as members of \tcode{*this}. Iterators referring to the moved elements will continue to -refer to their elements, but they now behave as iterators into \tcode{*this}, not into -\tcode{x}. +\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 -At most \tcode{size() + x.size() - 1} comparisons -if \tcode{addressof(x) != this}; -otherwise, no comparisons are performed. +Linear in the number of reserved blocks deallocated. \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. +All references, pointers, and iterators referring to elements in \tcode{*this}, +as well as the past-the-end iterator, remain valid. \end{itemdescr} -\indexlibrarymember{reverse}{list}% +\indexlibrarymember{block_capacity_limits}{hive}% \begin{itemdecl} -void reverse() noexcept; +constexpr hive_limits block_capacity_limits() const 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 +\exposid{current-limits}. \pnum \complexity -Linear time. +Constant. \end{itemdescr} -\indexlibrarymember{sort}{list}% +\indexlibrarymember{block_capacity_default_limits}{hive}% \begin{itemdecl} -void sort(); -template void sort(Compare comp); +static constexpr hive_limits block_capacity_default_limits() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Sorts the list according to the \tcode{operator<} or a \tcode{Compare} function object. -If an exception is thrown, -the order of the elements in \tcode{*this} is unspecified. -Does not affect the validity of iterators and references. +\returns +A \tcode{hive_limits} struct +with the \tcode{min} and \tcode{max} members set to +the implementation's default limits. \pnum \complexity -Approximately -$N \log N$ -comparisons, where -\tcode{N == size()}. - -\pnum -\remarks -Stable\iref{algorithm.stable}. +Constant. \end{itemdescr} -\rSec3[list.erasure]{Erasure} - -\indexlibrarymember{erase}{list}% +\indexlibrarymember{block_capacity_hard_limits}{hive}% \begin{itemdecl} -template - typename list::size_type - erase(list& c, const U& value); +static constexpr hive_limits block_capacity_hard_limits() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return erase_if(c, [\&](auto\& elem) \{ return elem == value; \});} +\returns +A \tcode{hive_limits} struct +with the \tcode{min} and \tcode{max} members set to +the implementation's hard limits. + +\pnum +\complexity +Constant. \end{itemdescr} -\indexlibrarymember{erase_if}{list}% +\indexlibrarymember{reshape}{hive}% \begin{itemdecl} -template - typename list::size_type - erase_if(list& c, Predicate pred); +void reshape(hive_limits block_limits); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return c.remove_if(pred);} -\end{itemdescr} - -\rSec2[vector]{Class template \tcode{vector}} - -\rSec3[vector.overview]{Overview} +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{hive}. \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 +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 -A \tcode{vector} meets all of the requirements -of a container\iref{container.reqmts}, -of a reversible container\iref{container.rev.reqmts}, -of an allocator-aware container\iref{container.alloc.reqmts}, -of a sequence container, including most of the optional sequence container -requirements\iref{sequence.reqmts}, -and, for an element type other than \tcode{bool}, -of a contiguous container\iref{container.requirements.general}. -The exceptions are the -\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. +\ensures +\tcode{size()} is unchanged. \pnum -The types \tcode{iterator} and \tcode{const_iterator} meet -the constexpr iterator requirements\iref{iterator.requirements.general}. - -\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; - - // \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; - - // iterators - constexpr iterator begin() noexcept; - constexpr const_iterator begin() const noexcept; - constexpr iterator end() noexcept; - constexpr const_iterator end() const noexcept; - constexpr reverse_iterator rbegin() noexcept; - constexpr const_reverse_iterator rbegin() const noexcept; - constexpr reverse_iterator rend() noexcept; - constexpr const_reverse_iterator rend() const noexcept; - - constexpr const_iterator cbegin() const noexcept; - constexpr const_iterator cend() const noexcept; - constexpr const_reverse_iterator crbegin() const noexcept; - constexpr const_reverse_iterator crend() const noexcept; - - // \ref{vector.capacity}, capacity - [[nodiscard]] constexpr bool empty() const noexcept; - constexpr size_type size() const noexcept; - constexpr size_type max_size() const noexcept; - constexpr size_type capacity() const noexcept; - constexpr void resize(size_type sz); - constexpr void resize(size_type sz, const T& c); - constexpr void reserve(size_type n); - constexpr void shrink_to_fit(); +\complexity +Linear in the number of element blocks in \tcode{*this}. +If reallocation happens, also linear in the number of elements reallocated. - // 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; +\pnum +\remarks +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} - // \ref{vector.data}, data access - constexpr T* data() noexcept; - constexpr const T* data() const noexcept; +\rSec3[hive.modifiers]{Modifiers} - // \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(); +\indexlibrarymember{emplace}{hive}% +\begin{itemdecl} +template iterator emplace(Args&&... args); +template iterator emplace_hint(const_iterator hint, Args&&... args); +\end{itemdecl} - 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; - }; +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{hive} from \tcode{args}. - template>> - vector(InputIterator, InputIterator, Allocator = Allocator()) - -> vector<@\placeholder{iter-value-type}@, Allocator>; +\pnum +\effects +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} - template>> - vector(from_range_t, R&&, Allocator = Allocator()) - -> vector, Allocator>; -} -\end{codeblock}% -\indexlibrarymember{vector}{operator==}% -\indexlibrarymember{vector}{operator<} +\pnum +\returns +An iterator that points to the new element. \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. +\complexity +Constant. Exactly one object of type \tcode{T} is constructed. -\rSec3[vector.cons]{Constructors} +\pnum +\remarks +Invalidates the past-the-end iterator. +\end{itemdescr} -\indexlibraryctor{vector} +\indexlibrarymember{insert}{hive}% \begin{itemdecl} -constexpr explicit vector(const Allocator&) noexcept; +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 -Constructs an empty \tcode{vector}, using the -specified allocator. - -\pnum -\complexity -Constant. +Equivalent to: \tcode{return emplace(std::forward(x));} +\begin{note} +The \tcode{hint} parameter is ignored. +\end{note} \end{itemdescr} -\indexlibraryctor{vector} +\indexlibrarymember{insert}{hive}% \begin{itemdecl} -constexpr explicit vector(size_type n, const Allocator& = Allocator()); +void insert(initializer_list rg); +template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{EmplaceInsertable} into \tcode{hive} +from \tcode{*ranges::begin(rg)}. +\tcode{rg} and \tcode{*this} do not overlap. \pnum \effects -Constructs a \tcode{vector} with \tcode{n} -default-inserted elements using the specified allocator. +Inserts copies of elements in \tcode{rg}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. \pnum \complexity -Linear in \tcode{n}. +Linear in the number of elements inserted. +Exactly one object of type \tcode{T} is constructed for each element inserted. + +\pnum +\remarks +If an element is inserted, invalidates the past-the-end iterator. \end{itemdescr} -\indexlibraryctor{vector} +\indexlibrarymember{insert}{hive}% \begin{itemdecl} -constexpr vector(size_type n, const T& value, - const Allocator& = Allocator()); +void insert(size_type n, const T& x); \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{vector} with \tcode{n} -copies of \tcode{value}, using the specified allocator. +Inserts \tcode{n} copies of \tcode{x}. \pnum \complexity Linear in \tcode{n}. +Exactly one object of type \tcode{T} is constructed for each element inserted. + +\pnum +\remarks +If an element is inserted, invalidates the past-the-end iterator. \end{itemdescr} -\indexlibraryctor{vector} +\indexlibrarymember{insert}{hive}% \begin{itemdecl} template - constexpr vector(InputIterator first, InputIterator last, - const Allocator& = Allocator()); + void insert(InputIterator first, InputIterator last); \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. +Equivalent to \tcode{insert_range(ranges::subrange(first, last))}. \end{itemdescr} -\indexlibraryctor{vector}% +\indexlibrarymember{erase}{hive}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); +iterator erase(const_iterator position); +iterator erase(const_iterator first, const_iterator last); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Constructs a \tcode{vector} object with the elements of the range \tcode{rg}, -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 -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}. +\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} -\rSec3[vector.capacity]{Capacity} - -\indexlibrarymember{capacity}{vector}% +\indexlibrarymember{swap}{hive}% \begin{itemdecl} -constexpr size_type capacity() const noexcept; +void swap(hive& x) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); \end{itemdecl} \begin{itemdescr} \pnum -\returns -The total number of elements that the vector can hold -without requiring reallocation. +\effects +Exchanges the contents, \tcode{capacity()}, and \exposid{current-limits} +of \tcode{*this} with that of \tcode{x}. \pnum \complexity -Constant time. +Constant. \end{itemdescr} -\indexlibrarymember{reserve}{vector}% +\rSec3[hive.operations]{Operations} + +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. + +\indexlibrarymember{splice}{hive}% \begin{itemdecl} -constexpr void reserve(size_type n); +void splice(hive& x); +void splice(hive&& x); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{MoveInsertable} into \tcode{*this}. +\tcode{get_allocator() == x.get_allocator()} is \tcode{true}. \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. +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 \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} +\tcode{length_error} if any of \tcode{x}'s active blocks +are not within the bounds of \exposid{current-limits}. \pnum \complexity -It does not change the size of the sequence and takes at most linear -time in the size of the sequence. +Linear in the sum of +all element blocks in \tcode{x} plus all element blocks in \tcode{*this}. \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()}. +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{shrink_to_fit}{vector}% +\indexlibrarymember{unique}{hive}% \begin{itemdecl} -constexpr void shrink_to_fit(); +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 -\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. +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 -\complexity -If reallocation happens, -linear in the size of the sequence. +\returns +The number of elements erased. \pnum -\remarks -Reallocation invalidates all the references, pointers, and iterators -referring to the elements in the sequence as well as the past-the-end iterator. -\begin{note} -If no reallocation happens, they remain valid. -\end{note} -\end{itemdescr} - -\indexlibrarymember{swap}{vector}% -\begin{itemdecl} -constexpr void swap(vector& x) - noexcept(allocator_traits::propagate_on_container_swap::value || - allocator_traits::is_always_equal::value); -\end{itemdecl} +\throws +Nothing unless an exception is thrown by the predicate. -\begin{itemdescr} \pnum -\effects -Exchanges the contents and -\tcode{capacity()} -of -\tcode{*this} -with that of \tcode{x}. +\complexity +If \tcode{empty()} is \tcode{false}, +exactly \tcode{size() - 1} applications of the corresponding predicate, +otherwise no applications of the predicate. \pnum -\complexity -Constant time. +\remarks +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{resize}{vector}% +\indexlibrarymember{sort}{hive}% \begin{itemdecl} -constexpr void resize(size_type sz); +template> + void sort(Compare comp = Compare()); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is -\oldconcept{MoveInsertable} and \oldconcept{DefaultInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{hive}, +\oldconcept{MoveAssignable}, and \oldconcept{Swappable}. \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. +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 +\bigoh{N \log N} comparisons, where $N$ is \tcode{size()}. \pnum \remarks -If an exception is thrown other than by the move constructor of a non-\oldconcept{CopyInsertable} -\tcode{T} there are no effects. +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} +Not required to be stable\ref{algorithm.stable}. +\end{note} \end{itemdescr} -\indexlibrarymember{resize}{vector}% +\indexlibrarymember{get_iterator}{hive}% \begin{itemdecl} -constexpr void resize(size_type sz, const T& c); +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{CopyInsertable} into \tcode{*this}. - -\pnum -\effects -If \tcode{sz < size()}, erases the last \tcode{size() - sz} elements -from the sequence. Otherwise, -appends \tcode{sz - size()} copies of \tcode{c} to the sequence. - -\pnum -\remarks -If an exception is thrown there are no effects. -\end{itemdescr} - -\rSec3[vector.data]{Data} - -\indexlibrarymember{data}{vector}% -\begin{itemdecl} -constexpr T* data() noexcept; -constexpr const T* data() const noexcept; -\end{itemdecl} +\tcode{p} points to an element in \tcode{*this}. -\begin{itemdescr} \pnum \returns -A pointer such that \range{data()}{data() + size()} is a valid range. For a -non-empty vector, \tcode{data()} \tcode{==} \tcode{addressof(front())}. +An \tcode{iterator} or \tcode{const_iterator} +pointing to the same element as \tcode{p}. \pnum \complexity -Constant time. +Linear in the number of active blocks in \tcode{*this}. \end{itemdescr} -\rSec3[vector.modifiers]{Modifiers} +\rSec3[hive.erasure]{Erasure} -\indexlibrarymember{insert}{vector}% +\indexlibrarymember{erase}{hive}% \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); +template + typename hive::size_type + erase(hive& c, const U& value); \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. +\effects +Equivalent to: +\begin{codeblock} +return erase_if(c, [&](auto& elem) { return elem == value; }); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{erase}{vector}% +\indexlibrarymember{erase_if}{hive}% \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); +template + typename hive::size_type + erase_if(hive& c, Predicate pred); \end{itemdecl} \begin{itemdescr} @@ -9093,96 +8978,140 @@ \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; +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{erase_if}{vector}% -\begin{itemdecl} -template - constexpr typename vector::size_type - erase_if(vector& c, Predicate pred); -\end{itemdecl} +\rSec2[list.syn]{Header \tcode{} synopsis} -\begin{itemdescr} -\pnum -\effects -Equivalent to: +\indexheader{list}% \begin{codeblock} -auto it = remove_if(c.begin(), c.end(), pred); -auto r = distance(it, c.end()); -c.erase(it, c.end()); -return r; +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{list}, class template \tcode{list} + template> class list; + + 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); + + template + constexpr void swap(list& x, list& y) + noexcept(noexcept(x.swap(y))); + + // \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); + + namespace pmr { + template + using list = std::list>; + } +} \end{codeblock} -\end{itemdescr} -\rSec2[vector.bool]{Specialization of \tcode{vector} for \tcode{bool}} +\rSec2[list]{Class template \tcode{list}} -\rSec3[vector.bool.pspc]{Partial class template specialization \tcode{vector}} +\rSec3[list.overview]{Overview} \pnum -\indexlibraryglobal{vector}% -To optimize space allocation, a partial specialization of \tcode{vector} for -\tcode{bool} elements is provided: +\indexlibraryglobal{list}% +A +\tcode{list} +is a sequence container that supports +bidirectional iterators and allows constant time insert and erase +operations anywhere within the sequence, with storage management handled +automatically. Unlike vectors\iref{vector} and deques\iref{deque}, +fast random access to list elements is not supported, but many +algorithms only need sequential access anyway. + +\pnum +A \tcode{list} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of a sequence container, +including most of the optional sequence container +requirements\iref{sequence.reqmts}. +The exceptions are the +\tcode{operator[]} +and +\tcode{at} +member functions, which are not provided. +\begin{footnote} +These member functions +are only provided by containers whose iterators +are random access iterators. +\end{footnote} +Descriptions are provided here only for operations on +\tcode{list} +that are not described in one of these tables +or for operations where there is additional semantic information. + +\pnum +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 reference { - 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() : vector(Allocator()) { } - constexpr explicit vector(const Allocator&); - 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); - 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); - 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 @@ -9200,892 +9129,5493 @@ 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&); - constexpr static 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; }; -} -\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. + template>> + list(InputIterator, InputIterator, Allocator = Allocator()) + -> list<@\placeholder{iter-value-type}@, Allocator>; -\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. + template>> + list(from_range_t, R&&, Allocator = Allocator()) + -> list, Allocator>; +} +\end{codeblock} \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. +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. -\indexlibrarymember{flip}{vector}% +\rSec3[list.cons]{Constructors, copy, and assignment} + +\indexlibraryctor{list}% \begin{itemdecl} -constexpr void flip() noexcept; +constexpr explicit list(const Allocator&); \end{itemdecl} \begin{itemdescr} \pnum \effects -Replaces each element in the container with its complement. +Constructs an empty list, using the specified allocator. + +\pnum +\complexity +Constant. \end{itemdescr} -\indexlibrarymember{swap}{vector}% +\indexlibraryctor{list}% \begin{itemdecl} -constexpr static void swap(reference x, reference y) noexcept; +constexpr explicit list(size_type n, 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{DefaultInsertable} into \tcode{list}. -\begin{codeblock} -bool b = x; -x = y; -y = b; -\end{codeblock} +\pnum +\effects +Constructs a \tcode{list} with +\tcode{n} default-inserted elements using the specified allocator. +\pnum +\complexity +Linear in +\tcode{n}. \end{itemdescr} +\indexlibraryctor{list}% \begin{itemdecl} -template struct hash>; +constexpr list(size_type n, const T& value, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum -The specialization is enabled\iref{unord.hash}. -\end{itemdescr} +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{list}. -\indexlibraryglobal{\exposid{is-vector-bool-reference}}% -\begin{itemdecl} -template - inline constexpr bool @\exposid{is-vector-bool-reference}@ = @\seebelow@; -\end{itemdecl} +\pnum +\effects +Constructs a +\tcode{list} +with +\tcode{n} +copies of +\tcode{value}, +using the specified allocator. -\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. +\complexity +Linear in +\tcode{n}. \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}% +\indexlibraryctor{list}% \begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); +template + constexpr list(InputIterator first, InputIterator last, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum -Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +\effects +Constructs a +\tcode{list} +equal to the range +\range{first}{last}. + +\pnum +\complexity +Linear in +\tcode{distance(first, last)}. \end{itemdescr} -\indexlibrarymember{format}{formatter}% +\indexlibraryctor{list}% \begin{itemdecl} -template - typename FormatContext::iterator - format(const T& ref, FormatContext& ctx) const; +template<@\exposconcept{container-compatible-range}@ R> + constexpr list(from_range_t, R&& rg, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum -Equivalent to: \tcode{return \exposid{underlying_}.format(ref, ctx);} +\effects +Constructs a \tcode{list} object with the elements of the range \tcode{rg}. + +\pnum +\complexity +Linear in \tcode{ranges::distance(rg)}. \end{itemdescr} -\rSec1[associative]{Associative containers} +\rSec3[list.capacity]{Capacity} -\rSec2[associative.general]{In general} +\indexlibrarymember{resize}{list}% +\begin{itemdecl} +constexpr void resize(size_type sz); +\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}. +\expects +\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{list}. \pnum -The following exposition-only alias templates may appear in deduction guides for associative containers: +\effects +If \tcode{size() < sz}, +appends \tcode{sz - size()} default-inserted elements to the +sequence. +If \tcode{sz <= size()}, equivalent to: + \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 +list::iterator it = begin(); +advance(it, sz); +erase(it, end()); \end{codeblock} +\end{itemdescr} -\rSec2[associative.map.syn]{Header \tcode{} synopsis} +\indexlibrarymember{resize}{list}% +\begin{itemdecl} +constexpr void resize(size_type sz, const T& c); +\end{itemdecl} -\indexheader{map}% +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{list}. + +\pnum +\effects +As if by: \begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} +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} -namespace std { - // \ref{map}, class template \tcode{map} - template, - class Allocator = allocator>> - class map; +\rSec3[list.modifiers]{Modifiers} - template - bool operator==(const map& x, - const map& y); - template - @\placeholder{synth-three-way-result}@> - operator<=>(const map& x, - const map& y); +\indexlibrarymember{insert}{list}% +\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 - void swap(map& x, - map& y) - noexcept(noexcept(x.swap(y))); +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} - // \ref{map.erasure}, erasure for \tcode{map} - template - typename map::size_type - erase_if(map& c, Predicate pred); +\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. - // \ref{multimap}, class template \tcode{multimap} - template, - class Allocator = allocator>> - class multimap; +\pnum +\remarks +Does not affect the validity of iterators and references. +If an exception is thrown, there are no effects. +\end{itemdescr} - template - bool operator==(const multimap& x, - const multimap& y); - template - @\placeholder{synth-three-way-result}@> - operator<=>(const multimap& x, - const multimap& y); +\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} - template - void swap(multimap& x, - multimap& y) - noexcept(noexcept(x.swap(y))); +\begin{itemdescr} +\pnum +\effects +Invalidates only the iterators and references to the erased elements. - // \ref{multimap.erasure}, erasure for \tcode{multimap} - template - typename multimap::size_type - erase_if(multimap& c, Predicate pred); +\pnum +\throws +Nothing. - namespace pmr { - template> - using map = std::map>>; +\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} - template> - using multimap = std::multimap>>; - } -} -\end{codeblock} +\rSec3[list.ops]{Operations} -\rSec2[associative.set.syn]{Header \tcode{} synopsis}% +\pnum +Since lists allow fast insertion and erasing from the middle of a list, certain +operations are provided specifically for them. +\begin{footnote} +As specified +in~\ref{allocator.requirements}, the requirements in this Clause apply only to +lists whose allocators compare equal. +\end{footnote} +In this subclause, +arguments for a template parameter +named \tcode{Predicate} or \tcode{BinaryPredicate} +shall meet the corresponding requirements in \ref{algorithms.requirements}. +The semantics of \tcode{i + n} and \tcode{i - n}, +where \tcode{i} is an iterator into the list and \tcode{n} is an integer, +are the same as those of \tcode{next(i, n)} and \tcode{prev(i, n)}, +respectively. +For \tcode{merge} and \tcode{sort}, +the definitions and requirements in \ref{alg.sorting} apply. + +\pnum +\tcode{list} provides three splice operations that destructively move elements from one list to +another. The behavior of splice operations is undefined if \tcode{get_allocator() != +x.get_allocator()}. + +\indexlibrarymember{splice}{list}% +\begin{itemdecl} +constexpr void splice(const_iterator position, list& x); +constexpr void splice(const_iterator position, list&& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{addressof(x) != this} is \tcode{true}. + +\pnum +\effects +Inserts the contents of +\tcode{x} +before +\tcode{position} +and +\tcode{x} +becomes empty. +Pointers and references to the moved elements of +\tcode{x} +now refer to those same elements but as members of +\tcode{*this}. +Iterators referring to the moved elements will continue to refer to their +elements, but they now behave as iterators into +\tcode{*this}, +not into +\tcode{x}. + +\pnum +\throws +Nothing. + +\pnum +\complexity +Constant time. +\end{itemdescr} + +\indexlibrarymember{splice}{list}% +\begin{itemdecl} +constexpr void splice(const_iterator position, list& x, const_iterator i); +constexpr void splice(const_iterator position, list&& x, const_iterator i); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{i} is a valid dereferenceable iterator of \tcode{x}. + +\pnum +\effects +Inserts an element pointed to by +\tcode{i} +from list +\tcode{x} +before \tcode{position} and removes the element from +\tcode{x}. +The result is unchanged if +\tcode{position == i} +or +\tcode{position == ++i}. +Pointers and references to +\tcode{*i} +continue to refer to this same element but as a member of +\tcode{*this}. +Iterators +to +\tcode{*i} +(including +\tcode{i} +itself) continue to refer to the same element, but now behave as iterators into +\tcode{*this}, +not into +\tcode{x}. + +\pnum +\throws +Nothing. + +\pnum +\complexity +Constant time. +\end{itemdescr} + +\indexlibrarymember{splice}{list}% +\begin{itemdecl} +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} + +\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}. + +\pnum +\effects +Inserts elements in the range +\range{first}{last} +before +\tcode{position} +and removes the elements from +\tcode{x}. +Pointers and references to the moved elements of +\tcode{x} +now refer to those same elements but as members of +\tcode{*this}. +Iterators referring to the moved elements will continue to refer to their +elements, but they now behave as iterators into +\tcode{*this}, +not into +\tcode{x}. + +\pnum +\throws +Nothing. + +\pnum +\complexity +Constant time if +\tcode{addressof(x) == this}; +otherwise, linear time. +\end{itemdescr} + +\indexlibrarymember{remove}{list}% +\begin{itemdecl} +constexpr size_type remove(const T& value); +template constexpr size_type remove_if(Predicate pred); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Erases all the elements in the list referred to by a list iterator \tcode{i} for which the +following conditions hold: \tcode{*i == value}, \tcode{pred(*i) != false}. +Invalidates only the iterators and references to the erased elements. + +\pnum +\returns +The number of elements erased. + +\pnum +\throws +Nothing unless an exception is thrown by +\tcode{*i == value} +or +\tcode{pred(*i) != false}. + +\pnum +\complexity +Exactly +\tcode{size()} +applications of the corresponding predicate. + +\pnum +\remarks +Stable\iref{algorithm.stable}. +\end{itemdescr} + +\indexlibrarymember{unique}{list}% +\begin{itemdecl} +constexpr size_type unique(); +template constexpr size_type unique(BinaryPredicate binary_pred); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{binary_pred} be \tcode{equal_to<>\{\}} for the first overload. + +\pnum +\expects +\tcode{binary_pred} is an equivalence relation. + +\pnum +\effects +Erases all but the first element from every +consecutive group of equivalent elements. +That is, for a nonempty list, erases all elements referred to +by the iterator \tcode{i} in the range \range{begin() + 1}{end()} +for which \tcode{binary_pred(*i, *(i - 1))} is \tcode{true}. +Invalidates only the iterators and references to the erased elements. + +\pnum +\returns +The number of elements erased. + +\pnum +\throws +Nothing unless an exception is thrown by the predicate. + +\pnum +\complexity +If \tcode{empty()} is \tcode{false}, +exactly \tcode{size() - 1} applications of the corresponding predicate, +otherwise no applications of the predicate. +\end{itemdescr} + +\indexlibrarymember{merge}{list}% +\begin{itemdecl} +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} + +\begin{itemdescr} +\pnum +Let \tcode{comp} be \tcode{less<>{}} for the first two overloads. + +\pnum +\expects +\tcode{*this} and \tcode{x} are both sorted +with respect to the comparator \tcode{comp}, and +\tcode{get_allocator() == x.get_allocator()} is \tcode{true}. + +\pnum +\effects +If \tcode{addressof(x) == this}, there are no effects. +Otherwise, merges +the two sorted ranges \range{begin()}{end()} and \range{x.begin()}{x.end()}. +The result is a range +that is sorted with respect to the comparator \tcode{comp}. +Pointers and references to the moved elements of \tcode{x} now refer to those same elements +but as members of \tcode{*this}. Iterators referring to the moved elements will continue to +refer to their elements, but they now behave as iterators into \tcode{*this}, not into +\tcode{x}. + +\pnum +\complexity +At most \tcode{size() + x.size() - 1} comparisons +if \tcode{addressof(x) != this}; +otherwise, no comparisons are performed. + +\pnum +\remarks +Stable\iref{algorithm.stable}. +If \tcode{addressof(x) != this}, \tcode{x} is empty after the merge. +No elements are copied by this operation. +If an exception is thrown other than by a comparison, there are no effects. +\end{itemdescr} + +\indexlibrarymember{reverse}{list}% +\begin{itemdecl} +constexpr void reverse() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Reverses the order of the elements in the list. +Does not affect the validity of iterators and references. + +\pnum +\complexity +Linear time. +\end{itemdescr} + +\indexlibrarymember{sort}{list}% +\begin{itemdecl} +void sort(); +template void sort(Compare comp); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Sorts the list according to the \tcode{operator<} or a \tcode{Compare} function object. +If an exception is thrown, +the order of the elements in \tcode{*this} is unspecified. +Does not affect the validity of iterators and references. + +\pnum +\complexity +Approximately +$N \log N$ +comparisons, where $N$ is \tcode{size()}. + +\pnum +\remarks +Stable\iref{algorithm.stable}. +\end{itemdescr} + +\rSec3[list.erasure]{Erasure} + +\indexlibrarymember{erase}{list}% +\begin{itemdecl} +template + typename list::size_type + constexpr erase(list& c, const U& value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return erase_if(c, [&](const auto& elem) -> bool { return elem == value; }); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{erase_if}{list}% +\begin{itemdecl} +template + typename list::size_type + constexpr erase_if(list& c, Predicate pred); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return c.remove_if(pred);} +\end{itemdescr} + +\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[vector]{Class template \tcode{vector}} + +\rSec3[vector.overview]{Overview} + +\pnum +\indexlibraryglobal{vector}% +A +\tcode{vector} +is a sequence container that supports +(amortized) constant time insert and erase operations at the end; +insert and erase in the middle take linear time. +Storage management is handled automatically, though hints can be given +to improve efficiency. + +\pnum +A \tcode{vector} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, +of a sequence container, including most of the optional sequence container +requirements\iref{sequence.reqmts}, +and, for an element type other than \tcode{bool}, +of a contiguous container\iref{container.reqmts}. +The exceptions are the +\tcode{push_front}, \tcode{prepend_range}, \tcode{pop_front}, and \tcode{emplace_front} member functions, which are not +provided. Descriptions are provided here only for operations on \tcode{vector} +that are not described in one of these tables or for operations where there is +additional semantic information. + +\pnum +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + +\begin{codeblock} +namespace std { + template> + class 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; + + // \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; + + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; + + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // \ref{vector.capacity}, capacity + 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 +An incomplete type \tcode{T} may be used when instantiating \tcode{vector} +if the allocator meets the +allocator completeness requirements\iref{allocator.requirements.completeness}. +\tcode{T} shall be complete before any member of the resulting specialization +of \tcode{vector} is referenced. + +\rSec3[vector.cons]{Constructors} + +\indexlibraryctor{vector} +\begin{itemdecl} +constexpr explicit vector(const Allocator&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{vector}, using the +specified allocator. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexlibraryctor{vector} +\begin{itemdecl} +constexpr explicit vector(size_type n, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{vector}. + +\pnum +\effects +Constructs a \tcode{vector} with \tcode{n} +default-inserted elements using the specified allocator. + +\pnum +\complexity +Linear in \tcode{n}. +\end{itemdescr} + +\indexlibraryctor{vector} +\begin{itemdecl} +constexpr vector(size_type n, const T& value, + const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is +\oldconcept{CopyInsertable} into \tcode{vector}. + +\pnum +\effects +Constructs a \tcode{vector} with \tcode{n} +copies of \tcode{value}, using the specified allocator. + +\pnum +\complexity +Linear in \tcode{n}. +\end{itemdescr} + +\indexlibraryctor{vector} +\begin{itemdecl} +template + constexpr vector(InputIterator first, InputIterator last, + const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{vector} equal to the +range \range{first}{last}, using the specified allocator. + +\pnum +\complexity +Makes only $N$ +calls to the copy constructor of +\tcode{T} +(where $N$ +is the distance between +\tcode{first} +and +\tcode{last}) +and no reallocations if +\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} + +\indexlibraryctor{vector}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{vector} object with the elements of the range \tcode{rg}, +using the specified allocator. + +\pnum +\complexity +Initializes exactly $N$ elements +from the results of dereferencing successive iterators of \tcode{rg}, +where $N$ is \tcode{ranges::distance(rg)}. + +\pnum +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 +A directive that informs a +\tcode{vector} +of a planned change in size, so that it can manage the storage allocation accordingly. +After +\tcode{reserve()}, +\tcode{capacity()} +is greater or equal to the argument of +\tcode{reserve} +if reallocation happens; and equal to the previous value of +\tcode{capacity()} +otherwise. +Reallocation happens at this point if and only if the current capacity is less than the +argument of +\tcode{reserve()}. If an exception is thrown +other than by the move constructor of a non-\oldconcept{CopyInsertable} type, +there are no effects. + +\pnum +\throws +\tcode{length_error} if \tcode{n > +max_size()}. +\begin{footnote} +\tcode{reserve()} uses \tcode{Allocator::allocate()} which +can throw an appropriate exception. +\end{footnote} + +\pnum +\complexity +It does not change the size of the sequence and takes at most linear +time in the size of the sequence. + +\pnum +\remarks +Reallocation invalidates all the references, pointers, and iterators +referring to the elements in the sequence, as well as the past-the-end iterator. +\begin{note} +If no reallocation happens, they remain valid. +\end{note} +No reallocation shall take place during insertions that happen +after a call to \tcode{reserve()} +until an insertion would make the size of the vector +greater than the value of \tcode{capacity()}. +\end{itemdescr} + +\indexlibrarymember{shrink_to_fit}{vector}% +\begin{itemdecl} +constexpr void shrink_to_fit(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{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} +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}% +\begin{itemdecl} +constexpr void resize(size_type sz); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is +\oldconcept{MoveInsertable} and \oldconcept{DefaultInsertable} into \tcode{vector}. + +\pnum +\effects +If \tcode{sz < size()}, erases the last \tcode{size() - sz} elements +from the sequence. Otherwise, +appends \tcode{sz - size()} default-inserted elements to the sequence. + +\pnum +\remarks +If an exception is thrown other than by the move constructor of a non-\oldconcept{CopyInsertable} +\tcode{T}, there are no effects. +\end{itemdescr} + +\indexlibrarymember{resize}{vector}% +\begin{itemdecl} +constexpr void resize(size_type sz, const T& c); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is +\oldconcept{CopyInsertable} into \tcode{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}, size/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; + + constexpr friend bool operator==(const inplace_vector& x, + const inplace_vector& y); + constexpr friend @\exposid{synth-three-way-result}@ + operator<=>(const inplace_vector& x, const inplace_vector& y); + constexpr friend 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]{Size and 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} + +\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{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} + +\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}, +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>; + + template + unordered_map(initializer_list>, Allocator) + -> unordered_map, equal_to, Allocator>; + + template + unordered_map(initializer_list>, typename @\seebelow@::size_type, Hash, + Allocator) + -> unordered_map, Allocator>; +} +\end{codeblock} + +\pnum +A \tcode{size_type} parameter type in an \tcode{unordered_map} deduction guide +refers to the \tcode{size_type} member type of the type deduced by the deduction guide. + +\rSec3[unord.map.cnstr]{Constructors} + +\indexlibraryctor{unordered_map}% +\begin{itemdecl} +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} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{unordered_map} using the +specified hash function, key equality predicate, and allocator, and +using at least \tcode{n} buckets. For the default constructor, +the number of buckets is \impldef{default number of buckets in +\tcode{unordered_map}}. +\tcode{max_load_factor()} returns \tcode{1.0}. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexlibraryctor{unordered_map}% +\begin{itemdecl} +template + 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} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{unordered_map} using the +specified hash function, key equality predicate, and allocator, and +using at least \tcode{n} buckets. If \tcode{n} is not +provided, the number of buckets is \impldef{default number of buckets in +\tcode{unordered_map}}. Then +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. +\tcode{max_load_factor()} returns \tcode{1.0}. + +\pnum +\complexity +Average case linear, worst case quadratic. +\end{itemdescr} + +\rSec3[unord.map.elem]{Element access} + +\indexlibrarymember{unordered_map}{operator[]}% +\indextext{\idxcode{unordered_map}!element access}% +\begin{itemdecl} +constexpr mapped_type& operator[](const key_type& k); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return try_emplace(k).first->second;} +\end{itemdescr} + +\indexlibrarymember{unordered_map}{operator[]}% +\indextext{\idxcode{unordered_map}!element access}% +\begin{itemdecl} +constexpr mapped_type& operator[](key_type&& k); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return try_emplace(std::move(k)).first->second;} +\end{itemdescr} + +\indexlibrarymember{unordered_map}{operator[]}% +\indextext{\idxcode{unordered_map}!element access}% +\begin{itemdecl} +template constexpr mapped_type& operator[](K&& k); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and +\tcode{Pred::is_transparent} are valid and denote types. + +\pnum +\effects +Equivalent to: \tcode{return try_emplace(std::forward(k)).first->second;} +\end{itemdescr} + +\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} -\indexheader{set}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} +\begin{itemdescr} +\pnum +\returns +A reference to \tcode{x.second}, where \tcode{x} is the (unique) element whose key is equivalent to \tcode{k}. -namespace std { - // \ref{set}, class template \tcode{set} - template, class Allocator = allocator> - class set; +\pnum +\throws +An exception object of type \tcode{out_of_range} if no such element is present. +\end{itemdescr} - template - bool operator==(const set& x, - const set& y); - template - @\placeholder{synth-three-way-result}@ operator<=>(const set& x, - @\itcorr@ const set& y); +\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 - void swap(set& x, - set& y) - noexcept(noexcept(x.swap(y))); +\begin{itemdescr} +\pnum +\constraints +The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and +\tcode{Pred::is_transparent} are valid and denote types. - // \ref{set.erasure}, erasure for \tcode{set} - template - typename set::size_type - erase_if(set& c, Predicate pred); +\pnum +\expects +The expression \tcode{find(k)} is well-formed and has well-defined behavior. - // \ref{multiset}, class template \tcode{multiset} - template, class Allocator = allocator> - class multiset; +\pnum +\returns +A reference to \tcode{find(k)->second}. - template - bool operator==(const multiset& x, - const multiset& y); - template - @\placeholder{synth-three-way-result}@ operator<=>(const multiset& x, - @\itcorr@ const multiset& y); +\pnum +\throws +An exception object of type \tcode{out_of_range} +if \tcode{find(k) == end()} is \tcode{true}. +\end{itemdescr} - template - void swap(multiset& x, - multiset& y) - noexcept(noexcept(x.swap(y))); +\rSec3[unord.map.modifiers]{Modifiers} - // \ref{multiset.erasure}, erasure for \tcode{multiset} - template - typename multiset::size_type - erase_if(multiset& c, Predicate pred); +\indexlibrarymember{unordered_map}{insert}% +\begin{itemdecl} +template + constexpr pair insert(P&& obj); +\end{itemdecl} - namespace pmr { - template> - using set = std::set>; +\begin{itemdescr} - template> - using multiset = std::multiset>; - } -} -\end{codeblock} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. -\rSec2[map]{Class template \tcode{map}} +\pnum +\effects +Equivalent to: \tcode{return emplace(std::forward

(obj));} +\end{itemdescr} -\rSec3[map.overview]{Overview} +\indexlibrarymember{unordered_map}{insert}% +\begin{itemdecl} +template + constexpr iterator insert(const_iterator hint, P&& obj); +\end{itemdecl} -\indexlibraryglobal{map}% +\begin{itemdescr} \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. +\constraints +\tcode{is_constructible_v} is \tcode{true}. \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. +\effects +Equivalent to: +\tcode{return emplace_hint(hint, std::forward

(obj));} +\end{itemdescr} -\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}@; +\indexlibrarymember{try_emplace}{unordered_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} - 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); - } - }; +\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)...)}. - // \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; +\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)...)}. - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() 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}. + +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. +\end{itemdescr} - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; +\indexlibrarymember{try_emplace}{unordered_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} - 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 +\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)...)}. - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() 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(std::move(k))}, +\tcode{forward_as_tuple(std::forward(args)...)}. - // \ref{map.access}, element access - mapped_type& operator[](const key_type& x); - mapped_type& operator[](key_type&& x); - mapped_type& at(const key_type& x); - const mapped_type& at(const key_type& x) 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}. - // \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); +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. +\end{itemdescr} - 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); +\indexlibrarymember{try_emplace}{unordered_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} - 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 - 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); - - 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; +\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 - void merge(map& source); - template - void merge(map&& source); - template - void merge(multimap& source); - template - void merge(multimap&& source); +\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)...)}. - // observers - key_compare key_comp() const; - value_compare value_comp() const; +\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}. - // 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; +\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}. - size_type count(const key_type& x) const; - template size_type count(const K& x) const; +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +\end{itemdescr} - bool contains(const key_type& x) const; - template bool contains(const K& x) const; +\indexlibrarymember{insert_or_assign}{unordered_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} - 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 +\mandates +\tcode{is_assignable_v} is \tcode{true}. - 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 +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{unordered_map} +from \tcode{k}, \tcode{std::for\-ward(obj)}. - 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 +\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>, - 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 +\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, - 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 +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. +\end{itemdescr} - template, - class Allocator = allocator>> - map(initializer_list>, Compare = Compare(), Allocator = Allocator()) - -> map; +\indexlibrarymember{insert_or_assign}{unordered_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} - template - map(InputIterator, InputIterator, Allocator) - -> map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, - less<@\placeholder{iter-key-type}@>, Allocator>; +\begin{itemdescr} +\pnum +\mandates +\tcode{is_assignable_v} is \tcode{true}. - 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{value_type} is \oldconcept{Emplace\-Constructible} into \tcode{unordered_map} +from \tcode{std::move(k)}, \tcode{std::\brk{}forward(obj)}. - template - map(initializer_list>, Allocator) -> map, Allocator>; -} -\end{codeblock} +\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}. -\rSec3[map.cons]{Constructors, copy, and assignment}% -\indexlibrarymember{map}{operator==}% -\indexlibrarymember{map}{operator<} +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. +\end{itemdescr} -\indexlibraryctor{map}% +\indexlibrarymember{insert_or_assign}{unordered_map}% \begin{itemdecl} -explicit map(const Compare& comp, 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 +\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 -Constructs an empty -\tcode{map} -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::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 -Constant. +The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. \end{itemdescr} -\indexlibraryctor{map}% +\rSec3[unord.map.erasure]{Erasure} + +\indexlibrarymember{erase_if}{unordered_map}% \begin{itemdecl} -template - map(InputIterator first, InputIterator last, - const Compare& comp = Compare(), const Allocator& = Allocator()); +template + constexpr typename unordered_map::size_type + erase_if(unordered_map& c, Predicate pred); \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}. +Equivalent to: +\begin{codeblock} +auto original_size = c.size(); +for (auto i = c.begin(), last = c.end(); i != last; ) { + if (pred(*i)) { + i = c.erase(i); + } else { + ++i; + } +} +return original_size - c.size(); +\end{codeblock} +\end{itemdescr} + +\rSec2[unord.multimap]{Class template \tcode{unordered_multimap}}% +\indexlibraryglobal{unordered_multimap} + +\rSec3[unord.multimap.overview]{Overview} + +\pnum +\indextext{\idxcode{unordered_multimap}!equivalent keys}% +\indextext{unordered associative containers!equivalent keys}% +An \tcode{unordered_multimap} is an unordered associative container +that supports equivalent keys (an instance of \tcode{unordered_multimap} may contain +multiple copies of each key value) and that associates values of +another type \tcode{mapped_type} with the keys. +The \tcode{unordered_multimap} class +supports forward iterators. + +\pnum +An \tcode{unordered_multimap} meets all of the requirements +of a container\iref{container.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an unordered associative container\iref{unord.req}. +It provides the operations described in the +preceding requirements table for equivalent keys; that is, an \tcode{unordered_multimap} +supports the \tcode{a_eq} operations in that table, not the \tcode{a_uniq} operations. +For an \tcode{unordered_multimap} 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.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 +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 Pred = equal_to, + class Allocator = allocator>> + class unordered_multimap { + 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 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 + 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> + 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 + 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> + 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 && is_nothrow_move_assignable_v); + constexpr unordered_multimap& operator=(initializer_list); + constexpr allocator_type get_allocator() const noexcept; -\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} + // 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; -\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} + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; -\begin{itemdescr} -\pnum -\effects -Constructs an empty \tcode{map} -using the specified comparison object and allocator, -and inserts elements from the range \tcode{rg}. + // \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> + 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 && is_nothrow_swappable_v); + constexpr void clear() noexcept; -\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} + 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); -\rSec3[map.access]{Element access} + // observers + constexpr hasher hash_function() const; + constexpr key_equal key_eq() const; -\indexlibrary{\idxcode{operator[]}!\idxcode{map}}% -\begin{itemdecl} -mapped_type& operator[](const key_type& x); -\end{itemdecl} + // 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; -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return try_emplace(x).first->second;} -\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; -\indexlibrary{\idxcode{operator[]}!\idxcode{map}}% -\begin{itemdecl} -mapped_type& operator[](key_type&& x); -\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 -\effects -Equivalent to: \tcode{return try_emplace(std::move(x)).first->second;} -\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>; -\indexlibrarymember{at}{map}% -\begin{itemdecl} -mapped_type& at(const key_type& x); -const mapped_type& at(const key_type& x) const; -\end{itemdecl} + 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>; -\begin{itemdescr} -\pnum -\returns -A reference to the \tcode{mapped_type} corresponding to \tcode{x} in \tcode{*this}. + 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; -\pnum -\throws -An exception object of type \tcode{out_of_range} if -no such element is present. + 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>; -\pnum -\complexity -Logarithmic. -\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>; -\rSec3[map.modifiers]{Modifiers} + 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>; -\indexlibrarymember{insert}{map}% -\begin{itemdecl} -template - pair insert(P&& x); -template - iterator insert(const_iterator position, P&& x); -\end{itemdecl} + 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>; -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. + 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>; -\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 + 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>; -\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} + template + unordered_multimap(initializer_list>, typename @\seebelow@::size_type, + Allocator) + -> unordered_multimap, equal_to, Allocator>; -\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)...)}. + template + unordered_multimap(initializer_list>, Allocator) + -> unordered_multimap, equal_to, Allocator>; -\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)...)}. + template + unordered_multimap(initializer_list>, typename @\seebelow@::size_type, + Hash, Allocator) + -> unordered_multimap, Allocator>; +} +\end{codeblock} \pnum -\returns -In the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. +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. -\pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. -\end{itemdescr} +\rSec3[unord.multimap.cnstr]{Constructors} -\indexlibrarymember{try_emplace}{map}% +\indexlibraryctor{unordered_multimap}% \begin{itemdecl} -template - pair try_emplace(key_type&& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); +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 -\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}. +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 -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. +Constant. \end{itemdescr} -\indexlibrarymember{insert_or_assign}{map}% +\indexlibraryctor{unordered_multimap}% \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); +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> + 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 -\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}. +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{unordered_multimap} using the +specified hash function, key equality predicate, and allocator, and +using at least \tcode{n} buckets. If \tcode{n} is not +provided, the number of buckets is \impldef{default number of buckets in +\tcode{unordered_multimap}}. Then +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. +\tcode{max_load_factor()} returns \tcode{1.0}. \pnum \complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. +Average case linear, worst case quadratic. \end{itemdescr} -\indexlibrarymember{insert_or_assign}{map}% +\rSec3[unord.multimap.modifiers]{Modifiers} + +\indexlibrarymember{unordered_multimap}{insert}% \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 iterator insert(P&& 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)}. +\constraints +\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::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)}. +Equivalent to: \tcode{return emplace(std::forward

(obj));} +\end{itemdescr} + +\indexlibrarymember{unordered_multimap}{insert}% +\begin{itemdecl} +template + constexpr iterator insert(const_iterator hint, P&& obj); +\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}. +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. +\effects +Equivalent to: +\tcode{return emplace_hint(hint, std::forward

(obj));} \end{itemdescr} -\rSec3[map.erasure]{Erasure} +\rSec3[unord.multimap.erasure]{Erasure} -\indexlibrarymember{erase_if}{map}% +\indexlibrarymember{erase_if}{unordered_multimap}% \begin{itemdecl} -template - typename map::size_type - erase_if(map& c, Predicate pred); +template + constexpr typename unordered_multimap::size_type + erase_if(unordered_multimap& c, Predicate pred); \end{itemdecl} \begin{itemdescr} @@ -10105,347 +14635,430 @@ \end{codeblock} \end{itemdescr} -\rSec2[multimap]{Class template \tcode{multimap}} +\rSec2[unord.set.syn]{Header \tcode{} synopsis} -\rSec3[multimap.overview]{Overview} +\indexheader{unordered_set}% +\indexlibraryglobal{unordered_set}% +\indexlibraryglobal{unordered_multiset}% +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{unord.set}, class template \tcode{unordered_set} + template, + class Pred = equal_to, + class Alloc = allocator> + class unordered_set; + + // \ref{unord.multiset}, class template \tcode{unordered_multiset} + template, + class Pred = equal_to, + class Alloc = allocator> + class unordered_multiset; + + template + constexpr bool operator==(const unordered_set& a, + const unordered_set& b); + + template + constexpr bool operator==(const unordered_multiset& a, + const unordered_multiset& b); + + template + constexpr void swap(unordered_set& x, + unordered_set& y) + noexcept(noexcept(x.swap(y))); + + template + constexpr void swap(unordered_multiset& x, + unordered_multiset& y) + noexcept(noexcept(x.swap(y))); + + // \ref{unord.set.erasure}, erasure for \tcode{unordered_set} + template + constexpr typename unordered_set::size_type + erase_if(unordered_set& c, Predicate pred); + + // \ref{unord.multiset.erasure}, erasure for \tcode{unordered_multiset} + template + constexpr typename unordered_multiset::size_type + erase_if(unordered_multiset& c, Predicate pred); + + namespace pmr { + template, + class Pred = equal_to> + using unordered_set = std::unordered_set>; + + template, + class Pred = equal_to> + using unordered_multiset = std::unordered_multiset>; + } +} +\end{codeblock} + +\rSec2[unord.set]{Class template \tcode{unordered_set}}% +\indexlibraryglobal{unordered_set} + +\rSec3[unord.set.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. +\indextext{\idxcode{unordered_set}!unique keys}% +\indextext{unordered associative containers!unique keys}% +An \tcode{unordered_set} is an unordered associative container that +supports unique keys (an \tcode{unordered_set} contains at most one of each +key value) and in which the elements' keys are the elements +themselves. +The \tcode{unordered_set} class +supports forward iterators. \pnum -A \tcode{multimap} meets all of the requirements +An \tcode{unordered_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{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. +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. -\indexlibrarymember{comp}{multimap::value_compare}% -\indexlibrarymember{operator()}{multimap::value_compare}% +\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. + +\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 Allocator = allocator>> - class multimap { + template, + class Pred = equal_to, + class Allocator = allocator> + class unordered_set { 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@; + 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} - class value_compare { - friend class multimap; - protected: - Compare comp; - value_compare(Compare c) : comp(c) { } - public: - bool operator()(const value_type& x, const value_type& y) const { - return comp(x.first, y.first); - } - }; + 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{multimap.cons}, construct/copy/destroy - multimap() : multimap(Compare()) { } - explicit multimap(const Compare& comp, const Allocator& = Allocator()); + // \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 + 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> + 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 + constexpr unordered_set(InputIterator f, InputIterator l, size_type n, + const allocator_type& a) + : unordered_set(f, l, n, hasher(), key_equal(), a) { } template - multimap(InputIterator first, InputIterator last, - const Compare& comp = Compare(), - const Allocator& = Allocator()); + 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> - 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) { } + 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> - 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) + 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); - multimap& 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; - - 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; - // \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); + // \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); - 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&) + 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& 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); - void clear() noexcept; + is_nothrow_swappable_v && is_nothrow_swappable_v); + constexpr void clear() noexcept; - template - void merge(multimap& source); - template - void merge(multimap&& source); - template - void merge(map& source); - template - void merge(map&& source); + template + constexpr void merge(unordered_set& source); + template + constexpr void merge(unordered_set&& source); + template + constexpr void merge(unordered_multiset& source); + template + constexpr void merge(unordered_multiset&& 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; - - 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; + // 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 - pair equal_range(const K& x); + constexpr pair equal_range(const K& k); template - pair equal_range(const K& x) const; + 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-to-alloc-type}@>> - multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) - -> multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, - Compare, Allocator>; + 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>; - 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 Pred = equal_to>, + class Allocator = allocator>> + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, +Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_set, Hash, Pred, Allocator>; - template, - class Allocator = allocator>> - multimap(initializer_list>, Compare = Compare(), Allocator = Allocator()) - -> multimap; + 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 - multimap(InputIterator, InputIterator, Allocator) - -> multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, - less<@\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_set(InputIterator, InputIterator, typename @\seebelow@::size_type, + Hash, Allocator) + -> unordered_set<@\placeholder{iter-value-type}@, Hash, + equal_to<@\placeholder{iter-value-type}@>, + Allocator>; template - multimap(from_range_t, R&&, Allocator) - -> multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, Allocator>; + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_set, hash>, + equal_to>, Allocator>; - template - multimap(initializer_list>, Allocator) - -> multimap, Allocator>; -} -\end{codeblock}% -\indexlibrarymember{multimap}{operator==}% -\indexlibrarymember{multimap}{operator<} + template + unordered_set(from_range_t, R&&, Allocator) + -> unordered_set, hash>, + equal_to>, Allocator>; -\rSec3[multimap.cons]{Constructors} + template + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_set, Hash, + equal_to>, Allocator>; -\indexlibraryctor{multimap}% -\begin{itemdecl} -explicit multimap(const Compare& comp, const Allocator& = Allocator()); -\end{itemdecl} + template + unordered_set(initializer_list, typename @\seebelow@::size_type, Allocator) + -> unordered_set, equal_to, Allocator>; -\begin{itemdescr} -\pnum -\effects -Constructs an empty -\tcode{multimap} -using the specified comparison object and allocator. + template + unordered_set(initializer_list, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_set, Allocator>; +} +\end{codeblock} \pnum -\complexity -Constant. -\end{itemdescr} +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. -\indexlibraryctor{multimap}% +\rSec3[unord.set.cnstr]{Constructors} + +\indexlibraryctor{unordered_set}% \begin{itemdecl} -template - multimap(InputIterator first, InputIterator last, - const Compare& comp = Compare(), - const Allocator& = Allocator()); +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{multimap} -using the specified comparison object and allocator, -and inserts elements from the range -\range{first}{last}. +Constructs an empty \tcode{unordered_set} using the +specified hash function, key equality predicate, and allocator, and +using at least \tcode{n} buckets. For the default constructor, +the number of buckets is \impldef{default number of buckets in +\tcode{unordered_set}}. +\tcode{max_load_factor()} returns \tcode{1.0}. \pnum \complexity -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{multimap}% +\indexlibraryctor{unordered_set}% \begin{itemdecl} +template + 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> - multimap(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); + 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{multimap} -using the specified comparison object and allocator, and -inserts elements from the range \tcode{rg}. +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 -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 iterator insert(P&& x); -template 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))}. +Average case linear, worst case quadratic. \end{itemdescr} -\rSec3[multimap.erasure]{Erasure} +\rSec3[unord.set.erasure]{Erasure} -\indexlibrarymember{erase_if}{multimap}% +\indexlibrarymember{erase_if}{unordered_set}% \begin{itemdecl} -template - typename multimap::size_type - erase_if(multimap& c, Predicate pred); +template + constexpr typename unordered_set::size_type + erase_if(unordered_set& c, Predicate pred); \end{itemdecl} \begin{itemdescr} @@ -10465,301 +15078,405 @@ \end{codeblock} \end{itemdescr} -\rSec2[set]{Class template \tcode{set}} +\rSec3[unord.set.modifiers]{Modifiers} -\rSec3[set.overview]{Overview} +\indexlibrarymember{insert}{unordered_set}% +\begin{itemdecl} +template constexpr pair insert(K&& obj); +template constexpr iterator insert(const_iterator hint, K&& obj); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and +\tcode{Pred::is_transparent} are valid and denote types. +For the second overload, +\tcode{is_convertible_v} 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)}. + +\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. +\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 -\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. +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 -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. +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. +\indexlibraryglobal{unordered_multiset}% \begin{codeblock} namespace std { - template, + template, + class Pred = equal_to, class Allocator = allocator> - class set { + class unordered_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{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}@; + 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} - // \ref{set.cons}, construct/copy/destroy - set() : set(Compare()) { } - explicit set(const Compare& comp, const Allocator& = Allocator()); + 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 + 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 - set(InputIterator first, InputIterator last, - const Compare& comp = Compare(), const Allocator& = Allocator()); + 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> - 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()); + 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 - set(InputIterator first, InputIterator last, const Allocator& a) - : set(first, last, Compare(), a) { } + 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> - 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) + 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); - set& operator=(initializer_list); - allocator_type get_allocator() const noexcept; + is_nothrow_move_assignable_v && is_nothrow_move_assignable_v); + constexpr unordered_multiset& 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 pair emplace(Args&&... args); - template iterator emplace_hint(const_iterator position, Args&&... args); - pair insert(const value_type& x); - pair 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); + 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> - 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 iterator insert(node_type&& nh); + constexpr iterator insert(const_iterator hint, node_type&& nh); - iterator erase(iterator position) + constexpr 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&) + 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); - void clear() noexcept; + is_nothrow_swappable_v && is_nothrow_swappable_v); + constexpr void clear() noexcept; - template - void merge(set& source); - template - void merge(set&& source); - template - void merge(multiset& source); - template - void merge(multiset&& source); + 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); // observers - key_compare key_comp() const; - value_compare value_comp() const; + constexpr hasher hash_function() const; + constexpr key_equal key_eq() 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; + 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 Hash = hash<@\placeholder{iter-value-type}@>, + class Pred = equal_to<@\placeholder{iter-value-type}@>, class Allocator = allocator<@\placeholder{iter-value-type}@>> - set(InputIterator, InputIterator, - Compare = Compare(), Allocator = Allocator()) - -> set<@\placeholder{iter-value-type}@, Compare, Allocator>; + unordered_multiset(InputIterator, InputIterator, @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multiset<@\placeholder{iter-value-type}@, + Hash, Pred, Allocator>; - template>, + template>, + class Pred = equal_to>, class Allocator = allocator>> - set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) - -> set, Compare, Allocator>; + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multiset, Hash, Pred, Allocator>; - template, class Allocator = allocator> - set(initializer_list, Compare = Compare(), Allocator = Allocator()) - -> set; + 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; template - set(InputIterator, InputIterator, Allocator) - -> set<@\placeholder{iter-value-type}@, - less<@\placeholder{iter-value-type}@>, Allocator>; + 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>; + + 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>; template - set(from_range_t, R&&, Allocator) - -> set, less>, Allocator>; + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_multiset, hash>, + equal_to>, Allocator>; - template - set(initializer_list, Allocator) -> set, Allocator>; -} -\end{codeblock}% -\indexlibrarymember{set}{operator==}% -\indexlibrarymember{set}{operator<} + template + unordered_multiset(from_range_t, R&&, Allocator) + -> unordered_multiset, hash>, + equal_to>, Allocator>; -\rSec3[set.cons]{Constructors, copy, and assignment} + template + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_multiset, Hash, equal_to>, + Allocator>; -\indexlibraryctor{set}% -\begin{itemdecl} -explicit set(const Compare& comp, const Allocator& = Allocator()); -\end{itemdecl} + template + unordered_multiset(initializer_list, typename @\seebelow@::size_type, Allocator) + -> unordered_multiset, equal_to, Allocator>; -\begin{itemdescr} -\pnum -\effects -Constructs an empty \tcode{set} using the specified comparison object and allocator. + template + unordered_multiset(initializer_list, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_multiset, Allocator>; +} +\end{codeblock} \pnum -\complexity -Constant. -\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. -\indexlibraryctor{set}% +\rSec3[unord.multiset.cnstr]{Constructors} + +\indexlibraryctor{unordered_multiset}% \begin{itemdecl} -template - set(InputIterator first, InputIterator last, - const Compare& comp = Compare(), const Allocator& = Allocator()); +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 \effects -Constructs an empty -\tcode{set} -using the specified comparison object and allocator, -and inserts elements from the range -\range{first}{last}. +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 -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{set}% +\indexlibraryctor{unordered_multiset}% \begin{itemdecl} +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> - set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); + 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 \effects -Constructs an empty \tcode{set} using the specified comparison object and allocator, -and inserts elements from the range \tcode{rg}. +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 -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[set.erasure]{Erasure} +\rSec3[unord.multiset.erasure]{Erasure} -\indexlibrarymember{erase_if}{set}% +\indexlibrarymember{erase_if}{unordered_multiset}% \begin{itemdecl} -template - typename set::size_type - erase_if(set& c, Predicate pred); +template + constexpr typename unordered_multiset::size_type + erase_if(unordered_multiset& c, Predicate pred); \end{itemdecl} \begin{itemdescr} @@ -10779,7672 +15496,7847 @@ \end{codeblock} \end{itemdescr} -\rSec2[multiset]{Class template \tcode{multiset}} +\rSec1[container.adaptors]{Container adaptors} -\rSec3[multiset.overview]{Overview} +\rSec2[container.adaptors.general]{General} \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. +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 -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} +Each container adaptor takes +one or more template parameters +named \tcode{Container}, \tcode{KeyContainer}, or \tcode{MappedContainer} +that denote the types of containers that the container adaptor adapts. +Each container adaptor has at least one constructor +that takes a reference argument to one or more such template parameters. +For each constructor reference argument to a container \tcode{C}, +the constructor copies the container into the container adaptor. +If \tcode{C} takes an allocator, then a compatible allocator may be passed in +to the adaptor's constructor. Otherwise, normal copy or move construction is used for the container +argument. +For the container adaptors +that take a single container template parameter \tcode{Container}, +the first template parameter \tcode{T} of the container adaptor +shall denote the same type as \tcode{Container::value_type}. + +\pnum +For container adaptors, no \tcode{swap} function throws an exception unless that +exception is thrown by the swap of the adaptor's +\tcode{Container}, +\tcode{KeyContainer}, +\tcode{MappedContainer}, or +\tcode{Compare} object (if any). + +\pnum +A constructor template of a container adaptor +shall not participate in overload resolution +if it has an \tcode{InputIterator} template parameter and +a type that does not qualify as an input iterator is deduced for that parameter. + +\pnum +For container adaptors that have them, +the \tcode{insert}, \tcode{emplace}, and \tcode{erase} members +affect the validity of iterators, references, and pointers +to the adaptor's container(s) in the same way that +the containers' respective +\tcode{insert}, \tcode{emplace}, and \tcode{erase} members do. +\begin{example} +A call to \tcode{flat_map::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 { + // \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{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. +\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 Allocator = allocator> - class multiset { + template> + class queue { 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 - multiset() : multiset(Compare()) { } - explicit multiset(const Compare& comp, const Allocator& = Allocator()); - template - multiset(InputIterator first, InputIterator last, - const Compare& comp = Compare(), const Allocator& = Allocator()); - template<@\exposconcept{container-compatible-range}@ R> - multiset(from_range_t, R&& rg, - const Compare& comp = Compare(), const Allocator& = Allocator()); - multiset(const multiset& x); - multiset(multiset&& x); - explicit multiset(const Allocator&); - multiset(const multiset&, const type_identity_t&); - multiset(multiset&&, const type_identity_t&); - multiset(initializer_list, const Compare& = Compare(), - const Allocator& = Allocator()); - template - multiset(InputIterator first, InputIterator last, const Allocator& a) - : multiset(first, last, Compare(), a) { } - template<@\exposconcept{container-compatible-range}@ R> - multiset(from_range_t, R&& rg, const Allocator& a)) - : multiset(from_range, std::forward(rg), Compare(), a) { } - multiset(initializer_list il, const Allocator& a) - : multiset(il, Compare(), a) { } - ~multiset(); - multiset& operator=(const multiset& x); - multiset& operator=(multiset&& x) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_move_assignable_v); - multiset& operator=(initializer_list); - allocator_type get_allocator() const noexcept; + 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; - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; + protected: + Container c; - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() 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); } + }; - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; + template + queue(Container) -> queue; - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; + template + queue(InputIterator, InputIterator) -> queue<@\exposid{iter-value-type}@>; - // 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); - template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); - void insert(initializer_list); + template + queue(from_range_t, R&&) -> queue>; - 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); + template + queue(Container, Allocator) -> queue; - 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&) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_swappable_v); - void clear() noexcept; + template + queue(InputIterator, InputIterator, Allocator) + -> queue<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, + Allocator>>; - template - void merge(multiset& source); - template - void merge(multiset&& source); - template - void merge(set& source); - template - void merge(set&& source); + template + queue(from_range_t, R&&, Allocator) + -> queue, deque, Allocator>>; - // observers - key_compare key_comp() const; - value_compare value_comp() const; + template + struct uses_allocator, Alloc> + : uses_allocator::type { }; +} +\end{codeblock} - // 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; +\rSec3[queue.cons]{Constructors} - size_type count(const key_type& x) const; - template size_type count(const K& x) const; +\indexlibraryctor{queue}% +\begin{itemdecl} +constexpr explicit queue(const Container& cont); +\end{itemdecl} - bool contains(const key_type& x) const; - template bool contains(const K& x) const; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{cont}. +\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{queue}% +\begin{itemdecl} +constexpr explicit queue(Container&& cont); +\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 +Initializes \tcode{c} with \tcode{std::move(cont)}. +\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; - }; +\indexlibraryctor{queue}% +\begin{itemdecl} +template + constexpr queue(InputIterator first, InputIterator last); +\end{itemdecl} - template>, - class Allocator = allocator<@\placeholder{iter-value-type}@>> - multiset(InputIterator, InputIterator, - Compare = Compare(), Allocator = Allocator()) - -> multiset<@\placeholder{iter-value-type}@, Compare, Allocator>; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with +\tcode{first} as the first argument and \tcode{last} as the second argument. +\end{itemdescr} - template>, - class Allocator = allocator>> - multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) - -> multiset, Compare, Allocator>; +\indexlibraryctor{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr queue(from_range_t, R&& rg); +\end{itemdecl} - template, class Allocator = allocator> - multiset(initializer_list, Compare = Compare(), Allocator = Allocator()) - -> multiset; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. +\end{itemdescr} - template - multiset(InputIterator, InputIterator, Allocator) - -> multiset<@\placeholder{iter-value-type}@, - less<@\placeholder{iter-value-type}@>, Allocator>; +\rSec3[queue.cons.alloc]{Constructors with allocators} - template - multiset(from_range_t, R&&, Allocator) - -> multiset, less>, Allocator>; +\pnum +If \tcode{uses_allocator_v} is \tcode{false} +the constructors in this subclause shall not participate in overload resolution. - template - multiset(initializer_list, Allocator) -> multiset, Allocator>; -} -\end{codeblock}% -\indexlibrarymember{multiset}{operator==}% -\indexlibrarymember{multiset}{operator<} +\indexlibraryctor{queue}% +\begin{itemdecl} +template constexpr explicit queue(const Alloc& a); +\end{itemdecl} -\rSec3[multiset.cons]{Constructors} +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{a}. +\end{itemdescr} -\indexlibraryctor{multiset}% +\indexlibraryctor{queue}% \begin{itemdecl} -explicit multiset(const Compare& comp, const Allocator& = Allocator()); +template constexpr queue(const container_type& cont, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an empty \tcode{multiset} using the specified comparison object and allocator. +Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} +as the second argument. +\end{itemdescr} + +\indexlibraryctor{queue}% +\begin{itemdecl} +template constexpr queue(container_type&& 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. \end{itemdescr} -\indexlibraryctor{multiset}% +\indexlibraryctor{queue}% \begin{itemdecl} -template - multiset(InputIterator first, InputIterator last, - const Compare& comp = Compare(), const Allocator& = Allocator()); +template constexpr queue(const queue& q, const Alloc& a); \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}. +Initializes \tcode{c} with \tcode{q.c} as the first argument and \tcode{a} as the +second argument. +\end{itemdescr} + +\indexlibraryctor{queue}% +\begin{itemdecl} +template constexpr queue(queue&& q, const Alloc& a); +\end{itemdecl} +\begin{itemdescr} \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}. +\effects +Initializes \tcode{c} with \tcode{std::move(q.c)} as the first argument and \tcode{a} +as the second argument. \end{itemdescr} -\indexlibraryctor{multiset}% +\indexlibraryctor{queue}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - multiset(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +template + constexpr queue(InputIterator first, InputIterator last, const Alloc& alloc); \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}. +Initializes \tcode{c} with +\tcode{first} as the first argument, +\tcode{last} as the second argument, and +\tcode{alloc} as the third argument. +\end{itemdescr} + +\indexlibraryctor{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr queue(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} +\begin{itemdescr} \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)}. +\effects +Initializes \tcode{c} with +\tcode{ranges::to(std::forward(rg), a)}. \end{itemdescr} -\rSec3[multiset.erasure]{Erasure} +\rSec3[queue.mod]{Modifiers} -\indexlibrarymember{erase_if}{multiset}% +\indexlibrarymember{push_range}{queue}% \begin{itemdecl} -template - typename multiset::size_type - erase_if(multiset& c, Predicate pred); +template<@\exposconcept{container-compatible-range}@ R> + constexpr void push_range(R&& rg); \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} +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} -\rSec1[unord]{Unordered associative containers} +\rSec3[queue.ops]{Operators} + +\indexlibrarymember{operator==}{queue}% +\begin{itemdecl} +template + constexpr bool operator==(const queue& x, const queue& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.c == y.c}. +\end{itemdescr} -\rSec2[unord.general]{In general} +\indexlibrary{\idxcode{operator"!=}!\idxcode{queue}}% +\begin{itemdecl} +template + constexpr bool operator!=(const queue& x, const queue& y); +\end{itemdecl} +\begin{itemdescr} \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}. +\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 -The exposition-only alias templates -\exposid{iter\--value\--type}, \exposid{iter\--key\--type}, -\exposid{iter\--mapped\--type}, and \exposid{iter\--to\--alloc\--type} -defined in \ref{associative.general} may appear in deduction guides for unordered containers. +\returns +\tcode{x.c < y.c}. +\end{itemdescr} -\rSec2[unord.map.syn]{Header \tcode{} synopsis} +\indexlibrarymember{operator>}{queue}% +\begin{itemdecl} +template + constexpr bool operator> (const queue& x, const queue& y); +\end{itemdecl} -\indexheader{unordered_map}% -\indexlibraryglobal{unordered_map}% -\indexlibraryglobal{unordered_multimap}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} +\begin{itemdescr} +\pnum +\returns +\tcode{x.c > y.c}. +\end{itemdescr} -namespace std { - // \ref{unord.map}, class template \tcode{unordered_map} - template, - class Pred = equal_to, - class Alloc = allocator>> - class unordered_map; +\indexlibrarymember{operator<=}{queue}% +\begin{itemdecl} +template + constexpr bool operator<=(const queue& x, const queue& y); +\end{itemdecl} - // \ref{unord.multimap}, class template \tcode{unordered_multimap} - template, - class Pred = equal_to, - class Alloc = allocator>> - class unordered_multimap; +\begin{itemdescr} +\pnum +\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} - template - bool operator==(const unordered_map& a, - const unordered_map& b); +\begin{itemdescr} +\pnum +\returns +\tcode{x.c >= y.c}. +\end{itemdescr} - template - bool operator==(const unordered_multimap& a, - const unordered_multimap& b); +\indexlibrarymember{operator<=>}{queue}% +\begin{itemdecl} +template + constexpr compare_three_way_result_t + operator<=>(const queue& x, const queue& y); +\end{itemdecl} - template - void swap(unordered_map& x, - unordered_map& y) - noexcept(noexcept(x.swap(y))); +\begin{itemdescr} +\pnum +\returns +\tcode{x.c <=> y.c}. +\end{itemdescr} - template - void swap(unordered_multimap& x, - unordered_multimap& y) - noexcept(noexcept(x.swap(y))); +\rSec3[queue.special]{Specialized algorithms} - // \ref{unord.map.erasure}, erasure for \tcode{unordered_map} - template - typename unordered_map::size_type - erase_if(unordered_map& c, Predicate pred); +\indexlibrarymember{swap}{queue}% +\begin{itemdecl} +template + constexpr void swap(queue& x, queue& y) + noexcept(noexcept(x.swap(y))); +\end{itemdecl} - // \ref{unord.multimap.erasure}, erasure for \tcode{unordered_multimap} - template - typename unordered_multimap::size_type - erase_if(unordered_multimap& c, Predicate pred); +\begin{itemdescr} +\pnum +\constraints +\tcode{is_swappable_v} is \tcode{true}. - namespace pmr { - template, - class Pred = equal_to> - using unordered_map = - std::unordered_map>>; - template, - class Pred = equal_to> - using unordered_multimap = - std::unordered_multimap>>; +\pnum +\effects +As if by \tcode{x.swap(y)}. +\end{itemdescr} - } -} -\end{codeblock} +\rSec2[priority.queue]{Class template \tcode{priority_queue}} -\rSec2[unord.set.syn]{Header \tcode{} synopsis} +\rSec3[priqueue.overview]{Overview} -\indexheader{unordered_set}% -\indexlibraryglobal{unordered_set}% -\indexlibraryglobal{unordered_multiset}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} +\pnum +\indexlibraryglobal{priority_queue}% +Any sequence container with random access iterator and supporting operations +\tcode{front()}, +\tcode{push_back()} +and +\tcode{pop_back()} +can be used to instantiate +\tcode{priority_queue}. +In particular, +\tcode{vector}\iref{vector} +and +\tcode{deque}\iref{deque} +can be used. +Instantiating +\tcode{priority_queue} +also involves supplying a function or function object for making +priority comparisons; the library assumes that the function or function +object defines a strict weak ordering\iref{alg.sorting}. +\begin{codeblock} namespace std { - // \ref{unord.set}, class template \tcode{unordered_set} - template, - class Pred = equal_to, - class Alloc = allocator> - class unordered_set; + template, + class Compare = less> + class priority_queue { + public: + using value_type = typename Container::value_type; + using reference = typename Container::reference; + using const_reference = typename Container::const_reference; + using size_type = typename Container::size_type; + using container_type = Container; + using value_compare = Compare; - // \ref{unord.multiset}, class template \tcode{unordered_multiset} - template, - class Pred = equal_to, - class Alloc = allocator> - class unordered_multiset; + protected: + Container c; + Compare comp; - template - bool operator==(const unordered_set& a, - const unordered_set& b); + 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 + constexpr priority_queue(InputIterator first, InputIterator last, + const Compare& x = Compare()); + template + constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x, + const Container&); + template + 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&); - template - bool operator==(const unordered_multiset& a, - const unordered_multiset& b); + 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 - void swap(unordered_set& x, - unordered_set& y) - noexcept(noexcept(x.swap(y))); + template + priority_queue(Compare, Container) + -> priority_queue; - template - void swap(unordered_multiset& x, - unordered_multiset& y) - noexcept(noexcept(x.swap(y))); + template>, + class Container = vector<@\exposid{iter-value-type}@>> + priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) + -> priority_queue<@\exposid{iter-value-type}@, Container, Compare>; - // \ref{unord.set.erasure}, erasure for \tcode{unordered_set} - template - typename unordered_set::size_type - erase_if(unordered_set& c, Predicate pred); + template>> + priority_queue(from_range_t, R&&, Compare = Compare()) + -> priority_queue, vector>, Compare>; - // \ref{unord.multiset.erasure}, erasure for \tcode{unordered_multiset} - template - typename unordered_multiset::size_type - erase_if(unordered_multiset& c, Predicate pred); + template + priority_queue(Compare, Container, Allocator) + -> priority_queue; - namespace pmr { - template, - class Pred = equal_to> - using unordered_set = std::unordered_set>; + template + priority_queue(InputIterator, InputIterator, Allocator) + -> priority_queue<@\exposid{iter-value-type}@, + vector<@\exposid{iter-value-type}@, Allocator>, + less<@\exposid{iter-value-type}@>>; - template, - class Pred = equal_to> - using unordered_multiset = std::unordered_multiset>; - } -} -\end{codeblock} + template + priority_queue(InputIterator, InputIterator, Compare, Allocator) + -> priority_queue<@\exposid{iter-value-type}@, + vector<@\exposid{iter-value-type}@, Allocator>, Compare>; -\rSec2[unord.map]{Class template \tcode{unordered_map}}% -\indexlibraryglobal{unordered_map} + template + priority_queue(InputIterator, InputIterator, Compare, Container, Allocator) + -> priority_queue; -\rSec3[unord.map.overview]{Overview} + template + priority_queue(from_range_t, R&&, Compare, Allocator) + -> priority_queue, vector, Allocator>, + Compare>; -\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. + template + priority_queue(from_range_t, R&&, Allocator) + -> priority_queue, vector, Allocator>>; -\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}. + // no equality is provided -\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. + template + struct uses_allocator, Alloc> + : uses_allocator::type { }; +} +\end{codeblock} -\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} +\rSec3[priqueue.cons]{Constructors} - 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}@; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +constexpr priority_queue(const Compare& x, const Container& y); +constexpr priority_queue(const Compare& x, Container&& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x} defines a strict weak ordering\iref{alg.sorting}. - // \ref{unord.map.cnstr}, construct/copy/destroy - unordered_map(); - explicit unordered_map(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - template - 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()); +\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} - 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) { } - template - unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a) - : unordered_map(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) { } - template<@\exposconcept{container-compatible-range}@ R> - unordered_map(from_range_t, R&& rg, size_type n, const allocator_type& a) - : unordered_map(from_range, std::forward(rg), n, hasher(), key_equal(), a) { } - template<@\exposconcept{container-compatible-range}@ R> - unordered_map(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) - : unordered_map(from_range, std::forward(rg), n, hf, key_equal(), a) { } - unordered_map(initializer_list il, size_type n, const allocator_type& a) - : unordered_map(il, n, hasher(), key_equal(), a) { } - unordered_map(initializer_list il, size_type n, const hasher& hf, - const allocator_type& a) - : unordered_map(il, n, hf, key_equal(), a) { } - ~unordered_map(); - unordered_map& operator=(const unordered_map&); - unordered_map& operator=(unordered_map&&) - noexcept(allocator_traits::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; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template + constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare()); +\end{itemdecl} - // 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; +\begin{itemdescr} +\pnum +\expects +\tcode{x} defines a strict weak ordering\iref{alg.sorting}. - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; +\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} - // \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); - template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); - void insert(initializer_list); +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +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} - 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); +\begin{itemdescr} +\pnum +\expects +\tcode{x} defines a strict weak ordering\iref{alg.sorting}. - 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 - 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); - - 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&) - 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{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} - template - void merge(unordered_map& source); - template - void merge(unordered_map&& source); - template - void merge(unordered_multimap& source); - template - void merge(unordered_multimap&& source); +\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} - // observers - hasher hash_function() const; - key_equal key_eq() const; +\begin{itemdescr} +\pnum +\expects +\tcode{x} defines a strict weak ordering\iref{alg.sorting}. - // 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; - template - 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; +\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} - // \ref{unord.map.elem}, element access - mapped_type& operator[](const key_type& k); - mapped_type& operator[](key_type&& k); - mapped_type& at(const key_type& k); - const mapped_type& at(const key_type& k) const; +\rSec3[priqueue.cons.alloc]{Constructors with allocators} - // 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; - 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; +\pnum +If \tcode{uses_allocator_v} is \tcode{false} +the constructors in this subclause shall not participate in overload resolution. - // 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 explicit priority_queue(const Alloc& a); +\end{itemdecl} - 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>; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{a} and value-initializes \tcode{comp}. +\end{itemdescr} - 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>; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template constexpr priority_queue(const Compare& compare, const Alloc& a); +\end{itemdecl} - 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; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{a} and initializes \tcode{comp} with \tcode{compare}. +\end{itemdescr} - 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>; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template + constexpr priority_queue(const Compare& compare, const Container& cont, const Alloc& a); +\end{itemdecl} - 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>; +\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_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>; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template + constexpr priority_queue(const Compare& compare, Container&& cont, const Alloc& a); +\end{itemdecl} - 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>; +\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_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>; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template constexpr priority_queue(const priority_queue& q, const Alloc& a); +\end{itemdecl} - 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>; +\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_map(initializer_list>, typename @\seebelow@::size_type, - Allocator) - -> unordered_map, equal_to, Allocator>; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template constexpr priority_queue(priority_queue&& q, const Alloc& a); +\end{itemdecl} - template - unordered_map(initializer_list>, Allocator) - -> unordered_map, 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_map(initializer_list>, typename @\seebelow@::size_type, Hash, - Allocator) - -> unordered_map, Allocator>; -} -\end{codeblock} +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template + constexpr priority_queue(InputIterator first, InputIterator last, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with +\tcode{first} as the first argument, +\tcode{last} as the second argument, and +\tcode{a} as the third argument, and +value-initializes \tcode{comp}; +calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} -\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. +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template + constexpr priority_queue(InputIterator first, InputIterator last, + const Compare& compare, const Alloc& a); +\end{itemdecl} -\rSec3[unord.map.cnstr]{Constructors} +\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{unordered_map}% +\indexlibraryctor{priority_queue}% \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()); +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_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}. +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_map}% +\indexlibraryctor{priority_queue}% \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()); -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()); +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_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}. +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.map.elem]{Element access} +\rSec3[priqueue.members]{Members} -\indexlibrarymember{unordered_map}{operator[]}% -\indextext{\idxcode{unordered_map}!element access}% +\indexlibrarymember{push}{priority_queue}% \begin{itemdecl} -mapped_type& operator[](const key_type& k); +constexpr void push(const value_type& x); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return try_emplace(k).first->second;} +As if by: +\begin{codeblock} +c.push_back(x); +push_heap(c.begin(), c.end(), comp); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{unordered_map}{operator[]}% -\indextext{\idxcode{unordered_map}!element access}% +\indexlibrarymember{push}{priority_queue}% \begin{itemdecl} -mapped_type& operator[](key_type&& k); +constexpr void push(value_type&& x); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return try_emplace(std::move(k)).first->second;} +As if by: +\begin{codeblock} +c.push_back(std::move(x)); +push_heap(c.begin(), c.end(), comp); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{unordered_map}{at}% -\indextext{\idxcode{unordered_map}!element access}% +\indexlibrarymember{push_range}{priority_queue}% \begin{itemdecl} -mapped_type& at(const key_type& k); -const mapped_type& at(const key_type& k) const; +template<@\exposconcept{container-compatible-range}@ R> + constexpr void push_range(R&& rg); \end{itemdecl} \begin{itemdescr} \pnum -\returns -A reference to \tcode{x.second}, where \tcode{x} is the (unique) element whose key is equivalent to \tcode{k}. +\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 -\throws -An exception object of type \tcode{out_of_range} if no such element is present. +\ensures +\tcode{is_heap(c.begin(), c.end(), comp)} is \tcode{true}. \end{itemdescr} -\rSec3[unord.map.modifiers]{Modifiers} - -\indexlibrarymember{unordered_map}{insert}% +\indexlibrarymember{emplace}{priority_queue}% \begin{itemdecl} -template - pair insert(P&& obj); +template constexpr void emplace(Args&&... args); \end{itemdecl} \begin{itemdescr} - -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. - \pnum \effects -Equivalent to: \tcode{return emplace(std::forward

(obj));} +As if by: +\begin{codeblock} +c.emplace_back(std::forward(args)...); +push_heap(c.begin(), c.end(), comp); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{unordered_map}{insert}% +\indexlibrarymember{pop}{priority_queue}% \begin{itemdecl} -template - iterator insert(const_iterator hint, P&& obj); +constexpr void pop(); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. - \pnum \effects -Equivalent to: -\tcode{return emplace_hint(hint, std::forward

(obj));} +As if by: +\begin{codeblock} +pop_heap(c.begin(), c.end(), comp); +c.pop_back(); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{try_emplace}{unordered_map}% +\rSec3[priqueue.special]{Specialized algorithms} + +\indexlibrarymember{swap}{priority_queue}% \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); +template + constexpr void swap(priority_queue& x, + priority_queue& y) noexcept(noexcept(x.swap(y))); \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)...)}. +\constraints +\tcode{is_swappable_v} is \tcode{true} and +\tcode{is_swappable_v} is \tcode{true}. \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)...)}. +As if by \tcode{x.swap(y)}. +\end{itemdescr} + +\rSec2[stack.syn]{Header \tcode{} synopsis} + +\indexheader{stack}% +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{stack}, class template \tcode{stack} + template> class stack; + + template + constexpr bool operator==(const stack& x, const stack& y); + template + constexpr bool operator!=(const stack& x, const stack& y); + template + constexpr bool operator< (const stack& x, const stack& y); + template + constexpr bool operator> (const stack& x, const stack& y); + template + constexpr bool operator<=(const stack& x, const stack& y); + template + constexpr bool operator>=(const stack& x, const stack& y); + template + constexpr compare_three_way_result_t + operator<=>(const stack& x, const stack& y); + + template + constexpr 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[stack]{Class template \tcode{stack}} + +\rSec3[stack.general]{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}. +\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; + + public: + 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 + constexpr stack(InputIterator first, InputIterator last, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + 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 + constexpr decltype(auto) emplace(Args&&... args) + { return c.emplace_back(std::forward(args)...); } + constexpr void pop() { c.pop_back(); } + constexpr void swap(stack& s) noexcept(is_nothrow_swappable_v) + { using std::swap; swap(c, s.c); } + }; + + template + stack(Container) -> stack; + + template + stack(InputIterator, InputIterator) -> stack<@\exposid{iter-value-type}@>; + + template + stack(from_range_t, R&&) -> stack>; + + template + stack(Container, Allocator) -> stack; + + template + stack(InputIterator, InputIterator, Allocator) + -> stack<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, + Allocator>>; + + template + stack(from_range_t, R&&, Allocator) + -> stack, deque, Allocator>>; -\pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. -\end{itemdescr} + template + struct uses_allocator, Alloc> + : uses_allocator::type { }; +} +\end{codeblock} -\indexlibrarymember{try_emplace}{unordered_map}% +\rSec3[stack.cons]{Constructors} + +\indexlibraryctor{stack}% \begin{itemdecl} -template - pair try_emplace(key_type&& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); +constexpr explicit stack(const Container& cont); \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 -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)...)}. +Initializes \tcode{c} with \tcode{cont}. +\end{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}. +\indexlibraryctor{stack}% +\begin{itemdecl} +constexpr explicit stack(Container&& cont); +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. +\effects +Initializes \tcode{c} with \tcode{std::move(cont)}. \end{itemdescr} -\indexlibrarymember{insert_or_assign}{unordered_map}% +\indexlibraryctor{stack}% \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); +template + constexpr stack(InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{is_assignable_v} is \tcode{true}. +\effects +Initializes \tcode{c} with +\tcode{first} as the first argument and \tcode{last} as the second argument. +\end{itemdescr} -\pnum -\expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{unordered_map} -from \tcode{k}, \tcode{std::for\-ward(obj)}. +\indexlibraryctor{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr stack(from_range_t, 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::for\-ward(obj)} to \tcode{e.second}. -Otherwise inserts an object of type \tcode{value_type} -constructed with \tcode{k}, \tcode{std::forward(obj)}. +Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. +\end{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}. +\rSec3[stack.cons.alloc]{Constructors with allocators} \pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. -\end{itemdescr} +If \tcode{uses_allocator_v} is \tcode{false} +the constructors in this subclause shall not participate in overload resolution. -\indexlibrarymember{insert_or_assign}{unordered_map}% +\indexlibraryctor{stack}% \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 explicit stack(const Alloc& a); \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)}. +Initializes \tcode{c} with \tcode{a}. +\end{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}. +\indexlibraryctor{stack}% +\begin{itemdecl} +template constexpr stack(const container_type& cont, const Alloc& a); +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. +\effects +Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} as the +second argument. \end{itemdescr} -\rSec3[unord.map.erasure]{Erasure} - -\indexlibrarymember{erase_if}{unordered_map}% +\indexlibraryctor{stack}% \begin{itemdecl} -template - typename unordered_map::size_type - erase_if(unordered_map& c, Predicate pred); +template constexpr stack(container_type&& cont, const Alloc& a); \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} +Initializes \tcode{c} with \tcode{std::move(cont)} as the first argument and \tcode{a} +as the second argument. \end{itemdescr} -\rSec2[unord.multimap]{Class template \tcode{unordered_multimap}}% -\indexlibraryglobal{unordered_multimap} - -\rSec3[unord.multimap.overview]{Overview} +\indexlibraryctor{stack}% +\begin{itemdecl} +template constexpr stack(const stack& s, const Alloc& a); +\end{itemdecl} +\begin{itemdescr} \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. +\effects +Initializes \tcode{c} with \tcode{s.c} as the first argument and \tcode{a} +as the second argument. +\end{itemdescr} -\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}. +\indexlibraryctor{stack}% +\begin{itemdecl} +template constexpr stack(stack&& s, const Alloc& a); +\end{itemdecl} +\begin{itemdescr} \pnum -Subclause~\ref{unord.multimap} only describes operations on \tcode{unordered_multimap} -that are not described in one of the requirement tables, or for which -there is additional semantic information. - -\indexlibraryglobal{unordered_multimap}% -\begin{codeblock} -namespace std { - template, - class Pred = equal_to, - class Allocator = allocator>> - class unordered_multimap { - 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 iterator = @\impdefx{type of \tcode{unordered_multimap::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{unordered_multimap::const_iterator}}@; // see \ref{container.requirements} - using local_iterator = @\impdefx{type of \tcode{unordered_multimap::local_iterator}}@; // see \ref{container.requirements} - using const_local_iterator = @\impdefx{type of \tcode{unordered_multimap::const_local_it\-erator}}@; // see \ref{container.requirements} - using node_type = @\unspec@; - - // \ref{unord.multimap.cnstr}, construct/copy/destroy - unordered_multimap(); - explicit unordered_multimap(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - template - 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; - - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; - - // \ref{unord.multimap.modifiers}, modifiers - template 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); - - 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; +\effects +Initializes \tcode{c} with \tcode{std::move(s.c)} as the first argument and \tcode{a} +as the second argument. +\end{itemdescr} - template - void merge(unordered_multimap& source); - template - void merge(unordered_multimap&& source); - template - void merge(unordered_map& source); - template - void merge(unordered_map&& source); +\indexlibraryctor{stack}% +\begin{itemdecl} +template + constexpr stack(InputIterator first, InputIterator last, const Alloc& alloc); +\end{itemdecl} - // observers - hasher hash_function() const; - key_equal key_eq() const; +\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} - // 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; +\indexlibraryctor{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr stack(from_range_t, R&& rg, 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; - 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{ranges::to(std::forward(rg), a)}. +\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); - }; +\rSec3[stack.mod]{Modifiers} - 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>; +\indexlibrarymember{push_range}{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr void push_range(R&& rg); +\end{itemdecl} - 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>; +\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} - 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; +\rSec3[stack.ops]{Operators} - 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>; +\indexlibrarymember{operator==}{stack}% +\begin{itemdecl} +template + constexpr bool operator==(const stack& x, const stack& y); +\end{itemdecl} - 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>; +\begin{itemdescr} +\pnum +\returns +\tcode{x.c == y.c}. +\end{itemdescr} - 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>; +\indexlibrary{\idxcode{operator"!=}!\idxcode{stack}}% +\begin{itemdecl} +template + constexpr bool operator!=(const stack& x, const stack& y); +\end{itemdecl} - 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>; +\begin{itemdescr} +\pnum +\returns +\tcode{x.c != y.c}. +\end{itemdescr} - 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>; +\indexlibrarymember{operator<}{stack}% +\begin{itemdecl} +template + constexpr bool operator< (const stack& x, const stack& y); +\end{itemdecl} - 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>; +\begin{itemdescr} +\pnum +\returns +\tcode{x.c < y.c}. +\end{itemdescr} - template - unordered_multimap(initializer_list>, typename @\seebelow@::size_type, - Allocator) - -> unordered_multimap, equal_to, Allocator>; +\indexlibrarymember{operator>}{stack}% +\begin{itemdecl} +template + constexpr bool operator> (const stack& x, const stack& y); +\end{itemdecl} - template - unordered_multimap(initializer_list>, Allocator) - -> unordered_multimap, equal_to, Allocator>; +\begin{itemdescr} +\pnum +\returns +\tcode{x.c > y.c}. +\end{itemdescr} - template - unordered_multimap(initializer_list>, typename @\seebelow@::size_type, - Hash, Allocator) - -> unordered_multimap, Allocator>; -} -\end{codeblock} +\indexlibrarymember{operator<=}{stack}% +\begin{itemdecl} +template + constexpr bool operator<=(const stack& x, const stack& y); +\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. - -\rSec3[unord.multimap.cnstr]{Constructors} +\returns +\tcode{x.c <= y.c}. +\end{itemdescr} -\indexlibraryctor{unordered_multimap}% +\indexlibrarymember{operator>=}{stack}% \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 + constexpr bool operator>=(const stack& x, const stack& 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. 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}. +\returns +\tcode{x.c >= y.c}. +\end{itemdescr} + +\indexlibrarymember{operator<=>}{stack}% +\begin{itemdecl} +template + constexpr compare_three_way_result_t + operator<=>(const stack& x, const stack& y); +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -Constant. +\returns +\tcode{x.c <=> y.c}. \end{itemdescr} -\indexlibraryctor{unordered_multimap}% +\rSec3[stack.special]{Specialized algorithms} + +\indexlibrarymember{swap}{stack}% \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 void swap(stack& x, stack& y) + noexcept(noexcept(x.swap(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}. +\constraints +\tcode{is_swappable_v} is \tcode{true}. \pnum -\complexity -Average case linear, worst case quadratic. +\effects +As if by \tcode{x.swap(y)}. \end{itemdescr} -\rSec3[unord.multimap.modifiers]{Modifiers} +\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}} -\indexlibrarymember{unordered_multimap}{insert}% -\begin{itemdecl} -template - iterator insert(P&& obj); -\end{itemdecl} +\rSec3[flat.map.overview]{Overview} -\begin{itemdescr} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\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 -\effects -Equivalent to: \tcode{return emplace(std::forward

(obj));} -\end{itemdescr} - -\indexlibrarymember{unordered_multimap}{insert}% -\begin{itemdecl} -template - iterator insert(const_iterator hint, P&& obj); -\end{itemdecl} +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} -\begin{itemdescr} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +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 -\effects -Equivalent to: -\tcode{return emplace_hint(hint, std::forward

(obj));} -\end{itemdescr} - -\rSec3[unord.multimap.erasure]{Erasure} +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. -\indexlibrarymember{erase_if}{unordered_multimap}% -\begin{itemdecl} -template - typename unordered_multimap::size_type - erase_if(unordered_multimap& c, Predicate pred); -\end{itemdecl} +\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} -\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} +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} -\rSec2[unord.set]{Class template \tcode{unordered_set}}% -\indexlibraryglobal{unordered_set} +\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} -\rSec3[unord.set.overview]{Overview} +\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 -\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. +The effect of calling a constructor +that takes +both \tcode{key_container_type} and \tcode{mapped_container_type} arguments with +containers of different sizes is undefined. \pnum -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. +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 -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. +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + +\rSec3[flat.map.defn]{Definition} -\indexlibraryglobal{unordered_set}% \begin{codeblock} namespace std { - template, - class Pred = equal_to, - class Allocator = allocator> - class unordered_set { + template, + class KeyContainer = vector, class MappedContainer = vector> + class flat_map { 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 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; - 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}@; + class value_compare { + private: + key_compare @\exposid{comp}@; // \expos + constexpr value_compare(key_compare c) : @\exposid{comp}@(c) { } // \expos - // \ref{unord.set.cnstr}, construct/copy/destroy - unordered_set(); - explicit unordered_set(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - template - 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) { } - template - unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a) - : unordered_set(f, l, n, hasher(), key_equal(), a) { } - 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; + public: + constexpr bool operator()(const_reference x, const_reference y) const { + return @\exposid{comp}@(x.first, y.first); + } + }; - // 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; + struct containers { + key_container_type keys; + mapped_container_type values; + }; - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; + // \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()); + + template + constexpr flat_map(InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(first, last); } + + template + constexpr flat_map(sorted_unique_t s, InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(s, first, last); } - // 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); - 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); + 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)); } - 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 flat_map(initializer_list il, const key_compare& comp = key_compare()) + : flat_map(il.begin(), il.end(), comp) { } - 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; + constexpr flat_map(sorted_unique_t s, initializer_list il, + const key_compare& comp = key_compare()) + : flat_map(s, il.begin(), il.end(), comp) { } - template - void merge(unordered_set& source); - template - void merge(unordered_set&& source); - template - void merge(unordered_multiset& source); - template - void merge(unordered_multiset&& source); + // \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 + 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); + + constexpr flat_map& operator=(initializer_list); - // observers - hasher hash_function() const; - key_equal key_eq() const; + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; - // 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; + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; - // 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; - 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 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; - // 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); - }; + // \ref{flat.map.capacity}, capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; - 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>; + // \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>, - 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>; + // \ref{flat.map.modifiers}, modifiers + template constexpr pair emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); - 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; + 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 - 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 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); - 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>; + constexpr void insert(initializer_list il) + { insert(il.begin(), il.end()); } + constexpr void insert(sorted_unique_t s, initializer_list il) + { insert(s, il.begin(), il.end()); } - template - unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) - -> unordered_set, hash>, - equal_to>, Allocator>; + constexpr containers extract() &&; + constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); - template - unordered_set(from_range_t, R&&, Allocator) - -> unordered_set, hash>, - equal_to>, Allocator>; + 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); - template - unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) - -> unordered_set, Hash, - equal_to>, Allocator>; + 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); - template - unordered_set(initializer_list, typename @\seebelow@::size_type, Allocator) - -> unordered_set, equal_to, Allocator>; + constexpr void swap(flat_map& y) noexcept; + constexpr void clear() noexcept; - template - unordered_set(initializer_list, typename @\seebelow@::size_type, Hash, Allocator) - -> unordered_set, Allocator>; -} -\end{codeblock} + // observers + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; -\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. + constexpr const key_container_type& keys() const noexcept { return @\exposid{c}@.keys; } + constexpr const mapped_container_type& values() const noexcept { return @\exposid{c}@.values; } -\rSec3[unord.set.cnstr]{Constructors} + // 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; -\indexlibraryctor{unordered_set}% -\begin{itemdecl} -unordered_set() : unordered_set(size_type(@\seebelow@)) { } -explicit unordered_set(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); -\end{itemdecl} + constexpr friend bool operator==(const flat_map& x, const flat_map& y); -\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}. + constexpr friend @\exposid{synth-three-way-result}@ + operator<=>(const flat_map& x, const flat_map& y); -\pnum -\complexity -Constant. -\end{itemdescr} + constexpr friend void swap(flat_map& x, flat_map& y) noexcept + { x.swap(y); } -\indexlibraryctor{unordered_set}% -\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()); -\end{itemdecl} + private: + containers @\exposid{c}@; // \expos + key_compare @\exposid{compare}@; // \expos -\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}. + 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; + }; + }; -\pnum -\complexity -Average case linear, worst case quadratic. -\end{itemdescr} + template> + flat_map(KeyContainer, MappedContainer, Compare = Compare()) + -> flat_map; -\rSec3[unord.set.erasure]{Erasure} + template + flat_map(KeyContainer, MappedContainer, Allocator) + -> flat_map, KeyContainer, MappedContainer>; + template + flat_map(KeyContainer, MappedContainer, Compare, Allocator) + -> flat_map; -\indexlibrarymember{erase_if}{unordered_set}% -\begin{itemdecl} -template - typename unordered_set::size_type - erase_if(unordered_set& c, Predicate pred); -\end{itemdecl} + template> + flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare = Compare()) + -> flat_map; -\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} + 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; -\rSec2[unord.multiset]{Class template \tcode{unordered_multiset}}% -\indexlibraryglobal{unordered_multiset} + template>> + flat_map(InputIterator, InputIterator, Compare = Compare()) + -> flat_map<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; -\rSec3[unord.multiset.overview]{Overview} + template>> + flat_map(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) + -> flat_map<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; -\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. + 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}@>>>; -\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. + 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}@>>>; -\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. + template> + flat_map(initializer_list>, Compare = Compare()) + -> flat_map; -\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} + template> + flat_map(sorted_unique_t, initializer_list>, Compare = Compare()) + -> flat_map; - 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@; + template + struct uses_allocator, Allocator> + : bool_constant && + uses_allocator_v> { }; +} +\end{codeblock} - // \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; +\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. - // 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[flat.map.cons]{Constructors} - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; +\indexlibraryctor{flat_map}% +\begin{itemdecl} +constexpr flat_map(key_container_type key_cont, mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); +\end{itemdecl} - // 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); +\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()}; 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} - 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); +\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} - 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; +\indexlibraryctor{flat_map}% +\begin{itemdecl} +constexpr flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); +\end{itemdecl} - template - void merge(unordered_multiset& source); - template - void merge(unordered_multiset&& source); - template - void merge(unordered_set& source); - template - void merge(unordered_set&& source); +\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}. - // observers - hasher hash_function() const; - key_equal key_eq() const; +\pnum +\complexity +Constant. +\end{itemdescr} - // 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; +\rSec3[flat.map.cons.alloc]{Constructors with allocators} - // 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; - 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; +\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}. - // 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{flat_map}% +\begin{itemdecl} +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} - 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 +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}. - 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 +\complexity +Same as \tcode{flat_map(key_cont, mapped_cont)} and +\tcode{flat_map(key_cont, mapped_cont, comp)}, respectively. +\end{itemdescr} - 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; +\indexlibraryctor{flat_map}% +\begin{itemdecl} +template + constexpr flat_map(sorted_unique_t s, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const Alloc& a); +template + constexpr flat_map(sorted_unique_t s, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const key_compare& comp, + const Alloc& a); +\end{itemdecl} - 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>; +\begin{itemdescr} +\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{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed +with uses-allocator construction\iref{allocator.uses.construction}. - 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>; +\pnum +\complexity +Linear. +\end{itemdescr} - template - unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) - -> unordered_multiset, hash>, - equal_to>, Allocator>; +\indexlibraryctor{flat_map}% +\begin{itemdecl} +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} - template - unordered_multiset(from_range_t, R&&, Allocator) - -> unordered_multiset, hash>, - equal_to>, Allocator>; +\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} - template - unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) - -> unordered_multiset, Hash, equal_to>, - Allocator>; +\rSec3[flat.map.capacity]{Capacity} - template - unordered_multiset(initializer_list, typename @\seebelow@::size_type, Allocator) - -> unordered_multiset, equal_to, Allocator>; +\indexlibrarymember{size}{flat_map}% +\begin{itemdecl} +constexpr size_type size() const noexcept; +\end{itemdecl} - template - unordered_multiset(initializer_list, typename @\seebelow@::size_type, Hash, Allocator) - -> unordered_multiset, Allocator>; -} -\end{codeblock} +\begin{itemdescr} +\pnum +\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 -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. +\returns +\tcode{min(\exposid{c}.keys.max_size(), \exposid{c}.values.max_size())}. +\end{itemdescr} -\rSec3[unord.multiset.cnstr]{Constructors} +\rSec3[flat.map.access]{Access} -\indexlibraryctor{unordered_multiset}% +\indexlibrarymember{operator[]}{flat_map}% \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()); +constexpr mapped_type& operator[](const key_type& x); \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}. +Equivalent to: \tcode{return try_emplace(x).first->second;} +\end{itemdescr} + +\indexlibrarymember{operator[]}{flat_map}% +\begin{itemdecl} +constexpr mapped_type& operator[](key_type&& x); +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -Constant. +\effects +Equivalent to: \tcode{return try_emplace(std::move(x)).first->second;} \end{itemdescr} -\indexlibraryctor{unordered_multiset}% +\indexlibrarymember{operator[]}{flat_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}{flat_map}% \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()); +constexpr mapped_type& at(const key_type& x); +constexpr const mapped_type& at(const key_type& x) const; \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}. +\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 -Average case linear, worst case quadratic. +Logarithmic. \end{itemdescr} -\rSec3[unord.multiset.erasure]{Erasure} - -\indexlibrarymember{erase_if}{unordered_multiset}% +\indexlibrarymember{at}{flat_map}% \begin{itemdecl} -template - typename unordered_multiset::size_type - erase_if(unordered_multiset& c, Predicate pred); +template constexpr mapped_type& at(const K& x); +template constexpr const mapped_type& at(const K& x) const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto original_size = c.size(); -for (auto i = c.begin(), last = c.end(); i != last; ) { - if (pred(*i)) { - i = c.erase(i); - } else { - ++i; - } -} -return original_size - c.size(); -\end{codeblock} -\end{itemdescr} - -\rSec1[container.adaptors]{Container adaptors} - -\rSec2[container.adaptors.general]{In general} +\constraints +The \grammarterm{qualified-id} \tcode{Compare::is_transparent} +is valid and denotes a type. \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. +\expects +The expression \tcode{find(x)} is well-formed and has well-defined behavior. \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}. +\returns +A reference to the \tcode{mapped_type} corresponding to +\tcode{x} in \tcode{*this}. \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). +\throws +An exception object of type \tcode{out_of_range} +if no such element is present. \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. +\complexity +Logarithmic. +\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} +\rSec3[flat.map.modifiers]{Modifiers} -\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{MappedContainer} and \tcode{Allocator} template parameters, and -\tcode{uses_allocator_v} is \tcode{false}. -\end{itemize} +\indexlibrarymember{emplace}{flat_map}% +\begin{itemdecl} +template constexpr pair emplace(Args&&... args); +\end{itemdecl} +\begin{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} and \exposid{iter-mapped-type} -defined in \ref{associative.general} -may appear in deduction guides for container adaptors. +\constraints +\tcode{is_constructible_v, Args...>} is \tcode{true}. \pnum -The following exposition-only alias templates may appear in deduction guides -for container adaptors: +\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} -template - using @\exposid{cont-key-type}@ = // \expos - remove_const_t; -template - using @\exposid{cont-mapped-type}@ = // \expos - typename Container::value_type::second_type; +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} -\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 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); +\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 - void swap(queue& x, queue& y) noexcept(noexcept(x.swap(y))); - template - struct uses_allocator, Alloc>; +\indexlibrarymember{insert}{flat_map}% +\begin{itemdecl} +template constexpr pair insert(P&& x); +template constexpr iterator insert(const_iterator position, P&& x); +\end{itemdecl} - template, - class Compare = less> - class priority_queue; +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v, P>} is \tcode{true}. - template - void swap(priority_queue& x, - priority_queue& y) noexcept(noexcept(x.swap(y))); - template - struct uses_allocator, Alloc>; -} -\end{codeblock} +\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} -\rSec2[stack.syn]{Header \tcode{} synopsis} +\indexlibrarymember{insert}{flat_map}% +\begin{itemdecl} +template + constexpr void insert(InputIterator first, InputIterator last); +\end{itemdecl} -\indexheader{stack}% +\begin{itemdescr} +\pnum +\effects +Adds elements to \exposid{c} as if by: \begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} - -namespace std { - template> class stack; - - template - bool operator==(const stack& x, const stack& y); - template - bool operator!=(const stack& x, const stack& y); - template - bool operator< (const stack& x, const stack& y); - template - bool operator> (const stack& x, const stack& y); - template - bool operator<=(const stack& x, const stack& y); - template - bool operator>=(const stack& x, const stack& y); - template - 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>; +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} - -\rSec2[flat.map.syn]{Header \tcode{} synopsis} - -\indexheader{flat_map}% +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} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} +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} -namespace std { - // \ref{flat.map}, class template \tcode{flat_map} - template, - class KeyContainer = vector, class MappedContainer = vector> - class flat_map; +\pnum +\complexity +$N$ + $M \log M$, +where $N$ is \tcode{size()} before the operation and +$M$ is \tcode{distance(first, last)}. - struct sorted_unique_t { explicit sorted_unique_t() = default; }; - inline constexpr sorted_unique_t sorted_unique{}; +\pnum +\remarks +Since this operation performs an in-place merge, it may allocate memory. +\end{itemdescr} - template - struct uses_allocator, - Allocator>; +\indexlibrarymember{insert}{flat_map}% +\begin{itemdecl} +template + constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); +\end{itemdecl} - // \ref{flat.map.erasure}, erasure for \tcode{flat_map} - template - typename flat_map::size_type - erase_if(flat_map& c, Predicate pred); +\begin{itemdescr} +\pnum +\effects +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} - // \ref{flat.multimap}, class template \tcode{flat_multimap} - template, - class KeyContainer = vector, class MappedContainer = vector> - class flat_multimap; +\pnum +\complexity +Linear in $N$, where $N$ is \tcode{size()} after the operation. - struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; - inline constexpr sorted_equivalent_t sorted_equivalent{}; +\pnum +\remarks +Since this operation performs an in-place merge, it may allocate memory. +\end{itemdescr} - template - struct uses_allocator, - Allocator>; +\indexlibrarymember{insert_range}{flat_map}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); +\end{itemdecl} - // \ref{flat.multimap.erasure}, erasure for \tcode{flat_multimap} - template - typename flat_multimap::size_type - erase_if(flat_multimap& c, Predicate pred); +\begin{itemdescr} +\pnum +\effects +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} - -\rSec2[flat.set.syn]{Header \tcode{} synopsis}% -\indexheader{flat_set}% - +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} -#include // see \ref{initializer.list.syn} - -namespace std { - // \ref{flat.set}, class template \tcode{flat_set} - template, class KeyContainer = vector> - class flat_set; +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} - struct sorted_unique_t { explicit sorted_unique_t() = default; }; - inline constexpr sorted_unique_t sorted_unique{}; +\pnum +\complexity +$N$ + $M \log M$, +where $N$ is \tcode{size()} before the operation and +$M$ is \tcode{ranges::distance(rg)}. - template - struct uses_allocator, Allocator>; +\pnum +\remarks +Since this operation performs an in-place merge, it may allocate memory. +\end{itemdescr} - // \ref{flat.set.erasure}, erasure for \tcode{flat_set} - template - typename flat_set::size_type - erase_if(flat_set& c, Predicate pred); +\indexlibrarymember{try_emplace}{flat_map}% +\begin{itemdecl} +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} - // \ref{flat.multiset}, class template \tcode{flat_multiset} - template, class KeyContainer = vector> - class flat_multiset; +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. - struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; - inline constexpr sorted_equivalent_t sorted_equivalent{}; +\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(@\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} - template - struct uses_allocator, Allocator>; +\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}. - // \ref{flat.multiset.erasure}, erasure for \tcode{flat_multiset} - template - typename flat_multiset::size_type - erase_if(flat_multiset& c, Predicate pred); -} -\end{codeblock} +\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} -\rSec2[queue]{Class template \tcode{queue}} +\indexlibrarymember{try_emplace}{flat_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} -\rSec3[queue.defn]{Definition} +\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} \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. +\expects +The conversion from \tcode{k} into \tcode{key_type} constructs +an object \tcode{u}, +for which \tcode{find(k) == find(u)} is \tcode{true}. +\pnum +\effects +If the map already contains an element whose key is equivalent to \tcode{k}, +\tcode{*this} and \tcode{args...} are unchanged. +Otherwise equivalent to: \begin{codeblock} -namespace std { - template> - class queue { - public: - using value_type = typename Container::value_type; - using reference = typename Container::reference; - using const_reference = typename Container::const_reference; - using size_type = typename Container::size_type; - using container_type = Container; +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.emplace(key_it, std::forward(k)); +@\exposid{c}@.values.emplace(value_it, std::forward(args)...); +\end{codeblock} - protected: - Container c; +\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}. - 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&); - template - queue(InputIterator first, InputIterator last, const Alloc&); - template<@\exposconcept{container-compatible-range}@ R, class Alloc> - queue(from_range_t, R&& rg, const Alloc&); - - [[nodiscard]] bool empty() const { return c.empty(); } - size_type size() const { return c.size(); } - 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); - template - 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); } - }; +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +\end{itemdescr} - template - queue(Container) -> queue; +\indexlibrarymember{insert_or_assign}{flat_map}% +\begin{itemdecl} +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} - template - queue(InputIterator, InputIterator) -> queue<@\exposid{iter-value-type}@>; +\begin{itemdescr} +\pnum +\constraints +\tcode{is_assignable_v} is \tcode{true} and +\tcode{is_constructible_v} is \tcode{true}. - template - queue(from_range_t, R&&) -> queue>; +\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. - template - queue(Container, Allocator) -> queue; +\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}. - template - queue(InputIterator, InputIterator, Allocator) - -> queue<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, - Allocator>>; +\pnum +\complexity +The same as \tcode{emplace} for the first two overloads and +the same as \tcode{emplace_hint} for the last two overloads. +\end{itemdescr} + +\indexlibrarymember{insert_or_assign}{flat_map}% +\begin{itemdecl} +template + 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 +\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} - template - queue(from_range_t, R&&, Allocator) - -> queue, deque, Allocator>>; +\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}. - template - struct uses_allocator, Alloc> - : uses_allocator::type { }; -} +\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. -\rSec3[queue.cons]{Constructors} +\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}. -\indexlibraryctor{queue}% +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +\end{itemdescr} + +\indexlibrarymember{swap}{flat_map}% \begin{itemdecl} -explicit queue(const Container& cont); +constexpr void swap(flat_map& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c} with \tcode{cont}. +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} -\indexlibraryctor{queue}% +\indexlibrarymember{extract}{flat_map}% \begin{itemdecl} -explicit queue(Container&& cont); +constexpr containers extract() &&; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{std::move(cont)}. +\ensures +\tcode{*this} is emptied, even if the function exits via an exception. + +\pnum +\returns +\tcode{std::move(\exposid{c})}. \end{itemdescr} -\indexlibraryctor{queue}% +\indexlibrarymember{replace}{flat_map}% \begin{itemdecl} -template - queue(InputIterator first, InputIterator last); +constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{key_cont.size() == mapped_cont.size()} is \tcode{true}, +the elements of \tcode{key_cont} are sorted with respect to \exposid{compare}, and +\tcode{key_cont} contains no equal elements. + \pnum \effects -Initializes \tcode{c} with -\tcode{first} as the first argument and \tcode{last} as the second argument. +Equivalent to: +\begin{codeblock} +@\exposid{c}@.keys = std::move(key_cont); +@\exposid{c}@.values = std::move(mapped_cont); +\end{codeblock} \end{itemdescr} -\indexlibraryctor{queue}% +\rSec3[flat.map.erasure]{Erasure} + +\indexlibrarymember{erase_if}{flat_map}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - queue(from_range_t, R&& rg); +template + constexpr typename flat_map::size_type + erase_if(flat_map& c, Predicate pred); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{Key} and \tcode{T} meet the \oldconcept{MoveAssignable} requirements. + \pnum \effects -Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. +Let $E$ be \tcode{bool(pred(pair(e)))}. +Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. + +\pnum +\returns +The number of elements erased. + +\pnum +\complexity +Exactly \tcode{c.size()} applications of the predicate. + +\pnum +\remarks +Stable\iref{algorithm.stable}. +If an invocation of \tcode{erase_if} exits via an exception, +\tcode{c} is in a valid but unspecified state\iref{defns.valid}. +\begin{note} +\tcode{c} still meets its invariants, +but can be empty. +\end{note} \end{itemdescr} -\rSec3[queue.cons.alloc]{Constructors with allocators} +\rSec2[flat.multimap]{Class template \tcode{flat_multimap}} + +\rSec3[flat.multimap.overview]{Overview} \pnum -If \tcode{uses_allocator_v} is \tcode{false} -the constructors in this subclause shall not participate in overload resolution. +\indexlibraryglobal{flat_multimap}% +A \tcode{flat_multimap} is a container adaptor +that provides an associative container interface +that supports equivalent keys +(i.e., possibly containing multiple copies of the same key value) and +provides for fast retrieval of values of another type \tcode{T} +based on the keys. +\tcode{flat_multimap} supports iterators that meet +the \oldconcept{InputIterator} requirements and +model the +\libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}. -\indexlibraryctor{queue}% -\begin{itemdecl} -template explicit queue(const Alloc& a); -\end{itemdecl} +\pnum +A \tcode{flat_multimap} meets all of the requirements +for a container\iref{container.reqmts} and +for a reversible container\iref{container.rev.reqmts}, +plus the optional container requirements\iref{container.opt.reqmts}. +\tcode{flat_multimap} meets the requirements of +an associative container\iref{associative.reqmts}, except that: +\begin{itemize} +\item +it does not meet the requirements related to node handles\iref{container.node}, +\item +it does not meet the requirements related to iterator invalidation, and +\item +the time complexity of the operations +that insert or erase a single element from the map is linear, +including the ones that take an insertion position iterator. +\end{itemize} +\begin{note} +A \tcode{flat_multimap} does not meet the additional requirements of an +allocator-aware container\iref{container.alloc.reqmts}. +\end{note} -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{a}. -\end{itemdescr} +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}. -\indexlibraryctor{queue}% -\begin{itemdecl} -template queue(const container_type& cont, const Alloc& a); -\end{itemdecl} +\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} -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} -as the second argument. -\end{itemdescr} +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} -\indexlibraryctor{queue}% -\begin{itemdecl} -template queue(container_type&& cont, const Alloc& a); -\end{itemdecl} +\pnum +If any member function in \ref{flat.multimap.defn} exits via an exception, +the invariants are restored. +\begin{note} +This can result in the \tcode{flat_multimap} being emptied. +\end{note} -\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} +Any type \tcode{C} +that meets the sequence container requirements\iref{sequence.reqmts} +can be used to instantiate \tcode{flat_multimap}, +as long as +\tcode{C::iterator} meets the \oldconcept{RandomAccessIterator} requirements and +invocations of +member functions \tcode{C::size} and \tcode{C::max_size} do not exit via an exception. +In particular, +\tcode{vector}\iref{vector} and \tcode{deque}\iref{deque} can be used. +\begin{note} +\tcode{vector} is not a sequence container. +\end{note} -\indexlibraryctor{queue}% -\begin{itemdecl} -template queue(const queue& q, const Alloc& a); -\end{itemdecl} +\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}. -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{q.c} as the first argument and \tcode{a} as the -second argument. -\end{itemdescr} +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. -\indexlibraryctor{queue}% -\begin{itemdecl} -template queue(queue&& q, const Alloc& a); -\end{itemdecl} +\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. + +\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_multimap { + 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 @\exposid{comp}@; // \expos + constexpr value_compare(key_compare c) : @\exposid{comp}@(c) { } // \expos -\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} + public: + constexpr bool operator()(const_reference x, const_reference y) const { + return @\exposid{comp}@(x.first, y.first); + } + }; -\indexlibraryctor{queue}% -\begin{itemdecl} -template - queue(InputIterator first, InputIterator last, const Alloc& alloc); -\end{itemdecl} + struct containers { + key_container_type keys; + mapped_container_type values; + }; -\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} + // \ref{flat.multimap.cons}, constructors + constexpr flat_multimap() : flat_multimap(key_compare()) { } -\indexlibraryctor{queue}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R, class Alloc> - queue(from_range_t, R&& rg, const Alloc& a); -\end{itemdecl} + constexpr explicit flat_multimap(const key_compare& comp) + : @\exposid{c}@(), @\exposid{compare}@(comp) { } -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{c} with -\tcode{ranges::to(std::forward(rg), a)}. -\end{itemdescr} + constexpr flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); -\rSec3[queue.mod]{Modifiers} + constexpr flat_multimap(sorted_equivalent_t, + key_container_type key_cont, mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); -\indexlibrarymember{push_range}{queue}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - void push_range(R&& rg); -\end{itemdecl} + template + constexpr flat_multimap(InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(), @\exposid{compare}@(comp) + { insert(first, last); } -\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} + template + constexpr flat_multimap(sorted_equivalent_t s, InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(s, first, last); } -\rSec3[queue.ops]{Operators} + template<@\exposconcept{container-compatible-range}@ R> + constexpr flat_multimap(from_range_t, R&& rg) + : flat_multimap(from_range, std::forward(rg), key_compare()) { } + template<@\exposconcept{container-compatible-range}@ R> + constexpr flat_multimap(from_range_t, R&& rg, const key_compare& comp) + : flat_multimap(comp) { insert_range(std::forward(rg)); } -\indexlibrarymember{operator==}{queue}% -\begin{itemdecl} -template - bool operator==(const queue& x, const queue& y); -\end{itemdecl} + constexpr flat_multimap(initializer_list il, + const key_compare& comp = key_compare()) + : flat_multimap(il.begin(), il.end(), comp) { } -\begin{itemdescr} -\pnum -\returns -\tcode{x.c == y.c}. -\end{itemdescr} + constexpr flat_multimap(sorted_equivalent_t s, initializer_list il, + const key_compare& comp = key_compare()) + : flat_multimap(s, il.begin(), il.end(), comp) { } -\indexlibrary{\idxcode{operator"!=}!\idxcode{queue}}% -\begin{itemdecl} -template - bool operator!=(const queue& x, const queue& y); -\end{itemdecl} + // \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); -\begin{itemdescr} -\pnum -\returns -\tcode{x.c != y.c}. -\end{itemdescr} + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; -\indexlibrarymember{operator<}{queue}% -\begin{itemdecl} -template - bool operator< (const queue& x, const queue& y); -\end{itemdecl} + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; -\begin{itemdescr} -\pnum -\returns -\tcode{x.c < y.c}. -\end{itemdescr} + 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; -\indexlibrarymember{operator>}{queue}% -\begin{itemdecl} -template - bool operator> (const queue& x, const queue& y); -\end{itemdecl} + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; -\begin{itemdescr} -\pnum -\returns -\tcode{x.c > y.c}. -\end{itemdescr} + // modifiers + template constexpr iterator emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); -\indexlibrarymember{operator<=}{queue}% -\begin{itemdecl} -template - bool operator<=(const queue& x, const queue& y); -\end{itemdecl} + 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)); } -\begin{itemdescr} -\pnum -\returns -\tcode{x.c <= y.c}. -\end{itemdescr} + template constexpr iterator insert(P&& x); + template + constexpr iterator insert(const_iterator position, P&&); + template + 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); -\indexlibrarymember{operator>=}{queue}% -\begin{itemdecl} -template - bool operator>=(const queue& x, - const queue& y); -\end{itemdecl} + constexpr void insert(initializer_list il) + { insert(il.begin(), il.end()); } + constexpr void insert(sorted_equivalent_t s, initializer_list il) + { insert(s, il.begin(), il.end()); } -\begin{itemdescr} -\pnum -\returns -\tcode{x.c >= y.c}. -\end{itemdescr} + constexpr containers extract() &&; + constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); -\indexlibrarymember{operator<=>}{queue}% -\begin{itemdecl} -template - compare_three_way_result_t - operator<=>(const queue& x, const queue& 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 -\returns -\tcode{x.c <=> y.c}. -\end{itemdescr} + constexpr void swap(flat_multimap&) noexcept; + constexpr void clear() noexcept; -\rSec3[queue.special]{Specialized algorithms} + // observers + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; -\indexlibrarymember{swap}{queue}% -\begin{itemdecl} -template - void swap(queue& x, queue& y) noexcept(noexcept(x.swap(y))); -\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 -\constraints -\tcode{is_swappable_v} is \tcode{true}. + // 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; -\pnum -\effects -As if by \tcode{x.swap(y)}. -\end{itemdescr} + constexpr size_type count(const key_type& x) const; + template constexpr size_type count(const K& x) const; -\rSec2[priority.queue]{Class template \tcode{priority_queue}} + constexpr bool contains(const key_type& x) const; + template constexpr bool contains(const K& x) const; -\rSec3[priqueue.overview]{Overview} + 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; -\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}. + 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{codeblock} -namespace std { - template, - class Compare = less> - class priority_queue { - public: - using value_type = typename Container::value_type; - using reference = typename Container::reference; - using const_reference = typename Container::const_reference; - using size_type = typename Container::size_type; - using container_type = Container; - using value_compare = Compare; + 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; - protected: - Container c; - Compare comp; + constexpr friend bool operator==(const flat_multimap& x, const flat_multimap& y); - 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&); - 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&); - template - priority_queue(InputIterator, InputIterator, const Alloc&); - template - priority_queue(InputIterator, InputIterator, const Compare&, const Alloc&); - template - priority_queue(InputIterator, InputIterator, const Compare&, const Container&, - const Alloc&); - template - priority_queue(InputIterator, InputIterator, const Compare&, Container&&, const Alloc&); - template<@\exposconcept{container-compatible-range}@ R, class Alloc> - priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&); - template<@\exposconcept{container-compatible-range}@ R, class Alloc> - priority_queue(from_range_t, R&& rg, const Alloc&); + constexpr friend @\exposid{synth-three-way-result}@ + operator<=>(const flat_multimap& x, const flat_multimap& y); - [[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); } - }; + constexpr friend void swap(flat_multimap& x, flat_multimap& y) noexcept + { x.swap(y); } - template - priority_queue(Compare, Container) - -> priority_queue; + private: + containers @\exposid{c}@; // \expos + key_compare @\exposid{compare}@; // \expos + }; - template>, - class Container = vector<@\exposid{iter-value-type}@>> - priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) - -> priority_queue<@\exposid{iter-value-type}@, Container, Compare>; + template> + flat_multimap(KeyContainer, MappedContainer, Compare = Compare()) + -> flat_multimap; - template>> - priority_queue(from_range_t, R&&, Compare = Compare()) - -> priority_queue, vector>, Compare>; + template + flat_multimap(KeyContainer, MappedContainer, Allocator) + -> flat_multimap, KeyContainer, MappedContainer>; + template + flat_multimap(KeyContainer, MappedContainer, Compare, Allocator) + -> flat_multimap; - template - priority_queue(Compare, Container, Allocator) - -> priority_queue; + template> + flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare = Compare()) + -> flat_multimap; - template - priority_queue(InputIterator, InputIterator, Allocator) - -> priority_queue<@\exposid{iter-value-type}@, - vector<@\exposid{iter-value-type}@, Allocator>, - less<@\exposid{iter-value-type}@>>; + 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 - priority_queue(InputIterator, InputIterator, Compare, Allocator) - -> priority_queue<@\exposid{iter-value-type}@, - vector<@\exposid{iter-value-type}@, Allocator>, Compare>; + template>> + flat_multimap(InputIterator, InputIterator, Compare = Compare()) + -> flat_multimap<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; - template - priority_queue(InputIterator, InputIterator, Compare, Container, Allocator) - -> priority_queue; + template>> + flat_multimap(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) + -> flat_multimap<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; - template - priority_queue(from_range_t, R&&, Compare, Allocator) - -> priority_queue, vector, Allocator>, - 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 - priority_queue(from_range_t, R&&, Allocator) - -> priority_queue, vector, Allocator>>; + 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}@>>>; - // no equality is provided + template> + flat_multimap(initializer_list>, Compare = Compare()) + -> flat_multimap; - template - struct uses_allocator, Alloc> - : uses_allocator::type { }; + template> + flat_multimap(sorted_equivalent_t, initializer_list>, Compare = Compare()) + -> flat_multimap; + + template + struct uses_allocator, + Allocator> + : bool_constant && + uses_allocator_v> { }; } \end{codeblock} -\rSec3[priqueue.cons]{Constructors} +\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. -\indexlibraryctor{priority_queue}% +\rSec3[flat.multimap.cons]{Constructors} + +\indexlibraryctor{flat_multimap}% \begin{itemdecl} -priority_queue(const Compare& x, const Container& y); -priority_queue(const Compare& x, Container&& y); +constexpr flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{x} defines a strict weak ordering\iref{alg.sorting}. - \pnum \effects Initializes -\tcode{comp} with -\tcode{x} and -\tcode{c} with -\tcode{y} (copy constructing or move constructing as appropriate); -calls -\tcode{make_heap(c.begin(), c.end(), comp)}. +\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()}. + +\pnum +\complexity +Linear in $N$ if the container arguments are already sorted +with respect to \tcode{value_comp()} and otherwise $N \log N$, +where $N$ is the value of \tcode{key_cont.size()} before this call. \end{itemdescr} -\indexlibraryctor{priority_queue}% +\indexlibraryctor{flat_multimap}% \begin{itemdecl} -template - priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare()); +constexpr flat_multimap(sorted_equivalent_t, key_container_type key_cont, + mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{x} defines a strict weak ordering\iref{alg.sorting}. +\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}. \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)}. +\complexity +Constant. \end{itemdescr} -\indexlibraryctor{priority_queue}% +\rSec3[flat.multimap.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} +and \tcode{uses_allocator_v} is \tcode{true}. + +\indexlibraryctor{flat_multimap}% \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); +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} \begin{itemdescr} \pnum -\expects -\tcode{x} defines a strict weak ordering\iref{alg.sorting}. +\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}. \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)}. +\complexity +Same as \tcode{flat_multimap(key_cont, mapped_cont)} and +\tcode{flat_multimap(key_cont, \linebreak{}mapped_cont, comp)}, respectively. \end{itemdescr} -\indexlibraryctor{priority_queue}% +\indexlibraryctor{flat_multimap}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); +template + constexpr flat_multimap(sorted_equivalent_t s, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const Alloc& a); +template + constexpr flat_multimap(sorted_equivalent_t s, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const key_compare& comp, + const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{x} defines a strict weak ordering\iref{alg.sorting}. +\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{\exposid{c}.keys} and \tcode{\exposid{c}.val\-ues} are constructed +with uses-allocator construction\iref{allocator.uses.construction}. \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)}. +\complexity +Linear. \end{itemdescr} -\rSec3[priqueue.cons.alloc]{Constructors with allocators} +\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} +\begin{itemdescr} \pnum -If \tcode{uses_allocator_v} is \tcode{false} -the constructors in this subclause shall not participate in overload resolution. +\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} -\indexlibraryctor{priority_queue}% +\rSec3[flat.multimap.erasure]{Erasure} + +\indexlibrarymember{erase_if}{flat_multimap}% \begin{itemdecl} -template explicit priority_queue(const Alloc& a); +template + constexpr typename flat_multimap::size_type + erase_if(flat_multimap& c, Predicate pred); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{Key} and \tcode{T} meet the \oldconcept{MoveAssignable} requirements. + \pnum \effects -Initializes \tcode{c} with \tcode{a} and value-initializes \tcode{comp}. +Let $E$ be \tcode{bool(pred(pair(e)))}. +Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. + +\pnum +\returns +The number of elements erased. + +\pnum +\complexity +Exactly \tcode{c.size()} applications of the predicate. + +\pnum +\remarks +Stable\iref{algorithm.stable}. +If an invocation of \tcode{erase_if} exits via an exception, +\tcode{c} is in a valid but unspecified state\iref{defns.valid}. +\begin{note} +\tcode{c} still meets its invariants, +but can be empty. +\end{note} \end{itemdescr} -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template priority_queue(const Compare& compare, const Alloc& a); -\end{itemdecl} +\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 + constexpr 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>; + + // \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} + +\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} -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{a} and initializes \tcode{comp} with \tcode{compare}. -\end{itemdescr} - -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(const Compare& compare, const Container& cont, const Alloc& a); -\end{itemdecl} +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}. -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} as the second -argument, and initializes \tcode{comp} with \tcode{compare}; -calls \tcode{make_heap(c.begin(), c.end(), comp)}. -\end{itemdescr} - -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(const Compare& compare, Container&& cont, const Alloc& a); -\end{itemdecl} +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 -\effects -Initializes \tcode{c} with \tcode{std::move(cont)} as the first argument and \tcode{a} -as the second argument, and initializes \tcode{comp} with \tcode{compare}; -calls \tcode{make_heap(c.begin(), c.end(), comp)}. -\end{itemdescr} - -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template priority_queue(const priority_queue& q, const Alloc& a); -\end{itemdecl} +A \tcode{flat_set} maintains the invariant that the keys are sorted with +respect to the comparison object. -\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} +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} -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template priority_queue(priority_queue&& q, const Alloc& a); -\end{itemdecl} +\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} -\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} +The program is ill-formed if \tcode{Key} is not the same type +as \tcode{KeyContainer::value_type}. -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(InputIterator first, InputIterator last, const Alloc& a); -\end{itemdecl} +\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. -\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} +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(InputIterator first, InputIterator last, const Compare& compare, const Alloc& a); -\end{itemdecl} +\rSec3[flat.set.defn]{Definition} -\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} +\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; -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(InputIterator first, InputIterator last, const Compare& compare, - const Container& cont, const Alloc& a); -\end{itemdecl} + // \ref{flat.set.cons}, constructors + constexpr flat_set() : flat_set(key_compare()) { } -\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} + constexpr explicit flat_set(const key_compare& comp) + : @\exposid{c}@(), @\exposid{compare}@(comp) { } -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(InputIterator first, InputIterator last, const Compare& compare, Container&& cont, - const Alloc& a); -\end{itemdecl} + constexpr explicit flat_set(container_type cont, const key_compare& comp = key_compare()); -\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} + constexpr flat_set(sorted_unique_t, container_type cont, + const key_compare& comp = key_compare()) + : @\exposid{c}@(std::move(cont)), @\exposid{compare}@(comp) { } -\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} + template + constexpr flat_set(InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(), @\exposid{compare}@(comp) + { insert(first, last); } -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{comp} with \tcode{compare} and -\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}; -calls \tcode{make_heap(c.begin(), c.end(), comp)}. -\end{itemdescr} + template + constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(first, last), @\exposid{compare}@(comp) { } -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R, class Alloc> - priority_queue(from_range_t, R&& rg, const Alloc& a); -\end{itemdecl} + 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 -\effects -Initializes -\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}; -calls \tcode{make_heap(c.\linebreak begin(), c.end(), comp)}. -\end{itemdescr} + constexpr flat_set(initializer_list il, const key_compare& comp = key_compare()) + : flat_set(il.begin(), il.end(), comp) { } -\rSec3[priqueue.members]{Members} + constexpr flat_set(sorted_unique_t s, initializer_list il, + const key_compare& comp = key_compare()) + : flat_set(s, il.begin(), il.end(), comp) { } -\indexlibrarymember{push}{priority_queue}% -\begin{itemdecl} -void push(const value_type& x); -\end{itemdecl} + // \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 -\effects -As if by: -\begin{codeblock} -c.push_back(x); -push_heap(c.begin(), c.end(), comp); -\end{codeblock} -\end{itemdescr} + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; -\indexlibrarymember{push}{priority_queue}% -\begin{itemdecl} -void push(value_type&& x); -\end{itemdecl} + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; -\begin{itemdescr} -\pnum -\effects -As if by: -\begin{codeblock} -c.push_back(std::move(x)); -push_heap(c.begin(), c.end(), comp); -\end{codeblock} -\end{itemdescr} + 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; -\indexlibrarymember{push_range}{priority_queue}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - void push_range(R&& rg); -\end{itemdecl} + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; -\begin{itemdescr} -\pnum -\effects -Insert all elements of \tcode{rg} in \tcode{c}. + // \ref{flat.set.modifiers}, modifiers + template constexpr pair emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); -\pnum -\ensures -\tcode{is_heap(c.begin(), c.end(), comp)} is \tcode{true}. -\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{emplace}{priority_queue}% -\begin{itemdecl} -template void emplace(Args&&... args); -\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 -\effects -As if by: -\begin{codeblock} -c.emplace_back(std::forward(args)...); -push_heap(c.begin(), c.end(), comp); -\end{codeblock} -\end{itemdescr} + constexpr void insert(initializer_list il) + { insert(il.begin(), il.end()); } + constexpr void insert(sorted_unique_t s, initializer_list il) + { insert(s, il.begin(), il.end()); } + constexpr container_type extract() &&; + constexpr void replace(container_type&&); -\indexlibrarymember{pop}{priority_queue}% -\begin{itemdecl} -void pop(); -\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 -\effects -As if by: -\begin{codeblock} -pop_heap(c.begin(), c.end(), comp); -c.pop_back(); -\end{codeblock} -\end{itemdescr} + constexpr void swap(flat_set& y) noexcept; + constexpr void clear() noexcept; -\rSec3[priqueue.special]{Specialized algorithms} + // observers + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; -\indexlibrarymember{swap}{priority_queue}% -\begin{itemdecl} -template - void swap(priority_queue& x, - priority_queue& y) noexcept(noexcept(x.swap(y))); -\end{itemdecl} + // 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; -\begin{itemdescr} -\pnum -\constraints -\tcode{is_swappable_v} is \tcode{true} and -\tcode{is_swappable_v} is \tcode{true}. + constexpr size_type count(const key_type& x) const; + template constexpr size_type count(const K& x) const; -\pnum -\effects -As if by \tcode{x.swap(y)}. -\end{itemdescr} + constexpr bool contains(const key_type& x) const; + template constexpr bool contains(const K& x) const; -\rSec2[stack]{Class template \tcode{stack}} + 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; -\rSec3[stack.general]{General} + 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; -\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. + 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; -\rSec3[stack.defn]{Definition} + constexpr friend bool operator==(const flat_set& x, const flat_set& y); -\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; + constexpr friend @\placeholder{synth-three-way-result}@ + operator<=>(const flat_set& x, const flat_set& y); - protected: - Container c; + constexpr friend void swap(flat_set& x, flat_set& y) noexcept { x.swap(y); } - 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); } + private: + container_type @\exposidnc{c}@; // \expos + key_compare @\exposidnc{compare}@; // \expos }; - template - stack(Container) -> stack; - - template - stack(InputIterator, InputIterator) -> stack<@\exposid{iter-value-type}@>; + template> + flat_set(KeyContainer, Compare = Compare()) + -> flat_set; + template + flat_set(KeyContainer, Allocator) + -> flat_set, KeyContainer>; + template + flat_set(KeyContainer, Compare, Allocator) + -> flat_set; + + 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; - template - stack(from_range_t, R&&) -> stack>; + template>> + flat_set(InputIterator, InputIterator, Compare = Compare()) + -> flat_set<@\placeholder{iter-value-type}@, Compare>; - template - stack(Container, Allocator) -> stack; + template>> + flat_set(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) + -> flat_set<@\placeholder{iter-value-type}@, Compare>; - template - stack(InputIterator, InputIterator, Allocator) - -> stack<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, - Allocator>>; + template>, + class Allocator = allocator>> + flat_set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> flat_set, Compare, + vector, + @\exposid{alloc-rebind}@>>>; template - stack(from_range_t, R&&, Allocator) - -> stack, deque, Allocator>>; + flat_set(from_range_t, R&&, Allocator) + -> flat_set, less>, + vector, + @\exposid{alloc-rebind}@>>>; - template - struct uses_allocator, Alloc> - : uses_allocator::type { }; + template> + flat_set(initializer_list, Compare = Compare()) + -> flat_set; + + template> + flat_set(sorted_unique_t, initializer_list, Compare = Compare()) + -> flat_set; + + template + struct uses_allocator, Allocator> + : bool_constant> { }; } \end{codeblock} -\rSec3[stack.cons]{Constructors} +\rSec3[flat.set.cons]{Constructors} -\indexlibraryctor{stack}% +\indexlibraryctor{flat_set}% \begin{itemdecl} -explicit stack(const Container& cont); +constexpr explicit flat_set(container_type cont, const key_compare& comp = key_compare()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c} with \tcode{cont}. -\end{itemdescr} - -\indexlibraryctor{stack}% -\begin{itemdecl} -explicit stack(Container&& cont); -\end{itemdecl} +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. -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{std::move(cont)}. +\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} -\indexlibraryctor{stack}% -\begin{itemdecl} -template - stack(InputIterator first, InputIterator last); -\end{itemdecl} +\rSec3[flat.set.cons.alloc]{Constructors with allocators} -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with -\tcode{first} as the first argument and \tcode{last} as the second argument. -\end{itemdescr} +The constructors in this subclause shall not participate in overload resolution +unless \tcode{uses_allocator_v} is \tcode{true}. -\indexlibraryctor{stack}% +\indexlibraryctor{flat_set}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - stack(from_range_t, R&& rg); +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 -Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. -\end{itemdescr} - -\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{stack}% -\begin{itemdecl} -template explicit stack(const Alloc& a); -\end{itemdecl} +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}. -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{a}. +\complexity +Same as \tcode{flat_set(cont)} and \tcode{flat_set(cont, comp)}, respectively. \end{itemdescr} -\indexlibraryctor{stack}% +\indexlibraryctor{flat_set}% \begin{itemdecl} -template stack(const container_type& cont, const Alloc& a); +template + constexpr flat_set(sorted_unique_t s, const container_type& cont, const Alloc& a); +template + constexpr flat_set(sorted_unique_t s, const container_type& cont, + const key_compare& comp, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} as the -second argument. -\end{itemdescr} - -\indexlibraryctor{stack}% -\begin{itemdecl} -template stack(container_type&& cont, const Alloc& a); -\end{itemdecl} +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}. -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{std::move(cont)} as the first argument and \tcode{a} -as the second argument. +\complexity +Linear. \end{itemdescr} -\indexlibraryctor{stack}% +\indexlibraryctor{flat_set}% \begin{itemdecl} -template stack(const stack& s, const Alloc& a); +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 \effects -Initializes \tcode{c} with \tcode{s.c} as the first argument and \tcode{a} -as the second argument. +Equivalent to the corresponding non-allocator constructors +except that \exposid{c} is constructed with +uses-allocator construction\iref{allocator.uses.construction}. \end{itemdescr} -\indexlibraryctor{stack}% +\rSec3[flat.set.modifiers]{Modifiers} + +\indexlibrarymember{insert}{flat_set}% \begin{itemdecl} -template stack(stack&& s, const Alloc& a); +template constexpr pair insert(K&& x); +template constexpr iterator insert(const_iterator hint, K&& x); \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 +The \grammarterm{qualified-id} \tcode{Compare::is_transparent} +is valid and denotes a type. +\tcode{is_constructi\-ble_v} is \tcode{true}. -\indexlibraryctor{stack}% -\begin{itemdecl} -template - stack(InputIterator first, InputIterator last, const Alloc& alloc); -\end{itemdecl} +\pnum +\expects +The conversion from \tcode{x} into \tcode{value_type} constructs +an object \tcode{u}, for which \tcode{find(x) == 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} - -\indexlibraryctor{stack}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R, class Alloc> - stack(from_range_t, R&& rg, const Alloc& a); -\end{itemdecl} +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))}. -\begin{itemdescr} \pnum -\effects -Initializes -\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}. +\returns +In the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the element +whose key is equivalent to \tcode{x}. \end{itemdescr} -\rSec3[stack.mod]{Modifiers} - -\indexlibrarymember{push_range}{stack}% +\indexlibrarymember{insert}{flat_set}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - void push_range(R&& rg); +template + constexpr void insert(InputIterator first, InputIterator last); \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} +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. -\indexlibrarymember{operator==}{stack}% -\begin{itemdecl} -template - bool operator==(const stack& x, const stack& y); -\end{itemdecl} +\pnum +\complexity +$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and +$M$ is \tcode{distance(first, last)}. -\begin{itemdescr} \pnum -\returns -\tcode{x.c == y.c}. +\remarks +Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{stack}}% +\indexlibrarymember{insert}{flat_set}% \begin{itemdecl} -template - bool operator!=(const stack& x, const stack& y); +template + constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.c != y.c}. +\effects +Equivalent to \tcode{insert(first, last)}. + +\pnum +\complexity +Linear. \end{itemdescr} -\indexlibrarymember{operator<}{stack}% +\indexlibrarymember{insert_range}{flat_set}% \begin{itemdecl} -template - bool operator< (const stack& x, const stack& y); +template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.c < y.c}. -\end{itemdescr} +\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. -\indexlibrarymember{operator>}{stack}% -\begin{itemdecl} -template - bool operator> (const stack& x, const stack& y); -\end{itemdecl} +\pnum +\complexity +$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$ +is \tcode{ranges::distance(rg)}. -\begin{itemdescr} \pnum -\returns -\tcode{x.c > y.c}. +\remarks +Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} -\indexlibrarymember{operator<=}{stack}% +\indexlibrarymember{swap}{flat_set}% \begin{itemdecl} -template - bool operator<=(const stack& x, const stack& y); +constexpr void swap(flat_set& 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}@, y.@\exposid{c}@); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator>=}{stack}% +\indexlibrarymember{extract}{flat_set}% \begin{itemdecl} -template - bool operator>=(const stack& x, const stack& y); +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{x.c >= y.c}. +\tcode{std::move(\exposid{c})}. \end{itemdescr} -\indexlibrarymember{operator<=>}{stack}% +\indexlibrarymember{replace}{flat_set}% \begin{itemdecl} -template - compare_three_way_result_t - operator<=>(const stack& x, const stack& y); +constexpr void replace(container_type&& cont); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.c <=> y.c}. +\expects +The elements of \tcode{cont} are sorted with respect to \exposid{compare}, and +\tcode{cont} contains no equal elements. + +\pnum +\effects +Equivalent to: \tcode{\exposid{c} = std::move(cont);} \end{itemdescr} -\rSec3[stack.special]{Specialized algorithms} +\rSec3[flat.set.erasure]{Erasure} -\indexlibrarymember{swap}{stack}% +\indexlibrarymember{erase_if}{flat_set}% \begin{itemdecl} -template - void swap(stack& x, stack& y) noexcept(noexcept(x.swap(y))); +template + constexpr typename flat_set::size_type + erase_if(flat_set& c, Predicate pred); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_swappable_v} is \tcode{true}. +\expects +\tcode{Key} meets the \oldconcept{MoveAssignable} requirements. \pnum \effects -As if by \tcode{x.swap(y)}. +Let $E$ be \tcode{bool(pred(as_const(e)))}. +Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. + +\pnum +\returns +The number of elements erased. + +\pnum +\complexity +Exactly \tcode{c.size()} applications of the predicate. + +\pnum +\remarks +Stable\iref{algorithm.stable}. +If an invocation of \tcode{erase_if} exits via an exception, +\tcode{c} is in a valid but unspecified state\iref{defns.valid}. +\begin{note} +\tcode{c} still meets its invariants, but can be empty. +\end{note} \end{itemdescr} -\rSec2[flat.map]{Class template \tcode{flat_map}} +\rSec2[flat.multiset]{Class template \tcode{flat_multiset}} -\rSec3[flat.map.overview]{Overview} +\rSec3[flat.multiset.overview]{Overview} \pnum -\indexlibraryglobal{flat_map}% -A \tcode{flat_map} is a container adaptor +\indexlibraryglobal{flat_multiset}% +A \tcode{flat_multiset} 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 +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_map} meets all of the requirements -of a container\iref{container.reqmts} and -of a reversible container\iref{container.rev.reqmts}, +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_map} meets the requirements of -an associative container\iref{associative.reqmts}, -except that: +\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, including the ones that take an insertion -position iterator. +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_map} 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_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}. +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_map} that -are not described in one of those sets of requirements or for operations where -there is additional semantic information. +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_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} +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.map.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_map} being emptied. +This can result in the \tcode{flat_multiset}'s being emptied. \end{note} \pnum -Any sequence container\iref{sequence.reqmts} \tcode{C} -supporting \oldconcept{RandomAccessIterator} can be used -to instantiate \tcode{flat_map}, -as long as 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. +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} \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_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. +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. -\rSec3[flat.map.defn]{Definition} +\rSec3[flat.multiset.defn]{Definition} \begin{codeblock} namespace std { - template, - class KeyContainer = vector, class MappedContainer = vector> - class flat_map { + 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_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; - - 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.map.cons}, construct/copy/destroy - flat_map() : flat_map(key_compare()) { } + constexpr explicit flat_multiset(const key_compare& comp) + : @\exposid{c}@(), @\exposid{compare}@(comp) { } - flat_map(key_container_type key_cont, mapped_container_type mapped_cont); - template - flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const Allocator& a); + constexpr explicit flat_multiset(container_type cont, + const key_compare& comp = key_compare()); - flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont); - template - flat_map(sorted_unique_t, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, 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) { } - 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); + template + constexpr flat_multiset(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_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_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_multiset(from_range_t, R&& rg) + : flat_multiset(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_multiset(from_range_t, R&& rg, const key_compare& comp) + : flat_multiset(comp) + { insert_range(std::forward(rg)); } - 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 flat_multiset(initializer_list il, + const key_compare& comp = key_compare()) + : flat_multiset(il.begin(), il.end(), comp) { } - 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 flat_multiset(sorted_equivalent_t s, initializer_list il, + const key_compare& comp = key_compare()) + : flat_multiset(s, il.begin(), il.end(), comp) { } - flat_map& operator=(initializer_list il); + // \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; - - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() 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 cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() 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{flat.map.capacity}, capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() 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{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; + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; - // \ref{flat.map.modifiers}, modifiers - template pair 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); - pair insert(const value_type& x) + constexpr iterator insert(const value_type& x) { return emplace(x); } - pair 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 pair 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_unique_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_unique_t s, initializer_list il) + constexpr void insert(sorted_equivalent_t s, initializer_list il) { insert(s, il.begin(), il.end()); } - containers extract() &&; - void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); - - 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); + 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_map& y) 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; + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; - const key_container_type& keys() const noexcept { return c.keys; } - const mapped_container_type& values() const noexcept { return c.values; } - - // map operations - iterator find(const key_type& x); - const_iterator find(const key_type& x) const; - template 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; - template pair equal_range(const K& x); - template pair equal_range(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 bool operator==(const flat_map& x, const flat_map& y); + constexpr friend bool operator==(const flat_multiset& x, const flat_multiset& y); - friend @\exposid{synth-three-way-result}@ - operator<=>(const flat_map& x, const flat_map& y); + friend @\placeholder{synth-three-way-result}@ + constexpr operator<=>(const flat_multiset& x, const flat_multiset& y); - friend void swap(flat_map& x, flat_map& y) noexcept + constexpr friend void swap(flat_multiset& x, flat_multiset& y) noexcept { x.swap(y); } private: - containers c; // \expos - key_compare compare; // \expos - - struct key_equiv { // \expos - key_equiv(key_compare c) : comp(c) { } - bool operator()(const_reference x, const_reference y) const { - return !comp(x.first, y.first) && !comp(y.first, x.first); - } - key_compare comp; - }; + container_type @\exposidnc{c}@; // \expos + key_compare @\exposidnc{compare}@; // \expos }; - template - flat_map(KeyContainer, MappedContainer) - -> flat_map, KeyContainer, MappedContainer>; - - template - flat_map(KeyContainer, MappedContainer, Allocator) - -> flat_map, KeyContainer, MappedContainer>; - - template - flat_map(sorted_unique_t, KeyContainer, MappedContainer) - -> flat_map, KeyContainer, MappedContainer>; - - template - flat_map(sorted_unique_t, KeyContainer, MappedContainer, Allocator) - -> flat_map, KeyContainer, MappedContainer>; - - template>> - flat_map(InputIterator, InputIterator, Compare = Compare()) - -> flat_map<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; - - template>> - flat_map(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) - -> flat_map<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; - - template>, - class Allocator> - flat_map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) - -> flat_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare>; - - template - flat_map(from_range_t, R&&, Allocator) - -> flat_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@>; - - template> - flat_map(initializer_list>, Compare = Compare()) - -> flat_map; - - template> - flat_map(sorted_unique_t, initializer_list>, Compare = Compare()) - -> flat_map; - - template - struct uses_allocator, Allocator> - : bool_constant && - uses_allocator_v> { }; -} -\end{codeblock} - -\pnum -The member type \tcode{containers} has the data members and special members -specified above. -It has no base classes or members other than those specified. - -\rSec3[flat.map.cons]{Constructors} - -\indexlibraryctor{flat_map}% -\begin{itemdecl} -flat_map(key_container_type key_cont, mapped_container_type mapped_cont); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{c.keys} with \tcode{std::move(key_cont)} and -\tcode{c.values} with \tcode{std::move(mapped_cont)}; -value-initializes \tcode{compare}; -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 = ranges::zip_view(c.keys, c.values); -auto it = ranges::unique(zv, key_equiv(compare)).begin(); -auto dist = distance(zv.begin(), it); -c.keys.erase(c.keys.begin() + dist, c.keys.end()); -c.values.erase(c.values.begin() + dist, c.values.end()); -\end{codeblock} - -\pnum -\complexity -Linear in $N$ if the container arguments are already sorted -with respect to \tcode{value_comp()} and otherwise $N \log N$, -where $N$ is the value of \tcode{key_cont.size()} before this call. -\end{itemdescr} - -\indexlibraryctor{flat_map}% -\begin{itemdecl} -template - flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const Allocator& a); -\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_map(key_cont, mapped_cont)}, -except that \tcode{c.keys} and \tcode{c.values} are constructed with -uses-allocator construction\iref{allocator.uses.construction}. - -\pnum -\complexity -Same as \tcode{flat_map(key_cont, mapped_cont)}. -\end{itemdescr} - -\indexlibraryctor{flat_map}% -\begin{itemdecl} -flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{c.keys} with \tcode{std::move(key_cont)} and -\tcode{c.values} with \tcode{std::move(mapped_cont)}; -value-initializes \tcode{compare}. - -\pnum -\complexity -Constant. -\end{itemdescr} - -\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); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true} and -\tcode{uses_allocator_v} is \tcode{true}. + 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_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; -\pnum -\effects -Equivalent to \tcode{flat_map(s, key_cont, mapped_cont)}, -except that \tcode{c.keys} and \tcode{c.values} are constructed -with uses-allocator construction\iref{allocator.uses.construction}. - -\pnum -\complexity -Linear. -\end{itemdescr} - -\indexlibraryctor{flat_map}% -\begin{itemdecl} -template - 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} - -\begin{itemdescr} -\pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true}. - -\pnum -\effects -Equivalent to the corresponding non-allocator constructors -except that \tcode{c.keys} and \tcode{c.values} are constructed -with uses-allocator construction\iref{allocator.uses.construction}. -\end{itemdescr} + template>> + flat_multiset(InputIterator, InputIterator, Compare = Compare()) + -> flat_multiset<@\placeholder{iter-value-type}@, Compare>; -\rSec3[flat.map.capacity]{Capacity} + template>> + flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) + -> flat_multiset<@\placeholder{iter-value-type}@, Compare>; -\indexlibrarymember{size}{flat_map}% -\begin{itemdecl} -size_type size() const noexcept; -\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 -\returns -\tcode{c.keys.size()}. -\end{itemdescr} + template + flat_multiset(from_range_t, R&&, Allocator) + -> flat_multiset, less>, + vector, + @\exposid{alloc-rebind}@>>>; -\indexlibrarymember{max_size}{flat_map}% -\begin{itemdecl} -size_type max_size() const noexcept; -\end{itemdecl} + template> + flat_multiset(initializer_list, Compare = Compare()) + -> flat_multiset; -\begin{itemdescr} -\pnum -\returns -\tcode{min(c.keys.max_size(), c.values.max_size())}. -\end{itemdescr} + template> + flat_multiset(sorted_equivalent_t, initializer_list, Compare = Compare()) + -> flat_multiset; -\rSec3[flat.map.access]{Access} + template + struct uses_allocator, Allocator> + : bool_constant> { }; +} +\end{codeblock} -\indexlibrarymember{operator[]}{flat_map}% +\rSec3[flat.multiset.cons]{Constructors} + +\indexlibraryctor{flat_multiset}% \begin{itemdecl} -mapped_type& operator[](const key_type& x); +constexpr explicit flat_multiset(container_type cont, const key_compare& comp = key_compare()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return try_emplace(x).first->second;} +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} -\indexlibrarymember{operator[]}{flat_map}% -\begin{itemdecl} -mapped_type& operator[](key_type&& x); -\end{itemdecl} +\rSec3[flat.multiset.cons.alloc]{Constructors with allocators} -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return try_emplace(std::move(x)).first->second;} -\end{itemdescr} +The constructors in this subclause shall not participate in overload resolution +unless \tcode{uses_allocator_v} is \tcode{true}. -\indexlibrarymember{operator[]}{flat_map}% +\indexlibraryctor{flat_multiset}% \begin{itemdecl} -template mapped_type& operator[](K&& x); +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 -\constraints -The \grammarterm{qualified-id} \tcode{Compare::is_transparent} is valid and -denotes a type. +\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 -\effects -Equivalent to: \tcode{return try_emplace(std::forward(x)).first->second;} +\complexity +Same as \tcode{flat_multiset(cont)} and +\tcode{flat_multiset(cont, comp)}, respectively. \end{itemdescr} -\indexlibrarymember{at}{flat_map}% +\indexlibraryctor{flat_multiset}% \begin{itemdecl} -mapped_type& at(const key_type& x); -const mapped_type& at(const key_type& x) const; +template + constexpr flat_multiset(sorted_equivalent_t s, const container_type& cont, const Alloc& a); +template + constexpr flat_multiset(sorted_equivalent_t s, const container_type& cont, + const key_compare& comp, const Alloc& a); \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. +\effects +Equivalent to \tcode{flat_multiset(s, cont)} and +\tcode{flat_multiset(s, cont, comp)}, respectively, +except that \exposid{c} is constructed with +uses-allocator construction\iref{allocator.uses.construction}. \pnum \complexity -Logarithmic. +Linear. \end{itemdescr} -\indexlibrarymember{at}{flat_map}% +\indexlibraryctor{flat_multiset}% \begin{itemdecl} -template mapped_type& at(const K& x); -template const mapped_type& at(const K& x) const; +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 -\constraints -The \grammarterm{qualified-id} \tcode{Compare::is_transparent} -is valid and denotes a type. - -\pnum -\expects -The expression \tcode{find(x)} is well-formed and has well-defined behavior. - -\pnum -\returns -A reference to the \tcode{mapped_type} corresponding to -\tcode{x} in \tcode{*this}. - -\pnum -\throws -An exception object of type \tcode{out_of_range} -if no such element is present. - -\pnum -\complexity -Logarithmic. +\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.map.modifiers]{Modifiers} +\rSec3[flat.multiset.modifiers]{Modifiers} -\indexlibrarymember{emplace}{flat_map}% +\indexlibrarymember{emplace}{flat_multiset}% \begin{itemdecl} -template pair emplace(Args&&... args); +template constexpr iterator emplace(Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_constructible_v, Arg...>} is \tcode{true}. +\tcode{is_constructible_v} is \tcode{true}. \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: +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 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)); +auto it = ranges::upper_bound(@\exposid{c}@, t, @\exposid{compare}@); +@\exposid{c}@.insert(it, std::move(t)); \end{codeblock} \pnum \returns -The \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place, and -the iterator component of the pair points to -the element with key equivalent to \tcode{t.first}. -\end{itemdescr} - -\indexlibrarymember{insert}{flat_map}% -\begin{itemdecl} -template pair insert(P&& x); -template iterator insert(const_iterator position, P&& x); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v, P>} 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));}. +An iterator that points to the inserted element. \end{itemdescr} -\indexlibrarymember{insert}{flat_map}% +\indexlibrarymember{insert}{flat_multiset}% \begin{itemdecl} template - void insert(InputIterator first, InputIterator last); + constexpr void insert(InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} \pnum \effects -Adds elements to \tcode{c} as if by: -\begin{codeblock} -for (; first != last; ++first) { - value_type value = *first; - c.keys.insert(c.keys.end(), std::move(value.first)); - c.values.insert(c.values.end(), std::move(value.second)); -} -\end{codeblock} -Then, sorts the range of newly inserted elements -with respect to \tcode{value_comp()}; -merges the resulting sorted range and -the sorted range of pre-existing elements into a single sorted range; and -finally erases the duplicate elements as if by: +Adds elements to \exposid{c} as if by: \begin{codeblock} -auto zv = ranges::zip_view(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()); +@\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 -$N$ + $M \log M$, -where $N$ is \tcode{size()} before the operation and -$M$ is \tcode{distance(first, last)}. +$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$ +is \tcode{distance(first, last)}. \pnum \remarks Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} -\indexlibrarymember{insert}{flat_map}% +\indexlibrarymember{insert}{flat_multiset}% \begin{itemdecl} template - void insert(sorted_unique_t, InputIterator first, InputIterator last); + constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} \pnum \effects -Adds elements to \tcode{c} as if by: -\begin{codeblock} -for (; first != last; ++first) { - value_type value = *first; - c.keys.insert(c.keys.end(), std::move(value.first)); - c.values.insert(c.values.end(), std::move(value.second)); -} -\end{codeblock} -Then, merges the sorted range of newly added elements and -the sorted range of pre-existing elements into a single sorted range; and -finally erases the duplicate elements as if by: -\begin{codeblock} -auto zv = ranges::zip_view(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{insert(first, last)}. \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. +Linear. \end{itemdescr} -\indexlibrarymember{insert_range}{flat_map}% +\indexlibrarymember{swap}{flat_multiset}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); +constexpr void swap(flat_multiset& y) noexcept; \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: +Equivalent to: \begin{codeblock} -auto zv = ranges::zip_view(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()); +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 -\complexity -$N$ + $M \log M$, -where $N$ is \tcode{size()} before the operation and -$M$ is \tcode{ranges::distance(rg)}. +\ensures +\tcode{*this} is emptied, even if the function exits via an exception. \pnum -\remarks -Since this operation performs an in-place merge, it may allocate memory. +\returns +\tcode{std::move(\exposid{c})}. \end{itemdescr} -\indexlibrarymember{try_emplace}{flat_map}% +\indexlibrarymember{replace}{flat_multiset}% \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); +constexpr void replace(container_type&& cont); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\expects +The elements of \tcode{cont} are sorted with respect to \exposid{compare}. \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: \tcode{\exposid{c} = std::move(cont);} \end{itemdescr} -\indexlibrarymember{try_emplace}{flat_map}% -\begin{itemdecl} -template - pair try_emplace(K&& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, K&& k, Args&&... args); +\rSec3[flat.multiset.erasure]{Erasure} + +\indexlibrarymember{erase_if}{flat_multiset}% +\begin{itemdecl} +template + constexpr typename flat_multiset::size_type + erase_if(flat_multiset& c, Predicate pred); \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} - \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}. +\tcode{Key} meets the \oldconcept{MoveAssignable} requirements. \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} +Let $E$ be \tcode{bool(pred(as_const(e)))}. +Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. \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}. +The number of elements erased. \pnum \complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +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} -\indexlibrarymember{insert_or_assign}{flat_map}% -\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); -\end{itemdecl} +\rSec2[container.adaptors.format]{Container adaptors formatting} -\begin{itemdescr} \pnum -\constraints -\tcode{is_assignable_v} is \tcode{true} and -\tcode{is_constructible_v} is \tcode{true}. +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: -\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 +\indexlibraryglobal{formatter}% \begin{codeblock} -try_emplace_hint(hint, std::forward(k), std::forward(obj)) +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} -for the last two overloads. -\pnum -\returns -In the first two overloads, the \tcode{bool} component of the returned pair -is \tcode{true} if and only if the insertion took place. The returned -iterator points to the map element whose key is equivalent to \tcode{k}. +\indexlibrarymember{parse}{formatter}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -The same as \tcode{emplace} for the first two overloads and -the same as \tcode{emplace_hint} for the last two overloads. +\effects +Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} \end{itemdescr} -\indexlibrarymember{insert_or_assign}{flat_map}% +\indexlibrarymember{format}{formatter}% \begin{itemdecl} -template - pair insert_or_assign(K&& k, M&& obj); -template - iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); +template + typename FormatContext::iterator + format(@\exposid{maybe-const-adaptor}@& r, FormatContext& ctx) const; \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{return \exposid{underlying_}.format(r.c, ctx);} +\end{itemdescr} -\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}. +\rSec1[views]{Views} + +\rSec2[views.general]{General} \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 +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. + +\rSec2[views.contiguous]{Contiguous access} + +\rSec3[span.syn]{Header \tcode{} synopsis}% + +\indexheader{span}% \begin{codeblock} -try_emplace_hint(hint, std::forward(k), std::forward(obj)) +#include // see \ref{initializer.list.syn} + +// mostly freestanding +namespace std { + // constants + inline constexpr size_t @\libglobal{dynamic_extent}@ = numeric_limits::max(); + + 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 + 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}; + + // \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} -for the second overload. + +\rSec3[views.span]{Class template \tcode{span}} + +\rSec4[span.overview]{Overview} \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}. +\indexlibraryglobal{span}% +A \tcode{span} is a view over a contiguous sequence of objects, +the storage of which is owned by some other object. \pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. -\end{itemdescr} +All member functions of \tcode{span} have constant time complexity. + +\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{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; + + constexpr span& operator=(const span& other) noexcept = default; + + // \ref{span.sub}, subviews + template + constexpr span first() const; + template + constexpr span last() const; + template + constexpr span subspan() const; + + 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{span.obs}, observers + constexpr size_type size() const noexcept; + constexpr size_type size_bytes() const noexcept; + constexpr bool empty() const noexcept; + + // \ref{span.elem}, element access + constexpr reference operator[](size_type idx) const; + constexpr reference at(size_type idx) const; // freestanding-deleted + constexpr reference front() const; + constexpr reference back() const; + constexpr pointer data() const noexcept; + + // \ref{span.iterators}, iterator support + constexpr iterator begin() const noexcept; + constexpr iterator end() const noexcept; + constexpr const_iterator cbegin() const noexcept { return begin(); } + constexpr const_iterator cend() const noexcept { return end(); } + constexpr reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); } + constexpr const_reverse_iterator crend() const noexcept { return rend(); } -\indexlibrarymember{swap}{flat_map}% -\begin{itemdecl} -void swap(flat_map& y) noexcept; -\end{itemdecl} + private: + pointer @\exposid{data_}@; // \expos + size_type @\exposid{size_}@; // \expos + }; -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -ranges::swap(compare, y.compare); -ranges::swap(c.keys, y.c.keys); -ranges::swap(c.values, y.c.values); + 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} -\end{itemdescr} -\indexlibrarymember{extract}{flat_map}% -\begin{itemdecl} -containers extract() &&; -\end{itemdecl} +\pnum +\tcode{span} is +a trivially copyable type\iref{term.trivially.copyable.type}. -\begin{itemdescr} \pnum -\ensures -\tcode{*this} is emptied, even if the function exits via an exception. +\tcode{ElementType} is required to be +a complete object type that is not an abstract class type. \pnum -\returns -\tcode{std::move(c)}. -\end{itemdescr} +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}. -\indexlibrarymember{replace}{flat_map}% +\rSec4[span.cons]{Constructors, copy, and assignment} + +\indexlibraryctor{span}% \begin{itemdecl} -void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); +constexpr span() noexcept; \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. +\constraints +\tcode{Extent == dynamic_extent || Extent == 0} is \tcode{true}. \pnum -\effects -Equivalent to: -\begin{codeblock} -c.keys = std::move(key_cont); -c.values = std::move(mapped_cont); -\end{codeblock} +\ensures +%FIXME: Should "is \tcode{true}" be appended here? +\tcode{size() == 0 \&\& data() == nullptr}. \end{itemdescr} -\rSec3[flat.map.erasure]{Erasure} - -\indexlibrarymember{erase_if}{flat_map}% +\indexlibraryctor{span}% \begin{itemdecl} -template - typename flat_map::size_type - erase_if(flat_map& c, Predicate pred); +template + constexpr explicit(extent != dynamic_extent) span(It first, size_type count); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{Key} and \tcode{T} meet the \oldconcept{MoveAssignable} requirements. +\constraints +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 -\effects -Let $E$ be \tcode{bool(pred(pair(e)))}. -Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. +\expects +\begin{itemize} +\item \range{first}{first + count} is a valid range. +\item \tcode{It} models \libconcept{contiguous_iterator}. +\end{itemize} \pnum -\returns -The number of elements erased. +\hardexpects +If \tcode{extent} is not equal to \tcode{dynamic_extent}, +then \tcode{count == extent} is \tcode{true}. \pnum -\complexity -Exactly \tcode{c.size()} applications of the predicate. +\effects +Initializes \exposid{data_} with \tcode{to_address(first)} and +\exposid{size_} with \tcode{count}. \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} +\throws +Nothing. \end{itemdescr} -\rSec2[flat.multimap]{Class template \tcode{flat_multimap}} - -\rSec3[flat.multimap.overview]{Overview} - -\pnum -\indexlibraryglobal{flat_multimap}% -A \tcode{flat_multimap} is a container adaptor -that provides an associative container interface -that supports equivalent keys -(i.e., possibly containing multiple copies of the same key value) and -provides for fast retrieval of values of another type \tcode{T} -based on the keys. -\tcode{flat_multimap} supports iterators that meet -the \oldconcept{InputIterator} requirements and -model the -\libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}. +\indexlibraryctor{span}% +\begin{itemdecl} +template + constexpr explicit(extent != dynamic_extent) span(It first, End last); +\end{itemdecl} +\begin{itemdescr} \pnum -A \tcode{flat_multimap} meets all of the requirements -for a container\iref{container.reqmts} and -for a reversible container\iref{container.rev.reqmts}, -plus the optional container requirements\iref{container.opt.reqmts}. -\tcode{flat_multimap} meets the requirements of -an associative container\iref{associative.reqmts}, except that: +\constraints +Let \tcode{U} be \tcode{remove_reference_t>}. \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} +\tcode{is_convertible_v} is \tcode{true}. \begin{note} -A \tcode{flat_multimap} does not meet the additional requirements of an -allocator-aware container\iref{container.alloc.reqmts}. +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 -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 -Except as otherwise noted, -operations on \tcode{flat_multimap} are equivalent to those of \tcode{flat_map}, -except that \tcode{flat_multimap} operations -do not remove or replace elements with equal keys. -\begin{example} -\tcode{flat_multimap} constructors and emplace do not erase -non-unique elements after sorting them. -\end{example} - -\pnum -A \tcode{flat_multimap} maintains the following invariants: +\expects \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. +\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 -If any member function in \ref{flat.multimap.defn} exits via an exception, -the invariants are restored. -\begin{note} -This can result in the \tcode{flat_multimap} being emptied. -\end{note} - -\pnum -Any sequence container\iref{sequence.reqmts} \tcode{C} -supporting \oldconcept{RandomAccessIterator} can be used to -instantiate \tcode{flat_multimap}, -as long as 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}. +\hardexpects +If \tcode{extent} is not equal to \tcode{dynamic_extent}, +then \tcode{(last - first) == extent} is \tcode{true}. \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. +\effects +Initializes \exposid{data_} with \tcode{to_address(first)} and +\exposid{size_} with \tcode{last - first}. \pnum -The effect of calling a constructor or member function -that takes a \tcode{sorted_equivalent_t} argument -with a container, containers, or range -that are not sorted with respect to \tcode{key_comp()} is undefined. - -\rSec3[flat.multimap.defn]{Definition} - -\begin{codeblock} -namespace std { - template, - class KeyContainer = vector, class MappedContainer = vector> - class flat_multimap { - 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); - } - }; - - struct containers { - key_container_type keys; - mapped_container_type values; - }; - - // \ref{flat.multimap.cons}, construct/copy/destroy - flat_multimap() : flat_multimap(key_compare()) { } - - flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont); - template - flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const Allocator& a); +\throws +When and what \tcode{last - first} throws. +\end{itemdescr} - flat_multimap(sorted_equivalent_t, - key_container_type key_cont, mapped_container_type mapped_cont); - template - flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, const Allocator& a); +\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; +\end{itemdecl} - 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); +\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} - template - flat_multimap(InputIterator first, InputIterator last, - const key_compare& comp = key_compare()) - : c(), 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); +\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} - 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); - 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); +\pnum +\ensures +\tcode{size() == N \&\& data() == std::data(arr)} is \tcode{true}. +\end{itemdescr} - 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); +\indexlibraryctor{span}% +\begin{itemdecl} +template constexpr explicit(extent != dynamic_extent) span(R&& r); +\end{itemdecl} - flat_multimap& operator=(initializer_list il); +\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} - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; +\pnum +\expects +\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} - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; +\pnum +\hardexpects +If \tcode{extent} is not equal to \tcode{dynamic_extent}, +then \tcode{ranges::size(r) == extent} is \tcode{true}. - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; +\pnum +\effects +Initializes \exposid{data_} with \tcode{ranges::data(r)} and +\exposid{size_} with \tcode{ranges::size(r)}. - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; +\pnum +\throws +What and when \tcode{ranges::data(r)} and \tcode{ranges::size(r)} throw. +\end{itemdescr} - // modifiers - template iterator emplace(Args&&... args); - template - iterator emplace_hint(const_iterator position, Args&&... args); +\indexlibraryctor{span}% +\begin{itemdecl} +constexpr explicit(extent != dynamic_extent) span(std::initializer_list il); +\end{itemdecl} - 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)); } +\begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{true}. - template iterator insert(P&& x); - template - iterator insert(const_iterator position, P&&); - 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); +\pnum +\hardexpects +If \tcode{extent} is not equal to \tcode{dynamic_extent}, +then \tcode{il.size() == extent} is \tcode{true}. - 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()); } +\pnum +\effects +Initializes \exposid{data_} with \tcode{il.begin()} and +\exposid{size_} with \tcode{il.size()}. +\end{itemdescr} - containers extract() &&; - void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); +\indexlibraryctor{span}% +\begin{itemdecl} +constexpr span(const span& other) noexcept = default; +\end{itemdecl} - 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); +\begin{itemdescr} +\pnum +\ensures +\tcode{other.size() == size() \&\& other.data() == data()}. +\end{itemdescr} - void swap(flat_multimap&) noexcept; - void clear() noexcept; +\indexlibraryctor{span}% +\begin{itemdecl} +template + constexpr explicit(@\seebelow@) span(const span& s) noexcept; +\end{itemdecl} - // observers - key_compare key_comp() const; - value_compare value_comp() const; +\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} - const key_container_type& keys() const noexcept { return c.keys; } - const mapped_container_type& values() const noexcept { return c.values; } +\pnum +\hardexpects +If \tcode{extent} is not equal to \tcode{dynamic_extent}, +then \tcode{s.size() == extent} is \tcode{true}. - // 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; +\pnum +\effects +Constructs a \tcode{span} that is a view over the range +\range{s.data()}{s.data() + s.size()}. - size_type count(const key_type& x) const; - template size_type count(const K& x) const; +\pnum +\ensures +\tcode{size() == s.size() \&\& data() == s.data()}. - bool contains(const key_type& x) const; - template bool contains(const K& x) const; +\pnum +\remarks +The expression inside \keyword{explicit} is equivalent to: +\begin{codeblock} +extent != dynamic_extent && OtherExtent == dynamic_extent +\end{codeblock} +\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; +\indexlibrarymember{operator=}{span}% +\begin{itemdecl} +constexpr span& operator=(const span& other) noexcept = default; +\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 +\ensures +\tcode{size() == other.size() \&\& data() == other.data()}. +\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; +\rSec4[span.deduct]{Deduction guides} - friend bool operator==(const flat_multimap& x, const flat_multimap& y); +\indexlibrary{\idxcode{span}!deduction guide}% +\begin{itemdecl} +template + span(It, EndOrSize) -> span>, + @\exposconcept{maybe-static-ext}@>; +\end{itemdecl} - friend @\exposid{synth-three-way-result}@ - operator<=>(const flat_multimap& x, const flat_multimap& y); +\begin{itemdescr} +\pnum +\constraints +\tcode{It} satisfies \libconcept{contiguous_iterator}. +\end{itemdescr} - friend void swap(flat_multimap& x, flat_multimap& y) noexcept - { x.swap(y); } +\indexlibrary{\idxcode{span}!deduction guide}% +\begin{itemdecl} +template + span(R&&) -> span>>; +\end{itemdecl} - private: - containers c; // \expos - key_compare compare; // \expos - }; +\begin{itemdescr} +\pnum +\constraints +\tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}}. +\end{itemdescr} - template - flat_multimap(KeyContainer, MappedContainer) - -> flat_multimap, KeyContainer, MappedContainer>; +\rSec4[span.sub]{Subviews} - template - flat_multimap(KeyContainer, MappedContainer, Allocator) - -> flat_multimap, KeyContainer, MappedContainer>; +\indexlibrarymember{span}{first}% +\begin{itemdecl} +template constexpr span first() const; +\end{itemdecl} - template - flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer) - -> flat_multimap, KeyContainer, MappedContainer>; +\begin{itemdescr} +\pnum +\mandates +\tcode{Count <= Extent} is \tcode{true}. - template - flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Allocator) - -> flat_multimap, KeyContainer, MappedContainer>; +\pnum +\hardexpects +\tcode{Count <= size()} is \tcode{true}. - template>> - flat_multimap(InputIterator, InputIterator, Compare = Compare()) - -> flat_multimap<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; +\pnum +\effects +Equivalent to: \tcode{return R\{data(), Count\};} +where \tcode{R} is the return type. +\end{itemdescr} - template>> - flat_multimap(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) - -> flat_multimap<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; +\indexlibrarymember{span}{last}% +\begin{itemdecl} +template constexpr span last() const; +\end{itemdecl} - template>, - class Allocator> - flat_multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) - -> flat_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare>; +\begin{itemdescr} +\pnum +\mandates +\tcode{Count <= Extent} is \tcode{true}. - template - flat_multimap(from_range_t, R&&, Allocator) - -> flat_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@>; +\pnum +\hardexpects +\tcode{Count <= size()} is \tcode{true}. - template> - flat_multimap(initializer_list>, Compare = Compare()) - -> flat_multimap; +\pnum +\effects +Equivalent to: \tcode{return R\{data() + (size() - Count), Count\};} +where \tcode{R} is the return type. +\end{itemdescr} - template> - flat_multimap(sorted_equivalent_t, initializer_list>, Compare = Compare()) - -> flat_multimap; +\indexlibrarymember{span}{subspan}% +\begin{itemdecl} +template + constexpr span subspan() const; +\end{itemdecl} - template - struct uses_allocator, - Allocator> - : bool_constant && - uses_allocator_v> { }; -} +\begin{itemdescr} +\pnum +\mandates +\begin{codeblock} +Offset <= Extent && (Count == dynamic_extent || Count <= Extent - Offset) +\end{codeblock} +is \tcode{true}. + +\pnum +\hardexpects +\begin{codeblock} +Offset <= size() && (Count == dynamic_extent || Count <= size() - Offset) \end{codeblock} +is \tcode{true}. \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. +\effects +Equivalent to: +\begin{codeblock} +return span( + data() + Offset, Count != dynamic_extent ? Count : size() - Offset); +\end{codeblock} -\rSec3[flat.multimap.cons]{Constructors} +\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} -\indexlibraryctor{flat_multimap}% +\indexlibrarymember{span}{first}% \begin{itemdecl} -flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont); +constexpr span first(size_type count) const; \end{itemdecl} \begin{itemdescr} +\pnum +\hardexpects +\tcode{count <= size()} is \tcode{true}. + \pnum \effects -Initializes \tcode{c.keys} with \tcode{std::move(key_cont)} and -\tcode{c.values} with \tcode{std::move(mapped_cont)}; -value-initializes \tcode{compare}; and -sorts the range \range{begin()}{end()} with respect to \tcode{value_comp()}. +Equivalent to: \tcode{return \{data(), count\};} +\end{itemdescr} + +\indexlibrarymember{span}{last}% +\begin{itemdecl} +constexpr span last(size_type count) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\hardexpects +\tcode{count <= size()} is \tcode{true}. \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. +\effects +Equivalent to: \tcode{return \{data() + (size() - count), count\};} \end{itemdescr} -\indexlibraryctor{flat_multimap}% +\indexlibrarymember{span}{subspan}% \begin{itemdecl} -template - flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const Allocator& a); +constexpr span subspan( + size_type offset, size_type count = dynamic_extent) const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true} and -\tcode{uses_allocator_v} is \tcode{true}. +\hardexpects +\begin{codeblock} +offset <= size() && (count == dynamic_extent || count <= size() - offset) +\end{codeblock} +is \tcode{true}. \pnum \effects -Equivalent to \tcode{flat_multimap(key_cont, mapped_cont)}, -except that \tcode{c.keys} and \tcode{c.values} are constructed -with uses-allocator construction\iref{allocator.uses.construction}. +Equivalent to: +\begin{codeblock} +return {data() + offset, count == dynamic_extent ? size() - offset : count}; +\end{codeblock} +\end{itemdescr} +\rSec4[span.obs]{Observers} + +\indexlibrarymember{span}{size}% +\begin{itemdecl} +constexpr size_type size() const noexcept; +\end{itemdecl} + +\begin{itemdescr} \pnum -\complexity -Same as \tcode{flat_multimap(key_cont, mapped_cont)}. +\effects +Equivalent to: \tcode{return \exposid{size_};} \end{itemdescr} -\indexlibraryctor{flat_multimap}% +\indexlibrarymember{span}{size_bytes}% \begin{itemdecl} -flat_multimap(sorted_equivalent_t, key_container_type key_cont, mapped_container_type mapped_cont); +constexpr size_type size_bytes() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c.keys} with \tcode{std::move(key_cont)} and -\tcode{c.values} with \tcode{std::move(mapped_cont)}; -value-initializes \tcode{compare}. +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 -Constant. +\effects +Equivalent to: \tcode{return size() == 0;} \end{itemdescr} -\indexlibraryctor{flat_multimap}% +\rSec4[span.elem]{Element access} + +\indexlibrary{\idxcode{operator[]}!\idxcode{span}}% \begin{itemdecl} -template - flat_multimap(sorted_equivalent_t s, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, const Allocator& a); +constexpr reference operator[](size_type idx) const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true} and -\tcode{uses_allocator_v} is \tcode{true}. +\hardexpects +\tcode{idx < size()} is \tcode{true}. \pnum -\effects -Equivalent to \tcode{flat_multimap(s, key_cont, mapped_cont)}, -except that \tcode{c.keys} and \tcode{c.val\-ues} are constructed -with uses-allocator construction\iref{allocator.uses.construction}. +\returns +\tcode{*(data() + idx)}. \pnum -\complexity -Linear. +\throws +Nothing. \end{itemdescr} -\indexlibraryctor{flat_multimap}% +\indexlibrarymember{span}{at}% \begin{itemdecl} -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 reference at(size_type idx) const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true} and -\tcode{uses_allocator_v} is \tcode{true}. +\returns +\tcode{*(data() + idx)}. \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}. +\throws +\tcode{out_of_range} if \tcode{idx >= size()} is \tcode{true}. \end{itemdescr} -\rSec3[flat.multimap.erasure]{Erasure} - -\indexlibrarymember{erase_if}{flat_multimap}% +\indexlibrarymember{span}{front}% \begin{itemdecl} -template - typename flat_multimap::size_type - erase_if(flat_multimap& c, Predicate pred); +constexpr reference front() const; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{Key} and \tcode{T} meet the \oldconcept{MoveAssignable} requirements. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum -\effects -Let $E$ be \tcode{bool(pred(pair(e)))}. -Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. +\returns +\tcode{*data()}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{span}{back}% +\begin{itemdecl} +constexpr reference back() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum \returns -The number of elements erased. +\tcode{*(data() + (size() - 1))}. \pnum -\complexity -Exactly \tcode{c.size()} applications of the predicate. +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{span}{data}% +\begin{itemdecl} +constexpr pointer data() const noexcept; +\end{itemdecl} +\begin{itemdescr} \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} +\returns +\exposid{data_}. \end{itemdescr} -\rSec2[flat.set]{Class template \tcode{flat_set}} +\rSec4[span.iterators]{Iterator support} -\rSec3[flat.set.overview]{Overview} +\indexlibrarymember{iterator}{span}% +\begin{itemdecl} +using iterator = @\impdefx{type of \tcode{span::iterator}}@; +\end{itemdecl} +\begin{itemdescr} \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}. +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 -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} +All requirements on container iterators\iref{container.reqmts} apply to +\tcode{span::iterator} as well. +\end{itemdescr} -\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}. +\indexlibrarymember{span}{begin}% +\begin{itemdecl} +constexpr iterator begin() const noexcept; +\end{itemdecl} +\begin{itemdescr} \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. +\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} -\pnum -A \tcode{flat_set} maintains the invariant that the keys are sorted with -respect to the comparison object. +\indexlibrarymember{span}{end}% +\begin{itemdecl} +constexpr iterator end() const noexcept; +\end{itemdecl} +\begin{itemdescr} \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} +\returns +An iterator which is the past-the-end value. +\end{itemdescr} -\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} +\indexlibrarymember{span}{rbegin}% +\begin{itemdecl} +constexpr reverse_iterator rbegin() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -The program is ill-formed if \tcode{Key} is not the same type -as \tcode{KeyContainer::value_type}. +\effects +Equivalent to: \tcode{return reverse_iterator(end());} +\end{itemdescr} + +\indexlibrarymember{span}{rend}% +\begin{itemdecl} +constexpr reverse_iterator rend() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -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. +\effects +Equivalent to: \tcode{return reverse_iterator(begin());} +\end{itemdescr} -\rSec3[flat.set.defn]{Definition} +\rSec3[span.objectrep]{Views of object representation} -\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; +\indexlibraryglobal{as_bytes}% +\begin{itemdecl} +template + span + as_bytes(span s) noexcept; +\end{itemdecl} - // \ref{flat.set.cons}, constructors - flat_set() : flat_set(key_compare()) { } +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return R\{reinterpret_cast(s.data()), s.size_bytes()\};} +where \tcode{R} is the return type. +\end{itemdescr} - explicit flat_set(container_type cont); - template - flat_set(const container_type& cont, const Allocator& a); +\indexlibraryglobal{as_writable_bytes}% +\begin{itemdecl} +template + span + as_writable_bytes(span s) noexcept; +\end{itemdecl} - flat_set(sorted_unique_t, container_type cont) - : @\exposid{c}@(std::move(cont)), @\exposid{compare}@(key_compare()) { } - template - flat_set(sorted_unique_t, const container_type& cont, const Allocator& a); +\begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. - 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 +\effects +Equivalent to: \tcode{return R\{reinterpret_cast(s.data()), s.size_bytes()\};} +where \tcode{R} is the return type. +\end{itemdescr} - 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); +\rSec2[views.multidim]{Multidimensional access} - 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); +\rSec3[mdspan.overview]{Overview} - 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); +\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. - 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); +\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$})$. - 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); +\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} - flat_set& operator=(initializer_list); +\rSec3[mdspan.syn]{Header \tcode{} synopsis} - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; +\indexheader{mdspan}% +\begin{codeblock} +// all freestanding +namespace std { + // \ref{mdspan.extents}, class template \tcode{extents} + template + class extents; - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; + // \ref{mdspan.extents.dextents}, alias template \tcode{dextents} + template + using dextents = @\seebelow@; - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; + // \ref{mdspan.extents.dims}, alias template \tcode{dims} + template + using dims = @\seebelow@; - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; + // \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{flat.set.modifiers}, modifiers - template pair emplace(Args&&... args); - template - iterator emplace_hint(const_iterator position, Args&&... args); + // \ref{mdspan.accessor.default}, class template \tcode{default_accessor} + template + class default_accessor; - 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); + // \ref{mdspan.accessor.aligned}, class template \tcode{aligned_accessor} + template + class aligned_accessor; - 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); + // \ref{mdspan.mdspan}, class template \tcode{mdspan} + template> + class mdspan; - 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()); } + // \ref{mdspan.sub}, \tcode{submdspan} creation + template + struct strided_slice; - container_type extract() &&; - void replace(container_type&&); + template + struct submdspan_mapping_result; - 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); + struct full_extent_t { explicit full_extent_t() = default; }; + inline constexpr full_extent_t full_extent{}; - void swap(flat_set& y) noexcept; - void clear() noexcept; + template + constexpr auto submdspan_extents(const extents&, SliceSpecifiers...); - // observers - key_compare key_comp() const; - value_compare value_comp() const; + // \ref{mdspan.sub.sub}, \tcode{submdspan} function template + template + constexpr auto submdspan( + const mdspan& src, + SliceSpecifiers... slices) -> @\seebelow@; - // 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; + template + concept @\defexposconcept{index-pair-like}@ = // \expos + @\exposconcept{pair-like}@ && + @\libconcept{convertible_to}@, IndexType> && + @\libconcept{convertible_to}@, IndexType>; +} +\end{codeblock} - size_type count(const key_type& x) const; - template size_type count(const K& x) const; +\rSec3[mdspan.extents]{Class template \tcode{extents}} - bool contains(const key_type& x) const; - template bool contains(const K& x) const; +\rSec4[mdspan.extents.overview]{Overview} - 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; +The class template \tcode{extents} represents +a multidimensional index space of rank equal to \tcode{sizeof...(Extents)}. +In \iref{views}, +\tcode{extents} is used synonymously with multidimensional index space. + +\begin{codeblock} +namespace std { + template + class @\libglobal{extents}@ { + public: + using index_type = IndexType; + using size_type = make_unsigned_t; + using rank_type = size_t; - 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; + // \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; - 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; + // \ref{mdspan.extents.cons}, constructors + constexpr extents() noexcept = default; - friend bool operator==(const flat_set& x, const flat_set& y); + 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; - friend @\placeholder{synth-three-way-result}@ - operator<=>(const flat_set& x, const flat_set& y); + // \ref{mdspan.extents.cmp}, comparison operators + template + friend constexpr bool operator==(const extents&, + const extents&) noexcept; - friend void swap(flat_set& x, flat_set& y) noexcept { x.swap(y); } + // \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: - container_type @\exposid{c}@; // \expos - key_compare @\exposid{compare}@; // \expos + 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>> - flat_set(InputIterator, InputIterator, Compare = Compare()) - -> flat_set<@\placeholder{iter-value-type}@, Compare>; + template + explicit extents(Integrals...) + -> @\seebelow@; +} +\end{codeblock} - template>> - flat_set(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) - -> flat_set<@\placeholder{iter-value-type}@, Compare>; +\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} - template>, - class Allocator = allocator>> - flat_set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) - -> flat_set, Compare>; +\pnum +Each specialization of \tcode{extents} models \libconcept{regular} and +is trivially copyable. - template - flat_set(from_range_t, R&&, Allocator) - -> flat_set, less>>; +\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$. - template> - flat_set(initializer_list, Compare = Compare()) - -> flat_set; +\pnum +The $r^\text{th}$ interval of the multidimensional index space +represented by an \tcode{extents} object is $[0, D_r)$. - template> - flat_set(sorted_unique_t, initializer_list, Compare = Compare()) - -> flat_set; +\rSec4[mdspan.extents.expo]{Exposition-only helpers} - template - struct uses_allocator, Allocator> - : bool_constant> { }; -} -\end{codeblock} +\begin{itemdecl} +static constexpr rank_type @\exposid{dynamic-index}@(rank_type i) noexcept; +\end{itemdecl} -\rSec3[flat.set.cons]{Constructors} +\begin{itemdescr} +\pnum +\expects +\tcode{i <= rank()} is \tcode{true}. + +\pnum +\returns +The number of $E_r$ with $r < \tcode{i}$ for which $E_r$ is a dynamic extent. +\end{itemdescr} -\indexlibraryctor{flat_set}% \begin{itemdecl} -explicit flat_set(container_type cont); +static constexpr rank_type @\exposid{dynamic-index-inv}@(rank_type i) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{c} with \tcode{std::move(cont)}, -value-initializes \exposid{compare}, -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. +\expects +\tcode{i < rank_dynamic()} 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. +\returns +The minimum value of $r$ +such that \tcode{\exposid{dynamic-index}($r$ + 1) == i + 1} is \tcode{true}. \end{itemdescr} -\indexlibraryctor{flat_set}% \begin{itemdecl} -template - flat_set(const container_type& cont, const Allocator& a); +constexpr size_t @\exposid{fwd-prod-of-extents}@(rank_type i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true}. - -\pnum -\effects -Equivalent to \tcode{flat_set(cont)}, -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. +\expects +\tcode{i <= rank()} is \tcode{true}. \pnum -\complexity -Same as \tcode{flat_set(cont)}. +\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{flat_set}% \begin{itemdecl} -template - flat_set(sorted_unique_t s, const container_type& cont, const Allocator& a); +constexpr size_t @\exposid{rev-prod-of-extents}@(rank_type i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true}. - -\pnum -\effects -Equivalent to \tcode{flat_set(s, cont)}, -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. +\expects +\tcode{i < rank()} is \tcode{true}. \pnum -\complexity -Linear. +\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{flat_set}% \begin{itemdecl} -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 + static constexpr auto @\exposid{index-cast}@(OtherIndexType&& i) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true}. - \pnum \effects -Equivalent to the corresponding non-allocator constructors -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. +\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} -\rSec3[flat.set.modifiers]{Modifiers} +\rSec4[mdspan.extents.cons]{Constructors} -\indexlibrarymember{insert}{flat_set}% +\indexlibraryctor{extents}% \begin{itemdecl} -template pair insert(K&& x); -template iterator insert(const_iterator hint, K&& x); +template + constexpr explicit(@\seebelow@) + extents(const extents& other) noexcept; \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}. +\begin{itemize} +\item +\tcode{sizeof...(OtherExtents) == rank()} is \tcode{true}. +\item +\tcode{((OtherExtents == dynamic_extent || Extents == dynamic_extent || OtherExtents ==\newline Extents) \&\& ...)} is \tcode{true}. +\end{itemize} \pnum \expects -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{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 -\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))}. +\ensures +\tcode{*this == other} is \tcode{true}. \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}. +\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} \end{itemdescr} -\indexlibrarymember{insert}{flatset}% +\indexlibraryctor{extents}% \begin{itemdecl} -template - void insert(InputIterator first, InputIterator last); +template + constexpr explicit extents(OtherIndexTypes... exts) noexcept; \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. +Let \tcode{N} be \tcode{sizeof...(OtherIndexTypes)}, +and let \tcode{exts_arr} be +\tcode{array\{static_cast<\\index_type>(std::move(exts))...\}}. \pnum -\complexity -$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and -$M$ is \tcode{distance(first, last)}. +\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}. +\begin{note} +One can construct \tcode{extents} from just dynamic extents, +which are all the values getting stored, or +from all the extents with a precondition. +\end{note} +\end{itemize} \pnum -\remarks -Since this operation performs an in-place merge, it may allocate memory. +\expects +\begin{itemize} +\item +If \tcode{N != rank_dynamic()} is \tcode{true}, +\tcode{exts_arr[$r$]} equals $E_r$ +for each $r$ for which $E_r$ is a static extent, and +\item +either +\begin{itemize} +\item +\tcode{sizeof...(exts) == 0} is \tcode{true}, or +\item +each element of \tcode{exts} is representable +as a nonnegative value of type \tcode{index_type}. +\end{itemize} +\end{itemize} + +\pnum +\ensures +\tcode{*this == extents(exts_arr)} is \tcode{true}. \end{itemdescr} -\indexlibrarymember{insert}{flat_set}% +\indexlibraryctor{extents}% \begin{itemdecl} -template - void insert(sorted_unique_t, InputIterator first, InputIterator last); +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 -\effects -Equivalent to \tcode{insert(first, last)}. +\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 -\complexity -Linear. +\expects +\begin{itemize} +\item +If \tcode{N != rank_dynamic()} is \tcode{true}, +\tcode{exts[$r$]} equals $E_r$ for each $r$ for which $E_r$ is a static extent, and +\item +either +\begin{itemize} +\item +\tcode{N} is zero, or +\item +\tcode{exts[$r$]} is representable +as a nonnegative value of type \tcode{index_type} for every rank index $r$. +\end{itemize} +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +If \tcode{N} equals \tcode{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{insert_range}{flat_set}% +\indexlibraryctor{extents}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); +template + explicit extents(Integrals...) -> @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Adds elements to \exposid{c} as if by: -\begin{codeblock} -for (const auto& e : rg) { - @\exposid{c}@.insert(@\exposid{c}@.end(), e); -} -\end{codeblock} -Then, -sorts the range of newly inserted elements with respect to \exposid{compare}; -merges the resulting sorted range and -the sorted range of pre-existing elements into a single sorted range; and -finally erases all but the first element -from each group of consecutive equivalent elements. - -\pnum -\complexity -$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$ -is \tcode{distance(first, last)}. +\constraints +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}. \pnum \remarks -Since this operation performs an in-place merge, it may allocate memory. +The deduced type is \tcode{extents...>}. \end{itemdescr} -\indexlibrarymember{swap}{flat_set}% +\rSec4[mdspan.extents.obs]{Observers of the multidimensional index space} + +\indexlibrarymember{static_extent}{extents}% \begin{itemdecl} -void swap(flat_set& y) noexcept; +static constexpr size_t static_extent(rank_type i) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -ranges::swap(compare, y.compare); -ranges::swap(@\exposid{c}@, y.@\exposid{c}@); -\end{codeblock} +\expects +\tcode{i < rank()} is \tcode{true}. + +\pnum +\returns +$E_\tcode{i}$. \end{itemdescr} -\indexlibrarymember{extract}{flatset}% +\indexlibrarymember{extent}{extents}% \begin{itemdecl} -container_type extract() &&; +constexpr index_type extent(rank_type i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{*this} is emptied, even if the function exits via an exception. +\expects +\tcode{i < rank()} is \tcode{true}. \pnum \returns -\tcode{std::move(\exposid{c})}. +$D_\tcode{i}$. \end{itemdescr} -\indexlibrarymember{replace}{flat_set}% +\rSec4[mdspan.extents.cmp]{Comparison operators} + +\indexlibrarymember{operator==}{extents}% \begin{itemdecl} -void replace(container_type&& cont); +template + friend constexpr bool operator==(const extents& lhs, + const extents& rhs) noexcept; \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. +\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{\exposid{c} = std::move(cont);} +\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[flat.set.erasure]{Erasure} +\rSec4[mdspan.extents.dims]{Alias template \tcode{dims}} -\indexlibrarymember{erase_if}{flat_set}% +\indexlibraryglobal{dims}% \begin{itemdecl} -template - typename flat_set::size_type - erase_if(flat_set& c, Predicate pred); +template + using dims = @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto [erase_first, erase_last] = ranges::remove_if(c, pred); -auto n = erase_last - erase_first; -c.erase(erase_first, erase_last); -return n; -\end{codeblock} +\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} -\rSec2[flat.multiset]{Class template \tcode{flat_multiset}} +\rSec3[mdspan.layout]{Layout mapping} -\rSec3[flat.multiset.overview]{Overview} +\rSec4[mdspan.layout.general]{General} \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}. +In \ref{mdspan.layout.reqmts} and \ref{mdspan.layout.policy.reqmts}: -\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. +\tcode{M} denotes a layout mapping class. -\pnum -A \tcode{flat_multiset} maintains the invariant -that the keys are sorted with respect to the comparison object. +\item +\tcode{m} denotes a (possibly const) value of type \tcode{M}. -\pnum -If any member function in \ref{flat.multiset.defn} exits via an exception, -the invariant is restored. +\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} -This can result in the \tcode{flat_multiset}'s being emptied. +The type of each element of the packs can be a different integer type. \end{note} -\pnum -Any sequence container\iref{sequence.reqmts} -supporting \oldconcept{RandomAccessIterator} -can be used to instantiate \tcode{flat_multiset}. -In particular, -\tcode{vector}\iref{vector} and \tcode{deque}\iref{deque} can be used. -\begin{note} -\tcode{vector} is not a sequence container. -\end{note} +\item +\tcode{r} is a (possibly const) rank index of \tcode{typename M::extents_type}. -\pnum -The program is ill-formed if \tcode{Key} is not the same type -as \tcode{KeyContainer::value_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 -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} - +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} -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()) { } - - explicit flat_multiset(container_type cont); - template - flat_multiset(const container_type& cont, const Allocator& a); - - flat_multiset(sorted_equivalent_t, container_type cont) - : @\exposid{c}@(std::move(cont)), @\exposid{compare}@(key_compare()) { } - template - flat_multiset(sorted_equivalent_t, const container_type&, 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; - - 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; - - friend bool operator==(const flat_multiset& x, const flat_multiset& y); - - friend @\placeholder{synth-three-way-result}@ - operator<=>(const flat_multiset& x, const flat_multiset& y); - - friend void swap(flat_multiset& x, flat_multiset& y) noexcept - { x.swap(y); } - - private: - container_type @\exposid{c}@; // \expos - key_compare @\exposid{compare}@; // \expos - }; - - template>> - flat_multiset(InputIterator, InputIterator, Compare = Compare()) - -> flat_multiset<@\placeholder{iter-value-type}@, @\placeholder{iter-value-type}@, Compare>; - - template>> - flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) - -> flat_multiset<@\placeholder{iter-value-type}@, @\placeholder{iter-value-type}@, Compare>; - - template>, - class Allocator = allocator>> - flat_multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) - -> flat_multiset, Compare>; - - template - flat_multiset(from_range_t, R&&, Allocator) - -> flat_multiset, less>>; - - template> - flat_multiset(initializer_list, Compare = Compare()) - -> flat_multiset; +template +constexpr bool @\exposid{is-mapping-of}@ = // \expos + is_same_v, Mapping>; +\end{codeblock} +\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} - template> - flat_multiset(sorted_equivalent_t, initializer_list, Compare = Compare()) - -> flat_multiset; +\rSec4[mdspan.layout.reqmts]{Requirements} - template - struct uses_allocator, Allocator> - : bool_constant> { }; -} -\end{codeblock} +\pnum +A type \tcode{M} meets the \defn{layout mapping} requirements if -\rSec3[flat.multiset.cons]{Constructors} +\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} -\indexlibraryctor{flat_multiset}% \begin{itemdecl} -explicit flat_multiset(container_type cont); +typename M::extents_type \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{c} with \tcode{std::move(cont)}, -value-initializes \exposid{compare}, 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. +\result +A type that is a specialization of \tcode{extents}. \end{itemdescr} -\indexlibraryctor{flat_multiset}% \begin{itemdecl} -template - flat_multiset(const container_type& cont, const Allocator& a); +typename M::index_type \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true}. +\result +\tcode{typename M::extents_type::index_type}. +\end{itemdescr} -\pnum -\effects -Equivalent to \tcode{flat_multiset(cont)}, -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. +\begin{itemdecl} +typename M::rank_type +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -Same as \tcode{flat_multiset(cont)}. +\result +\tcode{typename M::extents_type::rank_type}. \end{itemdescr} -\indexlibraryctor{flat_multiset}% \begin{itemdecl} -template - flat_multiset(sorted_equivalent_t s, const container_type& cont, const Allocator& a); +typename M::layout_type \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true}. +\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} -\pnum -\effects -Equivalent to \tcode{flat_multiset(s, cont)}, -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. +\begin{itemdecl} +m.extents() +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -Linear. +\result +\tcode{const typename M::extents_type\&} \end{itemdescr} -\indexlibraryctor{flat_multiset}% \begin{itemdecl} -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); +m(i...) \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true}. +\result +\tcode{typename M::index_type} \pnum -\effects -Equivalent to the corresponding non-allocator constructors -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. +\returns +A nonnegative integer +less than \tcode{numeric_limits::max()} and +less than or equal to \tcode{numeric_limits::max()}. \end{itemdescr} -\rSec3[flat.multiset.modifiers]{Modifiers} - -\indexlibrarymember{emplace}{flat_multiset}% \begin{itemdecl} -template iterator emplace(Args&&... args); +m(i...) == m(static_cast(i)...) \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. - -\pnum -\effects -First, initializes an object \tcode{t} of type \tcode{key_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} +\result +\tcode{bool} \pnum \returns -An iterator that points to the inserted element. +\tcode{true} \end{itemdescr} -\indexlibrarymember{insert}{flat_mulitset}% \begin{itemdecl} -template - void insert(InputIterator first, InputIterator last); +m.required_span_size() \end{itemdecl} \begin{itemdescr} \pnum -\effects -Adds elements to \exposid{c} as if by: -\begin{codeblock} -c.insert(c.end(), first, last); -\end{codeblock} -Then, sorts the range of newly inserted elements with respect to \exposid{compare}, -and merges the resulting sorted range and -the sorted range of pre-existing elements into a single sorted range. - -\pnum -\complexity -$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$ -is \tcode{distance(first, last)}. +\result +\tcode{typename M::index_type} \pnum -\remarks -Since this operation performs an in-place merge, it may allocate memory. +\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{insert}{flat_multiset}% \begin{itemdecl} -template - void insert(sorted_equivalent_t, InputIterator first, InputIterator last); +m.is_unique() \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{insert(first, last)}. +\result +\tcode{bool} \pnum -\complexity -Linear. +\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{swap}{flat_multiset}% \begin{itemdecl} -void swap(flat_multiset& y) noexcept; +m.is_exhaustive() \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -ranges::swap(compare, y.compare); -ranges::swap(c, y.c); -\end{codeblock} +\result +\tcode{bool} + +\pnum +\returns +\tcode{true} only if +for all $k$ in the range $[0, \tcode{m.required_span_size()})$ +there exists an \tcode{i} such that \tcode{m(i...)} equals $k$. +\begin{note} +A mapping can return \tcode{false} even if the condition is met. +For certain layouts, it is possibly not feasible to determine efficiently +whether the layout is exhaustive. +\end{note} \end{itemdescr} -\indexlibrarymember{extract}{flat_multiset}% \begin{itemdecl} -container_type extract() &&; +m.is_strided() \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{*this} is emptied, even if the function exits via an exception. +\result +\tcode{bool} \pnum \returns -\tcode{std::move(c)}. +\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{replace}{flat_multiset}% \begin{itemdecl} -void replace(container_type&& cont); +m.stride(r) \end{itemdecl} \begin{itemdescr} \pnum \expects -The elements of \tcode{cont} are sorted with respect to \exposid{compare}. +\tcode{m.is_strided()} is \tcode{true}. \pnum -\effects -Equivalent to: \tcode{c = std::move(cont);} -\end{itemdescr} +\result +\tcode{typename M::index_type} -\rSec3[flat.multiset.erasure]{Erasure} +\pnum +\returns +$s_r$ as defined in \tcode{m.is_strided()} above. +\end{itemdescr} -\indexlibrarymember{erase_if}{flat_multiset}% \begin{itemdecl} -template - typename flat_multiset::size_type - erase_if(flat_multiset& c, Predicate pred); +M::is_always_unique() \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto [erase_first, erase_last] = ranges::remove_if(c, pred); -auto n = erase_last - erase_first; -c.erase(erase_first, erase_last); -return n; -\end{codeblock} -\end{itemdescr} - -\rSec2[container.adaptors.format]{Container adaptors formatting} +\result +A constant expression\iref{expr.const} of type \tcode{bool}. \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-adaptor}@ = // \expos - @\exposid{fmt-maybe-const}@<@\placeholder{adaptor-type}@, charT>; - formatter @\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} +\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} -\indexlibrarymember{parse}{formatter}% \begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); +M::is_always_exhaustive() \end{itemdecl} -\begin{itemdescr} +\begin{itemdescr} +\pnum +\result +A constant expression\iref{expr.const} of type \tcode{bool}. + \pnum -\effects -Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +\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} -\indexlibrarymember{format}{formatter}% \begin{itemdecl} -template - typename FormatContext::iterator - format(@\exposid{maybe-const-adaptor}@& r, FormatContext& ctx) const; +M::is_always_strided() \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{underlying_}.format(r.c, ctx);} -\end{itemdescr} +\result +A constant expression\iref{expr.const} of type \tcode{bool}. -\rSec1[views]{Views} +\pnum +\returns +\tcode{true} only if \tcode{m.is_strided()} is \tcode{true} +for all possible objects \tcode{m} of type \tcode{M}. +\begin{note} +A mapping can return \tcode{false} even if the above condition is met. +For certain layout mappings, it is possibly not feasible to determine +whether every instance is strided. +\end{note} +\end{itemdescr} -\rSec2[views.general]{General} +\rSec4[mdspan.layout.policy.reqmts]{Layout mapping policy requirements} \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 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}. -\rSec2[span.syn]{Header \tcode{} synopsis}% +\rSec4[mdspan.layout.policy.overview]{Layout mapping policies} -\indexheader{span}% \begin{codeblock} namespace std { - // constants - inline constexpr size_t @\libglobal{dynamic_extent}@ = numeric_limits::max(); - - // \ref{views.span}, class template \tcode{span} - template - class span; - - template - inline constexpr bool ranges::enable_view> = true; - template - inline constexpr bool ranges::enable_borrowed_range> = true; - - // \ref{span.objectrep}, views of object representation - template - span - as_bytes(span s) noexcept; + struct layout_left { + template + class mapping; + }; + struct layout_right { + template + class mapping; + }; + struct layout_stride { + template + class mapping; + }; - template - span - as_writable_bytes(span s) noexcept; + template + struct layout_left_padded { + template class mapping; + }; + template + struct layout_right_padded { + template class mapping; + }; } \end{codeblock} -\rSec2[views.span]{Class template \tcode{span}} +\pnum +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}. -\rSec3[span.overview]{Overview} +\rSec4[mdspan.layout.left]{Class template \tcode{layout_left::mapping}} -\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. +\rSec5[mdspan.layout.left.overview]{Overview} \pnum -All member functions of \tcode{span} have constant time complexity. +\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. -\indexlibraryglobal{span}% \begin{codeblock} namespace std { - template - class span { + template + class layout_left::mapping { 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; + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_left; - // \ref{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 span(const span& other) noexcept = default; - template - constexpr explicit(@\seebelow@) span(const span& s) noexcept; + // \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&); - ~span() noexcept = default; + constexpr mapping& operator=(const mapping&) noexcept = default; - constexpr span& operator=(const span& other) noexcept = default; + // \ref{mdspan.layout.left.obs}, observers + constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } - // \ref{span.sub}, subviews - template - constexpr span first() const; - template - constexpr span last() const; - template - constexpr span subspan() const; + constexpr index_type required_span_size() const noexcept; - 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 + constexpr index_type operator()(Indices...) const noexcept; - // \ref{span.obs}, observers - constexpr size_type size() const noexcept; - constexpr size_type size_bytes() const noexcept; - [[nodiscard]] constexpr bool empty() const noexcept; + static constexpr bool is_always_unique() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept { return true; } + static constexpr bool is_always_strided() noexcept { return true; } - // \ref{span.elem}, element access - constexpr reference operator[](size_type idx) const; - constexpr reference front() const; - constexpr reference back() const; - constexpr pointer data() const noexcept; + static constexpr bool is_unique() noexcept { return true; } + static constexpr bool is_exhaustive() noexcept { return true; } + static constexpr bool is_strided() noexcept { return true; } - // \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(); } + constexpr index_type stride(rank_type) const noexcept; + + template + friend constexpr bool operator==(const mapping&, const mapping&) noexcept; private: - pointer data_; // \expos - size_type size_; // \expos - }; + extents_type @\exposid{extents_}@{}; // \expos - template - span(It, EndOrSize) -> span>>; - template - span(T (&)[N]) -> span; - template - span(array&) -> span; - template - span(const array&) -> span; - template - span(R&&) -> span>>; + // \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} \pnum -\tcode{span} is -a trivially copyable type\iref{term.trivially.copyable.type}. +If \tcode{Extents} is not a specialization of \tcode{extents}, +then the program is ill-formed. \pnum -\tcode{ElementType} is required to be -a complete object type that is not an abstract class type. +\tcode{layout_left::mapping} is a trivially copyable type +that models \libconcept{regular} for each \tcode{E}. -\rSec3[span.cons]{Constructors, copy, and assignment} +\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}. -\indexlibraryctor{span}% +\rSec5[mdspan.layout.left.cons]{Constructors} + +\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -constexpr span() 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 +Direct-non-list-initializes \exposid{extents_} with \tcode{e}. +\end{itemdescr} + +\indexlibraryctor{layout_left::mapping}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) + mapping(const mapping& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{Extent == dynamic_extent || Extent == 0} is \tcode{true}. +\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}. + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +\end{itemdescr} + +\indexlibraryctor{layout_left::mapping}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) + mapping(const layout_right::mapping& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{extents_type::rank() <= 1} is \tcode{true}, and +\item +\tcode{is_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. \pnum -\ensures -\tcode{size() == 0 \&\& data() == nullptr}. +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \end{itemdescr} -\indexlibraryctor{span}% +\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -template - constexpr explicit(extent != dynamic_extent) span(It first, size_type count); +template + constexpr explicit(!is_convertible_v) + mapping(const LayoutLeftPaddedMapping&) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -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} +\tcode{\exposid{is-layout-left-padded-mapping-of}} is \tcode{true}. +\item +\tcode{is_constructible_v}\newline is \tcode{true}. \end{itemize} \pnum -\expects +\mandates +If \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}. +\tcode{Extents::rank()} is greater than one, +\item +\tcode{Extents::static_extent(0)} does not equal \tcode{dynamic_extent}, and +\item +\tcode{LayoutLeftPaddedMapping::\exposid{static-padding-stride}} +does not equal \tcode{dynamic_extent}, \end{itemize} +then \tcode{Extents::static_extent(0)} equals +\tcode{LayoutLeftPaddedMapping::\exposid{static-padding-stride}}. \pnum -\effects -Initializes \tcode{data_} with \tcode{to_address(first)} and -\tcode{size_} with \tcode{count}. +\expects +\begin{itemize} +\item +If \tcode{extents_type::rank() > 1} is \tcode{true}, +then \tcode{other.stride(1)} equals \tcode{other.extents(0)}. +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} \pnum -\throws -Nothing. +\effects +Direct-non-list-initializes \tcode{extents_} with \tcode{other.extents()}. \end{itemdescr} -\indexlibraryctor{span}% +\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -template - constexpr explicit(extent != dynamic_extent) span(It first, End last); +template + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping& other); \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} +\tcode{is_constructible_v} is \tcode{true}. \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}}. +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 -Initializes \tcode{data_} with \tcode{to_address(first)} and -\tcode{size_} with \tcode{last - first}. +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +\end{itemdescr} + +\rSec5[mdspan.layout.left.obs]{Observers} + +\indexlibrarymember{required_span_size}{layout_left::mapping}% +\begin{itemdecl} +constexpr index_type required_span_size() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -When and what \tcode{last - first} throws. +\returns +\tcode{extents().\exposid{fwd-prod-of-extents}(extents_type::rank())}. \end{itemdescr} -\indexlibraryctor{span}% +\indexlibrarymember{operator()}{layout_left::mapping}% \begin{itemdecl} -template constexpr span(type_identity_t (&arr)[N]) noexcept; -template constexpr span(array& arr) noexcept; -template constexpr span(const array& arr) noexcept; +template + constexpr index_type operator()(Indices... i) const 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} +\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 -\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{extents_type::\exposid{index-cast}(i)} is +a multidimensional index in \exposid{extents_}\iref{mdspan.overview}. \pnum -\ensures -\tcode{size() == N \&\& data() == data(arr)} is \tcode{true}. +\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} -\indexlibraryctor{span}% +\indexlibrarymember{stride}{layout_left::mapping}% \begin{itemdecl} -template constexpr explicit(extent != dynamic_extent) span(R&& r); +constexpr index_type stride(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} +\tcode{extents_type::rank() > 0} is \tcode{true}. \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} +\tcode{i < extents_type::rank()} is \tcode{true}. + +\pnum +\returns +\tcode{extents().\exposid{fwd-prod-of-extents}(i)}. +\end{itemdescr} + +\indexlibrarymember{operator==}{layout_left::mapping}% +\begin{itemdecl} +template + friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{extents_type::rank() == OtherExtents::rank()} is \tcode{true}. \pnum \effects -Initializes \tcode{data_} with \tcode{ranges::data(r)} and -\tcode{size_} with \tcode{ranges::size(r)}. +Equivalent to: \tcode{return x.extents() == y.extents();} +\end{itemdescr} + +\rSec4[mdspan.layout.right]{Class template \tcode{layout_right::mapping}} + +\rSec5[mdspan.layout.right.overview]{Overview} \pnum -\throws -What and when \tcode{ranges::data(r)} and \tcode{ranges::size(r)} throw. +\tcode{layout_right} provides a layout mapping +where the rightmost extent is stride 1, and +strides increase right-to-left as the product of extents. + +\begin{codeblock} +namespace std { + template + class layout_right::mapping { + public: + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_right; + + // \ref{mdspan.layout.right.cons}, constructors + constexpr mapping() noexcept = default; + constexpr mapping(const mapping&) noexcept = default; + constexpr mapping(const extents_type&) noexcept; + template + 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; + + constexpr mapping& operator=(const mapping&) noexcept = default; + + // \ref{mdspan.layout.right.obs}, observers + constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } + + constexpr index_type required_span_size() const noexcept; + + template + constexpr index_type operator()(Indices...) const noexcept; + + static constexpr bool is_always_unique() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept { return true; } + static constexpr bool is_always_strided() noexcept { return true; } + + static constexpr bool is_unique() noexcept { return true; } + static constexpr bool is_exhaustive() noexcept { return true; } + static constexpr bool is_strided() noexcept { return true; } + + constexpr index_type stride(rank_type) const noexcept; + + template + friend constexpr bool operator==(const mapping&, const mapping&) noexcept; + + 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} + +\pnum +If \tcode{Extents} is not a specialization of \tcode{extents}, +then the program is ill-formed. + +\pnum +\tcode{layout_right::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.right.cons]{Constructors} + +\indexlibraryctor{layout_right::mapping}% +\begin{itemdecl} +constexpr mapping(const extents_type& e) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The size of the multidimensional index space \tcode{e} is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{e}. \end{itemdescr} -\indexlibraryctor{span}% +\indexlibraryctor{layout_right::mapping}% \begin{itemdecl} -constexpr span(const span& other) noexcept = default; +template + constexpr explicit(!is_convertible_v) + mapping(const mapping& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{other.size() == size() \&\& other.data() == data()}. +\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}. + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \end{itemdescr} -\indexlibraryctor{span}% +\indexlibraryctor{layout_right::mapping}% \begin{itemdecl} -template - constexpr explicit(@\seebelow@) span(const span& s) noexcept; +template + constexpr explicit(!is_convertible_v) + mapping(const layout_left::mapping& 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{extents_type::rank() <= 1} is \tcode{true}, and +\item +\tcode{is_constructible_v} 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}. +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. \pnum \effects -Constructs a \tcode{span} that is a view over the range -\range{s.data()}{s.data() + s.size()}. - -\pnum -\ensures -\tcode{size() == s.size() \&\& data() == s.data()}. - -\pnum -\remarks -The expression inside \keyword{explicit} is equivalent to: -\begin{codeblock} -extent != dynamic_extent && OtherExtent == dynamic_extent -\end{codeblock} +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \end{itemdescr} -\indexlibrarymember{operator=}{span}% +\indexlibraryctor{layout_right::mapping}% \begin{itemdecl} -constexpr span& operator=(const span& other) noexcept = default; +template + constexpr explicit(!is_convertible_v) + mapping(const LayoutRightPaddedMapping&) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{size() == other.size() \&\& data() == other.data()}. -\end{itemdescr} +\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} -\rSec3[span.deduct]{Deduction guides} +\pnum +\mandates +If +\begin{itemize} +\item +\tcode{Extents::rank()} is greater than one, +\item +\tcode{Extents::static_extent(Extents::rank() - 1)} +does not equal \tcode{dynamic_extent}, and +\item +\tcode{LayoutRightPaddedMapping::\exposid{static-padding-stride}} +does not equal \tcode{dynamic_extent}, +\end{itemize} +then \tcode{Extents::static_extent(Extents::rank() - 1)} equals +\tcode{LayoutRightPaddedMapping::\exposid{sta\-tic-padding-stride}}. -\indexlibrary{\idxcode{span}!deduction guide}% +\pnum +\expects +\begin{itemize} +\item +If \tcode{extents_type::rank() > 1} is \tcode{true}, +then \tcode{other.stride(extents_type::rank() - 2)}\newline equals +\tcode{other.extents().extent(extents_type::rank() - 1)}. +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +Direct-non-list-initializes \tcode{extents_} with \tcode{other.extents()}. +\end{itemdescr} + +\indexlibraryctor{layout_right::mapping}% \begin{itemdecl} -template - span(It, EndOrSize) -> span>>; +template + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{It} satisfies \libconcept{contiguous_iterator}. +\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$)}. +\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} -\indexlibrary{\idxcode{span}!deduction guide}% +\rSec5[mdspan.layout.right.obs]{Observers} + +\indexlibrarymember{required_span_size}{layout_right::mapping}% \begin{itemdecl} -template - span(R&&) -> span>>; +index_type required_span_size() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}}. +\returns +\tcode{extents().\exposid{fwd-prod-of-extents}(extents_type::rank())}. \end{itemdescr} -\rSec3[span.sub]{Subviews} - -\indexlibrarymember{span}{first}% +\indexlibrarymember{operator()}{layout_right::mapping}% \begin{itemdecl} -template constexpr span first() const; +template + constexpr index_type operator()(Indices... i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{Count <= Extent} is \tcode{true}. +\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{Count <= size()} is \tcode{true}. +\tcode{extents_type::\exposid{index-cast}(i)} is +a multidimensional index in \exposid{extents_}\iref{mdspan.overview}. \pnum \effects -Equivalent to: \tcode{return R\{data(), Count\};} -where \tcode{R} is the return type. +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{span}{last}% +\indexlibrarymember{stride}{layout_right::mapping}% \begin{itemdecl} -template constexpr span last() const; +constexpr index_type stride(rank_type i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{Count <= Extent} is \tcode{true}. +\constraints +\tcode{extents_type::rank() > 0} is \tcode{true}. \pnum \expects -\tcode{Count <= size()} is \tcode{true}. +\tcode{i < extents_type::rank()} is \tcode{true}. \pnum -\effects -Equivalent to: \tcode{return R\{data() + (size() - Count), Count\};} -where \tcode{R} is the return type. +\returns +\tcode{extents().\exposid{rev-prod-of-extents}(i)}. \end{itemdescr} -\indexlibrarymember{span}{subspan}% +\indexlibrarymember{operator==}{layout_right::mapping}% \begin{itemdecl} -template - constexpr span subspan() const; +template + friend constexpr bool operator==(const mapping& x, const mapping& y) 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}. +\constraints +\tcode{extents_type::rank() == OtherExtents::rank()} is \tcode{true}. \pnum \effects -Equivalent to: -\begin{codeblock} -return span( - data() + Offset, Count != dynamic_extent ? Count : size() - Offset); -\end{codeblock} +Equivalent to: \tcode{return x.extents() == y.extents();} +\end{itemdescr} + +\rSec4[mdspan.layout.stride]{Class template \tcode{layout_stride::mapping}} + +\rSec5[mdspan.layout.stride.overview]{Overview} \pnum -\remarks -The second template argument of the returned \tcode{span} type is: +\tcode{layout_stride} provides a layout mapping +where the strides are user-defined. + \begin{codeblock} -Count != dynamic_extent ? Count - : (Extent != dynamic_extent ? Extent - Offset - : dynamic_extent) +namespace std { + template + class layout_stride::mapping { + public: + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_stride; + + private: + static constexpr rank_type @\exposid{rank_}@ = extents_type::rank(); // \expos + + public: + // \ref{mdspan.layout.stride.cons}, constructors + constexpr mapping() noexcept; + constexpr mapping(const mapping&) noexcept = default; + template + 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.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; + + 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 false; } + static constexpr bool is_always_strided() noexcept { return true; } + + static constexpr bool is_unique() noexcept { return true; } + constexpr bool is_exhaustive() const noexcept; + static constexpr bool is_strided() noexcept { return true; } + + constexpr index_type stride(rank_type i) const noexcept { return @\exposid{strides_}@[i]; } + + template + friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept; + + private: + extents_type @\exposid{extents_}@{}; // \expos + array @\exposid{strides_}@{}; // \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} -\end{itemdescr} -\indexlibrarymember{span}{first}% -\begin{itemdecl} -constexpr span first(size_type count) const; -\end{itemdecl} +\pnum +If \tcode{Extents} is not a specialization of \tcode{extents}, +then the program is ill-formed. -\begin{itemdescr} \pnum -\expects -\tcode{count <= size()} is \tcode{true}. +\tcode{layout_stride::mapping} is a trivially copyable type +that models \libconcept{regular} for each \tcode{E}. \pnum -\effects -Equivalent to: \tcode{return \{data(), count\};} -\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}. -\indexlibrarymember{span}{last}% -\begin{itemdecl} -constexpr span last(size_type count) const; -\end{itemdecl} +\rSec5[mdspan.layout.stride.expo]{Exposition-only helpers} -\begin{itemdescr} \pnum -\expects -\tcode{count <= size()} is \tcode{true}. +Let \tcode{\exposid{REQUIRED-SPAN-SIZE}(e, strides)} be: +\begin{itemize} +\item +\tcode{1}, if \tcode{e.rank() == 0} is \tcode{true}, +\item +otherwise \tcode{0}, if the size of the multidimensional index space \tcode{e} is 0, +\item +otherwise \tcode{1} plus the sum of products of +\tcode{(e.extent($r$) - 1)} and +\begin{codeblock} +extents_type::@\exposid{index-cast}@(strides[@$r$@]) +\end{codeblock} + for all $r$ in the range $[0, \tcode{e.rank()})$. +\end{itemize} \pnum -\effects -Equivalent to: \tcode{return \{data() + (size() - count), count\};} -\end{itemdescr} - -\indexlibrarymember{span}{subspan}% -\begin{itemdecl} -constexpr span subspan( - size_type offset, size_type count = dynamic_extent) const; -\end{itemdecl} +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} -\begin{itemdescr} \pnum -\expects +Let \exposid{is-extents} be the exposition-only variable template +defined as follows: \begin{codeblock} -offset <= size() && (count == dynamic_extent || count <= size() - offset) +template + constexpr bool @\exposid{is-extents}@ = false; // \expos +template + constexpr bool @\exposid{is-extents}@> = true; // \expos \end{codeblock} -is \tcode{true}. \pnum -\effects -Equivalent to: +Let \exposconcept{layout-mapping-alike} be the exposition-only concept +defined as follows: \begin{codeblock} -return {data() + offset, count == dynamic_extent ? size() - offset : count}; +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} -\end{itemdescr} +\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} -\rSec3[span.obs]{Observers} +\rSec5[mdspan.layout.stride.cons]{Constructors} -\indexlibrarymember{span}{size}% +\indexlibraryctor{layout_stride::mapping}% \begin{itemdecl} -constexpr size_type size() const noexcept; +constexpr mapping() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return size_;} -\end{itemdescr} - -\indexlibrarymember{span}{size_bytes}% -\begin{itemdecl} -constexpr size_type size_bytes() const noexcept; -\end{itemdecl} +\expects +\tcode{layout_right::mapping().required_span_size()} +is representable as a value of type \tcode{index_type}\iref{basic.fundamental}. -\begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return size() * sizeof(element_type);} +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} -\indexlibrarymember{span}{empty}% +\indexlibraryctor{layout_stride::mapping}% \begin{itemdecl} -[[nodiscard]] constexpr bool empty() const 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} \pnum -\effects -Equivalent to: \tcode{return size() == 0;} -\end{itemdescr} - -\rSec3[span.elem]{Element access} - -\indexlibrary{\idxcode{operator[]}!\idxcode{span}}% -\begin{itemdecl} -constexpr reference operator[](size_type idx) const; -\end{itemdecl} +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v} is \tcode{true}, and +\item +\tcode{is_nothrow_constructible_v} is \tcode{true}. +\end{itemize} -\begin{itemdescr} \pnum \expects -\tcode{idx < size()} is \tcode{true}. +\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 -Equivalent to: \tcode{return *(data() + idx);} +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} -\indexlibrarymember{span}{front}% +\indexlibraryctor{layout_stride::mapping}% \begin{itemdecl} -constexpr reference front() const; +template + constexpr explicit(@\seebelow@) + mapping(const StridedLayoutMapping& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{empty()} is \tcode{false}. - -\pnum -\effects -Equivalent to: \tcode{return *data();} -\end{itemdescr} - -\indexlibrarymember{span}{back}% -\begin{itemdecl} -constexpr reference back() const; -\end{itemdecl} +\constraints +\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} -\begin{itemdescr} \pnum \expects -\tcode{empty()} is \tcode{false}. - -\pnum -\effects -Equivalent to: \tcode{return *(data() + (size() - 1));} -\end{itemdescr} - -\indexlibrarymember{span}{data}% -\begin{itemdecl} -constexpr pointer data() const noexcept; -\end{itemdecl} +\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} -\begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return data_;} -\end{itemdescr} - -\rSec3[span.iterators]{Iterator support} - -\indexlibrarymember{iterator}{span}% -\begin{itemdecl} -using iterator = @\impdefx{type of \tcode{span::iterator}}@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The type -models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}, -meets the \oldconcept{RandomAccessIterator} -requirements\iref{random.access.iterators}, -and -meets the requirements for -constexpr iterators\iref{iterator.requirements.general}, -whose value type is \tcode{value_type} and -whose reference type is \tcode{reference}. - -\pnum -All requirements on container iterators\iref{container.requirements} apply to -\tcode{span::iterator} as well. -\end{itemdescr} - -\indexlibrarymember{span}{begin}% -\begin{itemdecl} -constexpr iterator begin() const noexcept; -\end{itemdecl} +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$)}. -\begin{itemdescr} \pnum -\returns -An iterator referring to the first element in the span. -If \tcode{empty()} is \tcode{true}, then it returns the -same value as \tcode{end()}. +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} -\indexlibrarymember{span}{end}% -\begin{itemdecl} -constexpr iterator end() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -An iterator which is the past-the-end value. -\end{itemdescr} +\rSec5[mdspan.layout.stride.obs]{Observers} -\indexlibrarymember{span}{rbegin}% +\indexlibrarymember{required_span_size}{layout_stride::mapping}% \begin{itemdecl} -constexpr reverse_iterator rbegin() const noexcept; +constexpr index_type required_span_size() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return reverse_iterator(end());} +\returns +\tcode{\exposid{REQUIRED-SPAN-SIZE}(extents(), \exposid{strides_})}. \end{itemdescr} -\indexlibrarymember{span}{rend}% +\indexlibrarymember{operator()}{layout_stride::mapping}% \begin{itemdecl} -constexpr reverse_iterator rend() const noexcept; +template + constexpr index_type operator()(Indices... i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return reverse_iterator(begin());} -\end{itemdescr} +\constraints +\begin{itemize} +\item +\tcode{sizeof...(Indices) == \exposid{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{extents_type::\exposid{index-cast}(i)} is +a multidimensional index in \exposid{extents_}\iref{mdspan.overview}. -\rSec3[span.objectrep]{Views of object representation} +\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} -\indexlibraryglobal{as_bytes}% +\indexlibrarymember{is_exhaustive}{layout_stride::mapping}% \begin{itemdecl} -template - span - as_bytes(span s) noexcept; +constexpr bool is_exhaustive() const noexcept; \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. +\returns +\begin{itemize} +\item +\tcode{true} if \exposid{rank_} is 0. +\item +Otherwise, \tcode{true} if there is +a permutation $P$ of the integers in the range $[0, \exposid{rank_})$ +such that \tcode{stride($p_0$)} equals 1, and +\tcode{stride($p_i$)} equals \tcode{stride($ p_{i-1}$) * extents().extent($p_{i-1}$)} +for $i$ in the range $[1, \exposid{rank_})$, +where $p_i$ is the $i^\text{th}$ element of $P$. +\item +Otherwise, \tcode{false}. +\end{itemize} \end{itemdescr} -\indexlibraryglobal{as_writable_bytes}% +\indexlibrarymember{operator==}{layout_stride::mapping}% \begin{itemdecl} -template - span - as_writable_bytes(span s) noexcept; +template + friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_const_v} is \tcode{false}. +\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 R\{reinterpret_cast(s.data()), s.size_bytes()\};} -where \tcode{R} is the return type. +\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} -\rSec2[mdspan.syn]{Header \tcode{} synopsis} +\rSec4[mdspan.layout.leftpad]{Class template \tcode{layout_left_padded::mapping}} + +\rSec5[mdspan.layout.leftpad.overview]{Overview} + +\pnum +\tcode{layout_left_padded} provides a layout mapping +that behaves like \tcode{layout_left::mapping}, +except that the padding stride \tcode{stride(1)} +can be greater than or equal to \tcode{extent(0)}. -\indexheader{mdspan}% \begin{codeblock} namespace std { - // \ref{mdspan.extents}, class template \tcode{extents} - template - class extents; + template + template + class layout_left_padded::mapping { + public: + static constexpr size_t padding_value = PaddingValue; - // \ref{mdspan.extents.dextents}, alias template \tcode{dextents} - template - using dextents = @\seebelow@; + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_left_padded; - // \ref{mdspan.layout}, layout mapping - struct layout_left; - struct layout_right; - struct layout_stride; + 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.accessor.default}, class template \tcode{default_accessor} - template - class default_accessor; + // \ref{mdspan.layout.leftpad.expo}, exposition-only members + static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; // \expos - // \ref{mdspan.mdspan}, class template \tcode{mdspan} - template> - class mdspan; + public: + // \ref{mdspan.layout.leftpad.cons}, constructors + constexpr mapping() noexcept : mapping(extents_type{}) {} + constexpr mapping(const mapping&) noexcept = default; + constexpr mapping(const extents_type&); + template + constexpr mapping(const extents_type&, OtherIndexType); + template + constexpr explicit(!is_convertible_v) + mapping(const layout_left::mapping&); + template + constexpr explicit(extents_type::rank() > 0) + 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.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; + static constexpr bool is_always_strided() noexcept { return true; } + + static constexpr bool is_unique() noexcept { return true; } + constexpr bool is_exhaustive() const noexcept; + static constexpr bool is_strided() noexcept { return true; } + + constexpr index_type stride(rank_type) const noexcept; + + template + friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept; + + private: + // \ref{mdspan.layout.leftpad.expo}, exposition-only members + index_type @\exposid{stride-1}@ = @\exposid{static-padding-stride}@; // \expos + extents_type @\exposid{extents_}@{}; // \expos + // \ref{mdspan.sub.map}, submdspan mapping specialization + template + 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} -\rSec2[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. +If \tcode{Extents} is not a specialization of \tcode{extents}, +then the program is ill-formed. \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$})$. +\tcode{layout_left_padded::mapping} is a trivially copyable type +that models \libconcept{regular} for each \tcode{E}. \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: +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 -\tcode{sizeof...(idx)} is equal to the rank of $S$, and +the empty parameter pack, if \exposid{rank_} equals zero; \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$. +\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} -\rSec2[mdspan.extents]{Class template \tcode{extents}} - -\rSec3[mdspan.extents.overview]{Overview} - -The class template \tcode{extents} represents -a multidimensional index space of rank equal to \tcode{sizeof...(Extents)}. -In subclause \iref{views}, -\tcode{extents} is used synonymously with multidimensional index space. - -\begin{codeblock} -namespace std { - template - class @\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 +\pnum +\mandates +\begin{itemize} +\item +If \tcode{rank_dynamic() == 0} is \tcode{true}, +then the size of the multidimensional index space \tcode{Extents()} +is representable as a value of type \tcode{index_type}. +\item +\tcode{padding_value} is representable as a value of type \tcode{index_type}. +\item +If +\begin{itemize} +\item +\exposid{rank_} is greater than one, +\item +\tcode{padding_value} does not equal \tcode{dynamic_extent}, and +\item +\exposid{first-static-extent} does not equal \tcode{dynamic_extent}, +\end{itemize} +then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{first-static-extent})} +is representable as a val\-ue of type \tcode{size_t}, and +is representable as a value of type \tcode{index_type}. +\item +If +\begin{itemize} +\item +\exposid{rank_} is greater than one, +\item +\tcode{padding_value} does not equal \tcode{dynamic_extent}, and +\item +\tcode{extents_type::static_extent($k$)} does not equal \tcode{dynamic_extent} +for all $k$ in the range \range{0}{extents_type::rank()}, +\end{itemize} +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.static_extent(0))} and +all values \tcode{ext.static_extent($k$)} +with $k$ in the range of \range{1}{\exposid{rank_}} +is representable as a value of type \tcode{size_t}, and +is representable as a value of type \tcode{index_type}. +\end{itemize} - 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 - }; +\rSec5[mdspan.layout.leftpad.expo]{Exposition-only members} - template - explicit extents(Integrals...) - -> @\seebelow@; -} -\end{codeblock} +\begin{itemdecl} +static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; +\end{itemdecl} +\begin{itemdescr} \pnum -\mandates +The value is \begin{itemize} \item -\tcode{IndexType} is a signed or unsigned integer type, and +\tcode{0}, if \exposid{rank_} equals zero or one; \item -each element of \tcode{Extents} is either equal to \tcode{dynamic_extent}, or -is representable as a value of type \tcode{IndexType}. +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} -\pnum -Each specialization of \tcode{extents} models \libconcept{regular} and -is trivially copyable. - -\pnum -Let $E_r$ be the $r^\text{th}$ element of \tcode{Extents}. -$E_r$ is a \defnadj{dynamic}{extent} if it is equal to \tcode{dynamic_extent}, -otherwise $E_r$ is a \defnadj{static}{extent}. -Let $D_r$ be the value of \tcode{\exposid{dynamic-extents}[\exposid{dynamic-index}($r$)]} -if $E_r$ is a dynamic extent, -otherwise $E_r$. +\begin{itemdecl} +index_type @\exposid{stride-1}@ = @\exposid{static-padding-stride}@; +\end{itemdecl} +\begin{itemdescr} \pnum -The $r^\text{th}$ interval of the multidimensional index space -represented by an \tcode{extents} object is $[0, D_r)$. +\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} -\rSec3[mdspan.extents.expo]{Exposition-only helpers} +\rSec5[mdspan.layout.leftpad.cons]{Constructors} +\indexlibraryctor{layout_left_padded::mapping}% \begin{itemdecl} -static constexpr rank_type @\exposid{dynamic-index}@(rank_type i) noexcept; // \expos +constexpr mapping(const extents_type& ext); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{i <= rank()} is \tcode{true}. +\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 -\returns -The number of $E_r$ with $r < \tcode{i}$ for which $E_r$ is a dynamic extent. +\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} -static constexpr rank_type @\exposid{dynamic-index-inv}@(rank_type i) noexcept; // \expos +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 -\tcode{i < rank_dynamic()} is \tcode{true}. +\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 -\returns -The minimum value of $r$ -such that \tcode{\exposid{dynamic-index}($r$ + 1) == i + 1} is \tcode{true}. +\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} -constexpr size_t @\exposid{fwd-prod-of-extents}@(rank_type i) const noexcept; // \expos +template + constexpr explicit(!is_convertible_v) + mapping(const layout_left::mapping& other); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{i <= rank()} is \tcode{true}. +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum -\returns -If \tcode{i > 0} is \tcode{true}, -the product of \tcode{extent($k$)} for all $k$ in the range $[0, \tcode{i})$, -otherwise \tcode{1}. -\end{itemdescr} - -\begin{itemdecl} -constexpr size_t @\exposid{rev-prod-of-extents}@(rank_type i) const noexcept; // \expos -\end{itemdecl} +\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}. -\begin{itemdescr} \pnum \expects -\tcode{i < rank()} is \tcode{true}. +\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 -\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}. +\effects +Equivalent to \tcode{mapping(other.extents())}. \end{itemdescr} +\indexlibraryctor{layout_left_padded::mapping}% \begin{itemdecl} -template - static constexpr auto @\exposid{index-cast}@(OtherIndexType&& i) noexcept; // \expos +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 +\begin{itemize} +\item +If \exposid{rank_} is greater than \tcode{1} and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{other.\linebreak stride(1)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extents().extent(0))) +\end{codeblock} +\item +If \exposid{rank_} is greater than 0, +then \tcode{other.stride(0)} equals 1. +\item +If \exposid{rank_} is greater than 2, +then for all $r$ in the range \range{2}{\exposid{rank_}}, +\tcode{other.stride(r)} equals +\begin{codeblock} +(other.extents().@\exposid{fwd-prod-of-extents}@(r) / other.extents().extent(0)) * other.stride(1) +\end{codeblock} +\item +\tcode{other.required_span_size()} is representable as +a value of type \exposid{index_type}. +\end{itemize} + \pnum \effects \begin{itemize} \item -If \tcode{OtherIndexType} is an integral type other than \tcode{bool}, -then equivalent to \tcode{return i;}, +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()} and \item -otherwise, equivalent to \tcode{return static_cast(i);}. +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-1} with +\tcode{other.stride(1)}. \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} -\rSec3[mdspan.extents.cons]{Constructors} - -\indexlibraryctor{extents}% +\indexlibraryctor{layout_left_padded::mapping}% \begin{itemdecl} -template +template constexpr explicit(@\seebelow@) - extents(const extents& other) noexcept; + mapping(const LayoutLeftPaddedMapping& other); \end{itemdecl} \begin{itemdescr} @@ -18452,935 +23344,1214 @@ \constraints \begin{itemize} \item -\tcode{sizeof...(OtherExtents) == rank()} is \tcode{true}. +\tcode{\exposid{is-layout-left-padded-mapping-of}} +is \tcode{true}. \item -\tcode{((OtherExtents == dynamic_extent || Extents == dynamic_extent || OtherExtents ==\newline Extents) \&\& ...)} is \tcode{true}. +\tcode{is_constructible_v} +\newline is \tcode{true}. \end{itemize} \pnum -\expects +\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 \begin{itemize} \item -\tcode{other.extent($r$)} equals $E_r$ -for each $r$ for which $E_r$ is a static extent, and +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 -either +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects \begin{itemize} \item -\tcode{sizeof...(OtherExtents)} is zero, or +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()} and \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} +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-1} with \tcode{other.stride(1)}. \end{itemize} -\pnum -\ensures -\tcode{*this == other} is \tcode{true}. - \pnum \remarks The expression inside \tcode{explicit} is equivalent to: \begin{codeblock} -(((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) || -(numeric_limits::max() < numeric_limits::max()) +rank_> 1 && +(padding_value != dynamic_extent || + LayoutLeftPaddedMapping::padding_value == dynamic_extent) \end{codeblock} \end{itemdescr} -\indexlibraryctor{extents}% +\indexlibraryctor{layout_left_padded::mapping}% \begin{itemdecl} -template - explicit constexpr extents(OtherIndexTypes... exts) noexcept; +template + constexpr explicit(@\seebelow@) + mapping(const LayoutRightPaddedMapping& 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}, +\tcode{\exposid{is-layout-right-padded-mapping-of}} +is \tcode{true} or\newline +\tcode{\exposid{is-mapping-of}} +is \tcode{true}. \item -\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}, and +\exposid{rank_} equals zero or one. \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 nonnegative and -is representable as a value of type \tcode{index_type}. -\end{itemize} -\end{itemize} +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. \pnum -\ensures -\tcode{*this == extents(exts_arr)} is \tcode{true}. +\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} -\indexlibraryctor{extents}% +\rSec5[mdspan.layout.leftpad.obs]{Observers} + \begin{itemdecl} -template - constexpr explicit(N != rank_dynamic()) - extents(span exts) noexcept; -template - constexpr explicit(N != rank_dynamic()) - extents(const array& exts) noexcept; +constexpr array strides() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints +\returns +\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{is_convertible_v} is \tcode{true}, -\item -\tcode{is_nothrow_constructible_v} is \tcode{true}, and +\tcode{0} if the multidimensional index space \exposid{extents_} is empty, \item -\tcode{N == rank_dynamic() || N == rank()} is \tcode{true}. +otherwise, \tcode{*this(((\exposid{extents_}(P_rank) - index_type(1))...)) + 1}. \end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template +constexpr size_t operator()(Indices... idxs) const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\expects +\constraints \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{sizeof...(Indices) == \exposid{rank_}} is \tcode{true}. \item -\tcode{N} is zero, or +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}. \item -\tcode{exts[$r$]} is nonnegative and -is representable as a value of type \tcode{index_type} for every rank index $r$. -\end{itemize} +\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}. \end{itemize} \pnum -\effects +\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} + +\begin{itemdecl} +static constexpr bool is_always_exhaustive() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns \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-extent}[$d$]} -with \tcode{as_const(exts[$d$])}. +If \exposid{rank_} equals zero or one, then \tcode{true}; \item -Otherwise, for all $d$ in the range $[0, \tcode{rank_dynamic()})$, -direct-non-list-initializes \exposidnc{dynamic-ex\-tent}\tcode{[$d$]} -with \tcode{as_const(exts[\exposidnc{dynamic-index-inv}($d$)])}. +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} -\indexlibraryctor{extents}% \begin{itemdecl} -template - explicit extents(Integrals...) -> @\seebelow@; +constexpr bool is_exhaustive() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{(is_convertible_v \&\& ...)} is \tcode{true}. - -\pnum -\remarks -The deduced type is \tcode{dextents}. +\returns +\tcode{true} if \exposid{rank_} equals zero or one; +otherwise, \tcode{extents_.extent(0) == stride(1)}. \end{itemdescr} -\rSec3[mdspan.extents.obs]{Observers of the multidimensional index space} - -\indexlibrarymember{static_extent}{extents}% \begin{itemdecl} -static constexpr size_t static_extent(rank_type i) noexcept; +constexpr index_type stride(rank_type r) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{i < rank()} is \tcode{true}. +\tcode{r} is smaller than \exposid{rank_}. \pnum \returns -$E_\tcode{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{extent}{extents}% \begin{itemdecl} -constexpr index_type extent(rank_type i) const noexcept; +template + friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{i < rank()} is \tcode{true}. +\constraints +\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 \returns -$D_\tcode{i}$. +\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} -\rSec3[mdspan.extents.cmp]{Comparison operators} +\rSec4[mdspan.layout.rightpad]{Class template \tcode{layout_right_padded::mapping}} -\indexlibrarymember{operator==}{extents}% -\begin{itemdecl} -template - friend constexpr bool operator==(const extents& lhs, - const extents& rhs) noexcept; -\end{itemdecl} +\rSec5[mdspan.layout.rightpad.overview]{Overview} -\begin{itemdescr} \pnum -\returns -\tcode{true} if \tcode{lhs.rank()} equals \tcode{rhs.rank()} and -if \tcode{lhs.extent(r)} equals \tcode{rhs.extent(r)} -for every rank index \tcode{r} of \tcode{rhs}, -otherwise \tcode{false}. -\end{itemdescr} +\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)}. -\rSec3[mdspan.extents.dextents]{Alias template \tcode{dextents}} +\begin{codeblock} +namespace std { + template + template + class layout_right_padded::mapping { + public: + static constexpr size_t padding_value = PaddingValue; -\indexlibraryglobal{dextents}% -\begin{itemdecl} -template - using dextents = @\seebelow@; -\end{itemdecl} + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_right_padded; -\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} + private: + static constexpr size_t @\exposid{rank_}@ = extents_type::rank(); // \expos + static constexpr size_t @\exposid{last-static-extent}@ = // \expos + extents_type::static_extent(@\exposid{rank_}@ - 1); -\rSec2[mdspan.layout]{Layout mapping} + // \ref{mdspan.layout.rightpad.expo}, exposition-only members + static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; // \expos -\rSec3[mdspan.layout.general]{General} + public: + // \ref{mdspan.layout.rightpad.cons}, constructors + constexpr mapping() noexcept : mapping(extents_type{}) {} + constexpr mapping(const mapping&) noexcept = default; + constexpr mapping(const extents_type&); + template + constexpr mapping(const extents_type&, OtherIndexType); -\pnum -In subclauses \ref{mdspan.layout.reqmts} and \ref{mdspan.layout.policy.reqmts}: + 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; -\begin{itemize} -\item -\tcode{M} denotes a layout mapping class. + constexpr mapping& operator=(const mapping&) noexcept = default; -\item -\tcode{m} denotes a (possibly const) value of type \tcode{M}. + // \ref{mdspan.layout.rightpad.obs}, observers + constexpr const extents_type& extents() const noexcept { return extents_; } + constexpr array strides() const noexcept; -\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} + constexpr index_type required_span_size() const noexcept; -\item -\tcode{r} is a (possibly const) rank index of \tcode{typename M::extents_type}. + template + constexpr index_type operator()(Indices...) const noexcept; -\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} + static constexpr bool is_always_unique() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept; + static constexpr bool is_always_strided() noexcept { return true; } -\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>; + static constexpr bool is_unique() noexcept { return true; } + constexpr bool is_exhaustive() const noexcept; + static constexpr bool is_strided() noexcept { return true; } + + constexpr index_type stride(rank_type) const noexcept; + + template + friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept; + + private: + // \ref{mdspan.layout.rightpad.expo}, exposition-only members + index_type @\exposid{stride-rm2}@ = @\exposid{static-padding-stride}@; // \expos + extents_type @\exposid{extents_}@{}; // \expos + + // \ref{mdspan.sub.map}, submdspan mapping specialization + template + 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} -\rSec3[mdspan.layout.reqmts]{Requirements} +\pnum +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 -A type \tcode{M} meets the \defn{layout mapping} requirements if +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 -\tcode{M} models \libconcept{copyable} and \libconcept{equality_comparable}, +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{is_nothrow_move_constructible_v} is \tcode{true}, +\tcode{padding_value} is representable as a value of type \tcode{index_type}. \item -\tcode{is_nothrow_move_assignable_v} is \tcode{true}, +If +\begin{itemize} \item -\tcode{is_nothrow_swappable_v} is \tcode{true}, and +\exposid{rank_} is greater than one, \item -the following types and expressions are well-formed and -have the specified semantics. +\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} -typename M::extents_type +static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\result -A type that is a specialization of \tcode{extents}. +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} -typename M::index_type +index_type @\exposid{stride-rm2}@ = @\exposid{static-padding-stride}@; \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{typename M::extents_type::index_type}. +\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} -typename M::rank_type +constexpr mapping(const extents_type& ext); \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{typename M::extents_type::rank_type}. +\expects +\begin{itemize} +\item +The size of the multidimensional index space \tcode{ext} +is representable as a value of type \tcode{index_type}. +\item +If \exposid{rank_} is greater than one and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{\exposid{LEAST-MUL\-TIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))} +is representable as a value of type \exposid{index_type}. +\item +If \exposid{rank_} is greater than one and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))} and +all values \tcode{ext.extent($k$)} +with $k$ in the range of \range{0}{\exposid{rank_} - 1} +is representable as a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{ext}; and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-rm2} +\begin{itemize} +\item +with \tcode{ext.extent(\exposid{rank_} - 1)} +if \tcode{padding_value} is \tcode{dynamic_extent}, +\item +otherwise with +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))}. +\end{itemize} +\end{itemize} \end{itemdescr} +\indexlibraryctor{layout_right_padded::mapping}% \begin{itemdecl} -typename M::layout_type +template +constexpr mapping(const extents_type& ext, OtherIndexType pad); \end{itemdecl} \begin{itemdescr} \pnum -\result -A type \tcode{MP} that meets -the layout mapping policy requirements\iref{mdspan.layout.policy.reqmts} and -for which \tcode{\exposid{is-mapping-of}} is \tcode{true}. -\end{itemdescr} +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v} is \tcode{true}. +\item +\tcode{is_nothrow_constructible_v} is \tcode{true}. +\end{itemize} -\begin{itemdecl} -m.extents() -\end{itemdecl} +\pnum +\expects +\begin{itemize} +\item +\tcode{pad} is representable as a value of type \tcode{index_type}. +\item +\tcode{extents_type::\exposid{index-cast}(pad)} is greater than zero. +\item +If \exposid{rank_} is greater than one, +then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\exposid{rank_} - 1))} +is representable as a value of type \tcode{index_type}. +\item +If \exposid{rank_} is greater than one, +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\exposid{\linebreak rank_} - 1))} and +all values \tcode{ext.extent($k$)} +with $k$ in the range of \range{0}{\exposid{rank_} - 1} +is representable as a value of type \tcode{index_type}. +\item +If \tcode{padding_value} is not equal to \tcode{dynamic_extent}, +\tcode{padding_value} equals \tcode{extents_type::\linebreak \exposid{index-cast}(pad)}. +\end{itemize} -\begin{itemdescr} \pnum -\result -\tcode{const typename M::extents_type\&} +\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} -m(i...) +template + constexpr explicit(!is_convertible_v) + mapping(const layout_right::mapping& other); \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{typename M::index_type} +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum -\returns -A nonnegative integer -less than \tcode{numeric_limits::max()} and -less than or equal to \tcode{numeric_limits::max()}. +\mandates +If \tcode{OtherExtents::rank()} is greater than 1, then +\begin{codeblock} +(@\exposid{static-padding-stride}@ == dynamic_extent) || +(OtherExtents::static_extent(@\exposid{rank_}@ - 1) == dynamic_extent) || +(@\exposid{static-padding-stride}@ == OtherExtents::static_extent(@\exposid{rank_}@ - 1)) +\end{codeblock} +is \tcode{true}. + +\pnum +\expects +\begin{itemize} +\item +If \tcode{\exposid{rank_} > 1} is \tcode{true} and +\tcode{padding_value == dynamic_extent} is \tcode{false}, then +\tcode{other.stride(\newline \exposid{rank_} - 2)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extents().extent(rank_ - 1))) +\end{codeblock} +and +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +Equivalent to \tcode{mapping(other.extents())}. \end{itemdescr} +\indexlibraryctor{layout_right_padded::mapping}% \begin{itemdecl} -m(i...) == m(static_cast(i)...) +template + constexpr explicit(rank_ > 0) + mapping(const layout_stride::mapping& other); \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{bool} +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum -\returns -\tcode{true} +\expects +\begin{itemize} +\item +If \exposid{rank_} is greater than 1 and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{other.\linebreak stride(\exposid{rank_} - 2)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extents().extent(@\exposid{rank_}@ - 1))) +\end{codeblock} +\item +If \exposid{rank_} is greater than 0, +then other.stride(\exposid{rank_} - 1) equals 1. +\item +If \exposid{rank_} is greater than 2, +then for all $r$ in the range \range{0}{\exposid{rank_} - 2}, +\tcode{other.stride($r$)} equals +\begin{codeblock} +(other.extents().@\exposid{rev-prod-of-extents}@(r) / other.extents().extent(@\exposid{rank_}@ - 1)) * + other.stride(@\exposid{rank_}@ - 2) +\end{codeblock} +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}; and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-rm2} +with \tcode{other.stride(\exposid{rank_} - 2)}. +\end{itemize} \end{itemdescr} +\indexlibraryctor{layout_right_padded::mapping}% \begin{itemdecl} -m.required_span_size() +template + constexpr explicit(@\seebelow@) + mapping(const LayoutRightPaddedMapping& other); \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{typename M::index_type} +\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 -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} +\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}. -\begin{itemdecl} -m.is_unique() -\end{itemdecl} +\pnum +\expects +\begin{itemize} +\item +If \exposid{rank_} is greater than 1 and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{other.\linebreak stride(\exposid{rank_} - 2)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extent(@\exposid{rank_}@ - 1))) +\end{codeblock} +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} -\begin{itemdescr} \pnum -\result -\tcode{bool} +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}; and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-rm2} +with \tcode{other.stride(rank_ - 2)}. +\end{itemize} \pnum -\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} +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +@\exposid{rank_}@ > 1 && +(padding_value != dynamic_extent || + LayoutRightPaddedMapping::padding_value == dynamic_extent) +\end{codeblock} \end{itemdescr} +\indexlibraryctor{layout_right_padded::mapping}% \begin{itemdecl} -m.is_exhaustive() +template + constexpr explicit(@\seebelow@) + mapping(const LayoutLeftPaddedMapping& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{bool} +\constraints +\begin{itemize} +\item +\tcode{\exposid{is-layout-left-padded-mapping-of}} +is \tcode{true} or\newline +\tcode{\exposid{is-mapping-of}} +is \tcode{true}. +\item +\exposid{rank_} equals zero or one. +\item +\tcode{is_constructible_v}\newline +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} +\expects +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. -\begin{itemdescr} \pnum -\result -\tcode{bool} +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \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} +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!is_convertible_v +\end{codeblock} \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. +Neither the input mapping nor the mapping to be constructed +uses the padding stride in the rank-0 or rank-1 case, +so the padding stride affects neither the constraints nor the preconditions. \end{note} \end{itemdescr} +\rSec5[mdspan.layout.rightpad.obs]{Observers} + +\indexlibrarymember{layout_right_padded::mapping}{strides}% \begin{itemdecl} -m.stride(r) +constexpr array strides() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{m.is_strided()} is \tcode{true}. - -\pnum -\result -\tcode{typename M::index_type} - \pnum \returns -$s_r$ as defined in \tcode{m.is_strided()} above. +\tcode{array({stride(P_rank)...})}. \end{itemdescr} +\indexlibrarymember{layout_right_padded::mapping}{required_span_size}% \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{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} -M::is_always_exhaustive() +template +constexpr size_t operator()(Indices... idxs) 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) == \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{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} +\tcode{((static_cast(idxs) * stride(P_rank)) + ... + 0)}. \end{itemdescr} +\indexlibrarymember{layout_right_padded::mapping}{is_always_exhaustive}% \begin{itemdecl} -M::is_always_strided() +static constexpr bool is_always_exhaustive() 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_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.layout.policy.reqmts]{Layout mapping policy requirements} - -\pnum -A type \tcode{MP} meets the \defn{layout mapping policy} requirements -if for a type \tcode{E} that is a specialization of \tcode{extents}, -\tcode{MP::mapping} 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}. - -\rSec3[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} - -\pnum -Each of \tcode{layout_left}, \tcode{layout_right}, and \tcode{layout_stride} -meets the layout mapping policy requirements and is a trivial type. - -\rSec3[mdspan.layout.left]{Class template \tcode{layout_left::mapping}} - -\rSec4[mdspan.layout.left.overview]{Overview} - -\pnum -\tcode{layout_left} provides a layout mapping -where the leftmost extent has stride 1, and -strides increase left-to-right as the product of extents. - -\begin{codeblock} -namespace std { - template - class layout_left::mapping { - public: - using extents_type = Extents; - using index_type = typename extents_type::index_type; - using size_type = typename extents_type::size_type; - using rank_type = typename extents_type::rank_type; - using layout_type = layout_left; - - // \ref{mdspan.layout.left.cons}, constructors - constexpr mapping() noexcept = default; - constexpr mapping(const mapping&) noexcept = default; - constexpr mapping(const extents_type&) noexcept; - template - 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&); +\begin{itemize} +\item +If \exposid{rank_} equals zero or one, then \tcode{true}; +\item +otherwise, +if neither \exposid{static-padding-stride} nor \exposid{last-static-extent} +equal \tcode{dynamic_extent}, +then \tcode{\exposid{static-padding-stride} == \exposid{last-static-extent}}; +\item +otherwise, \tcode{false}. +\end{itemize} +\end{itemdescr} - constexpr mapping& operator=(const mapping&) noexcept = default; +\indexlibrarymember{layout_right_padded::mapping}{is_exhaustive}% +\begin{itemdecl} +constexpr bool is_exhaustive() const noexcept; +\end{itemdecl} - // \ref{mdspan.layout.left.obs}, observers - constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \exposid{rank_} equals zero or one; +otherwise, +\begin{codeblock} +@\exposid{extents_}@.extent(@\exposid{rank_}@ - 1) == stride(@\exposid{rank_}@ - 2) +\end{codeblock} +\end{itemdescr} - constexpr index_type required_span_size() const noexcept; +\begin{itemdecl} +constexpr index_type stride(rank_type r) const noexcept; +\end{itemdecl} - template - constexpr index_type operator()(Indices...) const noexcept; +\begin{itemdescr} +\pnum +\expects +\tcode{r} is smaller than \exposid{rank_}. - 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; } +\pnum +\returns +\begin{itemize} +\item +If \tcode{r} equals \tcode{\exposid{rank_} - 1}: \tcode{1}; +\item +otherwise, if \tcode{r} equals \tcode{\exposid{rank_} - 2}: \exposid{stride-rm2}; +\item +otherwise, +the product of \exposid{stride-rm2} and +all values \tcode{extents_.extent($k$)} +with $k$ in the range of \range{r + 1}{\exposid{rank_} - 1}. +\end{itemize} +\end{itemdescr} - static constexpr bool is_unique() noexcept { return true; } - static constexpr bool is_exhaustive() noexcept { return true; } - static constexpr bool is_strided() noexcept { return true; } +\indexlibrarymember{layout_right_padded::mapping}{operator==}% +\begin{itemdecl} +template + friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept; +\end{itemdecl} - constexpr index_type stride(rank_type) const noexcept; +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{\exposid{is-layout-right-padded-mapping-of}} +is \tcode{true}. +\item +\tcode{LayoutRightPaddedMapping::extents_type::rank() == \exposid{rank_}} +is \tcode{true}. +\end{itemize} - template - friend constexpr bool operator==(const mapping&, const mapping&) noexcept; +\pnum +\returns +\tcode{true} if \tcode{x.extents() == y.extents()} is \tcode{true} and +\tcode{\exposid{rank_} < 2 || x.stride(\exposid{rank_} - 2) == y.stride(\exposid{rank_} - 2)} is \tcode{true}. +Otherwise, \tcode{false}. +\end{itemdescr} - private: - extents_type @\exposid{extents_}@{}; // \expos - }; -} -\end{codeblock} +\rSec3[mdspan.accessor]{Accessor policy} + +\rSec4[mdspan.accessor.general]{General} \pnum -If \tcode{Extents} is not a specialization of \tcode{extents}, -then the program is ill-formed. +An \defn{accessor policy} defines types and operations by which +a reference to a single object is created +from an abstract data handle to a number of such objects and an index. \pnum -\tcode{layout_left::mapping} is a trivially copyable type -that models \libconcept{regular} for each \tcode{E}. +A range of indices $[0, N)$ is an \defnadj{accessible}{range} of +a given data handle and an accessor +if, for each $i$ in the range, +the accessor policy's \tcode{access} function produces a valid reference to an object. -\rSec4[mdspan.layout.left.cons]{Constructors} +\pnum +In \ref{mdspan.accessor.reqmts}, + +\begin{itemize} +\item +\tcode{A} denotes an accessor policy. +\item +\tcode{a} denotes a value of type \tcode{A} or \tcode{const A}. +\item +\tcode{p} denotes a value of type \tcode{A::data_handle_type} or \tcode{const A::data_handle_type}. +\begin{note} +The type \tcode{A::data_handle_type} need not be dereferenceable. +\end{note} +\item +\tcode{n}, \tcode{i}, and \tcode{j} each denote values of type \tcode{size_t}. +\end{itemize} + +\rSec4[mdspan.accessor.reqmts]{Requirements} + +\pnum +A type \tcode{A} meets the accessor policy requirements if +\begin{itemize} +\item +\tcode{A} models \libconcept{copyable}, +\item +\tcode{is_nothrow_move_constructible_v} 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} -\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -constexpr mapping(const extents_type& e) noexcept; +typename A::element_type \end{itemdecl} \begin{itemdescr} \pnum -\expects -The size of the multidimensional index space \tcode{e} -is representable as a value of type \tcode{index_type}\iref{basic.fundamental}. - -\pnum -\effects -Direct-non-list-initializes \exposid{extents_} with \tcode{e}. +\result +A complete object type that is not an abstract class type. \end{itemdescr} -\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -template - constexpr explicit(!is_convertible_v) - mapping(const mapping& other) noexcept; +typename A::data_handle_type \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\result +A type that models \libconcept{copyable}, and +for which \tcode{is_nothrow_move_constructible_v} is \tcode{true}, +\tcode{is_nothrow_move_assignable_v} is \tcode{true}, and +\tcode{is_nothrow_swappable_v} is \tcode{true}. +\begin{note} +The type of \tcode{data_handle_type} need not be \tcode{element_type*}. +\end{note} +\end{itemdescr} -\pnum -\expects -\tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. +\begin{itemdecl} +typename A::reference +\end{itemdecl} +\begin{itemdescr} \pnum -\effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +\result +A type that models +\tcode{\libconcept{common_reference_with}}. +\begin{note} +The type of \tcode{reference} need not be \tcode{element_type\&}. +\end{note} \end{itemdescr} -\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -template - constexpr explicit(!is_convertible_v) - mapping(const layout_right::mapping& other) noexcept; +typename A::offset_policy \end{itemdecl} \begin{itemdescr} \pnum -\constraints +\result +A type \tcode{OP} such that: + \begin{itemize} \item -\tcode{extents_type::rank() <= 1} is \tcode{true}, and +\tcode{OP} meets the accessor policy requirements, \item -\tcode{is_constructible_v} is \tcode{true}. +\tcode{\libconcept{constructible_from}} is modeled, and +\item +\tcode{is_same_v} is \tcode{true}. \end{itemize} +\end{itemdescr} + +\begin{itemdecl} +a.access(p, i) +\end{itemdecl} +\begin{itemdescr} \pnum -\expects -\tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. +\result +\tcode{A::reference} \pnum -\effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +\remarks +The expression is equality preserving. + +\pnum +\begin{note} +Concrete accessor policies can impose preconditions for their \tcode{access} function. +However, they might not. +For example, an accessor where +\tcode{p} is \tcode{span} and +\tcode{access(p, i)} returns \tcode{p[i \% p.size()]} +does not need to impose a precondition on \tcode{i}. +\end{note} \end{itemdescr} -\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -template - constexpr explicit(extents_type::rank() > 0) - mapping(const layout_stride::mapping& other); +a.offset(p, i) \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\result +\tcode{A::offset_policy::data_handle_type} \pnum -\expects +\returns +\tcode{q} such that for \tcode{b} being \tcode{A::offset_policy(a)}, and +any integer \tcode{n} for which $[0, \tcode{n})$ is +an accessible range of \tcode{p} and \tcode{a}: \begin{itemize} \item -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{extents().\exposid{fwd-prod-of-extents}($r$)}, and +$[0, \tcode{n} - \tcode{i})$ is an accessible range of \tcode{q} and \tcode{b}; and \item -\tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. +\tcode{b.access(q, j)} provides access to +the same element as \tcode{a.access(p, i + j)}, +for every \tcode{j} in the range $[0, \tcode{n} - \tcode{i})$. \end{itemize} \pnum -\effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +\remarks +The expression is equality-preserving. \end{itemdescr} -\rSec4[mdspan.layout.left.obs]{Observers} +\rSec4[mdspan.accessor.default]{Class template \tcode{default_accessor}} -\indexlibrarymember{required_span_size}{layout_left::mapping}% -\begin{itemdecl} -constexpr index_type required_span_size() const noexcept; -\end{itemdecl} +\rSec5[mdspan.accessor.default.overview]{Overview} + +\begin{codeblock} +namespace std { + template + struct default_accessor { + using offset_policy = default_accessor; + using element_type = ElementType; + using reference = ElementType&; + using data_handle_type = ElementType*; + + constexpr default_accessor() noexcept = default; + template + constexpr default_accessor(default_accessor) noexcept; + constexpr reference access(data_handle_type p, size_t i) const noexcept; + constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept; + }; +} +\end{codeblock} -\begin{itemdescr} \pnum -\returns -\tcode{extents().\exposid{fwd-prod-of-extents}(extents_type::rank())}. -\end{itemdescr} +\tcode{default_accessor} meets the accessor policy requirements. + +\pnum +\tcode{ElementType} is required to be a complete object type +that is neither an abstract class type nor an array type. + +\pnum +Each specialization of \tcode{default_accessor} is +a trivially copyable type that models \libconcept{semiregular}. + +\pnum +$[0, n)$ is an accessible range for +an object \tcode{p} of type \tcode{data_handle_type} and +an object of type \tcode{default_accessor} +if and only if \range{p}{p + $n$} is a valid range. -\indexlibrarymember{operator()}{layout_left::mapping}% +\rSec5[mdspan.accessor.default.members]{Members} + +\indexlibraryctor{default_accessor}% \begin{itemdecl} -template - constexpr index_type operator()(Indices... i) const noexcept; +template + constexpr default_accessor(default_accessor) 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{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} +\tcode{is_convertible_v} is \tcode{true}. -Equivalent to: -\begin{codeblock} -return ((static_cast(i) * stride(P)) + ... + 0); -\end{codeblock} \end{itemdescr} -\indexlibrarymember{stride}{layout_left::mapping}% +\indexlibrarymember{access}{default_accessor}% \begin{itemdecl} -constexpr index_type stride(rank_type i) const; +constexpr reference access(data_handle_type p, size_t i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{extents_type::rank() > 0} is \tcode{true}. - -\pnum -\expects -\tcode{i < extents_type::rank()} is \tcode{true}. - -\pnum -\returns -\tcode{extents().\exposid{fwd-prod-of-extents}(i)}. +\effects +Equivalent to: \tcode{return p[i];} \end{itemdescr} -\indexlibrarymember{operator==}{layout_left::mapping}% +\indexlibrarymember{offset}{default_accessor}% \begin{itemdecl} -template - friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; +constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{extents_type::rank() == OtherExtents::rank()} is \tcode{true}. - \pnum \effects -Equivalent to: \tcode{return x.extents() == y.extents();} +Equivalent to: \tcode{return p + i;} \end{itemdescr} -\rSec3[mdspan.layout.right]{Class template \tcode{layout_right::mapping}} - -\rSec4[mdspan.layout.right.overview]{Overview} +\rSec4[mdspan.accessor.aligned]{Class template \tcode{aligned_accessor}} -\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. +\rSec5[mdspan.accessor.aligned.overview]{Overview} \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; - - // \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(extents_type::rank() > 0) - mapping(const layout_stride::mapping&) noexcept; - - constexpr mapping& operator=(const mapping&) noexcept = default; - - // \ref{mdspan.layout.right.obs}, observers - constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } - - constexpr index_type required_span_size() const noexcept; - - template - constexpr index_type operator()(Indices...) const noexcept; + template + struct @\libglobal{aligned_accessor}@ { + using offset_policy = default_accessor; + using element_type = ElementType; + using reference = ElementType&; + using data_handle_type = ElementType*; - static constexpr bool is_always_unique() noexcept { return true; } - static constexpr bool is_always_exhaustive() noexcept { return true; } - static constexpr bool is_always_strided() noexcept { return true; } + static constexpr size_t byte_alignment = ByteAlignment; - static constexpr bool is_unique() noexcept { return true; } - static constexpr bool is_exhaustive() noexcept { return true; } - static constexpr bool is_strided() noexcept { return true; } + constexpr aligned_accessor() noexcept = default; + template + constexpr aligned_accessor( + aligned_accessor) noexcept; + template + constexpr explicit aligned_accessor(default_accessor) noexcept; - constexpr index_type stride(rank_type) const noexcept; + template + constexpr operator default_accessor() const noexcept; - template - friend constexpr bool operator==(const mapping&, const mapping&) noexcept; + constexpr reference access(data_handle_type p, size_t i) const noexcept; - private: - extents_type @\exposid{extents_}@{}; // \expos + constexpr typename offset_policy::data_handle_type offset( + data_handle_type p, size_t i) const noexcept; }; } \end{codeblock} \pnum -If \tcode{Extents} is not a specialization of \tcode{extents}, -then the program is ill-formed. +\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{layout_right::mapping} is a trivially copyable type -that models \libconcept{regular} for each \tcode{E}. +\tcode{aligned_accessor} meets the accessor policy requirements. -\rSec4[mdspan.layout.right.cons]{Constructors} +\pnum +\tcode{ElementType} is required to be a complete object type +that is neither an abstract class type nor an array type. -\indexlibraryctor{layout_right::mapping}% -\begin{itemdecl} -constexpr mapping(const extents_type& e) noexcept; -\end{itemdecl} +\pnum +Each specialization of \tcode{aligned_accessor} is +a trivially copyable type that models \libconcept{semiregular}. -\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}. +\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 -\effects -Direct-non-list-initializes \exposid{extents_} with \tcode{e}. -\end{itemdescr} +\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); -\indexlibraryctor{layout_right::mapping}% -\begin{itemdecl} -template - constexpr explicit(!is_convertible_v) - mapping(const mapping& other) noexcept; -\end{itemdecl} +void compute_without_requiring_overalignment( + std::mdspan, std::layout_right> x); -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +void compute(std::mdspan> x) { + constexpr auto byte_alignment = 4 * sizeof(float); + auto accessor = std::aligned_accessor{}; + auto x_handle = x.data_handle(); -\pnum -\expects -\tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. + 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} -\pnum -\effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. -\end{itemdescr} +\rSec5[mdspan.accessor.aligned.members]{Members} -\indexlibraryctor{layout_right::mapping}% +\indexlibraryctor{aligned_accessor}% \begin{itemdecl} -template - constexpr explicit(!is_convertible_v) - mapping(const layout_left::mapping& other) noexcept; +template + constexpr aligned_accessor(aligned_accessor) noexcept; \end{itemdecl} \begin{itemdescr} @@ -19388,277 +24559,259 @@ \constraints \begin{itemize} \item -\tcode{extents_type::rank() <= 1} is \tcode{true}, and +\tcode{is_convertible_v} +is \tcode{true}. \item -\tcode{is_constructible_v} is \tcode{true}. +\tcode{OtherByteAlignment >= byte_alignment} is \tcode{true}. \end{itemize} -\pnum -\expects -\tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. - \pnum \effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +None. \end{itemdescr} -\indexlibraryctor{layout_right::mapping}% +\indexlibraryctor{aligned_accessor}% \begin{itemdecl} -template - constexpr explicit(extents_type::rank() > 0) - mapping(const layout_stride::mapping& other) noexcept; +template + constexpr explicit aligned_accessor(default_accessor) 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{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} +\tcode{is_convertible_v} +is \tcode{true}. \pnum \effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. -\end{itemdescr} - -\rSec4[mdspan.layout.right.obs]{Observers} - -\indexlibrarymember{required_span_size}{layout_right::mapping}% -\begin{itemdecl} -index_type required_span_size() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{extents().\exposid{fwd-prod-of-extents}(extents_type::rank())}. +None. \end{itemdescr} -\indexlibrarymember{operator()}{layout_right::mapping}% +\indexlibrarymember{access}{aligned_accessor}% \begin{itemdecl} -template - constexpr index_type operator()(Indices... i) const noexcept; +constexpr reference access(data_handle_type p, size_t 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{extents_type::\exposid{index-cast}(i)} is -a multidimensional index in \exposid{extents_}\iref{mdspan.overview}. +\range{0}{i + 1} is an accessible range for \tcode{p} and \tcode{*this}. \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} +Equivalent to: \tcode{return assume_aligned(p)[i];} \end{itemdescr} -\indexlibrarymember{stride}{layout_right::mapping}% +\indexlibrarymember{operator default_accessor}{aligned_accessor}% \begin{itemdecl} -constexpr index_type stride(rank_type i) const noexcept; +template + constexpr operator default_accessor() 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}. +\tcode{is_convertible_v} +is \tcode{true}. \pnum -\returns -\tcode{extents().\exposid{rev-prod-of-extents}(i)}. +\effects +Equivalent to: \tcode{return \{\};} \end{itemdescr} -\indexlibrarymember{operator==}{layout_right::mapping}% -\begin{itemdecl} -template - friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; +\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 -\constraints -\tcode{extents_type::rank() == OtherExtents::rank()} is \tcode{true}. +\expects +\range{0}{i + 1} is an accessible range for \tcode{p} and \tcode{*this}. \pnum \effects -Equivalent to: \tcode{return x.extents() == y.extents();} +Equivalent to: \tcode{return assume_aligned(p) + i;} \end{itemdescr} -\rSec3[mdspan.layout.stride]{Class template \tcode{layout_stride::mapping}} +\rSec3[mdspan.mdspan]{Class template \tcode{mdspan}} -\rSec4[mdspan.layout.stride.overview]{Overview} +\rSec4[mdspan.mdspan.overview]{Overview} \pnum -\tcode{layout_stride} provides a layout mapping -where the strides are user-defined. +\tcode{mdspan} is a view of a multidimensional array of elements. \begin{codeblock} namespace std { - template - class layout_stride::mapping { + template> + class mdspan { public: using extents_type = Extents; + using layout_type = LayoutPolicy; + using accessor_type = AccessorPolicy; + using mapping_type = typename layout_type::template mapping; + using element_type = ElementType; + using value_type = remove_cv_t; 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 data_handle_type = typename accessor_type::data_handle_type; + using reference = typename accessor_type::reference; - private: - static constexpr rank_type @\exposid{rank_}@ = extents_type::rank(); // \expos + static constexpr rank_type rank() noexcept { return extents_type::rank(); } + static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); } + static constexpr size_t static_extent(rank_type r) noexcept + { return extents_type::static_extent(r); } + constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); } - public: - // \ref{mdspan.layout.stride.cons}, constructors - constexpr mapping() noexcept = default; - constexpr mapping(const mapping&) noexcept = default; - template - constexpr mapping(const extents_type&, span) noexcept; - template - constexpr mapping(const extents_type&, const array&) noexcept; + // \ref{mdspan.mdspan.cons}, constructors + constexpr mdspan(); + constexpr mdspan(const mdspan& rhs) = default; + constexpr mdspan(mdspan&& rhs) = default; - template - constexpr explicit(@\seebelow@) mapping(const StridedLayoutMapping&) noexcept; + template + constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts); + template + constexpr explicit(N != rank_dynamic()) + mdspan(data_handle_type p, span exts); + template + constexpr explicit(N != rank_dynamic()) + mdspan(data_handle_type p, const array& exts); + constexpr mdspan(data_handle_type p, const extents_type& ext); + constexpr mdspan(data_handle_type p, const mapping_type& m); + constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a); - constexpr mapping& operator=(const mapping&) noexcept = default; + template + constexpr explicit(@\seebelow@) + mdspan(const mdspan& other); - // \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 mdspan& operator=(const mdspan& rhs) = default; + constexpr mdspan& operator=(mdspan&& rhs) = default; - constexpr index_type required_span_size() const noexcept; + // \ref{mdspan.mdspan.members}, members + template + constexpr reference operator[](OtherIndexTypes... indices) const; + template + constexpr reference operator[](span indices) const; + template + constexpr reference operator[](const array& indices) const; - template - constexpr index_type operator()(Indices...) const noexcept; + constexpr size_type size() const noexcept; + constexpr bool empty() const noexcept; - static constexpr bool is_always_unique() noexcept { return true; } - static constexpr bool is_always_exhaustive() noexcept { return false; } - static constexpr bool is_always_strided() noexcept { return true; } + friend constexpr void swap(mdspan& x, mdspan& y) noexcept; - static constexpr bool is_unique() noexcept { return true; } - constexpr bool is_exhaustive() const noexcept; - static constexpr bool is_strided() noexcept { return true; } + constexpr const extents_type& extents() const noexcept { return @\exposid{map_}@.extents(); } + constexpr const data_handle_type& data_handle() const noexcept { return @\exposid{ptr_}@; } + constexpr const mapping_type& mapping() const noexcept { return @\exposid{map_}@; } + constexpr const accessor_type& accessor() const noexcept { return @\exposid{acc_}@; } - constexpr index_type stride(rank_type i) const noexcept { return @\exposid{strides_}@[i]; } + static constexpr bool is_always_unique() + { return mapping_type::is_always_unique(); } + static constexpr bool is_always_exhaustive() + { return mapping_type::is_always_exhaustive(); } + static constexpr bool is_always_strided() + { return mapping_type::is_always_strided(); } - template - friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept; + constexpr bool is_unique() const + { return @\exposid{map_}@.is_unique(); } + constexpr bool is_exhaustive() const + { return @\exposid{map_}@.is_exhaustive(); } + constexpr bool is_strided() const + { return @\exposid{map_}@.is_strided(); } + constexpr index_type stride(rank_type r) const + { return @\exposid{map_}@.stride(r); } private: - extents_type @\exposid{extents_}@{}; // \expos - array @\exposid{strides_}@{}; // \expos + accessor_type @\exposid{acc_}@; // \expos + mapping_type @\exposid{map_}@; // \expos + data_handle_type @\exposid{ptr_}@; // \expos }; -} -\end{codeblock} -\pnum -If \tcode{Extents} is not a specialization of \tcode{extents}, -then the program is ill-formed. + template + requires (is_array_v && rank_v == 1) + mdspan(CArray&) + -> mdspan, extents>>; -\pnum -\tcode{layout_stride::mapping} is a trivially copyable type -that models \libconcept{regular} for each \tcode{E}. + template + requires (is_pointer_v>) + mdspan(Pointer&&) + -> mdspan>, extents>; + + template + requires ((is_convertible_v && ...) && sizeof...(Integrals) > 0) + explicit mdspan(ElementType*, Integrals...) + -> mdspan...>>; + + template + mdspan(ElementType*, span) + -> mdspan>; -\rSec4[mdspan.layout.stride.expo]{Exposition-only helpers} + template + mdspan(ElementType*, const array&) + -> mdspan>; + + template + mdspan(ElementType*, const extents&) + -> mdspan>; + + template + mdspan(ElementType*, const MappingType&) + -> mdspan; + + template + mdspan(const typename AccessorType::data_handle_type&, const MappingType&, + const AccessorType&) + -> mdspan; +} +\end{codeblock} \pnum -Let \tcode{\exposid{REQUIRED-SPAN-SIZE}(e, strides)} be: +\mandates \begin{itemize} \item -\tcode{1}, if \tcode{e.rank() == 0} is \tcode{true}, +\tcode{ElementType} is a complete object type +that is neither an abstract class type nor an array type, \item -otherwise \tcode{0}, if the size of the multidimensional index space \tcode{e} is 0, +\tcode{Extents} is a specialization of \tcode{extents}, and \item -otherwise \tcode{1} plus the sum of products of \tcode{(e.extent($r$) - 1)} and \tcode{strides[$r$]} -for all $r$ in the range $[0, \tcode{e.rank()})$. +\tcode{is_same_v} +is \tcode{true}. \end{itemize} \pnum -Let \tcode{\exposid{OFFSET}(m)} be: +\tcode{LayoutPolicy} shall meet +the layout mapping policy requirements\iref{mdspan.layout.policy.reqmts}, and +\tcode{AccessorPolicy} shall meet +the accessor policy requirements\iref{mdspan.accessor.reqmts}. + +\pnum +Each specialization \tcode{MDS} of \tcode{mdspan} models \libconcept{copyable} and \begin{itemize} \item -\tcode{m()}, if \tcode{e.rank() == 0} is \tcode{true}, +\tcode{is_nothrow_move_constructible_v} is \tcode{true}, \item -otherwise \tcode{0}, if the size of the multidimensional index space \tcode{e} is 0, +\tcode{is_nothrow_move_assignable_v} is \tcode{true}, and \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. +\tcode{is_nothrow_swappable_v} is \tcode{true}. \end{itemize} \pnum -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} - -\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} +A specialization of \tcode{mdspan} is a trivially copyable type if +its \tcode{accessor_type}, \tcode{mapping_type}, and \tcode{data_handle_type} +are trivially copyable types. -\rSec4[mdspan.layout.stride.cons]{Constructors} +\rSec4[mdspan.mdspan.cons]{Constructors} -\indexlibraryctor{layout_stride::mapping}% +\indexlibraryctor{mdspan}% \begin{itemdecl} -template - constexpr mapping(const extents_type& e, span s) noexcept; -template - constexpr mapping(const extents_type& e, const array& s) noexcept; +constexpr mdspan(); \end{itemdecl} \begin{itemdescr} @@ -19666,111 +24819,80 @@ \constraints \begin{itemize} \item -\tcode{is_convertible_v} is \tcode{true}, and +\tcode{rank_dynamic() > 0} is \tcode{true}. \item -\tcode{is_nothrow_constructible_v} is \tcode{true}. +\tcode{is_default_constructible_v} is \tcode{true}. +\item +\tcode{is_default_constructible_v} is \tcode{true}. +\item +\tcode{is_default_constructible_v} is \tcode{true}. \end{itemize} \pnum \expects -\begin{itemize} -\item -\tcode{s[$i$] > 0} is \tcode{true} -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} +$[0, \tcode{\exposid{map_}.required_span_size()})$ is +an accessible range of \exposid{ptr_} and \exposid{acc_} +for the values of \exposid{map_} and \exposid{acc_} +after the invocation of this constructor. \pnum \effects -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$])}. +Value-initializes \exposid{ptr_}, \exposid{map_}, and \exposid{acc_}. \end{itemdescr} -\indexlibraryctor{layout_stride::mapping}% -\begin{itemdecl} -template - constexpr explicit(@\seebelow@) - mapping(const StridedLayoutMapping& other) noexcept; +\indexlibraryctor{mdspan}% +\begin{itemdecl} +template + constexpr explicit mdspan(data_handle_type p, OtherIndexTypes... exts); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{N} be \tcode{sizeof...(OtherIndexTypes)}. + \pnum \constraints \begin{itemize} \item -\tcode{\exposconcept{layout-mapping-alike}} is satisfied. +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}, \item -\tcode{is_constructible_v} is\\\tcode{true}. +\tcode{(is_nothrow_constructible \&\& ...)} is \tcode{true}, \item -\tcode{StridedLayoutMapping::is_always_unique()} is \tcode{true}. +\tcode{N == rank() || N == rank_dynamic()} is \tcode{true}, \item -\tcode{StridedLayoutMapping::is_always_strided()} is \tcode{true}. +\tcode{is_constructible_v} is \tcode{true}, and +\item +\tcode{is_default_constructible_v} is \tcode{true}. \end{itemize} \pnum \expects +$[0, \tcode{\exposid{map_}.required_span_size()})$ is +an accessible range of \tcode{p} and \exposid{acc_} +for the values of \exposid{map_} and \exposid{acc_} +after the invocation of this constructor. + +\pnum +\effects \begin{itemize} \item -\tcode{StridedLayoutMapping} meets the layout mapping requirements\iref{mdspan.layout.policy.reqmts}, -\item -\tcode{other.stride($r$) > 0} is \tcode{true} -for every rank index $r$ of \tcode{extents()}, +Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)}, \item -\tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}, and +direct-non-list-initializes \exposid{map_} with +\tcode{extents_type(static_cast(std::move(exts\brk{}))...)}, and \item -\tcode{\exposid{OFFSET}(other) == 0} is \tcode{true}. +value-initializes \exposid{acc_}. \end{itemize} - -\pnum -\effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}, and -for all $d$ in the range $[0, \exposid{rank_})$, -direct-non-list-initializes \tcode{\exposid{strides_}[$d$]} -with \tcode{other.stride($d$)}. - -\pnum -Remarks: The expression inside \tcode{explicit} is equivalent to: -\begin{codeblock} -!(is_convertible_v && - (@\exposid{is-mapping-of}@ || - @\exposid{is-mapping-of}@ || - @\exposid{is-mapping-of}@)) -\end{codeblock} -\end{itemdescr} - -\rSec4[mdspan.layout.stride.obs]{Observers} - -\indexlibrarymember{required_span_size}{layout_stride::mapping}% -\begin{itemdecl} -constexpr index_type required_span_size() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{\exposid{REQUIRED-SPAN-SIZE}(extents(), \exposid{strides_})}. \end{itemdescr} -\indexlibrarymember{operator()}{layout_stride::mapping}% +\indexlibraryctor{mdspan}% \begin{itemdecl} -template - constexpr index_type operator()(Indices... i) const noexcept; +template + constexpr explicit(N != rank_dynamic()) + mdspan(data_handle_type p, span exts); +template + constexpr explicit(N != rank_dynamic()) + mdspan(data_handle_type p, const array& exts); \end{itemdecl} \begin{itemdescr} @@ -19778,58 +24900,39 @@ \constraints \begin{itemize} \item -\tcode{sizeof...(Indices) == \exposid{rank_}} is \tcode{true}, +\tcode{is_convertible_v} is \tcode{true}, \item -\tcode{(is_convertible_v \&\& ...)} is \tcode{true}, and +\tcode{is_nothrow_constructible_v} is \tcode{true}, \item -\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}. +\tcode{N == rank() || N == rank_dynamic()} is \tcode{true}, +\item +\tcode{is_constructible_v} is \tcode{true}, and +\item +\tcode{is_default_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}. +$[0, \tcode{\exposid{map_}.required_span_size()})$ is +an accessible range of \tcode{p} and \exposid{acc_} +for the values of \exposid{map_} and \exposid{acc_} +after the invocation of this constructor. \pnum \effects -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{is_exhaustive}{layout_stride::mapping}% -\begin{itemdecl} -constexpr bool is_exhaustive() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \begin{itemize} \item -\tcode{true} if \exposid{rank_} is 0. +Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)}, \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$. +direct-non-list-initializes \exposid{map_} with \tcode{extents_type(exts)}, and \item -Otherwise, \tcode{false}. +value-initializes \exposid{acc_}. \end{itemize} \end{itemdescr} -\indexlibrarymember{operator==}{layout_stride::mapping}% +\indexlibraryctor{mdspan}% \begin{itemdecl} -template - friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept; +constexpr mdspan(data_handle_type p, const extents_type& ext); \end{itemdecl} \begin{itemdescr} @@ -19837,817 +24940,1149 @@ \constraints \begin{itemize} \item -\tcode{\exposconcept{layout-mapping-alike}} is satisfied. -\item -\tcode{\exposid{rank_} == OtherMapping::extents_type::rank()} is \tcode{true}. +\tcode{is_constructible_v} is \tcode{true}, and \item -\tcode{OtherMapping::is_always_strided()} is \tcode{true}. +\tcode{is_default_constructible_v} is \tcode{true}. \end{itemize} \pnum \expects -\tcode{OtherMapping} meets the layout mapping requirements\iref{mdspan.layout.policy.reqmts}. +$[0, \tcode{\exposid{map_}.required_span_size()})$ is +an accessible range of \tcode{p} and \exposid{acc_} +for the values of \exposid{map_} and \exposid{acc_} +after the invocation of this constructor. \pnum -\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}. +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)}, +\item +direct-non-list-initializes \exposid{map_} with \tcode{ext}, and +\item +value-initializes \exposid{acc_}. +\end{itemize} \end{itemdescr} -\rSec2[mdspan.accessor]{Accessor policy} - -\rSec3[mdspan.accessor.general]{General} +\indexlibraryctor{mdspan}% +\begin{itemdecl} +constexpr mdspan(data_handle_type p, const mapping_type& m); +\end{itemdecl} +\begin{itemdescr} \pnum -An \defn{accessor policy} defines types and operations by which -a reference to a single object is created -from an abstract data handle to a number of such objects and an index. +\constraints +\tcode{is_default_constructible_v} is \tcode{true}. \pnum -A range of indices $[0, N)$ is an \defnadj{accessible}{range} of -a given data handle and an accessor -if, for each $i$ in the range, -the accessor policy's \tcode{access} function produces a valid reference to an object. +\expects +$[0, \tcode{m.required_span_size()})$ is +an accessible range of \tcode{p} and \exposid{acc_} +for the value of \exposid{acc_} after the invocation of this constructor. \pnum -In subclause \ref{mdspan.accessor.reqmts}, - +\effects \begin{itemize} \item -\tcode{A} denotes an accessor policy. -\item -\tcode{a} denotes a value of type \tcode{A} or \tcode{const A}. +Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)}, \item -\tcode{p} denotes a value of type \tcode{A::data_handle_type} or \tcode{const A::data_handle_type}. -\begin{note} -The type \tcode{A::data_handle_type} need not be dereferenceable. -\end{note} +direct-non-list-initializes \exposid{map_} with \tcode{m}, and \item -\tcode{n}, \tcode{i}, and \tcode{j} each denote values of type \tcode{size_t}. +value-initializes \exposid{acc_}. \end{itemize} +\end{itemdescr} -\rSec3[mdspan.accessor.reqmts]{Requirements} +\indexlibraryctor{mdspan}% +\begin{itemdecl} +constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a); +\end{itemdecl} +\begin{itemdescr} \pnum -A type \tcode{A} meets the accessor policy requirements if +\expects +$[0, \tcode{m.required_span_size()})$ is +an accessible range of \tcode{p} and \tcode{a}. + +\pnum +\effects \begin{itemize} \item -\tcode{A} models \libconcept{copyable}, -\item -\tcode{is_nothrow_move_constructible_v} is \tcode{true}, -\item -\tcode{is_nothrow_move_assignable_v} is \tcode{true}, +Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)}, \item -\tcode{is_nothrow_swappable_v} is \tcode{true}, and +direct-non-list-initializes \exposid{map_} with \tcode{m}, and \item -the following types and expressions -are well-formed and have the specified semantics. +direct-non-list-initializes \exposid{acc_} with \tcode{a}. \end{itemize} - -\begin{itemdecl} -typename A::element_type -\end{itemdecl} - -\begin{itemdescr} -\pnum -\result -A complete object type that is not an abstract class type. \end{itemdescr} +\indexlibraryctor{mdspan}% \begin{itemdecl} -typename A::data_handle_type +template + constexpr explicit(@\seebelow@) + mdspan(const mdspan& other); \end{itemdecl} \begin{itemdescr} \pnum -\result -A type that models \libconcept{copyable}, and -for which \tcode{is_nothrow_move_constructible_v} is \tcode{true}, -\tcode{is_nothrow_move_assignable_v} is \tcode{true}, and -\tcode{is_nothrow_swappable_v} is \tcode{true}. -\begin{note} -The type of \tcode{data_handle_type} need not be \tcode{element_type*}. -\end{note} -\end{itemdescr} - -\begin{itemdecl} -typename A::reference -\end{itemdecl} +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v\&>} +is \tcode{true}, and +\item +\tcode{is_constructible_v} is \tcode{true}. +\end{itemize} -\begin{itemdescr} \pnum -\result -A type that models -\tcode{\libconcept{common_reference_with}}. -\begin{note} -The type of \tcode{reference} need not be \tcode{element_type\&}. -\end{note} -\end{itemdescr} - -\begin{itemdecl} -typename A::offset_policy -\end{itemdecl} +\mandates +\begin{itemize} +\item +\tcode{is_constructible_v} is\newline \tcode{true}, and +\item +\tcode{is_constructible_v} is \tcode{true}. +\end{itemize} -\begin{itemdescr} \pnum -\result -A type \tcode{OP} such that: +\expects +$[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 -\tcode{OP} meets the accessor policy requirements, +Direct-non-list-initializes \exposid{ptr_} with \tcode{other.\exposid{ptr_}}, \item -\tcode{\libconcept{constructible_from}} is modeled, and +direct-non-list-initializes \exposid{map_} with \tcode{other.\exposid{map_}}, and \item -\tcode{is_same_v} is \tcode{true}. +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} -a.access(p, i) +template + constexpr reference operator[](OtherIndexTypes... indices) const; \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{A::reference} +\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 -\remarks -The expression is equality preserving. +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} -Concrete accessor policies can impose preconditions for their \tcode{access} function. -However, they might not. -For example, an accessor where -\tcode{p} is \tcode{span} and -\tcode{access(p, i)} returns \tcode{p[i \% p.size()]} -does not need to impose a precondition on \tcode{i}. +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} -a.offset(p, i) +template + constexpr reference operator[](span indices) const; +template + constexpr reference operator[](const array& indices) const; \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{A::offset_policy::data_handle_type} - -\pnum -\returns -\tcode{q} such that for \tcode{b} being \tcode{A::offset_policy(a)}, and -any integer \tcode{n} for which $[0, \tcode{n})$ is -an accessible range of \tcode{p} and \tcode{a}: +\constraints \begin{itemize} \item -$[0, \tcode{n} - \tcode{i})$ is an accessible range of \tcode{q} and \tcode{b}; and +\tcode{is_convertible_v} is \tcode{true}, and \item -\tcode{b.access(q, j)} provides access to -the same element as \tcode{a.access(p, i + j)}, -for every \tcode{j} in the range $[0, \tcode{n} - \tcode{i})$. +\tcode{is_nothrow_constructible_v} is \tcode{true}. \end{itemize} \pnum -\remarks -The expression is equality-preserving. -\end{itemdescr} - -\rSec3[mdspan.accessor.default]{Class template \tcode{default_accessor}} - -\rSec4[mdspan.accessor.default.overview]{Overview} - +\effects +Let \tcode{P} be a parameter pack such that \begin{codeblock} -namespace std { - template - struct default_accessor { - using offset_policy = default_accessor; - using element_type = ElementType; - using reference = ElementType&; - using data_handle_type = ElementType*; - - constexpr default_accessor() noexcept = default; - template - constexpr default_accessor(default_accessor) noexcept; - constexpr reference access(data_handle_type p, size_t i) const noexcept; - constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept; - }; -} +is_same_v, index_sequence> \end{codeblock} - -\pnum -\tcode{default_accessor} meets the accessor policy requirements. - -\pnum -\tcode{ElementType} is required to be a complete object type -that is neither an abstract class type nor an array type. - -\pnum -Each specialization of \tcode{default_accessor} is -a trivially copyable type that models \libconcept{semiregular}. - -\pnum -$[0, n)$ is an accessible range for -an object \tcode{p} of type \tcode{data_handle_type} and -an object of type \tcode{default_accessor} -if and only if \range{p}{p + $n$} is a valid range. - -\rSec4[mdspan.accessor.default.members]{Members} - -\indexlibraryctor{default_accessor}% -\begin{itemdecl} -template - constexpr default_accessor(default_accessor) noexcept {} -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_convertible_v} is \tcode{true}. +Equivalent to: +\begin{codeblock} +return operator[](extents_type::@\exposid{index-cast}@(as_const(indices[P]))...); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{access}{default_accessor}% +\indexlibrarymember{size}{mdspan}% \begin{itemdecl} -constexpr reference access(data_handle_type p, size_t i) const noexcept; +constexpr size_type size() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return p[i];} +\expects +The size of the multidimensional index space \tcode{extents()} +is representable as a value of type \tcode{size_type}\iref{basic.fundamental}. + +\pnum +\returns +\tcode{extents().\exposid{fwd-prod-of-extents}(rank())}. \end{itemdescr} -\indexlibrarymember{offset}{default_accessor}% +\indexlibrarymember{empty}{mdspan}% \begin{itemdecl} -constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept; +constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return p + i;} +\returns +\tcode{true} +if the size of the multidimensional index space \tcode{extents()} is 0, +otherwise \tcode{false}. \end{itemdescr} -\rSec2[mdspan.mdspan]{Class template \tcode{mdspan}} - -\rSec3[mdspan.mdspan.overview]{Overview} - -\pnum -\tcode{mdspan} is a view of a multidimensional array of elements. - -\begin{codeblock} -namespace std { - template - class mdspan { - public: - using extents_type = Extents; - using layout_type = LayoutPolicy; - using accessor_type = AccessorPolicy; - using mapping_type = typename layout_type::template mapping; - using element_type = ElementType; - using value_type = remove_cv_t; - using index_type = typename extents_type::index_type; - using size_type = typename extents_type::size_type; - using rank_type = typename extents_type::rank_type; - using data_handle_type = typename accessor_type::data_handle_type; - using reference = typename accessor_type::reference; - - static constexpr rank_type rank() noexcept { return extents_type::rank(); } - static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); } - static constexpr size_t static_extent(rank_type r) noexcept - { return extents_type::static_extent(r); } - constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); } - - // \ref{mdspan.mdspan.cons}, constructors - constexpr mdspan(); - constexpr mdspan(const mdspan& rhs) = default; - constexpr mdspan(mdspan&& rhs) = default; - - template - constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts); - template - constexpr explicit(N != rank_dynamic()) - mdspan(data_handle_type p, span exts); - template - constexpr explicit(N != rank_dynamic()) - mdspan(data_handle_type p, const array& exts); - constexpr mdspan(data_handle_type p, const extents_type& ext); - constexpr mdspan(data_handle_type p, const mapping_type& m); - constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a); - - template - constexpr explicit(@\seebelow@) - mdspan(const mdspan& other); - - constexpr mdspan& operator=(const mdspan& rhs) = default; - constexpr mdspan& operator=(mdspan&& rhs) = default; - - // \ref{mdspan.mdspan.members}, members - template - constexpr reference operator[](OtherIndexTypes... indices) const; - template - constexpr reference operator[](span indices) const; - template - constexpr reference operator[](const array& indices) const; - - constexpr size_type size() const noexcept; - [[nodiscard]] constexpr bool empty() const noexcept; - - friend constexpr void swap(mdspan& x, mdspan& y) noexcept; - - constexpr const extents_type& extents() const noexcept { return @\exposid{map_}@.extents(); } - constexpr const data_handle_type& data_handle() const noexcept { return @\exposid{ptr_}@; } - constexpr const mapping_type& mapping() const noexcept { return @\exposid{map_}@; } - constexpr const accessor_type& accessor() const noexcept { return @\exposid{acc_}@; } - - static constexpr bool is_always_unique() - { return mapping_type::is_always_unique(); } - static constexpr bool is_always_exhaustive() - { return mapping_type::is_always_exhaustive(); } - static constexpr bool is_always_strided() - { return mapping_type::is_always_strided(); } - - constexpr bool is_unique() const - { return @\exposid{map_}@.is_unique(); } - constexpr bool is_exhaustive() const - { return @\exposid{map_}@.is_exhaustive(); } - constexpr bool is_strided() const - { return @\exposid{map_.}@is_strided(); } - constexpr index_type stride(rank_type r) const - { return @\exposid{map_}@.stride(r); } - - private: - accessor_type @\exposid{acc_}@; // \expos - mapping_type @\exposid{map_}@; // \expos - data_handle_type @\exposid{ptr_}@; // \expos - }; +\indexlibrarymember{swap}{mdspan}% +\begin{itemdecl} +friend constexpr void swap(mdspan& x, mdspan& y) noexcept; +\end{itemdecl} - template - requires(is_array_v && rank_v == 1) - mdspan(CArray&) - -> mdspan, extents>>; +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +swap(x.@\exposid{ptr_}@, y.@\exposid{ptr_}@); +swap(x.@\exposid{map_}@, y.@\exposid{map_}@); +swap(x.@\exposid{acc_}@, y.@\exposid{acc_}@); +\end{codeblock} +\end{itemdescr} - template - requires(is_pointer_v>) - mdspan(Pointer&&) - -> mdspan>, extents>; +\rSec3[mdspan.sub]{\tcode{submdspan}} - template - requires((is_convertible_v && ...) && sizeof...(Integrals) > 0) - explicit mdspan(ElementType*, Integrals...) - -> mdspan>; +\rSec4[mdspan.sub.overview]{Overview} - template - mdspan(ElementType*, span) - -> mdspan>; +\pnum +The \tcode{submdspan} facilities create a new \tcode{mdspan} +viewing a subset of elements of an existing input \tcode{mdspan}. +The subset viewed by the created \tcode{mdspan} is determined by +the \tcode{SliceSpecifier} arguments. - template - mdspan(ElementType*, const array&) - -> mdspan>; +\pnum +For each function defined in \ref{mdspan.sub} that +takes a parameter pack named \tcode{slices} as an argument: - template - mdspan(ElementType*, const extents&) - -> mdspan>; +\begin{itemize} +\item let \tcode{index_type} be + \begin{itemize} + \item + \tcode{M::index_type} + if the function is a member of a class \tcode{M}, + \item + otherwise, + \tcode{remove_reference_t::index_type} + if the function has a parameter named \tcode{src}, + \item + otherwise, + the same type as the function's template argument \tcode{IndexType}; + \end{itemize} +\item let \tcode{rank} be the number of elements in \tcode{slices}; +\item let $s_k$ be the $k^\text{th}$ element of \tcode{slices}; +\item let $S_k$ be the type of $s_k$; and +\item let \tcode{\placeholder{map-rank}} be an \tcode{array} such that +for each $k$ in the range \range{0}{rank}, +\tcode{\placeholder{map-rank}[$k$]} equals: + \begin{itemize} + \item + \tcode{dynamic_extent} + if $S_k$ models \tcode{\libconcept{convertible_to}}, + \item + otherwise, + the number of types $S_j$ with $j < k$ that + do not model \tcode{\libconcept{convertible_to}}. + \end{itemize} +\end{itemize} - template - mdspan(ElementType*, const MappingType&) - -> mdspan; +\rSec4[mdspan.sub.strided.slice]{\tcode{strided_slice}} - template - mdspan(const typename AccessorType::data_handle_type&, const MappingType&, - const AccessorType&) - -> mdspan; +\pnum +\tcode{strided_slice} represents a set of +\tcode{extent} regularly spaced integer indices. +The indices start at \tcode{offset}, and +increase by increments of \tcode{stride}. + +\indexlibraryglobal{strided_slice}% +\begin{codeblock} +namespace std { + template + struct strided_slice { + using offset_type = OffsetType; + using extent_type = ExtentType; + using stride_type = StrideType; + + [[no_unique_address]] offset_type offset{}; + [[no_unique_address]] extent_type extent{}; + [[no_unique_address]] stride_type stride{}; + }; } \end{codeblock} +\pnum +\tcode{strided_slice} has the data members and special members specified above. +It has no base classes or members other than those specified. + \pnum \mandates -\begin{itemize} -\item -\tcode{ElementType} is a complete object type -that is neither an abstract class type nor an array type, -\item -\tcode{Extents} is a specialization of \tcode{extents}, and -\item -\tcode{is_same_v} -is \tcode{true}. -\end{itemize} +\tcode{OffsetType}, \tcode{ExtentType}, and \tcode{StrideType} +are signed or unsigned integer types, or +model \exposconcept{integral-constant-like}. +\begin{note} +\tcode{strided_slice\{.offset = 1, .extent = 10, .stride = 3\}} +indicates the indices \tcode{1}, \tcode{4}, \tcode{7}, and \tcode{10}. +Indices are selected from the half-open interval \range{1}{1 + 10}. +\end{note} + +\rSec4[mdspan.sub.map.result]{\tcode{submdspan_mapping_result}} \pnum -\tcode{LayoutPolicy} shall meet -the layout mapping policy requirements\iref{mdspan.layout.policy.reqmts}, and -\tcode{AccessorPolicy} shall meet -the accessor policy requirements\iref{mdspan.accessor.reqmts}. +Specializations of \tcode{submdspan_mapping_result} +are returned by overloads of \tcode{submdspan_mapping}. + +\indexlibraryglobal{submdspan_mapping_result}% +\begin{codeblock} +namespace std { + template + struct submdspan_mapping_result { + [[no_unique_address]] LayoutMapping mapping = LayoutMapping(); + size_t offset{}; + }; +} +\end{codeblock} \pnum -Each specialization \tcode{MDS} of \tcode{mdspan} models \libconcept{copyable} and -\begin{itemize} -\item -\tcode{is_nothrow_move_constructible_v} is \tcode{true}, -\item -\tcode{is_nothrow_move_assignable_v} is \tcode{true}, and -\item -\tcode{is_nothrow_swappable_v} is \tcode{true}. -\end{itemize} +\tcode{submdspan_mapping_result} has +the data members and special members specified above. +It has no base classes or members other than those specified. \pnum -A specialization of \tcode{mdspan} is a trivially copyable type if -its \tcode{accessor_type}, \tcode{mapping_type}, and \tcode{data_handle_type} -are trivially copyable types. +\tcode{LayoutMapping} shall meet +the layout mapping requirements\iref{mdspan.layout.policy.reqmts}. -\rSec3[mdspan.mdspan.cons]{Constructors} +\rSec4[mdspan.sub.helpers]{Exposition-only helpers} -\indexlibraryctor{mdspan}% +\indexlibraryglobal{\exposid{de-ice}}% +\indexlibraryglobal{\exposid{first_}}% \begin{itemdecl} -constexpr mdspan(); +template + constexpr T @\exposid{de-ice}@(T val) { return val; } +template<@\exposconcept{integral-constant-like}@ T> + constexpr auto @\exposid{de-ice}@(T) { return T::value; } + +template + constexpr IndexType @\exposid{first_}@(SliceSpecifiers... slices); \end{itemdecl} \begin{itemdescr} \pnum -\constraints +\mandates +\tcode{IndexType} is a signed or unsigned integer type. + +%FIXME: What is $k$ in this itemdescr? Did we mean the \tcode{k} passed to first_? If so, what do we do for de-ice? +\pnum +Let $\phi{}_k$ denote the following value: \begin{itemize} \item -\tcode{rank_dynamic() > 0} is \tcode{true}. +$s_k$ if $S_k$ models \tcode{\libconcept{convertible_to}}; \item -\tcode{is_default_constructible_v} is \tcode{true}. +otherwise, +\tcode{get<0>($s_k$)} +if $S_k$ models \tcode{\exposconcept{index-pair-like}}; \item -\tcode{is_default_constructible_v} is \tcode{true}. +otherwise, +\tcode{\exposid{de-ice}($s_k$.offset)} +if $S_k$ is a specialization of \tcode{strided_slice}; \item -\tcode{is_default_constructible_v} is \tcode{true}. +otherwise, +\tcode{0}. \end{itemize} \pnum \expects -$[0, \tcode{\exposid{map_}.required_span_size()})$ is -an accessible range of \exposid{ptr_} and \exposid{acc_} -for the values of \exposid{map_} and \exposid{acc_} -after the invocation of this constructor. +$\phi{}_k$ is representable as a value of type \tcode{IndexType}. \pnum -\effects -Value-initializes \exposid{ptr_}, \exposid{map_}, and \exposid{acc_}. +\returns +\tcode{extents::\exposid{index-cast}($\phi{}_k$)}. \end{itemdescr} -\indexlibraryctor{mdspan}% +\indexlibraryglobal{\exposid{last_}}% \begin{itemdecl} -template - constexpr explicit mdspan(data_handle_type p, OtherIndexTypes... exts); +template + constexpr auto @\exposid{last_}@(const Extents& src, SliceSpecifiers... slices); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{N} be \tcode{sizeof...(OtherIndexTypes)}. +\mandates +\tcode{Extents} is a specialization of \tcode{extents}. \pnum -\constraints +Let \tcode{index_type} be \tcode{typename Extents::index_type}. + +%FIXME: What is $k$ in this itemdescr? Don't we want \tcode{k} and not $k$? +\pnum +Let $\lambda{}_k$ denote the following value: \begin{itemize} \item -\tcode{(is_convertible_v \&\& ...)} is \tcode{true}, -\item -\tcode{(is_nothrow_constructible \&\& ...)} is \tcode{true}, +\tcode{\exposid{de-ice}($s_k$) + 1} +if $S_k$ models \tcode{\libconcept{convertible_to}}; otherwise \item -\tcode{N == rank() || N == rank_dynamic()} is \tcode{true}, +\tcode{get<1>($s_k$)} +if $S_k$ models \tcode{\exposconcept{index-pair-like}}; otherwise \item -\tcode{is_constructible_v} is \tcode{true}, and +\tcode{\exposid{de-ice}($s_k$.offset)} \tcode{+} +\tcode{\exposid{de-ice}($s_k$.extent)} +if $S_k$ is a specialization of \tcode{strided_slice}; otherwise \item -\tcode{is_default_constructible_v} is \tcode{true}. +%FIXME: Note that the paper uses \tcode{k} here. +\tcode{src.extent(k)}. \end{itemize} \pnum \expects -$[0, \tcode{\exposid{map_}.required_span_size()})$ is -an accessible range of \tcode{p} and \exposid{acc_} -for the values of \exposid{map_} and \exposid{acc_} -after the invocation of this constructor. +$\lambda{}_k$ is representable as a value of type \tcode{index_type}. \pnum -\effects +\returns +\tcode{Extents::\exposid{index-cast}($\lambda{}_k$)}. +\end{itemdescr} + +\indexlibraryglobal{\exposid{src-indices}}% +\begin{itemdecl} +template + constexpr array + @\exposid{src-indices}@(const array& indices, SliceSpecifiers... slices); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{IndexType} is a signed or unsigned integer type. + +\pnum +\returns +An \tcode{array src_idx} such that +for each $k$ in the range \range{0}{sizeof...(SliceSpecifiers)}, +\tcode{src_idx[$k$]} equals + \begin{itemize} \item -Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)}, -\item -direct-non-list-initializes \exposid{map_} with -\tcode{extents_type(static_cast(std::move(exts\brk{}))...)}, and +%FIXME: We're redefining what $k$ is here. +%FIXME: Also, calling first_ on each $k$ below gives us a set of indeces - how do we assign a set to the src_idx[$k$] above? +\tcode{\exposid{first_}(slices...)} for each $k$ +where \tcode{\placeholder{map-rank}[$k$]} equals +\tcode{dynamic_extent}, + \item -value-initializes \exposid{acc_}. +%FIXME: How do we fail the previous \item to get here? There's no "if" test to fail. +otherwise, +\tcode{\exposid{first_}(slices...)} \tcode{+} +\tcode{indices[\placeholder{map-rank}[$k$]]}. \end{itemize} \end{itemdescr} -\indexlibraryctor{mdspan}% +\rSec4[mdspan.sub.extents]{\tcode{submdspan_extents} function} + +\indexlibraryglobal{submdspan_extents}% \begin{itemdecl} -template - constexpr explicit(N != rank_dynamic()) - mdspan(data_handle_type p, span exts); -template - constexpr explicit(N != rank_dynamic()) - mdspan(data_handle_type p, const array& exts); +template + constexpr auto submdspan_extents(const extents& src, + SliceSpecifiers... slices); \end{itemdecl} \begin{itemdescr} \pnum \constraints +\tcode{sizeof...(slices)} equals \tcode{Extents::rank()}. + +\pnum +\mandates +For each rank index $k$ of \tcode{src.extents()}, +exactly one of the following is true: +\begin{itemize} +\item $S_k$ models \tcode{\libconcept{convertible_to}}, +\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 +\expects +For each rank index $k$ of \tcode{src.extents()}, +all of the following are \tcode{true}: \begin{itemize} \item -\tcode{is_convertible_v} is \tcode{true}, -\item -\tcode{(is_nothrow_constructible \&\& ...)} is \tcode{true}, +if $S_k$ is a specialization of \tcode{strided_slice} + \begin{itemize} + \item $\tcode{$s_k$.extent} = 0$, or + \item $\tcode{$s_k$.stride} > 0$ + \end{itemize} \item -\tcode{N == rank() || N == rank_dynamic()} is \tcode{true}, +$0 \le \tcode{\exposid{first_}(slices...)}$ +$\le \tcode{\exposid{last_}<$k$>(src, slices...)}$ +$\le \tcode{src.extent($k$)}$ +\end{itemize} + +\pnum +Let \tcode{SubExtents} be a specialization of \tcode{extents} such that: + +\begin{itemize} \item -\tcode{is_constructible_v} is \tcode{true}, and +%FIXME: I think we want the count here, "number" is ambiguous. +\tcode{SubExtents::rank()} equals the number of $k$ such that +$S_k$ does not model \tcode{\libconcept{convertible_to}}; and + \item -\tcode{is_default_constructible_v} is \tcode{true}. +for each rank index $k$ of \tcode{Extents} such that +\tcode{\placeholder{map-rank}[$k$] != dynamic_extent} is \tcode{true}, +\tcode{SubExt\-ents::static_extent(\placeholder{map-rank}[$k$])} equals: + + \begin{itemize} + \item + \tcode{Extents::static_extent($k$)} + if \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; + otherwise + + \item + \tcode{\exposid{de-ice}(tuple_element_t<1, $S_k$>()) -} + \tcode{\exposid{de-ice}(tuple_element_t<0, $S_k$>())} + if $S_k$ models \tcode{\exposconcept{index-pair-like}}, and + both \tcode{tuple_element_t<0, $S_k$>} and + \tcode{tuple_elem\-ent_t<1, $S_k$>} + model \exposconcept{integral-constant-like}; otherwise + + \item + \tcode{0}, + if $S_k$ is a specialization of \tcode{strided_slice}, whose + \tcode{extent_type} models \exposconceptx{integral-cons\-tant-like}{integral-constant-like}, + for which \tcode{extent_type()} equals zero; otherwise + + \item + \tcode{1 + (\exposid{de-ice}($S_k$::extent_type()) - 1) /} + \tcode{\exposid{de-ice}($S_k$::stride_type())}, + if $S_k$ is a specialization of \tcode{strided_slice} whose + \tcode{extent_type} and \tcode{stride_type} + model \exposconceptx{integral-cons\-tant-like}{integral-constant-like}; + + \item + otherwise, + \tcode{dynamic_extent}. + \end{itemize} \end{itemize} \pnum -\expects -$[0, \tcode{\exposid{map_}.required_span_size()})$ is -an accessible range of \tcode{p} and \exposid{acc_} -for the values of \exposid{map_} and \exposid{acc_} -after the invocation of this constructor. +\returns +A value \tcode{ext} of type \tcode{SubExtents} such that +for each $k$ +for which \tcode{\placeholder{map-rank}[$k$] != dynamic_extent} is \tcode{true}, +\tcode{ext.extent(\placeholder{map-rank}[$k$])} equals: -\pnum -\effects \begin{itemize} \item -Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)}, -\item -direct-non-list-initializes \exposid{map_} with \tcode{extents_type(exts)}, and +\tcode{$s_k$.extent == 0 ? 0 : 1 + (\exposid{de-ice}($s_k$.extent) - 1) / \exposid{de-ice}($s_k$.stride)} +if $S_k$ is a specialization of \tcode{strided_slice}, + \item -value-initializes \exposid{acc_}. +otherwise, +\tcode{\exposid{last_}<$k$>(src, slices...) - \exposid{first_}(slices...)}. \end{itemize} \end{itemdescr} -\indexlibraryctor{mdspan}% -\begin{itemdecl} -constexpr mdspan(data_handle_type p, const extents_type& ext); -\end{itemdecl} +\rSec4[mdspan.sub.map]{Specializations of \tcode{submdspan_mapping}} + +\rSec5[mdspan.sub.map.common]{Common} + +\pnum +The following elements apply to all functions in \ref{mdspan.sub.map}. -\begin{itemdescr} \pnum \constraints +\tcode{sizeof...(slices)} equals \tcode{extents_type::rank()}. + +\pnum +\mandates +For each rank index $k$ of \tcode{extents()}, +exactly one of the following is true: \begin{itemize} \item -\tcode{is_constructible_v} is \tcode{true}, and +$S_k$ models \tcode{\libconcept{convertible_to}}, \item -\tcode{is_default_constructible_v} is \tcode{true}. +$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 \expects -$[0, \tcode{\exposid{map_}.required_span_size()})$ is -an accessible range of \tcode{p} and \exposid{acc_} -for the values of \exposid{map_} and \exposid{acc_} -after the invocation of this constructor. +For each rank index $k$ of \tcode{extents()}, +all of the following are \tcode{true}: +\begin{itemize} +\item +if $S_k$ is a specialization of \tcode{strided_slice}, +\tcode{$s_k$.extent} is equal to zero or +\tcode{$s_k$.stride} is greater than zero; and +\item +$0 \leq \tcode{\exposid{first_}(slices...)} \\ +\hphantom{0 } \leq \tcode{\exposid{last_}<$k$>(extents(), slices...)} \\ +\hphantom{0 } \leq \tcode{extents().extent($k$)}$ +\end{itemize} \pnum -\effects +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{\exposid{map-rank}[$k$]} is not \tcode{dynamic_extent}, +\tcode{sub_strides[\exposid{map-rank}[$k$]]} equals: +\begin{itemize} +\item +\tcode{stride(k) * \exposid{de-ice}($s_k$.stride)} +if $S_k$ is a specialization of \tcode{strided_slice} and +\tcode{$s_k$.stride < $s_k$.\linebreak extent} is \tcode{true}; +\item +otherwise, \tcode{stride($k$)}. +\end{itemize} + +\pnum +Let \tcode{P} be a parameter pack +such that \tcode{is_same_v, index_sequence>} +is \tcode{true}. + +\pnum +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 + 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$ 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 -Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)}, +$S_0$ is a unit-stride slice for \tcode{mapping}; and \item -direct-non-list-initializes \exposid{map_} with \tcode{ext}, and +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 -value-initializes \exposid{acc_}. +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} -\indexlibraryctor{mdspan}% +\rSec5[mdspan.sub.map.right]{\tcode{layout_right} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_right::mapping}{submdspan-mapping-impl}% \begin{itemdecl} -constexpr mdspan(data_handle_type p, const mapping_type& m); +template +template +constexpr auto layout_right::mapping::@\exposid{submdspan-mapping-impl}@( + SliceSpecifiers... slices) const -> @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_default_constructible_v} is \tcode{true}. - -\pnum -\expects -$[0, \tcode{m.required_span_size()})$ is -an accessible range of \tcode{p} and \exposid{acc_} -for the value of \exposid{acc_} after the invocation of this constructor. - -\pnum -\effects +\returns \begin{itemize} \item -Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)}, +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{Extents::rank() == 0} is \tcode{true}; \item -direct-non-list-initializes \exposid{map_} with \tcode{m}, and +otherwise, +\tcode{submdspan_mapping_result\{layout_right::mapping(sub_ext), offset\}}, +if \tcode{Sub\-Extents::rank() == 0} is \tcode{true}; \item -value-initializes \exposid{acc_}. +otherwise, +\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}}, +if + \begin{itemize} + \item + for each $k$ in the range \range{\exposid{rank_} - SubExtents::rank() + 1}{\exposid{rank_}}, + \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and + \item + for $k$ equal to \exposid{_rank} - \tcode{SubExtents::rank()}, + $S_k$ is a unit-stride slice for \tcode{mapping}; + \end{itemize} +\begin{note} +If the above conditions are true, +all $S_k$ with $k < \tcode{\exposid{_rank} - SubExtents::rank()}$ +are convertible to \tcode{index_type}. +\end{note} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_right_padded::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} -\indexlibraryctor{mdspan}% +\rSec5[mdspan.sub.map.stride]{\tcode{layout_stride} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_stride::mapping}{submdspan-mapping-impl}% \begin{itemdecl} -constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a); +template +template +constexpr auto layout_stride::mapping::@\exposid{submdspan-mapping-impl}@( + SliceSpecifiers... slices) const -> @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\expects -$[0, \tcode{m.required_span_size()})$ is -an accessible range of \tcode{p} and \tcode{a}. - -\pnum -\effects +\returns \begin{itemize} \item -Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)}, -\item -direct-non-list-initializes \exposid{map_} with \tcode{m}, and +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{Extents::rank() == 0} is \tcode{true}; \item -direct-non-list-initializes \exposid{acc_} with \tcode{a}. +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} +\end{codeblock} \end{itemize} \end{itemdescr} -\indexlibraryctor{mdspan}% +\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 - constexpr explicit(@\seebelow@) - mdspan(const mdspan& other); +template +template +constexpr auto layout_left_padded::mapping::@\exposid{submdspan-mapping-impl}@( + SliceSpecifiers... slices) const -> @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\constraints +\returns \begin{itemize} \item -\tcode{is_constructible_v\&>} -is \tcode{true}, and +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{Extents::rank() == 0} is \tcode{true}; \item -\tcode{is_constructible_v} is \tcode{true}. -\end{itemize} - -\pnum -\mandates +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{is_constructible_v} is\newline \tcode{true}, and +\tcode{SubExtents::rank() == 1} is \tcode{true} and \item -\tcode{is_constructible_v} is \tcode{true}. +$S_0$ is a unit-stride slice for \tcode{mapping}; \end{itemize} - -\pnum -\expects +\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 -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}. +$S_0$ is a unit-stride slice for \tcode{mapping}; and \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. +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} - -\pnum -\effects +where \tcode{S_static} is: \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{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 -direct-non-list-initializes \exposid{acc_} with \tcode{other.\exposid{acc_}}. +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} - -\pnum -\remarks -The expression inside \tcode{explicit} is equivalent to: +\item +otherwise, \begin{codeblock} -!is_convertible_v&, mapping_type> -|| !is_convertible_v +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} \end{codeblock} +\end{itemize} \end{itemdescr} -\rSec3[mdspan.mdspan.members]{Members} +\rSec5[mdspan.sub.map.rightpad]{\tcode{layout_right_padded} specialization of \tcode{submdspan_mapping}} -\indexlibrarymember{operator[]}{mdspan}% +\indexlibrarymemberexpos{layout_right_padded::mapping}{submdspan-mapping-impl}% \begin{itemdecl} -template - constexpr reference operator[](OtherIndexTypes... indices) const; +template +template +constexpr auto layout_right_padded::mapping::submdspan-mapping-impl( + SliceSpecifiers... slices) const -> @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\constraints +\returns \begin{itemize} \item -\tcode{(is_convertible_v \&\& ...)} is \tcode{true}, +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{\exposid{rank_} == 0} is \tcode{true}; \item -\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}, and +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 -\tcode{sizeof...(OtherIndexTypes) == rank()} is \tcode{true}. +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} - -\pnum -Let \tcode{I} be \tcode{extents_type::\exposid{index-cast}(std::move(indices))}. - -\pnum -\expects -\tcode{I} is a multidimensional index in \tcode{extents()}. -\begin{note} -This implies that -\tcode{\exposid{map_}(I) < \exposid{map_}.required_span_size()} -is \tcode{true}. -\end{note} - -\pnum -\effects -Equivalent to: +\item +otherwise, \begin{codeblock} -return @\exposid{acc_}@.access(@\exposid{ptr_}@, @\exposid{map_}@(static_cast(std::move(indices))...)); +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, +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} \end{codeblock} +\end{itemize} \end{itemdescr} -\indexlibrarymember{operator[]}{mdspan}% +\rSec4[mdspan.sub.sub]{\tcode{submdspan} function template} + +\indexlibraryglobal{submdspan}% \begin{itemdecl} -template - constexpr reference operator[](span indices) const; -template - constexpr reference operator[](const array& indices) const; +template + constexpr auto submdspan( + const mdspan& src, + SliceSpecifiers... slices) -> @\seebelow@; \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{index_type} be \tcode{typename Extents::index_type}. + +\pnum +Let \tcode{sub_map_offset} be the result of +\tcode{submdspan_mapping(src.mapping(), slices...)}. +\begin{note} +This invocation of \tcode{submdspan_mapping} +selects a function call via overload resolution +on a candidate set that includes the lookup set +found by argument-dependent lookup\iref{basic.lookup.argdep}. +\end{note} + \pnum \constraints \begin{itemize} \item -\tcode{is_convertible_v} is \tcode{true}, and +\tcode{sizeof...(slices)} equals \tcode{Extents::rank()}, and \item -\tcode{is_nothrow_constructible_v} is \tcode{true}. +the expression \tcode{submdspan_mapping(src.mapping(), slices...)} +is well-formed when treated as an unevaluated operand. \end{itemize} \pnum -\effects -Let \tcode{P} be a parameter pack such that -\begin{codeblock} -is_same_v, index_sequence> -\end{codeblock} +\mandates +\begin{itemize} +\item +\tcode{decltype(submdspan_mapping(src.mapping(), slices...))} +is a specialization of \tcode{submd-\linebreak{}span_mapping_result}. + +\item +\tcode{is_same_v,} +\tcode{decltype(\linebreak{}submdspan_extents(src.mapping(), slices...))>} is \tcode{true}. -Equivalent to: -\begin{codeblock} -return operator[](as_const(indices[P])...); -\end{codeblock} -\end{itemdescr} -\indexlibrarymember{size}{mdspan}% -\begin{itemdecl} -constexpr size_type size() const noexcept; -\end{itemdecl} +\item +For each rank index $k$ of \tcode{src.extents()}, +exactly one of the following is true: + \begin{itemize} + \item $S_k$ models \tcode{\libconcept{convertible_to}}, + \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} +\end{itemize} -\begin{itemdescr} \pnum \expects -The size of the multidimensional index space \tcode{extents()} -is representable as a value of type \tcode{size_type}\iref{basic.fundamental}. - -\pnum -\returns -\tcode{extents().\exposid{fwd-prod-of-extents}(rank())}. -\end{itemdescr} +\begin{itemize} +\item +For each rank index $k$ of \tcode{src.extents()}, +all of the following are \tcode{true}: + \begin{itemize} + \item + if $S_k$ is a specialization of \tcode{strided_slice} + \begin{itemize} + \item $\tcode{$s_k$.extent} = 0$, or + \item $\tcode{$s_k$.stride} > 0$ + \end{itemize} + \item + $0 \le \tcode{\exposid{first_}(slices...)}$ + $\le \tcode{\exposid{last_}<$k$>(src.extents(), slices...)}$ + $\le \tcode{\linebreak{}src.extent($k$)}$ + \end{itemize} -\indexlibrarymember{empty}{mdspan}% -\begin{itemdecl} -[[nodiscard]] constexpr bool empty() const noexcept; -\end{itemdecl} +\item +\tcode{sub_map_offset.mapping.extents() == submdspan_extents(src.mapping(), slices...)}\linebreak +is \tcode{true}; and -\begin{itemdescr} -\pnum -\returns -\tcode{true} -if the size of the multidimensional index space \tcode{extents()} is 0, -otherwise \tcode{false}. -\end{itemdescr} +\item +for each integer pack \tcode{I} which is a multidimensional index +in \tcode{sub_map_offset.mapping.extents()}, +\begin{codeblock} +sub_map_offset.mapping(I...) + sub_map_offset.offset == + src.mapping()(@\exposid{src-indices}@(array{I...}, slices...)) +\end{codeblock} +is \tcode{true}. +\end{itemize} -\indexlibrarymember{swap}{mdspan}% -\begin{itemdecl} -friend constexpr void swap(mdspan& x, mdspan& y) noexcept; -\end{itemdecl} +\begin{note} +These conditions ensure that the mapping returned by \tcode{submdspan_mapping} +matches the algorithmically expected index-mapping given the slice specifiers. +\end{note} -\begin{itemdescr} \pnum \effects Equivalent to: \begin{codeblock} -swap(x.@\exposid{ptr_}@, y.@\exposid{ptr_}@); -swap(x.@\exposid{map_}@, y.@\exposid{map_}@); -swap(x.@\exposid{acc_}@, y.@\exposid{acc_}@); +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} + +\pnum +\begin{example} +Given a rank-3 \tcode{mdspan grid3d} representing a three-dimensional grid +of regularly spaced points in a rectangular prism, +the function \tcode{zero_surface} sets all elements on +the surface of the 3-dimensional shape to zero. +It does so by reusing a function \tcode{zero_2d} +that takes a rank-2 \tcode{mdspan}. + +\begin{codeblock} +// zero out all elements in an \tcode{mdspan} +template +void zero_2d(mdspan a) { + static_assert(a.rank() == 2); + for (int i = 0; i < a.extent(0); i++) + for (int j = 0; j < a.extent(1); j++) + a[i, j] = 0; +} + +// zero out just the surface +template +void zero_surface(mdspan grid3d) { + static_assert(grid3d.rank() == 3); + zero_2d(submdspan(grid3d, 0, full_extent, full_extent)); + zero_2d(submdspan(grid3d, full_extent, 0, full_extent)); + zero_2d(submdspan(grid3d, full_extent, full_extent, 0)); + zero_2d(submdspan(grid3d, grid3d.extent(0) - 1, full_extent, full_extent)); + zero_2d(submdspan(grid3d, full_extent, grid3d.extent(1) - 1, full_extent)); + zero_2d(submdspan(grid3d, full_extent, full_extent, grid3d.extent(2) - 1)); +} +\end{codeblock} +\end{example} 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/cover-wd.tex b/source/cover-wd.tex index 2da775b155..54d00f4b64 100644 --- a/source/cover-wd.tex +++ b/source/cover-wd.tex @@ -22,7 +22,7 @@ \vspace{2.5cm} \begin{center} \textbf{\Huge -Working Draft, Standard for Programming Language \Cpp{}} +Working Draft\\[2ex]Programming Languages --- \Cpp{}} \end{center} \vfill \textbf{Note: this is an early draft. It's known to be incomplet and diff --git a/source/declarations.tex b/source/declarations.tex index 52b5847d64..020161723b 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,20 +13,23 @@ the form \begin{bnf} \nontermdef{declaration-seq}\br - declaration\br - declaration-seq declaration + declaration \opt{declaration-seq} \end{bnf} \begin{bnf} \nontermdef{declaration}\br + name-declaration\br + special-declaration +\end{bnf} + +\begin{bnf} +\nontermdef{name-declaration}\br block-declaration\br nodeclspec-function-declaration\br function-definition\br + friend-type-declaration\br template-declaration\br deduction-guide\br - explicit-instantiation\br - explicit-specialization\br - export-declaration\br linkage-specification\br namespace-definition\br empty-declaration\br @@ -34,6 +37,13 @@ module-import-declaration \end{bnf} +\begin{bnf} +\nontermdef{special-declaration}\br + explicit-instantiation\br + explicit-specialization\br + export-declaration +\end{bnf} + \begin{bnf} \nontermdef{block-declaration}\br simple-declaration\br @@ -57,17 +67,39 @@ \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} +\nontermdef{static_assert-message}\br + unevaluated-string\br + constant-expression \end{bnf} \begin{bnf} \nontermdef{static_assert-declaration}\br \keyword{static_assert} \terminal{(} constant-expression \terminal{)} \terminal{;}\br - \keyword{static_assert} \terminal{(} constant-expression \terminal{,} string-literal \terminal{)} \terminal{;} + \keyword{static_assert} \terminal{(} constant-expression \terminal{,} static_assert-message \terminal{)} \terminal{;} \end{bnf} \begin{bnf} @@ -96,11 +128,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 @@ -170,24 +207,43 @@ \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}. -If the \grammarterm{decl-specifier-seq} contains -any \grammarterm{decl-specifier} other than -\keyword{static}, \keyword{thread_local}, \keyword{auto}\iref{dcl.spec.auto}, or -\grammarterm{cv-qualifier}{s}, -the program is ill-formed. +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; +C auto [x, y] = std::pair{1, 2}; // error: constrained \grammarterm{placeholder-type-specifier} + // not permitted for structured bindings +\end{codeblock} +\end{example} The \grammarterm{initializer} shall be 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 called a \defnx{typedef declaration}{declaration!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}. @@ -195,22 +251,44 @@ Such a \grammarterm{declarator-id} is an \grammarterm{identifier}\iref{class.conv.fct}. \end{note} -If the -\grammarterm{decl-specifier-seq} contains no \keyword{typedef} specifier, the -declaration is called a \defnx{function declaration}{declaration!function} if -the type associated with a \grammarterm{declarator-id} is a function type\iref{dcl.fct} and -an \defnx{object declaration}{declaration!object} otherwise. +Otherwise, if the type associated with a \grammarterm{declarator-id} +is a function type\iref{dcl.fct}, +the declaration is a \defnx{function declaration}{declaration!function}. +Otherwise, if the type associated with a \grammarterm{declarator-id} +is an object or reference type, the declaration is +an \defnx{object declaration}{declaration!object}. +Otherwise, the program is ill-formed. +\begin{example} +\begin{codeblock} +int f(), x; // OK, function declaration for \tcode{f} and object declaration for \tcode{x} +extern void g(), // OK, function declaration for \tcode{g} + y; // error: \tcode{void} is not an object type +\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 @@ -224,20 +302,83 @@ \end{note} \pnum -\indextext{\idxgram{static_assert}}% +If a \grammarterm{static_assert-message} +matches the syntactic requirements of \grammarterm{unevaluated-string}, +it is an \grammarterm{unevaluated-string} and +the text of the \grammarterm{static_assert-message} is +the text of the \grammarterm{unevaluated-string}. +Otherwise, a \grammarterm{static_assert-message} shall be an expression $M$ +such that +\begin{itemize} +\item +the expression \tcode{$M$.size()} is +implicitly convertible to the type \tcode{std::size_t}, and +\item +the expression \tcode{$M$.data()} is +implicitly convertible to the type ``pointer to \tcode{\keyword{const} \keyword{char}}''. +\end{itemize} + +\pnum +\indextext{\idxcode{static_assert}}% In a \grammarterm{static_assert-declaration}, -the \grammarterm{constant-expression} +the \grammarterm{constant-expression} $E$ is contextually converted to \keyword{bool} and the converted expression shall be a constant expression\iref{expr.const}. -If the value of the expression when -so converted is \tcode{true}, the declaration has no -effect. Otherwise, the program is ill-formed, and the resulting -diagnostic message\iref{intro.compliance} should include the text of -the \grammarterm{string-literal}, if one is supplied. +If the value of the expression $E$ when so converted is \tcode{true} or +the expression is evaluated in the context of a template definition, +the declaration has no effect and +the \grammarterm{static_assert-message} is +an unevaluated operand\iref{term.unevaluated.operand}. +Otherwise, +the \grammarterm{static_assert-declaration} \defnx{fails}{\idxcode{static_assert}!failed} and +\begin{itemize} +\item +the program is ill-formed, and +\item +if the \grammarterm{static_assert-message} is +a \grammarterm{constant-expression} $M$, +\begin{itemize} +\item +\tcode{$M$.size()} shall be a converted constant expression of +type \tcode{std::size_t} and +let $N$ denote the value of that expression, +\item +\tcode{$M$.data()}, implicitly converted to +the type ``pointer to \tcode{\keyword{const} \keyword{char}}'', +shall be a core constant expression and let $D$ denote the converted expression, +\item +for each $i$ where $0 \le i < N$, +\tcode{$D$[$i$]} shall be an integral constant expression, and +\item +the text of the \grammarterm{static_assert-message} is formed by +the sequence of $N$ code units, starting at $D$, of +the ordinary literal encoding\iref{lex.charset}. +\end{itemize} +\end{itemize} + +\pnum +\recommended +When a \grammarterm{static_assert-declaration} fails, +the resulting diagnostic message should include the text of +the \grammarterm{static_assert-message}, if one is supplied. \begin{example} \begin{codeblock} static_assert(sizeof(int) == sizeof(void*), "wrong pointer size"); static_assert(sizeof(int[2])); // OK, narrowing allowed + +template +void f(T t) { + if constexpr (sizeof(T) == sizeof(int)) { + use(t); + } else { + static_assert(false, "must be int-sized"); + } +} + +void g(char c) { + f(0); // OK + f(c); // error on implementations where \tcode{sizeof(int) > 1}: must be \tcode{int}-sized +} \end{codeblock} \end{example} @@ -282,9 +423,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}. @@ -515,6 +656,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 @@ -634,7 +778,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}. @@ -711,12 +855,14 @@ \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. A function or static data member declared with the \keyword{constexpr} or \keyword{consteval} specifier +on its first declaration is implicitly an inline function or variable\iref{dcl.inline}. If any declaration of a function or function template has a \keyword{constexpr} or \keyword{consteval} specifier, @@ -759,24 +905,27 @@ used in the declaration of a function declares that function to be a \defnx{constexpr function}{specifier!\idxcode{constexpr}!function}. +\begin{note} A function or constructor declared with the \keyword{consteval} specifier -is called an \defnadj{immediate}{function}. +is an immediate function\iref{expr.const}. +\end{note} A destructor, an allocation function, or a deallocation function shall not be declared with the \keyword{consteval} specifier. \pnum \indextext{specifier!\idxcode{constexpr}!function}% \indextext{constexpr function}% -The definition of a constexpr function shall satisfy the following -requirements: +A function is \defn{constexpr-suitable} if \begin{itemize} \item -it shall not be a coroutine\iref{dcl.fct.def.coroutine}; +it is not a coroutine\iref{dcl.fct.def.coroutine}, and \item if the function is a constructor or destructor, -its class shall not have any virtual base classes. +its class does not have any virtual base classes. \end{itemize} +Except for instantiated constexpr functions, +non-templated constexpr functions shall be constexpr-suitable. \begin{example} \begin{codeblock} @@ -810,16 +959,6 @@ \end{codeblock} \end{example} -\pnum -If the instantiated template specialization of a constexpr function -template -or member function of a class template -would fail to satisfy the requirements for a constexpr -function, -that specialization is still a constexpr function, -even though a call to such a function cannot appear in a constant -expression. - \pnum An invocation of a constexpr function in a given context produces the same result as @@ -862,10 +1001,10 @@ 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 have constant destruction. +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. \begin{example} \begin{codeblock} struct pixel { @@ -873,6 +1012,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} @@ -881,7 +1030,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 @@ -889,10 +1043,12 @@ \pnum If a variable declared with the \keyword{constinit} specifier has -dynamic initialization\iref{basic.start.dynamic}, the program is ill-formed. +dynamic initialization\iref{basic.start.dynamic}, the program is ill-formed, +even if the implementation would perform that initialization as +a static initialization\iref{basic.start.static}. \begin{note} The \keyword{constinit} specifier ensures that the variable -is initialized during static initialization\iref{basic.start.static}. +is initialized during static initialization. \end{note} \pnum @@ -1121,7 +1277,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} @@ -1174,10 +1330,10 @@ \indextext{\idxcode{volatile}!implementation-defined}% \begin{note} \tcode{volatile} is a hint to the implementation to avoid aggressive -optimization involving the object because the value of the object might -be changed by means undetectable by an implementation. -Furthermore, for some implementations, \tcode{volatile} might indicate that -special hardware instructions are required to access the object. +optimization involving the object because it is possible for the value of the object +to change by means undetectable by an implementation. +Furthermore, for some implementations, \tcode{volatile} can indicate that +special hardware instructions are needed to access the object. See~\ref{intro.execution} for detailed semantics. In general, the semantics of \tcode{volatile} are intended to be the same in \Cpp{} as they are in C. @@ -1192,7 +1348,7 @@ \nontermdef{simple-type-specifier}\br \opt{nested-name-specifier} type-name\br nested-name-specifier \keyword{template} simple-template-id\br - decltype-specifier\br + computed-type-specifier\br placeholder-type-specifier\br \opt{nested-name-specifier} template-name\br \keyword{char}\br @@ -1218,6 +1374,12 @@ typedef-name \end{bnf} +\begin{bnf} +\nontermdef{computed-type-specifier}\br + decltype-specifier\br + pack-index-specifier +\end{bnf} + \pnum \indextext{component name} The component names of a \grammarterm{simple-type-specifier} are those of its @@ -1289,6 +1451,7 @@ \grammarterm{type-name} & the type named \\ \grammarterm{simple-template-id} & the type as defined in~\ref{temp.names}\\ \grammarterm{decltype-specifier} & the type as defined in~\ref{dcl.type.decltype}\\ +\grammarterm{pack-index-specifier} & the type as defined in~\ref{dcl.type.pack.index}\\ \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}\\ @@ -1338,6 +1501,32 @@ forces \tcode{char} objects to be signed; it is redundant in other contexts. \end{note} +\rSec3[dcl.type.pack.index]{Pack indexing specifier} + +\begin{bnf} +\nontermdef{pack-index-specifier}\br + typedef-name \terminal{...} \terminal{[} constant-expression \terminal{]} +\end{bnf} + +\pnum +The \grammarterm{typedef-name} $P$ in a \grammarterm{pack-index-specifier} +shall denote a pack. + +\pnum +The \grammarterm{constant-expression} shall be +a converted constant expression\iref{expr.const} of type \tcode{std::size_t} +whose value $V$, termed the index, +is such that $0 \le V < \tcode{sizeof...($P$)}$. + +\pnum +A \grammarterm{pack-index-specifier} is a pack expansion\iref{temp.variadic}. + +\pnum +\begin{note} +The \grammarterm{pack-index-specifier} denotes +the type of the $V^\text{th}$ element of the pack. +\end{note} + \rSec3[dcl.type.elab]{Elaborated type specifiers}% \indextext{type specifier!elaborated}% \indextext{\idxcode{typename}}% @@ -1348,11 +1537,6 @@ class-key \opt{attribute-specifier-seq} \opt{nested-name-specifier} identifier\br class-key simple-template-id\br class-key nested-name-specifier \opt{\keyword{template}} simple-template-id\br - elaborated-enum-specifier -\end{bnf} - -\begin{bnf} -\nontermdef{elaborated-enum-specifier}\br \keyword{enum} \opt{nested-name-specifier} identifier \end{bnf} @@ -1368,8 +1552,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} @@ -1383,7 +1569,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. @@ -1398,30 +1584,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 @@ -1436,12 +1626,12 @@ \begin{codeblock} friend class T; \end{codeblock} -is ill-formed. However, the similar declaration \tcode{friend T;} is allowed\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 @@ -1481,8 +1671,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}; @@ -1516,6 +1706,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\&} + +void f() { + [](auto ...pack) { + decltype(pack...[0]) x5; // type is \tcode{int} + decltype((pack...[0])) x6; // type is \tcode{int\&} + }(0); +} \end{codeblock} \end{example} \begin{note} @@ -1587,20 +1784,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 @@ -1609,15 +1819,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}. @@ -1627,9 +1837,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 @@ -1643,6 +1855,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} @@ -1652,13 +1865,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}. @@ -1732,8 +1951,22 @@ \end{example} \pnum -Return type deduction for a templated entity -that is a function or function template with a placeholder in its +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 declared type occurs when the definition is instantiated even if the function body contains a \tcode{return} statement with a non-type-dependent operand. \begin{note} @@ -1887,9 +2120,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} @@ -2063,8 +2296,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 @@ -2074,7 +2307,7 @@ it is as if a unique identifier were included in the appropriate place\iref{dcl.name}. The preceding specifiers indicate -the type, storage class or other properties +the type, storage duration, linkage, or other properties of the entity or entities being declared. Each declarator specifies one entity and (optionally) names it and/or @@ -2128,10 +2361,10 @@ \end{note} \pnum -The optional \grammarterm{requires-clause}\iref{temp.pre} in an +The optional \grammarterm{requires-clause} in an \grammarterm{init-declarator} or \grammarterm{member-declarator} shall be present only if the declarator declares a -templated function\iref{dcl.fct}. +templated function\iref{temp.pre}. % \indextext{trailing requires-clause@trailing \gterm{requires-clause}|see{\gterm{requires-clause}, trailing}}% When present after a declarator, the \grammarterm{requires-clause} @@ -2156,6 +2389,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 @@ -2191,6 +2430,7 @@ \end{bnf} \begin{bnf} +\microtypesetup{protrusion=false} \nontermdef{ptr-operator}\br \terminal{*} \opt{attribute-specifier-seq} \opt{cv-qualifier-seq}\br \terminal{\&} \opt{attribute-specifier-seq}\br @@ -2234,7 +2474,7 @@ \tcode{typeid}, the name of a type shall be specified. This can be done with a -\grammarterm{type-id}, +\grammarterm{type-id} or \grammarterm{new-type-id}\iref{expr.new}, which is syntactically a declaration for a variable or function of that type that omits the name of the entity. @@ -2277,7 +2517,6 @@ \begin{bnf} \nontermdef{noptr-abstract-pack-declarator}\br noptr-abstract-pack-declarator parameters-and-qualifiers\br - noptr-abstract-pack-declarator \terminal{[} \opt{constant-expression} \terminal{]} \opt{attribute-specifier-seq}\br \terminal{...} \end{bnf} @@ -2313,8 +2552,11 @@ \end{example} \pnum -A type can also be named (often more easily) by using a -\tcode{typedef}\iref{dcl.typedef}. +\begin{note} +A type can also be named by a \grammarterm{typedef-name}, +which is introduced by a typedef declaration +or \grammarterm{alias-declaration}\iref{dcl.typedef}. +\end{note} \rSec2[dcl.ambig.res]{Ambiguity resolution}% \indextext{ambiguity!declaration versus cast}% @@ -2323,12 +2565,21 @@ \pnum The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in~\ref{stmt.ambig} can also occur in the context of a declaration. -In that context, the choice is between a function declaration with -a redundant set of parentheses around a parameter name and an object declaration -with a function-style cast as the initializer. +In that context, the choice is between +an object declaration +with a function-style cast as the initializer and +a declaration involving a function declarator +with a redundant set of parentheses around a parameter name. Just as for the ambiguities mentioned in~\ref{stmt.ambig}, -the resolution is to consider any construct that could possibly -be a declaration a declaration. +the resolution is to consider any construct, +such as the potential parameter declaration, +that could possibly be a declaration +to be a declaration. +However, a construct that can syntactically be a \grammarterm{declaration} +whose outermost \grammarterm{declarator} +would match the grammar of a \grammarterm{declarator} +with a \grammarterm{trailing-return-type} +is a declaration only if it starts with \keyword{auto}. \begin{note} A declaration can be explicitly disambiguated by adding parentheses around the argument. @@ -2340,13 +2591,16 @@ struct S { S(int); }; +typedef struct BB { int C[2]; } *B, C; void foo(double a) { - S w(int(a)); // function declaration - S x(int()); // function declaration - S y((int(a))); // object declaration + S v(int(a)); // function declaration + S w(int()); // function declaration + S x((int(a))); // object declaration S y((int)a); // object declaration S z = int(a); // object declaration + S a(B()->C); // object declaration + S b(auto()->C); // function declaration } \end{codeblock} \end{example} @@ -2359,6 +2613,11 @@ \grammarterm{type-id} in its syntactic context shall be considered a \grammarterm{type-id}. +However, a construct that can syntactically be a \grammarterm{type-id} +whose outermost \grammarterm{abstract-declarator} +would match the grammar of an \grammarterm{abstract-declarator} +with a \grammarterm{trailing-return-type} +is considered a \grammarterm{type-id} only if it starts with \keyword{auto}. \begin{example} \begin{codeblock} template struct X {}; @@ -2377,6 +2636,12 @@ (int(a))+1; // expression (int(unsigned(a)))+1; // type-id (ill-formed) } + +typedef struct BB { int C[2]; } *B, C; +void g() { + sizeof(B()->C[1]); // OK, \tcode{\keyword{sizeof}(}expression\tcode{)} + sizeof(auto()->C[1]); // error: \keyword{sizeof} of a function returning an array +} \end{codeblock} \end{example} @@ -2642,7 +2907,8 @@ \tcode{D} where \tcode{D} -is an unadorned name, the type of the declared entity is +is an unadorned \grammarterm{declarator-id}, +the type of the declared entity is ``\tcode{T}''. \pnum @@ -2761,7 +3027,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} @@ -2817,7 +3083,7 @@ A reference can be thought of as a name of an object. \end{note} \indextext{\idxcode{void\&}}% -A declarator that specifies the type +Forming the type ``reference to \cv{}~\keyword{void}'' is ill-formed. @@ -2913,16 +3179,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}% @@ -3280,60 +3576,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 @@ -3347,28 +3627,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} @@ -3380,9 +3658,9 @@ \begin{bnf} \nontermdef{parameter-declaration}\br \opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq declarator\br - \opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq declarator \terminal{=} initializer-clause\br + \opt{attribute-specifier-seq} decl-specifier-seq declarator \terminal{=} initializer-clause\br \opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq \opt{abstract-declarator}\br - \opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq \opt{abstract-declarator} \terminal{=} initializer-clause + \opt{attribute-specifier-seq} decl-specifier-seq \opt{abstract-declarator} \terminal{=} initializer-clause \end{bnf} The optional \grammarterm{attribute-specifier-seq} in a \grammarterm{parameter-declaration} @@ -3404,7 +3682,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}}% @@ -3424,9 +3702,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} @@ -3496,11 +3778,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} @@ -3755,7 +4041,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}, @@ -3765,7 +4051,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. @@ -3774,7 +4060,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 = /* ... */; @@ -3802,7 +4088,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} @@ -3910,9 +4196,7 @@ of a function declaration or \grammarterm{lambda-declarator} or in a -\grammarterm{template-parameter}\iref{temp.param}; -in the latter case, the \grammarterm{initializer-clause} shall be an -\grammarterm{assignment-expression}. +\grammarterm{template-parameter}\iref{temp.param}. A default argument shall not be specified for a template parameter pack or a function parameter pack. @@ -3997,7 +4281,12 @@ copy-initialization semantics\iref{dcl.init}. The names in the default argument are looked up, and the semantic constraints are checked, -at the point where the default argument appears. +at the point where the default argument appears, except that +an immediate invocation\iref{expr.const} that +is a potentially-evaluated subexpression\iref{intro.execution} of +the \grammarterm{initializer-clause} in a \grammarterm{parameter-declaration} is +neither evaluated +nor checked for whether it is a constant expression at that point. Name lookup and checking of semantic constraints for default arguments of templated functions are performed as described in~\ref{temp.inst}. \begin{example} @@ -4028,7 +4317,7 @@ \end{note} \pnum -Except for member functions of class templates, the +Except for member functions of templated classes, the default arguments in a member function definition that appears outside of the class definition are added to the set of default arguments provided by the @@ -4037,9 +4326,9 @@ copy or move constructor\iref{class.copy.ctor}, or copy or move assignment operator\iref{class.copy.assign} is so declared. -Default arguments for a member function of a class template +Default arguments for a member function of a templated class shall be specified on the initial declaration of the member -function within the class template. +function within the templated class. \begin{example} \begin{codeblock} class C { @@ -4180,79 +4469,399 @@ \indextext{declaration!default argument|)}% \indextext{declarator!meaning of|)} -\rSec1[dcl.init]{Initializers}% - -\rSec2[dcl.init.general]{General}% -\indextext{initialization|(} - -\pnum -The process of initialization described in \ref{dcl.init} applies to -all initializations regardless of syntactic context, including the -initialization of a function parameter\iref{expr.call}, the -initialization of a return value\iref{stmt.return}, or when an -initializer follows a declarator. - -\begin{bnf} -\nontermdef{initializer}\br - brace-or-equal-initializer\br - \terminal{(} expression-list \terminal{)} -\end{bnf} - -\begin{bnf} -\nontermdef{brace-or-equal-initializer}\br - \terminal{=} initializer-clause\br - braced-init-list -\end{bnf} - -\begin{bnf} -\nontermdef{initializer-clause}\br - assignment-expression\br - braced-init-list -\end{bnf} - -\begin{bnf} -\nontermdef{braced-init-list}\br - \terminal{\{} initializer-list \opt{\terminal{,}} \terminal{\}}\br - \terminal{\{} designated-initializer-list \opt{\terminal{,}} \terminal{\}}\br - \terminal{\{} \terminal{\}} -\end{bnf} +\rSec1[dcl.contract]{Function contract specifiers} +\rSec2[dcl.contract.func]{General} -\begin{bnf} -\nontermdef{initializer-list}\br - initializer-clause \opt{\terminal{...}}\br - initializer-list \terminal{,} initializer-clause \opt{\terminal{...}} -\end{bnf} +\indextext{contract assertion!function|(}% \begin{bnf} -\nontermdef{designated-initializer-list}\br - designated-initializer-clause\br - designated-initializer-list \terminal{,} designated-initializer-clause +\nontermdef{function-contract-specifier-seq}\br + function-contract-specifier \opt{function-contract-specifier-seq} \end{bnf} \begin{bnf} -\nontermdef{designated-initializer-clause}\br - designator brace-or-equal-initializer +\nontermdef{function-contract-specifier}\br + precondition-specifier\br + postcondition-specifier \end{bnf} \begin{bnf} -\nontermdef{designator}\br - \terminal{.} identifier +\nontermdef{precondition-specifier}\br + \terminal{pre} \opt{attribute-specifier-seq} \terminal{(} conditional-expression \terminal{)} \end{bnf} \begin{bnf} -\nontermdef{expr-or-braced-init-list}\br - expression\br - braced-init-list +\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} -The rules in \ref{dcl.init} apply even if the grammar permits only -the \grammarterm{brace-or-equal-initializer} form -of \grammarterm{initializer} in a given context. +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 -Except for objects declared with the \keyword{constexpr} specifier, for which see~\ref{dcl.constexpr}, +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}% +\indextext{initialization|(} + +\pnum +The process of initialization described in \ref{dcl.init} applies to +all initializations regardless of syntactic context, including the +initialization of a function parameter\iref{expr.call}, the +initialization of a return value\iref{stmt.return}, or when an +initializer follows a declarator. + +\begin{bnf} +\nontermdef{initializer}\br + brace-or-equal-initializer\br + \terminal{(} expression-list \terminal{)} +\end{bnf} + +\begin{bnf} +\nontermdef{brace-or-equal-initializer}\br + \terminal{=} initializer-clause\br + braced-init-list +\end{bnf} + +\begin{bnf} +\nontermdef{initializer-clause}\br + assignment-expression\br + braced-init-list +\end{bnf} + +\begin{bnf} +\nontermdef{braced-init-list}\br + \terminal{\{} initializer-list \opt{\terminal{,}} \terminal{\}}\br + \terminal{\{} designated-initializer-list \opt{\terminal{,}} \terminal{\}}\br + \terminal{\{} \terminal{\}} +\end{bnf} + +\begin{bnf} +\nontermdef{initializer-list}\br + initializer-clause \opt{\terminal{...}}\br + initializer-list \terminal{,} initializer-clause \opt{\terminal{...}} +\end{bnf} + +\begin{bnf} +\nontermdef{designated-initializer-list}\br + designated-initializer-clause\br + designated-initializer-list \terminal{,} designated-initializer-clause +\end{bnf} + +\begin{bnf} +\nontermdef{designated-initializer-clause}\br + designator brace-or-equal-initializer +\end{bnf} + +\begin{bnf} +\nontermdef{designator}\br + \terminal{.} identifier +\end{bnf} + +\begin{bnf} +\nontermdef{expr-or-braced-init-list}\br + expression\br + braced-init-list +\end{bnf} + +\begin{note} +The rules in \ref{dcl.init} apply even if the grammar permits only +the \grammarterm{brace-or-equal-initializer} form +of \grammarterm{initializer} in a given context. +\end{note} + +\pnum +Except for objects declared with the \keyword{constexpr} specifier, for which see~\ref{dcl.constexpr}, an \grammarterm{initializer} in the definition of a variable can consist of arbitrary expressions involving literals and previously declared variables and functions, @@ -4360,7 +4969,10 @@ \item If \tcode{T} -is an array type, each element is default-initialized. +is an array type, +the semantic constraints of default-initializing a hypothetical element +shall be met and +each element is default-initialized. \item Otherwise, @@ -4399,29 +5011,27 @@ an object of type \tcode{T} means: + \begin{itemize} \item -if +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 +If \tcode{T} -is an array type, then each element is value-initialized; +is an array type, +the semantic constraints of value-initializing a hypothetical element +shall be met and +each element is value-initialized. \item -otherwise, the object is zero-initialized. +Otherwise, the object is zero-initialized. \end{itemize} \pnum @@ -4432,7 +5042,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. @@ -4442,7 +5052,7 @@ If no initializer is specified for an object, the object is default-initialized. \pnum -If the entity being initialized does not have class type, the +If the entity being initialized does not have class or array type, the \grammarterm{expression-list} in a parenthesized initializer shall be a single expression. @@ -4455,7 +5065,8 @@ as well as in argument passing, function return, throwing an exception\iref{except.throw}, handling an exception\iref{except.handle}, -and aggregate member initialization\iref{dcl.init.aggr}, +and aggregate member initialization other than by a +\grammarterm{designated-initializer-clause}\iref{dcl.init.aggr}, is called \defn{copy-initialization}. \begin{note} @@ -4480,7 +5091,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 @@ -4516,13 +5127,15 @@ \tcode{X}. The form \tcode{()} -is permitted in certain other initialization contexts\iref{expr.new, +can appear in certain other initialization contexts\iref{expr.new, expr.type.conv,class.base.init}. \end{note} \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, @@ -4539,21 +5152,21 @@ 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()));} calls the \tcode{T} default constructor to initialize \tcode{x}. +\tcode{T x = T(T(T()));} value-initializes \tcode{x}. \end{example} \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 @@ -4584,7 +5197,7 @@ is sequenced before those associated with the initialization of $e_j$. \begin{note} By contrast with direct-list-initialization, -narrowing conversions\iref{dcl.init.list} are permitted, +narrowing conversions\iref{dcl.init.list} can appear, designators are not permitted, a temporary object bound to a reference does not have its lifetime extended\iref{class.temporary}, and @@ -4648,8 +5261,9 @@ \item Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression. -A standard conversion sequence\iref{conv} will be used, if necessary, -to convert the initializer expression to the cv-unqualified version of +A standard conversion sequence\iref{conv} is used +to convert the initializer expression to +a prvalue of the destination type; no user-defined conversions are considered. If the conversion cannot @@ -4676,10 +5290,26 @@ \end{note} \end{itemize} +\pnum +An immediate invocation\iref{expr.const} that is not evaluated where +it appears\iref{dcl.fct.default,class.mem.general} +is evaluated and checked for whether it is +a constant expression at the point where +the enclosing \grammarterm{initializer} is used in +a function call, a constructor definition, or an aggregate initialization. + \pnum An \grammarterm{initializer-clause} followed by an ellipsis is a pack expansion\iref{temp.variadic}. +\pnum +Initialization includes +the evaluation of all subexpressions of +each \grammarterm{initializer-clause} of +the initializer (possibly nested within \grammarterm{braced-init-list}{s}) and +the creation of any temporary objects for +function arguments or return values\iref{class.temporary}. + \pnum If the initializer is a parenthesized \grammarterm{expression-list}, the expressions are evaluated in the order @@ -4736,9 +5366,9 @@ \item no private or protected direct non-static data members\iref{class.access}, \item -no virtual functions\iref{class.virtual}, and +no private or protected direct base classes\iref{class.access.base}, and \item -no virtual, private, or protected base classes\iref{class.mi}. +no virtual functions\iref{class.virtual} or virtual base classes\iref{class.mi}. \end{itemize} \begin{note} Aggregate initialization does not allow accessing @@ -4775,8 +5405,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. @@ -4790,7 +5420,7 @@ the initializer list is a brace-enclosed \grammarterm{designated-initializer-list}, the element is initialized by the -\grammarterm{designated-initializer-list} \tcode{\{ }\placeholder{D}\tcode{ \}}, +\grammarterm{braced-init-list} \tcode{\{ }\placeholder{D}\tcode{ \}}, where \placeholder{D} is the \grammarterm{designated-initializer-clause} naming a member of the anonymous union member. There shall be only one such \grammarterm{designated-initializer-clause}. @@ -4807,17 +5437,31 @@ 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} +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 of the rules in this subclause if the element is an aggregate. @@ -4906,13 +5550,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 { @@ -4944,6 +5582,7 @@ \pnum The destructor for each element of class type +other than an anonymous union member is potentially invoked\iref{class.dtor} from the context where the aggregate initialization occurs. \begin{note} @@ -4953,15 +5592,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 }; @@ -4971,6 +5604,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} @@ -5018,19 +5660,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 @@ -5053,33 +5682,7 @@ \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 multi-dimensional array, +When initializing a multidimensional array, the \grammarterm{initializer-clause}{s} initialize the elements with the last (rightmost) index of the array @@ -5115,28 +5718,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] = { @@ -5158,7 +5804,7 @@ and \tcode{y[2]}. The initializer ends early and therefore -\tcode{y[3]}s +\tcode{y[3]}'s elements are initialized as if explicitly initialized with an expression of the form \tcode{float()}, @@ -5191,22 +5837,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 -required. +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 { @@ -5220,7 +5874,6 @@ A a; B b = { 4, a, a }; \end{codeblock} - Braces are elided around the \grammarterm{initializer-clause} for @@ -5371,7 +6024,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} @@ -5476,13 +6129,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} @@ -5491,8 +6145,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). @@ -5512,15 +6168,25 @@ 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 *A[3]; // array of 3 pointer to \tcode{int} +typedef const int *const CA[3]; // array of 3 const pointer to \tcode{const int} +ACPC &&r = AP{}; // binds directly \end{codeblock} \end{example} \item -Otherwise: +Otherwise, \tcode{T1} shall not be reference-related to \tcode{T2}. \begin{itemize} \item -If \tcode{T1} or \tcode{T2} is a class type and -\tcode{T1} is not reference-related to \tcode{T2}, +If \tcode{T1} or \tcode{T2} is a class type, user-defined conversions are considered using the rules for copy-initialization of an object of type ``\cvqual{cv1} \tcode{T1}'' by @@ -5539,24 +6205,6 @@ and the reference is bound to the result. \end{itemize} -If -\tcode{T1} -is reference-related to -\tcode{T2}: -\begin{itemize} -\item -\cvqual{cv1} -shall be the same cv-qualification as, or greater cv-qualification than, -\cvqual{cv2}; and -\item -if the reference is an rvalue reference, -the initializer expression shall not be an lvalue. -\begin{note} -This can be affected by -whether the initializer expression is move-eligible\iref{expr.prim.id.unqual}. -\end{note} -\end{itemize} - \begin{example} \begin{codeblock} struct Banana { }; @@ -5569,7 +6217,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 @@ -5577,9 +6225,10 @@ const int& r3 = a; // error: cv-qualifier dropped // from result of conversion function double d2 = 1.0; -double&& rrd2 = d2; // error: initializer is lvalue of related type +double&& rrd2 = d2; // error: initializer is lvalue of reference-related type struct X { operator int&(); }; -int&& rri2 = X(); // error: result of conversion function is lvalue of related type +int&& rri2 = X(); // error: result of conversion function is + // lvalue of reference-related type int i3 = 2; double&& rrd3 = i3; // \tcode{rrd3} refers to temporary with value \tcode{2.0} \end{codeblock} @@ -5615,19 +6264,22 @@ list-initialization in a direct-initialization context is called \defn{direct-list-initialization} and list-initialization in a copy-initialization context is called \defn{copy-list-initialization}. +Direct-initialization that is not list-initialization is called +\defn{direct-non-list-initialization}. \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 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} @@ -5665,11 +6317,12 @@ 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} -contains a \grammarterm{designated-initializer-list}, +contains a \grammarterm{designated-initializer-list} and +\tcode{T} is not a reference type, \tcode{T} shall be an aggregate class. The ordered \grammarterm{identifier}{s} in the \grammarterm{designator}{s} @@ -5687,7 +6340,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 @@ -5718,7 +6371,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. @@ -5732,12 +6385,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} @@ -5766,7 +6421,7 @@ \item Otherwise, if \tcode{T} is an enumeration with a fixed underlying type\iref{dcl.enum} \tcode{U}, -the \grammarterm{initializer-list} has a single element \tcode{v}, +the \grammarterm{initializer-list} has a single element \tcode{v} of scalar type, \tcode{v} can be implicitly converted to \tcode{U}, and the initialization is direct-list-initialization, the object is initialized with the value \tcode{T(v)}\iref{expr.type.conv}; @@ -5793,7 +6448,9 @@ \end{example} \item Otherwise, if -the initializer list has a single element of type \tcode{E} and either +the initializer list +is not a \grammarterm{designated-initializer-list} and +has a single element of type \tcode{E} and either \tcode{T} is not a reference type or its referenced type is reference-related to \tcode{E}, the object or reference is initialized from that element (by copy-initialization for copy-list-initialization, @@ -5809,11 +6466,11 @@ \end{example} \item Otherwise, if \tcode{T} is a reference type, a prvalue is generated. -The prvalue initializes its result object by copy-list-initialization. +The prvalue initializes its result object by copy-list-initialization from the initializer list. The prvalue is then used to direct-initialize the reference. -The type of the temporary is the type referenced by \tcode{T}, +The type of the prvalue is the type referenced by \tcode{T}, unless \tcode{T} is ``reference to array of unknown bound of \tcode{U}'', -in which case the type of the temporary is +in which case the type of the prvalue is the type of \tcode{x} in the declaration \tcode{U x[] $H$}, where $H$ is the initializer list. \begin{note} @@ -5838,6 +6495,9 @@ struct A { } a; struct B { explicit B(const A&); }; const B& b2{a}; // error: cannot copy-list-initialize \tcode{B} temporary from \tcode{A} + +struct C { int x; }; +C&& c = { .x = 1 }; // OK \end{codeblock} \end{example} @@ -5896,36 +6556,65 @@ an initializer list as if the implementation generated and materialized\iref{conv.rval} a prvalue of type ``array of $N$ \tcode{const E}'', -where $N$ is the number of elements in the -initializer list. Each element of that array is copy-initialized with the +where $N$ is the number of elements in the initializer list; +this is called the initializer list's \defnadj{backing}{array}. +Each element of the backing array is copy-initialized with the corresponding element of the initializer list, and the \tcode{std::initializer_list} object is constructed to refer to that array. \begin{note} -A constructor or conversion function selected for the copy is required to be +A constructor or conversion function selected for the copy needs to be accessible\iref{class.access} in the context of the initializer list. \end{note} -If a narrowing conversion is required to initialize any of the elements, the program is ill-formed. +If a narrowing conversion is required to initialize any of the elements, +the program is ill-formed. +\begin{note} +Backing arrays are potentially non-unique objects\iref{intro.object}. +\end{note} + +\pnum +The backing array has the same lifetime as any other temporary +object\iref{class.temporary}, except that initializing an +\tcode{initializer_list} object from the array extends the lifetime of +the array exactly like binding a reference to a temporary. \begin{example} \begin{codeblock} -struct X { - X(std::initializer_list v); +void f(std::initializer_list il); +void g(float x) { + f({1, x, 3}); +} +void h() { + f({1, 2, 3}); +} + +struct A { + mutable int i; }; -X x{ 1,2,3 }; +void q(std::initializer_list); +void r() { + q({A{1}, A{2}, A{3}}); +} \end{codeblock} The initialization will be implemented in a way roughly equivalent to this: \begin{codeblock} -const double __a[3] = {double{1}, double{2}, double{3}}; -X x(std::initializer_list(__a, __a+3)); +void g(float x) { + const double __a[3] = {double{1}, double{x}, double{3}}; // backing array + f(std::initializer_list(__a, __a+3)); +} +void h() { + static constexpr double __b[3] = {double{1}, double{2}, double{3}}; // backing array + f(std::initializer_list(__b, __b+3)); +} +void r() { + const A __c[3] = {A{1}, A{2}, A{3}}; // backing array + q(std::initializer_list(__c, __c+3)); +} \end{codeblock} -assuming that the implementation can construct an \tcode{initializer_list} object with a pair of pointers. +assuming that the implementation +can construct an \tcode{initializer_list} object with a pair of pointers, and +with the understanding that \tcode{__b} does not outlive the call to \tcode{f}. \end{example} -\pnum -The array has the same lifetime as any other temporary -object\iref{class.temporary}, except that initializing an -\tcode{initiali\-zer_list} object from the array extends the lifetime of -the array exactly like binding a reference to a temporary. \begin{example} \begin{codeblock} typedef std::complex cmplx; @@ -5952,9 +6641,6 @@ a temporary array to a reference member, so the program is ill-formed\iref{class.base.init}. \end{example} -\begin{note} -The implementation is free to allocate the array in read-only memory if an explicit array with the same initializer can be so allocated. -\end{note} \pnum A \defnadj{narrowing}{conversion} is an implicit conversion @@ -5964,10 +6650,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 @@ -5975,8 +6660,18 @@ original type, or \item from an integer type or unscoped enumeration type to an integer type that cannot -represent all the values of the original type, except where the source is a constant +represent all the values of the original type, except where +\begin{itemize} +\item +the source is a bit-field whose width $w$ is less than that of its type +(or, for an enumeration type, its underlying type) and +the target type can represent all the values +of a hypothetical extended integer type +with width $w$ and with the same signedness as the original type or +\item +the source is a constant expression whose value after integral promotions will fit into the target type, or +\end{itemize} \item from a pointer type or a pointer-to-member type to \tcode{bool}. \end{itemize} @@ -6014,7 +6709,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}% @@ -6023,8 +6718,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} @@ -6032,15 +6729,28 @@ \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 -the non-terminal \grammarterm{function-body}. +the non-terminal \grammarterm{function-body}, +including, for a constructor, +default member initializers or default initialization +used to initialize +a base or member subobject in the absence of +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}, @@ -6149,42 +6859,40 @@ 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 An explicitly defaulted special member function $\tcode{F}_1$ -with type $\tcode{T}_1$ is allowed to differ from the corresponding special member function $\tcode{F}_2$ -with type $\tcode{T}_2$ that would have been implicitly declared, as follows: \begin{itemize} \item - $\tcode{T}_1$ and $\tcode{T}_2$ may have differing \grammarterm{ref-qualifier}{s}; + $\tcode{F}_1$ and $\tcode{F}_2$ may have differing \grammarterm{ref-qualifier}{s}; \item if $\tcode{F}_2$ has an implicit object parameter of type ``reference to \tcode{C}'', $\tcode{F}_1$ may be an explicit object member function whose - explicit object parameter is of type ``reference to \tcode{C}'', - in which case $\tcode{T}_1$ would differ from $\tcode{T}_2$ - in that $\tcode{T}_1$ has an additional parameter; + explicit object parameter is of (possibly different) type ``reference to \tcode{C}'', + in which case the type of $\tcode{F}_1$ would differ from the type of $\tcode{F}_2$ + in that the type of $\tcode{F}_1$ has an additional parameter; \item - $\tcode{T}_1$ and $\tcode{T}_2$ may have differing exception specifications; and + $\tcode{F}_1$ and $\tcode{F}_2$ may have differing exception specifications; and \item if $\tcode{F}_2$ has a non-object parameter of type \tcode{const C\&}, the corresponding non-object parameter of $\tcode{F}_1$ may be of type \tcode{C\&}. \end{itemize} -If $\tcode{T}_1$ differs from $\tcode{T}_2$ in a way +If the type of $\tcode{F}_1$ differs from the type of $\tcode{F}_2$ in a way other than as allowed by the preceding rules, then: \begin{itemize} \item if $\tcode{F}_1$ is an assignment operator, and - the return type of $\tcode{T}_1$ differs from - the return type of $\tcode{T}_2$ or + the return type of $\tcode{F}_1$ differs from + the return type of $\tcode{F}_2$ or $\tcode{F}_1${'s} non-object parameter type is not a reference, the program is ill-formed; \item @@ -6198,7 +6906,10 @@ A function explicitly defaulted on its first declaration is implicitly inline\iref{dcl.inline}, and is implicitly constexpr\iref{dcl.constexpr} -if it satisfies the requirements for a constexpr function. +if it is constexpr-suitable. +\begin{note} +Other defaulted functions are not implicitly constexpr. +\end{note} \pnum \begin{example} @@ -6231,7 +6942,7 @@ Explicitly-defaulted functions and implicitly-declared functions are collectively called \defn{defaulted} functions, and the implementation shall provide implicit definitions -for them\iref{class.ctor,class.dtor,class.copy.ctor,class.copy.assign}, +for them\iref{class.ctor,class.dtor,class.copy.ctor,class.copy.assign} as described below, including possibly defining them as deleted. A defaulted prospective destructor\iref{class.dtor} that is not a destructor is defined as deleted. @@ -6243,13 +6954,20 @@ \defn{user-provided} if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) -is defined at the point where it is explicitly defaulted; if such a function is implicitly +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. +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} +The implicit definition of a non-user-provided defaulted function +does not bind any names. \end{note} \pnum @@ -6275,11 +6993,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 @@ -6289,6 +7004,12 @@ \pnum A program that refers to a deleted function implicitly or explicitly, other than to declare it, 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 @@ -6297,6 +7018,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 @@ -6417,17 +7141,23 @@ where $\tcode{p}_1$ denotes the object parameter and $\tcode{p}_{i+1}$ denotes the $i^\text{th}$ non-object function parameter -for a non-static member function, and +for an implicit object member function, and $\tcode{p}_i$ denotes the $i^\text{th}$ function parameter otherwise. -For a non-static member function, +For an implicit object member function, $\tcode{q}_1$ is an lvalue that denotes \tcode{*this}; any other $\tcode{q}_i$ is an lvalue that denotes the parameter copy corresponding to $\tcode{p}_i$, 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 @@ -6448,19 +7178,20 @@ where \begin{itemize} \item +\indextext{coroutine!await expression}% the \grammarterm{await-expression} containing the call to \tcode{initial_suspend} -is the \defn{initial suspend point}, and +is the \defnadj{initial}{await expression}, and \item the \grammarterm{await-expression} containing the call to \tcode{final_suspend} -is the \defn{final suspend point}, and +is the \defnadj{final}{await expression}, and \item \placeholder{initial-await-resume-called} is initially \tcode{false} and is set to \tcode{true} immediately before the evaluation of the \placeholder{await-resume} expression\iref{expr.await} -of the initial suspend point, and +of the initial await expression, and \item \placeholder{promise-type} denotes the promise type, and \item @@ -6476,8 +7207,27 @@ constructor is found\iref{over.match.viable}, then \placeholder{promise-constructor-arguments} is \tcode{($\tcode{q}_1$, $\dotsc$, $\tcode{q}_n$)}, otherwise -\placeholder{promise-constructor-arguments} is empty. +\placeholder{promise-constructor-arguments} is empty, and +\item +a coroutine is suspended at the \defnadj{initial}{suspend point} if +it is suspended at the initial await expression, and +\item +a coroutine is suspended at a \defnadj{final}{suspend point} if +it is suspended +\begin{itemize} +\item +at a final await expression or +\item +due to an exception exiting from \tcode{unhandled_exception()}. \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} @@ -6504,7 +7254,7 @@ a resumption member function\iref{coroutine.handle.resumption} of a coroutine handle\iref{coroutine.handle} that refers to the coroutine. -The function that invoked a resumption member function is +The evaluation that invoked a resumption member function is called the \defnx{resumer}{coroutine!resumer}. Invoking a resumption member function for a coroutine that is not suspended results in undefined behavior. @@ -6512,7 +7262,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 @@ -6520,7 +7271,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 @@ -6541,7 +7294,7 @@ the \tcode{::operator new(size_t, nothrow_t)} form is used. The allocation function used in this case shall have a non-throwing \grammarterm{noexcept-specifier}. -If the allocation function returns \keyword{nullptr}, the coroutine returns +If the allocation function returns \keyword{nullptr}, the coroutine transfers control to the caller of the coroutine and the return value is obtained by a call to \tcode{T::get_return_object_on_allocation_failure()}, where \tcode{T} is the promise type. @@ -6616,16 +7369,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 @@ -6642,26 +7408,75 @@ \pnum If the evaluation of the expression \tcode{\exposid{promise}.unhandled_exception()} exits via an exception, -the coroutine is considered suspended at the final suspend point. +the coroutine is considered suspended at the final suspend point +and the exception propagates to the caller or resumer. \pnum 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 @@ -6689,15 +7504,56 @@ \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 +If \tcode{E} is an 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} @@ -6708,6 +7564,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} @@ -6718,8 +7587,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$. @@ -6727,7 +7595,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}. @@ -6749,9 +7617,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, @@ -6761,12 +7635,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}; @@ -6896,16 +7770,17 @@ not omit the \grammarterm{enum-base}. The identifiers in an \grammarterm{enumerator-list} are declared as constants, and can appear wherever constants are required. +The same identifier shall not appear as +the name of multiple enumerators in an \grammarterm{enumerator-list}. \indextext{enumerator!value of}% An \grammarterm{enumerator-definition} with \tcode{=} gives the associated \grammarterm{enumerator} the value indicated by the \grammarterm{constant-expression}. -If the first \grammarterm{enumerator} -has no \grammarterm{initializer}, the value of the corresponding constant -is zero. An \grammarterm{enumerator-definition} without an -\grammarterm{initializer} gives the \grammarterm{enumerator} the value -obtained by increasing the value of the previous \grammarterm{enumerator} -by one. +An \grammarterm{enumerator-definition} without \tcode{=} gives the associated +\grammarterm{enumerator} the value zero +if it is the first \grammarterm{enumerator-definition}, +and the value of the previous \grammarterm{enumerator} +increased by one otherwise. \begin{example} \begin{codeblock} enum { a, b, c=0 }; @@ -7027,6 +7902,15 @@ this range. \end{footnote} +\pnum +An enumeration has +the same size, +value representation, and +alignment requirements\iref{basic.align} +as its underlying type. +Furthermore, each value of an enumeration has the same representation +as the corresponding value of the underlying type. + \pnum Two enumeration types are \defnx{layout-compatible enumerations}{layout-compatible!enumeration} if they have the same underlying type. @@ -7081,7 +7965,7 @@ \begin{codeblock} enum direction { left='l', right='r' }; -void g() { +void g() { direction d; // OK d = left; // OK d = direction::right; // OK @@ -7089,7 +7973,7 @@ enum class altitude { high='h', low='l' }; -void h() { +void h() { altitude a; // OK a = high; // error: \tcode{high} not in scope a = altitude::low; // OK @@ -7102,13 +7986,38 @@ \begin{bnf} \nontermdef{using-enum-declaration}\br - \terminal{using} elaborated-enum-specifier \terminal{;} + \keyword{using} \keyword{enum} using-enum-declarator \terminal{;} +\end{bnf} + +\begin{bnf} +\nontermdef{using-enum-declarator}\br + \opt{nested-name-specifier} identifier\br + \opt{nested-name-specifier} simple-template-id \end{bnf} \pnum -The \grammarterm{elaborated-enum-specifier} -shall not name a dependent type -and the type shall have a reachable \grammarterm{enum-specifier}. +A \grammarterm{using-enum-declarator} +names the set of declarations found by +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} @@ -7786,6 +8695,22 @@ \pnum If a declaration is named by two \grammarterm{using-declarator}s that inhabit the same class scope, the program is ill-formed. +\begin{example} +\begin{codeblock} +struct C { + int i; +}; + +struct D1 : C { }; +struct D2 : C { }; + +struct D3 : D1, D2 { + using D1::i; // OK, equivalent to \tcode{using C::i} + using D1::i; // error: duplicate + using D2::i; // error: duplicate, also names \tcode{C::i} +}; +\end{codeblock} +\end{example} \pnum \begin{note} @@ -7821,9 +8746,21 @@ \pnum If a declaration named by a \grammarterm{using-declaration} -that inhabits the target scope of another declaration +that inhabits the target scope of another declaration $B$ potentially conflicts with it\iref{basic.scope.scope}, and -either is reachable from the other, the program is ill-formed. +either is reachable from the other, the program is ill-formed +unless $B$ is name-independent and +the \grammarterm{using-declaration} precedes $B$. +\begin{example} +\begin{codeblock} +int _; +void f() { + int _; // B + _ = 0; + using ::_; // error: \grammarterm{using-declaration} does not precede B +} +\end{codeblock} +\end{example} If two declarations named by \grammarterm{using-declaration}s that inhabit the same scope potentially conflict, either is reachable from the other, and @@ -7868,6 +8805,7 @@ using A::h; // error: conflicts using B::x; using A::x; // OK, hides \tcode{struct B::x} + using A::x; // OK, does not conflict with previous \tcode{using A::x} x = 99; // assigns to \tcode{A::x} struct x x1; // \tcode{x1} has class type \tcode{B::x} } @@ -8029,11 +8967,12 @@ An \tcode{asm} declaration has the form \begin{bnf} \nontermdef{asm-declaration}\br - \opt{attribute-specifier-seq} \keyword{asm} \terminal{(} string-literal \terminal{)} \terminal{;} + \opt{attribute-specifier-seq} \keyword{asm} \terminal{(} balanced-token-seq \terminal{)} \terminal{;} \end{bnf} -The \tcode{asm} declaration is conditionally-supported; its meaning is -\impldef{meaning of \tcode{asm} declaration}. +The \tcode{asm} declaration is conditionally-supported; +any restrictions on the \grammarterm{balanced-token-seq} and +its meaning are \impldef{meaning of \tcode{asm} declaration}. The optional \grammarterm{attribute-specifier-seq} in an \grammarterm{asm-declaration} appertains to the \tcode{asm} declaration. \begin{note} @@ -8069,25 +9008,30 @@ % \begin{bnf} \nontermdef{linkage-specification}\br - \keyword{extern} string-literal \terminal{\{} \opt{declaration-seq} \terminal{\}}\br - \keyword{extern} string-literal declaration + \keyword{extern} unevaluated-string \terminal{\{} \opt{declaration-seq} \terminal{\}}\br + \keyword{extern} unevaluated-string name-declaration \end{bnf} -The \grammarterm{string-literal} indicates the required language linkage. +The \grammarterm{unevaluated-string} indicates the required language linkage. +\begin{note} +Escape sequences and \grammarterm{universal-character-name}s +have been replaced\iref{lex.string.uneval}. +\end{note} This document specifies the semantics for the -\grammarterm{string-literal}{s} \tcode{"C"} and \tcode{"C++"}. Use of a -\grammarterm{string-literal} other than \tcode{"C"} or \tcode{"C++"} is -conditionally-supported, with \impldef{semantics of linkage specifiers} semantics. +\grammarterm{unevaluated-string}{s} \tcode{"C"} and \tcode{"C++"}. +Use of an \grammarterm{unevaluated-string} +other than \tcode{"C"} or \tcode{"C++"} is conditionally-supported, +with \impldef{semantics of linkage specifiers} semantics. \begin{note} -Therefore, a linkage-specification with a \grammarterm{string-literal} that -is unknown to the implementation requires a diagnostic. +Therefore, a \grammarterm{linkage-specification} with a language linkage +that is unknown to the implementation requires a diagnostic. \end{note} \recommended -The spelling of the \grammarterm{string-literal} should be -taken from the document defining that language. For example, \tcode{Ada} -(not \tcode{ADA}) and \tcode{Fortran} or \tcode{FORTRAN}, depending on -the vintage. +The spelling of the language linkage should be taken +from the document defining that language. +For example, \tcode{Ada} (not \tcode{ADA}) and +\tcode{Fortran} or \tcode{FORTRAN}, depending on the vintage. \pnum \indextext{specification!linkage!implementation-defined}% @@ -8104,9 +9048,6 @@ \end{example} \pnum -A \grammarterm{module-import-declaration} -shall not be directly contained in -a \grammarterm{linkage-specification}. A \grammarterm{module-import-declaration} appearing in a linkage specification with other than \Cpp{} language linkage is conditionally-supported with @@ -8124,7 +9065,7 @@ In a \grammarterm{linkage-specification}, the specified language linkage applies to the function types of all function declarators and -to all functions and variables. +to all functions and variables whose names have external linkage. \begin{example} \begin{codeblock} extern "C" // \tcode{f1} and its function type have C language linkage; @@ -8163,7 +9104,7 @@ in determining the language linkage of class members, friend functions with a trailing \grammarterm{requires-clause}, and the -function type of class member functions. +function type of non-static class member functions. \begin{example} \begin{codeblock} extern "C" typedef void FUNC_c(); @@ -8231,7 +9172,7 @@ \keyword{extern} specifier\iref{dcl.stc} for the purpose of determining the linkage of the declared name and whether it is a definition. Such a declaration shall -not specify a storage class. +not have a \grammarterm{storage-class-specifier}. \begin{example} \begin{codeblock} extern "C" double f(); @@ -8254,8 +9195,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.% @@ -8269,11 +9210,11 @@ \pnum \indextext{attribute!syntax and semantics}% Attributes specify additional information for various source constructs -such as types, variables, names, blocks, or translation units. +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} @@ -8329,11 +9270,11 @@ \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} \nontermdef{balanced-token}\br \terminal{(} \opt{balanced-token-seq} \terminal{)}\br \terminal{[} \opt{balanced-token-seq} \terminal{]}\br @@ -8392,7 +9333,7 @@ \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 @@ -8400,7 +9341,7 @@ appertains to a friend declaration\iref{class.friend}, that declaration shall be a definition. \begin{note} -An \grammarterm{attribute-specifier-seq} cannot appeartain to +An \grammarterm{attribute-specifier-seq} cannot appertain to an explicit instantiation\iref{temp.explicit}. \end{note} @@ -8408,9 +9349,26 @@ For an \grammarterm{attribute-token} (including an \grammarterm{attribute-scoped-token}) not specified in this document, the -behavior is \impldef{behavior of non-standard attributes}. -Any \grammarterm{attribute-token} that is not recognized by the implementation +behavior is \impldef{behavior of non-standard attributes}; +any such \grammarterm{attribute-token} that is not recognized by the implementation is ignored. +\begin{note} +A program is ill-formed if it contains an \grammarterm{attribute} +specified in \ref{dcl.attr} that violates +the rules specifying to which entity or statement the attribute can apply or +the syntax rules for the attribute's \grammarterm{attribute-argument-clause}, if any. +\end{note} +\begin{note} +The \grammarterm{attribute}{s} specified in \ref{dcl.attr} +have optional semantics: +given a well-formed program, +removing all instances of any one of those \grammarterm{attribute}{s} +results in a program whose set of possible executions\iref{intro.abstract} +for a given input is +a subset of those of the original program for the same input, +absent implementation-defined guarantees +with respect to that \grammarterm{attribute}. +\end{note} An \grammarterm{attribute-token} is reserved for future standardization if \begin{itemize} \item it is not an \grammarterm{attribute-scoped-token} and @@ -8546,6 +9504,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 @@ -8558,7 +9517,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 @@ -8566,7 +9528,14 @@ deduce information used to optimize the program. Implementations are not required to deduce any information from any particular assumption. +It is expected that the value of +a \grammarterm{has-attribute-expression} for the \tcode{assume} attribute +is \tcode{0} +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) { @@ -8581,86 +9550,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} @@ -8675,10 +9564,10 @@ An \grammarterm{attribute-argument-clause} may be present and, if present, it shall have the form: \begin{ncbnf} -\terminal{(} string-literal \terminal{)} +\terminal{(} unevaluated-string \terminal{)} \end{ncbnf} \begin{note} -The \grammarterm{string-literal} in the \grammarterm{attribute-argument-clause} +The \grammarterm{unevaluated-string} in the \grammarterm{attribute-argument-clause} can be used to explain the rationale for deprecation and/or to suggest a replacing entity. \end{note} @@ -8691,7 +9580,8 @@ a function, a namespace, an enumeration, -an enumerator, or +an enumerator, +a concept, or a template specialization. \pnum @@ -8713,6 +9603,10 @@ declaration that specifies the attribute. The diagnostic message should include the text provided within the \grammarterm{attribute-argument-clause} of any \tcode{deprecated} attribute applied to the name or entity. +The value of +a \grammarterm{has-attribute-expression} for the \tcode{deprecated} attribute +should be \tcode{0} +unless the implementation can issue such diagnostic messages. \rSec2[dcl.attr.fallthrough]{Fallthrough attribute} \indextext{attribute!fallthrough} @@ -8739,6 +9633,10 @@ a warning that an implementation might otherwise issue for a case or default label that is reachable from another case or default label along some path of execution. +The value of +a \grammarterm{has-attribute-expression} for the \tcode{fallthrough} attribute +should be \tcode{0} +if the attribute does not cause suppression of such warnings. Implementations should issue a warning if a fallthrough statement is not dynamically reachable. @@ -8774,6 +9672,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} @@ -8788,7 +9732,7 @@ that contains the \grammarterm{attribute-token} \tcode{unlikely}. \pnum -\recommended +\begin{note} The use of the \tcode{likely} attribute is intended to allow implementations to optimize for the case where paths of execution including it @@ -8801,8 +9745,14 @@ are arbitrarily more unlikely than any alternative path of execution that does not include such an attribute on a statement or label. +It is expected that the value of a \grammarterm{has-attribute-expression} +for the \tcode{likely} and \tcode{unlikely} attributes +is \tcode{0} +if the implementation does not attempt to use these attributes +for such optimizations. A path of execution includes a label if and only if it contains a jump to that label. +\end{note} \begin{note} Excessive usage of either of these attributes is liable to result in performance degradation. @@ -8837,15 +9787,20 @@ \pnum The \grammarterm{attribute-token} \tcode{maybe_unused} -indicates that a name or entity is possibly intentionally unused. +indicates that a name, label, or entity is possibly intentionally unused. No \grammarterm{attribute-argument-clause} shall be present. \pnum The attribute may be applied to the declaration of a class, -a \grammarterm{typedef-name}, -a variable (including a structured binding declaration), -a non-static data member, -a function, an enumeration, or an enumerator. +\grammarterm{typedef-name}, +variable (including a structured binding declaration), +structured binding, +result binding\iref{dcl.contract.res}, +non-static data member, +function, +enumeration, or +enumerator, or +to an \grammarterm{identifier} label\iref{stmt.label}. \pnum A name or entity declared without the \tcode{maybe_unused} attribute @@ -8863,6 +9818,12 @@ For a structured binding declaration not marked \tcode{maybe_unused}, implementations should not emit such a warning unless all of its structured bindings are unused. +For a label to which \tcode{maybe_unused} is applied, +implementations should not emit a warning that the label is used or unused. +The value of +a \grammarterm{has-attribute-expression} for the \tcode{maybe_unused} attribute +should be \tcode{0} +if the attribute does not cause suppression of such warnings. \pnum \begin{example} @@ -8871,9 +9832,13 @@ [[maybe_unused]] bool thing2) { [[maybe_unused]] bool b = thing1 && thing2; assert(b); +#ifdef NDEBUG + goto x; +#endif + [[maybe_unused]] x: } \end{codeblock} -Implementations should not warn that \tcode{b} is unused, +Implementations should not warn that \tcode{b} or \tcode{x} is unused, whether or not \tcode{NDEBUG} is defined. \end{example} @@ -8888,7 +9853,7 @@ and, if present, shall have the form: \begin{ncbnf} -\terminal{(} string-literal \terminal{)} +\terminal{(} unevaluated-string \terminal{)} \end{ncbnf} \pnum @@ -8929,13 +9894,17 @@ \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 +a \grammarterm{has-attribute-expression} for the \tcode{nodiscard} attribute +should be \tcode{0} unless the implementation can issue such warnings. \begin{note} This is typically because discarding the return value of a nodiscard call has surprising consequences. \end{note} -The \grammarterm{string-literal} +The \grammarterm{unevaluated-string} in a \tcode{nodiscard} \grammarterm{attribute-argument-clause} should be used in the message of the warning as the rationale for why the result should not be discarded. @@ -8982,10 +9951,11 @@ 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 may +The function can terminate by throwing an exception. \end{note} @@ -8993,6 +9963,9 @@ \recommended Implementations should issue a warning if a function marked \tcode{[[noreturn]]} might return. +The value of +a \grammarterm{has-attribute-expression} for the \tcode{noreturn} attribute +should be \tcode{0} unless the implementation can issue such warnings. \pnum \begin{example} @@ -9027,6 +10000,14 @@ at the end of the object can be reused as storage for other members. \end{note} + +\recommended +The value of a \grammarterm{has-attribute-expression} +for the \tcode{no_unique_address} attribute +should be \tcode{0} for a given implementation +unless this attribute can cause a potentially-overlapping subobject +to have zero size. + \begin{example} \begin{codeblock} template} \\ \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} @@ -451,25 +452,56 @@ \pnum The header \libheaderdef{cassert} provides a macro for documenting \Cpp{} program assertions and a mechanism -for disabling the assertion checks. +for disabling the assertion checks through defining the macro \tcode{NDEBUG}. \rSec2[cassert.syn]{Header \tcode{} synopsis} -\indexlibraryglobal{assert}% \begin{codeblock} -#define assert(E) @\seebelow@ +#define @\libmacro{assert}@(...) @\seebelow@ \end{codeblock} +\rSec2[assertions.assert]{The \tcode{assert} macro} + \pnum -\indextext{static_assert@\tcode{static_assert}!not macro}% -The contents are the same as the C standard library header -\libheader{assert.h}, -except that a macro named \keyword{static_assert} -is not defined. +If \tcode{NDEBUG} is defined as a macro name +at the point in the source file where \tcode{} is included, +the \tcode{assert} macro is defined as +\begin{codeblock} +#define @\libmacro{assert}@(...) ((void)0) +\end{codeblock} -\xrefc{7.2} +\pnum +Otherwise, the \libmacro{assert} macro puts a diagnostic test into programs; +it expands to an expression of type \keyword{void} which +has the following effects: -\rSec2[assertions.assert]{The \tcode{assert} macro} +\begin{itemize} +\item +\mname{VA_ARGS} is evaluated and contextually converted to \tcode{bool}. +\item +If the evaluation yields \tcode{true} there are no further effects. +\item +Otherwise, the \tcode{assert} macro's expression +creates a diagnostic on the standard error stream in an +\impldef{format of diagnostic created by \tcode{assert} macro's expression} +format and calls \tcode{abort()}. +The diagnostic contains \tcode{\#}\mname{VA_ARGS} and +information on +the name of the source file, +the source line number, and +the name of the enclosing function +(such as provided by \tcode{source_location::current()}). +\end{itemize} + +\pnum +If \mname{VA_ARGS} does not expand to +an \grammarterm{assignment-expression}, +the program is ill-formed. + +\pnum +The macro \tcode{assert} is redefined according to +the current state of \tcode{NDEBUG} each time that +\tcode{} is included. \pnum An expression \tcode{assert(E)} @@ -489,174 +521,91 @@ \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} -A separate \tcode{errno} value shall be provided for each thread. +A separate \tcode{errno} value is provided for each thread. \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{ENODATA}% -\indexlibraryglobal{ENODEV}% -\indexlibraryglobal{ENOENT}% -\indexlibraryglobal{ENOEXEC}% -\indexlibraryglobal{ENOLCK}% -\indexlibraryglobal{ENOLINK}% -\indexlibraryglobal{ENOMEM}% -\indexlibraryglobal{ENOMSG}% -\indexlibraryglobal{ENOPROTOOPT}% -\indexlibraryglobal{ENOSPC}% -\indexlibraryglobal{ENOSR}% -\indexlibraryglobal{ENOSTR}% -\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{ETIME}% -\indexlibraryglobal{ETIMEDOUT}% -\indexlibraryglobal{ETXTBSY}% -\indexlibraryglobal{EWOULDBLOCK}% -\indexlibraryglobal{EXDEV}% \begin{codeblock} -#define errno @\seebelow@ - -#define E2BIG @\seebelow@ -#define EACCES @\seebelow@ -#define EADDRINUSE @\seebelow@ -#define EADDRNOTAVAIL @\seebelow@ -#define EAFNOSUPPORT @\seebelow@ -#define EAGAIN @\seebelow@ -#define EALREADY @\seebelow@ -#define EBADF @\seebelow@ -#define EBADMSG @\seebelow@ -#define EBUSY @\seebelow@ -#define ECANCELED @\seebelow@ -#define ECHILD @\seebelow@ -#define ECONNABORTED @\seebelow@ -#define ECONNREFUSED @\seebelow@ -#define ECONNRESET @\seebelow@ -#define EDEADLK @\seebelow@ -#define EDESTADDRREQ @\seebelow@ -#define EDOM @\seebelow@ -#define EEXIST @\seebelow@ -#define EFAULT @\seebelow@ -#define EFBIG @\seebelow@ -#define EHOSTUNREACH @\seebelow@ -#define EIDRM @\seebelow@ -#define EILSEQ @\seebelow@ -#define EINPROGRESS @\seebelow@ -#define EINTR @\seebelow@ -#define EINVAL @\seebelow@ -#define EIO @\seebelow@ -#define EISCONN @\seebelow@ -#define EISDIR @\seebelow@ -#define ELOOP @\seebelow@ -#define EMFILE @\seebelow@ -#define EMLINK @\seebelow@ -#define EMSGSIZE @\seebelow@ -#define ENAMETOOLONG @\seebelow@ -#define ENETDOWN @\seebelow@ -#define ENETRESET @\seebelow@ -#define ENETUNREACH @\seebelow@ -#define ENFILE @\seebelow@ -#define ENOBUFS @\seebelow@ -#define ENODATA @\seebelow@ -#define ENODEV @\seebelow@ -#define ENOENT @\seebelow@ -#define ENOEXEC @\seebelow@ -#define ENOLCK @\seebelow@ -#define ENOLINK @\seebelow@ -#define ENOMEM @\seebelow@ -#define ENOMSG @\seebelow@ -#define ENOPROTOOPT @\seebelow@ -#define ENOSPC @\seebelow@ -#define ENOSR @\seebelow@ -#define ENOSTR @\seebelow@ -#define ENOSYS @\seebelow@ -#define ENOTCONN @\seebelow@ -#define ENOTDIR @\seebelow@ -#define ENOTEMPTY @\seebelow@ -#define ENOTRECOVERABLE @\seebelow@ -#define ENOTSOCK @\seebelow@ -#define ENOTSUP @\seebelow@ -#define ENOTTY @\seebelow@ -#define ENXIO @\seebelow@ -#define EOPNOTSUPP @\seebelow@ -#define EOVERFLOW @\seebelow@ -#define EOWNERDEAD @\seebelow@ -#define EPERM @\seebelow@ -#define EPIPE @\seebelow@ -#define EPROTO @\seebelow@ -#define EPROTONOSUPPORT @\seebelow@ -#define EPROTOTYPE @\seebelow@ -#define ERANGE @\seebelow@ -#define EROFS @\seebelow@ -#define ESPIPE @\seebelow@ -#define ESRCH @\seebelow@ -#define ETIME @\seebelow@ -#define ETIMEDOUT @\seebelow@ -#define ETXTBSY @\seebelow@ -#define EWOULDBLOCK @\seebelow@ -#define EXDEV @\seebelow@ +#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 @@ -674,8 +623,10 @@ the operating system or other low-level application program interfaces. \pnum -Components described in \ref{syserr} shall not change the value of +Components described in \ref{syserr} do not change the value of \tcode{errno}\iref{errno}. + +\recommended Implementations should leave the error states provided by other libraries unchanged. @@ -686,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} @@ -702,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 { + enum class @\libglobal{errc}@ { // freestanding address_family_not_supported, // \tcode{EAFNOSUPPORT} address_in_use, // \tcode{EADDRINUSE} address_not_available, // \tcode{EADDRNOTAVAIL} @@ -748,18 +696,15 @@ no_child_process, // \tcode{ECHILD} no_link, // \tcode{ENOLINK} no_lock_available, // \tcode{ENOLCK} - no_message_available, // \tcode{ENODATA} no_message, // \tcode{ENOMSG} no_protocol_option, // \tcode{ENOPROTOOPT} no_space_on_device, // \tcode{ENOSPC} - no_stream_resources, // \tcode{ENOSR} no_such_device_or_address, // \tcode{ENXIO} no_such_device, // \tcode{ENODEV} no_such_file_or_directory, // \tcode{ENOENT} no_such_process, // \tcode{ESRCH} not_a_directory, // \tcode{ENOTDIR} not_a_socket, // \tcode{ENOTSOCK} - not_a_stream, // \tcode{ENOSTR} not_connected, // \tcode{ENOTCONN} not_enough_memory, // \tcode{ENOMEM} not_supported, // \tcode{ENOTSUP} @@ -777,7 +722,6 @@ resource_unavailable_try_again, // \tcode{EAGAIN} result_out_of_range, // \tcode{ERANGE} state_not_recoverable, // \tcode{ENOTRECOVERABLE} - stream_timeout, // \tcode{ETIME} text_file_busy, // \tcode{ETXTBSY} timed_out, // \tcode{ETIMEDOUT} too_many_files_open_in_system, // \tcode{ENFILE} @@ -814,14 +758,14 @@ // \ref{syserr}, system error support template - inline 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 - inline constexpr bool is_error_condition_enum_v = is_error_condition_enum::value; + constexpr bool is_error_condition_enum_v = is_error_condition_enum::value; } \end{codeblock} \pnum -The value of each \tcode{enum errc} constant shall be the same as +The value of each \tcode{enum errc} enumerator is the same as the value of the \libheader{cerrno} macro shown in the above synopsis. Whether or not the \libheader{system_error} implementation exposes the \libheader{cerrno} macros is unspecified. @@ -1098,8 +1042,8 @@ explicit operator bool() const noexcept; private: - int val_; // \expos - const error_category* cat_; // \expos + int @\exposid{val_}@; // \expos + const error_category* @\exposid{cat_}@; // \expos }; // \ref{syserr.errcode.nonmembers}, non-member functions @@ -1120,8 +1064,9 @@ \begin{itemdescr} \pnum -\ensures -\tcode{val_ == 0} and \tcode{cat_ == \&system_category()}. +\effects +Initializes \exposid{val_} with \tcode{0} +and \exposid{cat_} with \tcode{\&system_category()}. \end{itemdescr} \indexlibraryctor{error_code}% @@ -1131,8 +1076,9 @@ \begin{itemdescr} \pnum -\ensures -\tcode{val_ == val} and \tcode{cat_ == \&cat}. +\effects +Initializes \exposid{val_} with \tcode{val} +and \exposid{cat_} with \tcode{\&cat}. \end{itemdescr} \indexlibraryctor{error_code}% @@ -1147,8 +1093,12 @@ \tcode{is_error_code_enum_v} is \tcode{true}. \pnum -\ensures -\tcode{*this == make_error_code(e)}. +\effects +Equivalent to: +\begin{codeblock} +error_code ec = make_error_code(e); +assign(ec.value(), ec.category()); +\end{codeblock} \end{itemdescr} \rSec3[syserr.errcode.modifiers]{Modifiers} @@ -1161,7 +1111,7 @@ \begin{itemdescr} \pnum \ensures -\tcode{val_ == val} and \tcode{cat_ == \&cat}. +\tcode{\exposid{val_} == val} and \tcode{\exposid{cat_} == \&cat}. \end{itemdescr} \indexlibrarymember{operator=}{error_code}% @@ -1176,8 +1126,12 @@ \tcode{is_error_code_enum_v} is \tcode{true}. \pnum -\ensures -\tcode{*this == make_error_code(e)}. +\effects +Equivalent to: +\begin{codeblock} +error_code ec = make_error_code(e); +assign(ec.value(), ec.category()); +\end{codeblock} \pnum \returns @@ -1206,7 +1160,7 @@ \begin{itemdescr} \pnum \returns -\tcode{val_}. +\exposid{val_}. \end{itemdescr} \indexlibrarymember{category}{error_code}% @@ -1217,7 +1171,7 @@ \begin{itemdescr} \pnum \returns -\tcode{*cat_}. +\tcode{*\exposid{cat_}}. \end{itemdescr} \indexlibrarymember{default_error_condition}{error_code}% @@ -1315,8 +1269,8 @@ explicit operator bool() const noexcept; private: - int val_; // \expos - const error_category* cat_; // \expos + int @\exposid{val_}@; // \expos + const error_category* @\exposid{cat_}@; // \expos }; } \end{codeblock} @@ -1330,8 +1284,9 @@ \begin{itemdescr} \pnum -\ensures -\tcode{val_ == 0} and \tcode{cat_ == \&generic_category()}. +\effects +Initializes \exposid{val_} with \tcode{0} +and \exposid{cat_} with \tcode{\&generic_category()}. \end{itemdescr} \indexlibraryctor{error_condition}% @@ -1341,8 +1296,9 @@ \begin{itemdescr} \pnum -\ensures -\tcode{val_ == val} and \tcode{cat_ == \&cat}. +\effects +Initializes \exposid{val_} with \tcode{val} +and \exposid{cat_} with \tcode{\&cat}. \end{itemdescr} \indexlibraryctor{error_condition}% @@ -1357,8 +1313,12 @@ \tcode{is_error_condition_enum_v} is \tcode{true}. \pnum -\ensures -\tcode{*this == make_error_condition(e)}. +\effects +Equivalent to: +\begin{codeblock} +error_condition ec = make_error_condition(e); +assign(ec.value(), ec.category()); +\end{codeblock} \end{itemdescr} @@ -1372,7 +1332,7 @@ \begin{itemdescr} \pnum \ensures -\tcode{val_ == val} and \tcode{cat_ == \&cat}. +\tcode{\exposid{val_} == val} and \tcode{\exposid{cat_} == \&cat}. \end{itemdescr} \indexlibrarymember{operator=}{error_condition}% @@ -1387,8 +1347,12 @@ \tcode{is_error_condition_enum_v} is \tcode{true}. \pnum -\ensures -\tcode{*this == make_error_condition(e)}. +\effects +Equivalent to: +\begin{codeblock} +error_condition ec = make_error_condition(e); +assign(ec.value(), ec.category()); +\end{codeblock} \pnum \returns @@ -1416,7 +1380,7 @@ \begin{itemdescr} \pnum \returns -\tcode{val_}. +\exposid{val_}. \end{itemdescr} \indexlibrarymember{category}{error_condition}% @@ -1427,7 +1391,7 @@ \begin{itemdescr} \pnum \returns -\tcode{*cat_}. +\tcode{*\exposid{cat_}}. \end{itemdescr} \indexlibrarymember{message}{error_condition}% @@ -1730,13 +1694,13 @@ template string to_string(const basic_stacktrace& st); - template - basic_ostream& - operator<<(basic_ostream& os, const stacktrace_entry& f); + ostream& operator<<(ostream& os, const stacktrace_entry& f); + template + ostream& operator<<(ostream& os, const basic_stacktrace& st); - template - basic_ostream& - operator<<(basic_ostream& os, const basic_stacktrace& st); + // \ref{stacktrace.format}, formatting support + template<> struct formatter; + template struct formatter>; namespace pmr { using stacktrace = basic_stacktrace>; @@ -1967,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; @@ -1988,7 +1952,7 @@ allocator_traits::is_always_equal::value); private: - vector frames_; // \expos + vector @\exposid{frames_}@; // \expos }; } \end{codeblock} @@ -2020,17 +1984,17 @@ \pnum \returns A \tcode{basic_stacktrace} object -with \tcode{frames_} storing +with \exposid{frames_} storing the stacktrace of the current evaluation in the current thread of execution, or an empty \tcode{basic_stacktrace} object -if the initialization of \tcode{frames_} failed. -\tcode{alloc} is passed to the constructor of the \tcode{frames_} object. +if the initialization of \exposid{frames_} failed. +\tcode{alloc} is passed to the constructor of the \exposid{frames_} object. \begin{note} If the stacktrace was successfully obtained, -then \tcode{frames_.front()} is the \tcode{stacktrace_entry} +then \tcode{\exposid{frames_}.front()} is the \tcode{stacktrace_entry} representing approximately the current evaluation, and -\tcode{frames_.back()} is the \tcode{stacktrace_entry} +\tcode{\exposid{frames_}.back()} is the \tcode{stacktrace_entry} representing approximately the initial function of the current thread of execution. \end{note} @@ -2051,10 +2015,10 @@ \pnum \returns A \tcode{basic_stacktrace} object -where \tcode{frames_} is direct-non-list-initialized from arguments +where \exposid{frames_} is direct-non-list-initialized from arguments \tcode{t.begin() + min(n, skip)}, \tcode{t.end()}, and \tcode{alloc}, or an empty \tcode{basic_stacktrace} object -if the initialization of \tcode{frames_} failed. +if the initialization of \exposid{frames_} failed. \end{itemdescr} \indexlibrarymember{current}{basic_stacktrace}% @@ -2076,11 +2040,11 @@ \pnum \returns A \tcode{basic_stacktrace} object -where \tcode{frames_} is direct-non-list-initialized from arguments +where \exposid{frames_} is direct-non-list-initialized from arguments \tcode{t.begin() + min(n, skip)}, \tcode{t.begin() + min(n, skip + max_depth)}, and \tcode{alloc}, or an empty \tcode{basic_stacktrace} object -if the initialization of \tcode{frames_} failed. +if the initialization of \exposid{frames_} failed. \end{itemdescr} \indexlibraryctor{basic_stacktrace}% @@ -2102,7 +2066,7 @@ \begin{itemdescr} \pnum \effects -\tcode{alloc} is passed to the \tcode{frames_} constructor. +\tcode{alloc} is passed to the \exposid{frames_} constructor. \pnum \ensures @@ -2152,7 +2116,7 @@ \begin{itemdescr} \pnum \returns -\tcode{frames_.get_allocator()}. +\tcode{\exposid{frames_}.get_allocator()}. \end{itemdescr} \indexlibrarymember{begin}{basic_stacktrace}% @@ -2165,7 +2129,7 @@ \begin{itemdescr} \pnum \returns -An iterator referring to the first element in \tcode{frames_}. +An iterator referring to the first element in \exposid{frames_}. If \tcode{empty()} is \tcode{true}, then it returns the same value as \tcode{end()}. \end{itemdescr} @@ -2211,13 +2175,13 @@ \indexlibrarymember{empty}{basic_stacktrace}% \begin{itemdecl} -[[nodiscard]] bool empty() const noexcept; +bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{frames_.empty()}. +\tcode{\exposid{frames_}.empty()}. \end{itemdescr} \indexlibrarymember{size}{basic_stacktrace}% @@ -2228,7 +2192,7 @@ \begin{itemdescr} \pnum \returns -\tcode{frames_.size()}. +\tcode{\exposid{frames_}.size()}. \end{itemdescr} \indexlibrarymember{max_size}{basic_stacktrace}% @@ -2239,7 +2203,7 @@ \begin{itemdescr} \pnum \returns -\tcode{frames_.max_size()}. +\tcode{\exposid{frames_}.max_size()}. \end{itemdescr} \indexlibrarymember{operator[]}{basic_stacktrace}% @@ -2254,7 +2218,7 @@ \pnum \returns -\tcode{frames_[frame_no]}. +\tcode{\exposid{frames_}[frame_no]}. \pnum \throws @@ -2269,7 +2233,7 @@ \begin{itemdescr} \pnum \returns -\tcode{frames_[frame_no]}. +\tcode{\exposid{frames_}[frame_no]}. \pnum \throws @@ -2369,9 +2333,7 @@ \indexlibrarymember{operator<<}{stacktrace_entry}% \begin{itemdecl} -template -basic_ostream& - operator<<(basic_ostream& os, const stacktrace_entry& f); +ostream& operator<<(ostream& os, const stacktrace_entry& f); \end{itemdecl} \begin{itemdescr} @@ -2382,9 +2344,8 @@ \indexlibrarymember{operator<<}{basic_stacktrace}% \begin{itemdecl} -template -basic_ostream& - operator<<(basic_ostream& os, const basic_stacktrace& st); +template + ostream& operator<<(ostream& os, const basic_stacktrace& st); \end{itemdecl} \begin{itemdescr} @@ -2393,7 +2354,49 @@ Equivalent to: \tcode{return os << to_string(st);} \end{itemdescr} -\rSec3[stacktrace.basic.hash]{Hash support} +\rSec2[stacktrace.format]{Formatting support} + +\begin{itemdecl} +template<> struct formatter; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{formatter} interprets \fmtgrammarterm{format-spec} +as a \fmtgrammarterm{stacktrace-entry-format-spec}. +The syntax of format specifications is as follows: + +\begin{ncbnf} +\fmtnontermdef{stacktrace-entry-format-spec}\br + \opt{fill-and-align} \opt{width} +\end{ncbnf} + +\begin{note} +The productions \fmtgrammarterm{fill-and-align} and \fmtgrammarterm{width} +are described in \ref{format.string.std}. +\end{note} + +\pnum +A \tcode{stacktrace_entry} object \tcode{se} is formatted as if by +copying \tcode{to_string(se)} through the output iterator of the context +with additional padding and adjustments as specified by the format specifiers. +\end{itemdescr} + +\begin{itemdecl} +template struct formatter>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +For \tcode{formatter>}, +\fmtgrammarterm{format-spec} is empty. + +\pnum +A \tcode{basic_stacktrace} object \tcode{s} is formatted as if by +copying \tcode{to_string(s)} through the output iterator of the context. +\end{itemdescr} + +\rSec2[stacktrace.basic.hash]{Hash support} \begin{itemdecl} template<> struct hash; @@ -2404,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 15b2896a22..79684e4c51 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -257,13 +257,14 @@ \pnum Throwing an exception -copy-initializes\iref{dcl.init,class.copy.ctor} 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, +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} +or a pointer to an incomplete type other than +\cv{}~\keyword{void}\iref{basic.compound}, the program is ill-formed. \pnum @@ -308,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}% @@ -329,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} @@ -357,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}} @@ -405,22 +427,52 @@ \end{example} \pnum -If the initialization or destruction of an object +If the initialization of an object other than by delegating constructor is terminated by an exception, the destructor is invoked for -each of the object's direct subobjects -and, for a complete object, virtual base class subobjects, -whose initialization has completed\iref{dcl.init} -and whose destructor has not yet begun execution, -except that in the case of destruction, the variant members of a -union-like class are not destroyed. +each of the object's subobjects +that were known to be initialized by the object's initialization and +whose initialization has completed\iref{dcl.init}. \begin{note} If such an object has a reference member that extends the lifetime of a temporary object, this ends the lifetime of the reference member, so the lifetime of the temporary object is effectively not extended. \end{note} +\indextext{subobject!initialized, known to be}% +A subobject is \defn{known to be initialized} +if it is not an anonymous union member and +its initialization is specified +\begin{itemize} +\item in \ref{class.base.init} for initialization by constructor, +\item in \ref{class.copy.ctor} for initialization by defaulted copy/move constructor, +\item in \ref{class.inhctor.init} for initialization by inherited constructor, +\item in \ref{dcl.init.aggr} for aggregate initialization, +\item in \ref{expr.prim.lambda.capture} for the initialization of +the closure object when evaluating a \grammarterm{lambda-expression}, +\item in \ref{dcl.init.general} for +default-initialization, value-initialization, or direct-initialization +of an array. +\end{itemize} +\begin{note} +This includes virtual base class subobjects +if the initialization +is for a complete object, and +can include variant members +that were nominated explicitly by +a \grammarterm{mem-initializer} or \grammarterm{designated-initializer-clause} or +that have a default member initializer. +\end{note} +If the destructor of an object is terminated by an exception, +each destructor invocation +that would be performed after executing the body of the destructor\iref{class.dtor} and +that has not yet begun execution +is performed. +\begin{note} +This includes virtual base class subobjects if +the destructor was invoked for a complete object. +\end{note} The subobjects are destroyed in the reverse order of the completion of their construction. Such destruction is sequenced before entering a handler of the \grammarterm{function-try-block} of the constructor or destructor, @@ -572,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. @@ -586,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. @@ -603,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 @@ -696,7 +771,7 @@ \begin{bnf} \nontermdef{noexcept-specifier}\br \keyword{noexcept} \terminal{(} constant-expression \terminal{)}\br - \keyword{noexcept}\br + \keyword{noexcept} \end{bnf} \pnum @@ -775,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 @@ -818,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 @@ -939,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 @@ -961,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|)} @@ -975,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. @@ -984,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}% @@ -1002,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} @@ -1052,7 +1106,27 @@ \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 + +\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. \end{itemize} @@ -1060,14 +1134,12 @@ \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} @@ -1080,21 +1152,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..a26e23fc4c --- /dev/null +++ b/source/exec.tex @@ -0,0 +1,5675 @@ +%!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. + +\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@ }; + + 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}@{}; + + 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{sender_to}@ = @\seebelow@; + + template + struct @\exposidnc{type-list}@; // \expos + + // \ref{exec.getcomplsigs}, completion signatures + struct get_completion_signatures_t; + inline constexpr get_completion_signatures_t get_completion_signatures {}; + + template> + requires @\libconcept{sender_in}@ + using completion_signatures_of_t = @\exposid{call-result-t}@; + + 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}@ Sndr> + 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{split_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@ }; + + 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 split_t @\libglobal{split}@{}; + 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}@{}; + + // \ref{exec.util}, sender and receiver utilities + // \ref{exec.util.cmplsig} + template + concept @\exposconceptnc{completion-signature}@ = @\seebelownc@; // \expos + + template<@\exposconcept{completion-signature}@... Fns> + struct @\libglobal{completion_signatures}@ {}; + + template + concept @\exposconceptnc{valid-completion-signatures}@ = @\seebelownc@; // \expos + + // \ref{exec.util.cmplsig.trans} + template< + @\exposconcept{valid-completion-signatures}@ InputSignatures, + @\exposconcept{valid-completion-signatures}@ AdditionalSignatures = completion_signatures<>, + template class SetValue = @\seebelow@, + template class SetError = @\seebelow@, + @\exposconcept{valid-completion-signatures}@ SetStopped = completion_signatures> + using transform_completion_signatures = completion_signatures<@\seebelow@>; + + template< + @\libconcept{sender}@ Sndr, + class Env = env<>, + @\exposconcept{valid-completion-signatures}@ AdditionalSignatures = completion_signatures<>, + template class SetValue = @\seebelow@, + template class SetError = @\seebelow@, + @\exposconcept{valid-completion-signatures}@ SetStopped = completion_signatures> + requires @\libconcept{sender_in}@ + using transform_completion_signatures_of = + transform_completion_signatures< + completion_signatures_of_t, + AdditionalSignatures, SetValue, SetError, SetStopped>; + + // \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.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; +} +\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 types \tcode{Sndr} and \tcode{Env}, +\tcode{\exposid{single-sender-value-type}} is an alias for: +\begin{itemize} +\item +\tcode{value_types_of_t} +if that type is well-formed, +\item +Otherwise, \tcode{void} +if \tcode{value_types_of_t} is +\tcode{variant>} or \tcode{vari\-ant<>}, +\item +Otherwise, \tcode{value_types_of_t} +if that 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} + +\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}. + +\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 \tcode{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}@ && + is_object_v && + requires (O& o) { + { start(o) } noexcept; + }; +} +\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. +Then the type of the expression \tcode{get_completion_signatures(sndr, env)} is +a specialization of +the class template \tcode{completion_signatures}\iref{exec.util.cmplsig}, +the set of whose template arguments is \tcode{Sigs}. +If a user-provided implementation of the algorithm +that produced \tcode{sndr} is selected instead of the default, +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. + +\rSec2[exec.snd.expos]{Exposition-only entities} + +\pnum +Subclause \ref{exec.snd} makes use of the following exposition-only entities. + +\pnum +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...)}. + +\pnum +For a query object \tcode{q} and \tcode{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-or-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 + @...@ + 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} + +\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} \&\& ...)} +\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 @\defexposconcept{completion-tag}@ = // \expos + @\libconcept{same_as}@ || @\libconcept{same_as}@ || @\libconcept{same_as}@; + + template class T, class... Args> + concept @\defexposconcept{valid-specialization}@ = // \expos + requires { typename T; }; + + struct @\exposid{default-impls}@ { // \expos + static constexpr auto @\exposid{get-attrs}@ = @\seebelow@; // \expos + static constexpr auto @\exposid{get-env}@ = @\seebelow@; // \expos + static constexpr auto @\exposid{get-state}@ = @\seebelow@; // \expos + static constexpr auto @\exposid{start}@ = @\seebelow@; // \expos + static constexpr auto @\exposid{complete}@ = @\seebelow@; // \expos + }; + + template + struct @\exposid{impls-for}@ : @\exposid{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 @\exposid{child-type}@ = decltype(declval().template @\exposid{get}@()); // \expos + + template + using @\exposid{indices-for}@ = remove_reference_t::@\exposid{indices-for}@; // \expos + + template + struct @\exposid{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 @\exposid{rcvr}@; // \expos + @\exposid{state-type}@ @\exposid{state}@; // \expos + }; + + template + requires @\exposconcept{valid-specialization}@<@\exposid{env-type}@, Index, Sndr, Rcvr> + struct @\exposid{basic-receiver}@ { // \expos + using receiver_concept = receiver_t; + + using @\exposid{tag-t}@ = tag_of_t; // \expos + using @\exposid{state-t}@ = @\exposid{state-type}@; // \expos + static constexpr const auto& @\exposid{complete}@ = @\exposid{impls-for}@<@\exposid{tag-t}@>::@\exposid{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}@); + } + + @\exposid{basic-state}@* @\exposid{op}@; // \expos + }; + + constexpr auto @\exposid{connect-all}@ = @\seebelow@; // \expos + + template + using @\exposid{connect-all-result}@ = @\exposid{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 @\exposid{basic-operation}@ : @\exposid{basic-state}@ { // \expos + using operation_state_concept = operation_state_t; + using @\exposid{tag-t}@ = tag_of_t; // \expos + + @\exposid{connect-all-result}@ @\exposid{inner-ops}@; // \expos + + @\exposid{basic-operation}@(Sndr&& sndr, Rcvr&& rcvr) noexcept(@\seebelow@) // \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 + using @\exposid{completion-signatures-for}@ = @\seebelow@; // \expos + + template + struct @\exposid{basic-sender}@ : @\exposid{product-type}@ { // \expos + using sender_concept = sender_t; + using @\exposid{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> + auto get_completion_signatures(this Self&& self, Env&& env) noexcept + -> @\exposid{completion-signatures-for}@ { + return {}; + } + }; +} +\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 std::forward_like(data); +} +\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} + +\pnum +For a subexpression \tcode{sndr} let \tcode{Sndr} be \tcode{decltype((sndr))}. +Let \tcode{rcvr} be a receiver +with an associated environment of type \tcode{Env} +such that \tcode{\libconcept{sender_in}} is \tcode{true}. +\tcode{\exposid{completion-signatures-for}} denotes +a specialization of \tcode{completion_signatures}, +the set of whose template arguments correspond to +the set of completion operations that are potentially evaluated +as a result of starting\iref{exec.async.ops} +the operation state that results from connecting \tcode{sndr} and \tcode{rcvr}. +When \tcode{\libconcept{sender_in}} is \tcode{false}, +the type denoted by \tcode{\exposid{completion-signatures-for}}, +if any, is not a specialization of \tcode{completion_signatures}. + +\recommended +When \tcode{\libconcept{sender_in}} is \tcode{false}, +implementations are encouraged to use the type +denoted by \tcode{\exposid{completion-signatures-for}} +to communicate to users why. + +\begin{itemdecl} +template<@\libconcept{sender}@ Sndr, @\exposconcept{queryable}@ Env> + constexpr auto @\exposid{write-env}@(Sndr&& sndr, Env&& env); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\exposid{write-env} is an exposition-only sender adaptor 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} argument \tcode{env} +to the result of \tcode{get_env(rcvr)}. + +\pnum +Let \exposid{write-env-t} be an exposition-only empty class type. + +\pnum +\returns +\begin{codeblock} +@\exposid{make-sender}@(@\exposid{write-env-t}@(), std::forward(env), std::forward(sndr)) +\end{codeblock} + +\pnum +\remarks +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \exposid{write-env-t} as follows: +\begin{codeblock} +template<> +struct @\exposid{impls-for}@<@\exposid{write-env-t}@> : @\exposid{default-impls}@ { + static constexpr auto @\exposid{get-env}@ = + [](auto, const auto& state, const auto& rcvr) noexcept { + return @\seebelow@; + }; +}; +\end{codeblock} +Invocation of +\tcode{\exposid{impls-for}<\exposid{write-env-t}>::\exposid{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{state.query(q)} if that expression is valid, +otherwise, \tcode{e.query(q)} is expression-equivalent +to \tcode{get_env(rcvr).que\-ry(q)}. +\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. + +\begin{codeblock} +namespace std::execution { + template + concept @\exposconcept{valid-completion-signatures}@ = @\seebelow@; // \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 + concept @\deflibconcept{sender}@ = + bool(@\exposconcept{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}@ && + @\exposconcept{queryable}@ && + requires (Sndr&& sndr, Env&& env) { + { get_completion_signatures(std::forward(sndr), std::forward(env)) } + -> @\exposconcept{valid-completion-signatures}@; + }; + + 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 +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 +A type models +the exposition-only concept \defexposconcept{valid-completion-signatures} +if it denotes a specialization of +the \tcode{completion_signatures} class template. + +\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}@ = + @\libconcept{sender_in}@ && + @\exposid{MATCHING-SIG}@( // see \ref{exec.general} + set_value_t(Values...), + value_types_of_t); + + template + concept @\defexposconcept{sender-of}@ = @\exposconcept{sender-in-of}@, Values...>; +} +\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} + +\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())}. + +\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> + decltype(auto) await_transform(T&& value) + noexcept(noexcept(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{static_cast(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}} + +\pnum +\tcode{get_completion_signatures} is a customization point object. +Let \tcode{sndr} be an expression +such that \tcode{decltype((sndr))} is \tcode{Sndr}, and +let \tcode{env} be an expression +such that \tcode{decltype((env))} is \tcode{Env}. +Let \tcode{new_sndr} be the expression +\tcode{transform_sender(decltype(\exposid{get-domain-late}(sndr, env))\{\}, sndr, env)}, and +let \tcode{NewSndr} be \tcode{decltype((new_sndr))}. +Then \tcode{get_completion_signatures(sndr, env)} is expression-equiva\-lent to +\tcode{(void(sndr), void(env), CS())} +except that \tcode{void(sndr)} and \tcode{void(env)} are +indeterminately sequenced, +where \tcode{CS} is: +\begin{itemize} +\item +\tcode{decltype(new_sndr.get_completion_signatures(env))} +if that type is well-formed, + +\item +Otherwise, \tcode{remove_cvref_t::completion_signatures} +if that type is well-formed, + +\item +Otherwise, +if \tcode{\exposconcept{is-awaitable}>} is \tcode{true}, +then: +\begin{codeblock} +completion_signatures< + @\exposid{SET-VALUE-SIG}@(@\exposid{await-result-type}@>), // \iref{exec.snd.concepts} + set_error_t(exception_ptr), + set_stopped_t()> +\end{codeblock} + +\item +Otherwise, \tcode{CS} is ill-formed. +\end{itemize} + +\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 \iref{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(@\exposid{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{@\exposid{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} + +\mandates +\tcode{\libconcept{sender} \&\& \libconcept{receiver}} is \tcode{true}. + +\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: +\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))); + }; + }; +} +\end{codeblock} + +\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 +These requirements apply to any function +that is selected by the implementation of the sender adaptor. +\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.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-or-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-or-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: +\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@; + }; +} +\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}@, 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} + +\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}, env_of_t>}. +Let \exposid{as-tuple} be an alias template +that transforms a completion signature \tcode{Tag(Args...)} into +the tuple specialization \tcode{\exposid{decayed-tuple}}. +Then \tcode{variant_t} denotes +the type \tcode{variant...>}, +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; + + try { + state.@\exposid{async-result}@.template emplace(Tag(), std::forward(args)...); + } catch (...) { + if constexpr (!nothrow) { + set_error(std::move(rcvr), current_exception()); + return; + } + } + 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-or-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, and +let \exposid{not-a-sender} be the exposition-only type: +\begin{codeblock} +struct @\exposid{not-a-sender}@ { + using sender_concept = sender_t; + + auto get_completion_signatures(auto&&) const { + return @\seebelow@; + } +}; +\end{codeblock} +where the member function \tcode{get_completion_signatures} returns +an object of a type that is not +a specialization of the \tcode{completion_signatures} class template. + +\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 @\exposid{write-env}@( + continues_on( + std::forward_like(closure)( + continues_on( + @\exposid{write-env}@(std::forward_like(child), @\exposid{SCHED-ENV}@(orig_sch)), + sch)), + orig_sch), + @\exposid{SCHED-ENV}@(sch)); + } +} +\end{codeblock} + +\pnum +\recommended +Implementations should use +the return type of \tcode{\exposid{not-a-sender}::get_completion_signatures} +to inform users that their usage of \tcode{on} is incorrect +because there is no available scheduler onto which to restore execution. + +\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 +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 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: +\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)...); + } + }; + }; +} +\end{codeblock} + +\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: +\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@; + }; +} +\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 \tcode{e.query(q)} is expression-equivalent +to \tcode{get_env(\exposid{rcvr}).query(q)}. +\end{itemize} + +\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}@{std::forward_like(fn), @\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}, 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}<\linebreak Tag(Args...)>} 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 +\tcode{\exposid{JOIN-ENV}(\exposid{let-env}(sndr), \exposid{FWD-ENV}(env))}. + +\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}} + +\pnum +\tcode{bulk} runs a task repeatedly for every index in an index space. + +The name \tcode{bulk} denotes a pipeable sender adaptor object. +For subexpressions \tcode{sndr}, \tcode{shape}, and \tcode{f}, +let \tcode{Shape} be \tcode{decltype(auto(shape))}. +If +\begin{itemize} +\item +\tcode{decltype((sndr))} does not satisfy \libconcept{sender}, or +\item +\tcode{Shape} does not satisfy \libconcept{integral}, or +\item +\tcode{decltype((f))} does not satisfy \exposconcept{movable-value}, +\end{itemize} +\tcode{bulk(sndr, shape, f)} is ill-formed. + +\pnum +Otherwise, +the expression \tcode{bulk(sndr, shape, f)} is expression-equivalent to: + +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(bulk, @\exposid{product-type}@{shape, 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 \tcode{bulk_t} as follows: +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { + static constexpr auto @\exposid{complete}@ = @\seebelow@; + }; +} +\end{codeblock} + +\pnum +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} + +\pnum +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. + +\pnum +Let the subexpression \tcode{out_sndr} denote +the result of the invocation \tcode{bulk(sndr, 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 +on a value completion operation, +invokes \tcode{f(i, args...)} +for every \tcode{i} of type \tcode{Shape} in \range{\tcode{0}}{\tcode{shape}}, +where \tcode{args} is a pack of lvalue subexpressions +referring to the value completion result datums of the input sender, and +\item +propagates all completion operations sent by \tcode{sndr}. +\end{itemize} + +\rSec3[exec.split]{\tcode{execution::split}} + +\pnum +\tcode{split} adapts an arbitrary sender +into a sender that can be connected multiple times. + +\pnum +Let \exposid{split-env} be the type of an environment +such that, given an instance \tcode{env}, +the expression \tcode{get_stop_token(env)} is well-formed and +has type \tcode{inplace_stop_token.} + +\pnum +The name \tcode{split} denotes a pipeable sender adaptor object. +For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. +If \tcode{\libconcept{sender_in}} is \tcode{false}, +\tcode{split(sndr)} is ill-formed. + +\pnum +Otherwise, the expression \tcode{split(sndr)} is expression-equivalent to: +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(split, {}, sndr)) +\end{codeblock} +except that \tcode{sndr} is evaluated only once. +\begin{note} +The default implementation of \tcode{transform_sender} +will have the effect of connecting the sender to a receiver. +It will return a sender with a different tag type. +\end{note} + +\pnum +Let \exposid{local-state} denote the following exposition-only class template: + +\begin{codeblock} +namespace std::execution { + struct @\exposid{local-state-base}@ { // \expos + virtual ~@\exposid{local-state-base}@() = default; + virtual void @\exposid{notify}@() noexcept = 0; // \expos + }; + + template + struct @\exposid{local-state}@ : @\exposid{local-state-base}@ { // \expos + using @\exposid{on-stop-callback}@ = // \expos + stop_callback_for_t>, @\exposid{on-stop-request}@>; + + @\exposid{local-state}@(Sndr&& sndr, Rcvr& rcvr) noexcept; + ~@\exposid{local-state}@(); + + void @\exposid{notify}@() noexcept override; + + private: + optional<@\exposid{on-stop-callback}@> @\exposid{on_stop}@; // \expos + @\exposid{shared-state}@* @\exposid{sh_state}@; // \expos + Rcvr* @\exposid{rcvr}@; // \expos + }; +} +\end{codeblock} + +\begin{itemdecl} +@\exposid{local-state}@(Sndr&& sndr, Rcvr& rcvr) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto& [_, data, _] = sndr; +this->@\exposid{sh_state}@ = data.sh_state.get(); +this->@\exposid{sh_state}@->@\exposid{inc-ref}@(); +this->@\exposid{rcvr}@ = addressof(rcvr); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +~@\exposid{local-state}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +sh_state->@\exposid{dec-ref}@(); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +void @\exposid{notify}@() noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{on_stop}@.reset(); +visit( + [this](const auto& tupl) noexcept -> void { + apply( + [this](auto tag, const auto&... args) noexcept -> void { + tag(std::move(*@\exposid{rcvr}@), args...); + }, + tupl); + }, + @\exposid{sh_state}@->result); +\end{codeblock} +\end{itemdescr} + +\pnum +Let \exposid{split-receiver} denote +the following exposition-only class template: +\begin{codeblock} +namespace std::execution { + template + struct @\exposid{split-receiver}@ { // \expos + using receiver_concept = receiver_t; + + template + void @\exposid{complete}@(Tag, Args&&... args) noexcept { // \expos + using tuple_t = @\exposid{decayed-tuple}@; + try { + @\exposid{sh_state}@->result.template emplace(Tag(), std::forward(args)...); + } catch (...) { + using tuple_t = tuple; + @\exposid{sh_state}@->result.template emplace(set_error, current_exception()); + } + @\exposid{sh_state}@->notify(); + } + + template + void set_value(Args&&... args) && noexcept { + @\exposid{complete}@(execution::set_value, std::forward(args)...); + } + + template + void set_error(Error&& err) && noexcept { + @\exposid{complete}@(execution::set_error, std::forward(err)); + } + + void set_stopped() && noexcept { + @\exposid{complete}@(execution::set_stopped); + } + + struct @\exposid{env}@ { // \expos + @\exposid{shared-state}@* @\exposid{sh-state}@; // \expos + + inplace_stop_token query(get_stop_token_t) const noexcept { + return @\exposid{sh-state}@->stop_src.get_token(); + } + }; + + @\exposid{env}@ get_env() const noexcept { + return @\exposid{env}@{@\exposid{sh_state}@}; + } + + @\exposid{shared-state}@* @\exposid{sh_state}@; // \expos + }; +} +\end{codeblock} + +\pnum +Let \exposid{shared-state} denote the following exposition-only class template: +\begin{codeblock} +namespace std::execution { + template + struct @\exposid{shared-state}@ { + using @\exposid{variant-type}@ = @\seebelow@; // \expos + using @\exposid{state-list-type}@ = @\seebelow@; // \expos + + explicit @\exposid{shared-state}@(Sndr&& sndr); + + void @\exposid{start-op}@() noexcept; // \expos + void @\exposid{notify}@() noexcept; // \expos + void @\exposid{inc-ref}@() noexcept; // \expos + void @\exposid{dec-ref}@() noexcept; // \expos + + inplace_stop_source @\exposid{stop_src}@{}; // \expos + @\exposid{variant-type}@ @\exposid{result}@{}; // \expos + @\exposid{state-list-type}@ @\exposid{waiting_states}@; // \expos + atomic @\exposid{completed}@{false}; // \expos + atomic @\exposid{ref_count}@{1}; // \expos + connect_result_t> @\exposid{op_state}@; // \expos + }; +} +\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}. +For type \tcode{Tag} and pack \tcode{Args}, +let \exposid{as-tuple} be an alias template +such that \tcode{\exposid{as-tuple}} denotes +the type \tcode{\exposid{decayed-tuple}}. +Then \exposid{variant-type} denotes the type +\begin{codeblock} +variant, tuple, @\exposid{as-tuple}@...> +\end{codeblock} +but with duplicate types removed. + +\pnum +Let \exposid{state-list-type} be a type +that stores a list of pointers to \exposid{local-state-base} objects and +that permits atomic insertion. + +\begin{itemdecl} +explicit @\exposid{shared-state}@(Sndr&& sndr); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{op_state} with the result of +\tcode{connect(std::forward(sndr), \exposid{split-re\-ceiver}\{this\})}. + +\pnum +\ensures +\exposid{waiting_states} is empty, and \exposid{completed} is \tcode{false}. +\end{itemdescr} + +\begin{itemdecl} +void @\exposid{start-op}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Evaluates \tcode{\exposid{inc-ref}()}. +If \tcode{stop_src.stop_requested()} is \tcode{true}, +evaluates \tcode{\exposid{notify}()}; +otherwise, evaluates \tcode{start(\exposid{op_state})}. +\end{itemdescr} + +\begin{itemdecl} +void @\exposid{notify}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically does the following: +\begin{itemize} +\item +Sets \tcode{completed} to \tcode{true}, and +\item +Exchanges \tcode{waiting_states} with an empty list, +storing the old value in a local \tcode{prior_states}. +\end{itemize} +Then, for each pointer \tcode{p} in \tcode{prior_states}, +evaluates \tcode{p->\exposid{notify}()}. +Finally, evaluates \tcode{\exposid{dec-ref}()}. +\end{itemdescr} + +\begin{itemdecl} +void @\exposid{inc-ref}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Increments \exposid{ref_count}. +\end{itemdescr} + +\begin{itemdecl} +void @\exposid{dec-ref}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Decrements \exposid{ref_count}. +If the new value of \exposid{ref_count} is \tcode{0}, +calls \tcode{delete this}. + +\pnum +\sync +If an evaluation of \tcode{\exposid{dec-ref}()} does not +decrement the \tcode{ref_count} to \tcode{0} then +synchronizes with the evaluation of \tcode{dec-ref()} +that decrements \tcode{ref_count} to \tcode{0}. +\end{itemdescr} + +\pnum +Let \exposid{split-impl-tag} be an empty exposition-only class type. +Given an expression \tcode{sndr}, +the expression \tcode{split.transform_sender(sndr)} is equivalent to: +\begin{codeblock} +auto&& [tag, _, child] = sndr; +auto* sh_state = new @\exposid{shared-state}@{std::forward_like(child)}; +return @\exposid{make-sender}@(@\exposid{split-impl-tag}@(), @\exposid{shared-wrapper}@{sh_state, tag}); +\end{codeblock} +where \exposid{shared-wrapper} is an exposition-only class +that manages the reference count of the \exposid{shared-state} object +pointed to by sh_state. +\exposid{shared-wrapper} models \libconcept{copyable} +with move operations nulling out the moved-from object, +copy operations incrementing the reference count +by calling \tcode{sh_state->\exposid{inc-ref}()}, and +assignment operations performing a copy-and-swap operation. +The destructor has no effect if sh_state is null; +otherwise, it decrements the reference count +by evaluating \tcode{sh_state->\exposid{dec-ref}()}. + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \exposid{split-impl-tag} as follows: +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@<@\exposid{split-impl-tag}@> : @\exposid{default-impls}@ { + static constexpr auto @\exposid{get-state}@ = @\seebelow@; + static constexpr auto @\exposid{start}@ = @\seebelow@; + }; +} +\end{codeblock} + +\pnum +The member +\tcode{\exposid{impls-for}<\exposid{split-impl-tag}>::\exposid{get-state}} +is initialized with a callable object equivalent to +the following lambda expression: +\begin{codeblock} +[](Sndr&& sndr, auto& rcvr) noexcept { + return @\exposid{local-state}@{std::forward(sndr), rcvr}; +} +\end{codeblock} + +\pnum +The member +\tcode{\exposid{impls-for}<\exposid{split-impl-tag}>::\exposid{start}} +is initialized with a callable object +that has a function call operator equivalent to the following: +\begin{codeblock} +template +void operator()(@\exposid{local-state}@& state, Rcvr& rcvr) const noexcept; +\end{codeblock} + +\effects +If \tcode{state.\exposid{sh_state}->\exposid{completed}} is \tcode{true}, +evaluates \tcode{state.\exposid{notify}()} and returns. +Otherwise, does the following in order: +\begin{itemize} +\item +Evaluates +\begin{codeblock} +state.@\exposid{on_stop}@.emplace( + get_stop_token(get_env(rcvr)), + @\exposid{on-stop-request}@{state.@\exposid{sh_state}@->@\exposid{stop_src}@}); +\end{codeblock} +\item +Then atomically does the following: +\begin{itemize} +\item +Reads the value \tcode{c} of +\tcode{state.\exposid{sh_state}->\exposid{completed}}, and +\item +Inserts \tcode{addressof(state)} into +\tcode{state.\exposid{sh_state}->\exposid{waiting_states}} +if \tcode{c} is \tcode{false}. +\end{itemize} +\item +If \tcode{c} is \tcode{true}, +calls \tcode{state.\exposid{notify}()} and returns. +\item +Otherwise, +if \tcode{addressof(state)} is the first item added to +\tcode{state.\exposid{sh_state}->\exposid{waiting_states}}, +evaluates \tcode{state.\exposid{sh_state}->\exposid{start-op}()}. +\end{itemize} + +\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}. +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}, or +\item +\tcode{CD} is ill-formed. +\end{itemize} + +\pnum +The expression \tcode{when_all(sndrs...)} is expression-equivalent to: +\begin{codeblock} +transform_sender(CD(), @\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: +\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@; + }; +} +\end{codeblock} + +\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 @\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}, +\tcode{e.query(q)} is expression-equivalent to \tcode{get_env(rcvr).query(q)}. +\end{itemize} + +\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(@$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} +template +concept @\defexposconcept{max-1-sender-in}@ = @\libconcept{sender_in}@ && // \expos + (tuple_size_v> <= 1); + +enum class @\exposid{disposition}@ { @\exposid{started}@, @\exposid{error}@, @\exposid{stopped}@ }; // \expos + +template +struct @\exposid{make-state}@ { + template<@\exposconcept{max-1-sender-in}@>... Sndrs> + 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, \exposid{none-such}, +where \exposid{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<\exposid{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(CD(), @\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: +\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@; + }; +} +\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, 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 +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}, or +if the type \tcode{\exposid{single-sender-value-type}} +is ill-formed or \tcode{void}, +then the expression \tcode{stopped_as_optional.transform_sender(sndr, env)} +is ill-formed; +otherwise, it is equivalent to: +\begin{codeblock} +auto&& [_, _, child] = sndr; +using V = @\exposid{single-sender-value-type}@; +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} + +\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))}. +If \tcode{\libconcept{sender_in}} +is \tcode{false}, +the expression \tcode{this_thread::sync_wait(sndr)} is ill-formed. +Otherwise, it 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 +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))}. +If \tcode{\libconcept{sender_in}} +is \tcode{false}, +\tcode{this_thread::sync_wait_with_variant(sndr)} is ill-formed. +Otherwise, it 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 +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 +If \tcode{\exposconcept{callable}} is \tcode{false}, +the expression \tcode{sync_wait_with_variant.apply_sender(\linebreak sndr)} is ill-formed. +Otherwise, it 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} + +\rSec1[exec.util]{Sender/receiver utilities} + +\rSec2[exec.util.cmplsig]{\tcode{execution::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 +\begin{codeblock} +namespace std::execution { + template<@\exposconcept{completion-signature}@... Fns> + struct completion_signatures {}; + + 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} + +\rSec2[exec.util.cmplsig.trans]{\tcode{execution::transform_completion_signatures}} + +\pnum +\tcode{transform_completion_signatures} is an alias template +used to transform one set of completion signatures into another. +It takes a set of completion signatures and +several other template arguments +that apply modifications to each completion signature in the set +to generate a new specialization of \tcode{completion_signature}s. +\pnum +\begin{example} +Given a sender \tcode{Sndr} and an environment \tcode{Env}, +adapt the completion signatures of \tcode{Sndr} by +lvalue-ref qualifying the values, +adding an additional \tcode{exception_ptr} error completion +if it is not already there, and +leaving the other completion signatures alone. +\begin{codeblock} +template + using my_set_value_t = + completion_signatures< + set_value_t(add_lvalue_reference_t...)>; + +using my_completion_signatures = + transform_completion_signatures< + completion_signatures_of_t, + completion_signatures, + my_set_value_t>; +\end{codeblock} +\end{example} + +\pnum +This subclause makes use of the following exposition-only entities: +\begin{codeblock} +template + using @\exposid{default-set-value}@ = + completion_signatures; + +template + using @\exposid{default-set-error}@ = + completion_signatures; +\end{codeblock} + +\pnum +\begin{codeblock} +namespace std::execution { + template<@\exposconcept{valid-completion-signatures}@ InputSignatures, + @\exposconcept{valid-completion-signatures}@ AdditionalSignatures = completion_signatures<>, + template class SetValue = @\exposid{default-set-value}@, + template class SetError = @\exposid{default-set-error}@, + @\exposconcept{valid-completion-signatures}@ SetStopped = completion_signatures> + using transform_completion_signatures = completion_signatures<@\seebelow@>; +} +\end{codeblock} + +\pnum +\tcode{SetValue} shall name an alias template +such that for any pack of types \tcode{As}, +the type \tcode{SetValue} is either ill-formed or else +\tcode{\exposconcept{valid-completion-signatures}>} is satisfied. +\tcode{SetError} shall name an alias template +such that for any type \tcode{Err}, +\tcode{SetError} is either ill-formed or else +\tcode{\exposconcept{valid-completion-signatures}>} is satisfied. + +\pnum +Let \tcode{Vs} be a pack of the types in the \exposid{type-list} named by +\tcode{\exposid{gather-signatures}}. + +\pnum +Let \tcode{Es} be a pack of the types in the \exposid{type-list} named by +\tcode{\exposid{gather-signatures}}, +where \exposid{error-list} is an alias template +such that \tcode{\exposid{error-list}<\linebreak Ts...>} is +\tcode{\exposid{type-list}...>}. + +\pnum +Let \tcode{Ss} name the type \tcode{completion_signatures<>} if +\tcode{\exposid{gather-signatures}} +is an alias for the type \tcode{\exposid{type-list}<>}; +otherwise, \tcode{SetStopped}. + +\pnum +If any of the above types are ill-formed, +then +\begin{codeblock} +transform_completion_signatures +\end{codeblock} +is ill-formed. +Otherwise, +\begin{codeblock} +transform_completion_signatures +\end{codeblock} +is the type \tcode{completion_signatures} +where \tcode{Sigs...} is the unique set of types in all the template arguments +of all the \tcode{completion_signatures} specializations in the set +\tcode{AdditionalSignatures}, \tcode{Vs...}, \tcode{Es...}, \tcode{Ss}. + +\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}. +For any type \tcode{Env}, +\tcode{completion_signatures_of_t<\exposid{run-loop-sender}, Env>} 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 + 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}\{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} diff --git a/source/expressions.tex b/source/expressions.tex index ec05f026da..aed3d0b9dc 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -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} @@ -158,7 +158,7 @@ \end{itemize} \pnum -Every expression belongs to exactly one of the fundamental classifications in this +Every expression belongs to exactly one of the fundamental categories in this taxonomy: lvalue, xvalue, or prvalue. This property of an expression is called its \defn{value category}. \begin{note} @@ -178,7 +178,7 @@ glvalues are ``generalized'' lvalues, prvalues are ``pure'' rvalues, and xvalues are ``eXpiring'' lvalues. -Despite their names, these terms classify expressions, not values. +Despite their names, these terms apply to expressions, not values. \end{note} \pnum @@ -233,20 +233,18 @@ 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} \pnum Whenever a glvalue appears as an operand of an operator that -expects a prvalue for that operand, the +requires a prvalue for that operand, the lvalue-to-rvalue\iref{conv.lval}, array-to-pointer\iref{conv.array}, or function-to-pointer\iref{conv.func} standard conversions are applied to convert the expression to a prvalue. @@ -266,20 +264,24 @@ \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 +\begin{note} The discussion of reference initialization in~\ref{dcl.init.ref} and of temporaries in~\ref{class.temporary} indicates the behavior of lvalues and rvalues in other significant contexts. +\end{note} \pnum Unless otherwise indicated\iref{dcl.type.decltype}, a prvalue shall always have complete type or the \keyword{void} type; -if it has a class type or (possibly multi-dimensional) array of class type, +if it has a class type or (possibly multidimensional) array of class type, that class shall not be an abstract class\iref{class.abstract}. A glvalue shall not have type \cv{}~\keyword{void}. \begin{note} @@ -294,34 +296,35 @@ \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. +In C, an entire object of structure type can be accessed, e.g., using assignment. By contrast, \Cpp{} has no notion of accessing an object of class type through an lvalue of class type. \end{note} @@ -332,9 +335,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}). @@ -430,7 +437,8 @@ \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, @@ -518,7 +526,8 @@ conversions. \end{note} A standard conversion sequence will be applied to -an expression if necessary to convert it to a required destination type. +an expression if necessary to convert it to an expression having +a required destination type and value category. \pnum \begin{note} @@ -618,7 +627,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} @@ -666,11 +675,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 @@ -828,29 +855,22 @@ \rSec2[conv.prom]{Integral promotions} +\pnum +For the purposes of \ref{conv.prom}, +a \defnadj{converted}{bit-field} is a prvalue that is the result of +an lvalue-to-rvalue conversion\iref{conv.lval} applied to +a bit-field\iref{class.bit}. + \pnum \indextext{promotion!integral}% -A prvalue of an integer type other than \keyword{bool}, \keyword{char8_t}, \keyword{char16_t}, +A prvalue that is not a converted bit-field and has an integer type other than +\keyword{bool}, \keyword{char8_t}, \keyword{char16_t}, \keyword{char32_t}, or \keyword{wchar_t} whose integer conversion rank\iref{conv.rank} is less than the rank of \keyword{int} can be converted to a prvalue of type \keyword{int} if \keyword{int} can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type \tcode{\keyword{unsigned} \keyword{int}}. -\pnum -\indextext{type!underlying!\idxcode{wchar_t}}% -\indextext{type!underlying!\idxcode{char16_t}}% -\indextext{type!underlying!\idxcode{char32_t}}% -A prvalue of type \keyword{char8_t}, \keyword{char16_t}, \keyword{char32_t}, or -\keyword{wchar_t}\iref{basic.fundamental} can be converted to a prvalue -of the first of the following types that can represent all the values of -its underlying type: \keyword{int}, \tcode{\keyword{unsigned} \keyword{int}}, \tcode{\keyword{long} \keyword{int}}, -\tcode{\keyword{unsigned} \keyword{long} \keyword{int}}, \tcode{\keyword{long} \keyword{long} \keyword{int}}, -or \tcode{\keyword{unsigned} \keyword{long} \keyword{long} \keyword{int}}. If none of the types in that list can -represent all the values of its underlying type, a prvalue of type -\keyword{char8_t}, \keyword{char16_t}, \keyword{char32_t}, or \keyword{wchar_t} can be converted -to a prvalue of its underlying type. - \pnum \indextext{type!underlying!enumeration}% A prvalue of an unscoped enumeration type whose underlying type is not @@ -870,15 +890,38 @@ if integral promotion can be applied to its underlying type, a prvalue of an unscoped enumeration type whose underlying type is fixed can also be converted to a prvalue of the promoted underlying type. +\begin{note} +A converted bit-field of enumeration type is treated as +any other value of that type for promotion purposes. +\end{note} \pnum -A prvalue for an integral bit-field\iref{class.bit} can be converted +A converted bit-field of integral type can be converted to a prvalue of type \keyword{int} if \keyword{int} can represent all the values of the bit-field; otherwise, it can be converted to \tcode{\keyword{unsigned} \keyword{int}} if \tcode{\keyword{unsigned} \keyword{int}} can represent all the -values of the bit-field. If the bit-field is larger yet, no integral -promotion applies to it. If the bit-field has enumeration type, it is -treated as any other value of that type for promotion purposes. +values of the bit-field. + +\pnum +\indextext{type!underlying!\idxcode{wchar_t}}% +\indextext{type!underlying!\idxcode{char16_t}}% +\indextext{type!underlying!\idxcode{char32_t}}% +A prvalue of type +\keyword{char8_t}, \keyword{char16_t}, \keyword{char32_t}, or +\keyword{wchar_t}\iref{basic.fundamental} +(including a converted bit-field that was not +already promoted to \keyword{int} or \tcode{\keyword{unsigned} \keyword{int}} +according to the rules above) +can be converted to a prvalue +of the first of the following types that can represent all the values of +its underlying type: +\keyword{int}, +\tcode{\keyword{unsigned} \keyword{int}}, +\tcode{\keyword{long} \keyword{int}}, +\tcode{\keyword{unsigned} \keyword{long} \keyword{int}}, +\tcode{\keyword{long} \keyword{long} \keyword{int}}, +\tcode{\keyword{unsigned} \keyword{long} \keyword{long} \keyword{int}}, or +its underlying type. \pnum \indextext{promotion!bool to int}% @@ -995,8 +1038,7 @@ object pointer or function pointer type. Such a conversion is called a \defnx{null pointer conversion}{conversion!null pointer}. -Two null pointer values of the same type shall compare -equal. The conversion of a null pointer constant to a pointer to +The conversion of a null pointer constant to a pointer to cv-qualified type is a single conversion, and not the sequence of a pointer conversion followed by a qualification conversion\iref{conv.qual}. A null pointer constant of integral type @@ -1012,16 +1054,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} @@ -1035,8 +1087,7 @@ of that type and is distinguishable from any pointer to member not created from a null pointer constant. Such a conversion is called a \defnx{null member pointer conversion}{conversion!null member pointer}. -Two null member pointer values of -the same type shall compare equal. The conversion of a null pointer +The conversion of a null pointer constant to a pointer to member of cv-qualified type is a single conversion, and not the sequence of a pointer-to-member conversion followed by a qualification conversion\iref{conv.qual}. @@ -1051,7 +1102,10 @@ ambiguous\iref{class.member.lookup}, or virtual\iref{class.mi} base class of \tcode{D}, or a base class of a virtual base class of \tcode{D}, a program that necessitates this conversion is ill-formed. -The result of the conversion refers to the same member as the pointer to +If class \tcode{D} does not contain the original member and +is not a base class of the class containing the original member, +the behavior is undefined. Otherwise, +the result of the conversion refers to the same member as the pointer to member before the conversion took place, but it refers to the base class member as if it were a member of the derived class. The result refers to the member in \tcode{D}'s instance of \tcode{B}. Since the result has @@ -1117,14 +1171,21 @@ which are defined as follows: \begin{itemize} +\item The lvalue-to-rvalue conversion\iref{conv.lval} +is applied to each operand and +the resulting prvalues are used in place of the original operands +for the remainder of this section. \item If either operand is of scoped enumeration type\iref{dcl.enum}, no conversions are performed; if the other operand does not have the same type, the expression is ill-formed. +\item Otherwise, if one operand is of enumeration type and the other operand is +of a different enumeration type or a floating-point type, the expression is +ill-formed. \item Otherwise, if either operand is of floating-point type, 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 @@ -1142,51 +1203,42 @@ \item Otherwise, the expression is ill-formed. \end{itemize} -\item Otherwise, the integral promotions\iref{conv.prom} are -performed on both operands. +\item Otherwise, each operand is converted to a common type \tcode{C}. +The integral promotion rules\iref{conv.prom} are used +to determine a type \tcode{T1} and type \tcode{T2} for each operand. \begin{footnote} As a consequence, operands of type \keyword{bool}, \keyword{char8_t}, \keyword{char16_t}, \keyword{char32_t}, \keyword{wchar_t}, or of enumeration type are converted to some integral type. \end{footnote} -Then the following rules are applied to the promoted operands: +Then the following rules are applied to determine \tcode{C}: \begin{itemize} -\item If both operands have the same type, no further conversion is -needed. - -\item Otherwise, if both operands have signed integer types or both have -unsigned integer types, the operand with the type of lesser integer -conversion rank is converted to the type of the operand with -greater rank. +\item If \tcode{T1} and \tcode{T2} are the same type, \tcode{C} is that type. -\item Otherwise, if the operand that has unsigned integer type has rank -greater than or equal to the rank of the type of the other operand, the -operand with signed integer type is converted to the type of the -operand with unsigned integer type. +\item Otherwise, if \tcode{T1} and \tcode{T2} are both signed integer types or +are both unsigned integer types, +\tcode{C} is the type with greater rank. -\item Otherwise, if the type of the operand with signed integer type can -represent all of the values of the type of the operand with unsigned -integer type, the operand with unsigned integer type is converted -to the type of the operand with signed integer type. - -\item Otherwise, both operands are converted to the unsigned -integer type corresponding to the type of the operand with signed -integer type. +\item Otherwise, let \tcode{U} be the unsigned integer type and +\tcode{S} be the signed integer type. +\begin{itemize} +\item If \tcode{U} has rank greater than or equal to the rank of \tcode{S}, +\tcode{C} is \tcode{U}. +\item Otherwise, if \tcode{S} can represent all of the values of \tcode{U}, +\tcode{C} is \tcode{S}. +\item Otherwise, +\tcode{C} is the unsigned integer type corresponding to \tcode{S}. +\end{itemize} \end{itemize} \end{itemize} - -\pnum -If one operand is of enumeration type -and the other operand is of -a different enumeration type or -a floating-point type, -this behavior is deprecated\iref{depr.arith.conv.enum}. \rSec1[expr.prim]{Primary expressions}% \indextext{expression!primary|(} +\rSec2[expr.prim.grammar]{Grammar} + \begin{bnf} \nontermdef{primary-expression}\br literal\br @@ -1227,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 @@ -1235,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). @@ -1305,7 +1367,8 @@ \begin{bnf} \nontermdef{id-expression}\br unqualified-id\br - qualified-id + qualified-id\br + pack-index-expression \end{bnf} \pnum @@ -1318,14 +1381,57 @@ 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 +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. @@ -1345,15 +1451,13 @@ \pnum An \grammarterm{id-expression} that denotes a non-static data member or -non-static member function of a class can only be used: +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 @@ -1372,15 +1476,6 @@ \end{example} \end{itemize} -\pnum -A potentially-evaluated \grammarterm{id-expression} -that denotes an immediate function\iref{dcl.constexpr} -shall appear only -\begin{itemize} -\item as a subexpression of an immediate invocation, or -\item in an immediate function context\iref{expr.const}. -\end{itemize} - \pnum For an \grammarterm{id-expression} that denotes an overload set, overload resolution is performed @@ -1404,7 +1499,7 @@ \end{codeblock} In each case, the constraints of \tcode{f} are not satisfied. In the declaration of \tcode{p2}, -those constraints are required to be satisfied +those constraints need to be satisfied even though \tcode{f} is an unevaluated operand\iref{term.unevaluated.operand}. \end{example} @@ -1419,7 +1514,7 @@ conversion-function-id\br literal-operator-id\br \terminal{\~} type-name\br - \terminal{\~} decltype-specifier\br + \terminal{\~} computed-type-specifier\br template-id \end{bnf} @@ -1427,21 +1522,16 @@ \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 \grammarterm{literal-operator-id}{s}, see~\ref{over.literal}; for \grammarterm{template-id}{s}, see~\ref{temp.names}. -A \grammarterm{type-name} or \grammarterm{decltype-specifier} +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 @@ -1464,21 +1554,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 @@ -1488,27 +1585,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 -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. +if \tcode{U} is ``reference to \tcode{T}'', +then the type of the expression is +\tcode{const T}; +\item +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() { @@ -1540,30 +1776,26 @@ \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} 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 names 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 \grammarterm{id-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} @@ -1584,7 +1816,7 @@ \terminal{::}\br type-name \terminal{::}\br namespace-name \terminal{::}\br - decltype-specifier \terminal{::}\br + computed-type-specifier \terminal{::}\br nested-name-specifier identifier \terminal{::}\br nested-name-specifier \opt{\keyword{template}} simple-template-id \terminal{::} \end{bnf} @@ -1614,7 +1846,7 @@ 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}. 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. @@ -1622,8 +1854,8 @@ \pnum The \grammarterm{nested-name-specifier} \tcode{::} nominates the global namespace. -A \grammarterm{nested-name-specifier} with a \grammarterm{decltype-specifier} -nominates the type denoted by the \grammarterm{decltype-specifier}, +A \grammarterm{nested-name-specifier} with a \grammarterm{computed-type-specifier} +nominates the type denoted by the \grammarterm{computed-type-specifier}, which shall be a class or enumeration type. If a \grammarterm{nested-name-specifier} $N$ is declarative and @@ -1655,14 +1887,39 @@ \pnum A \grammarterm{qualified-id} shall not be of the form \grammarterm{nested-name-specifier} \opt{\keyword{template}} \tcode{\~} -\grammarterm{decltype-specifier} +\grammarterm{computed-type-specifier} nor of the form -\grammarterm{decltype-specifier} \tcode{::} \tcode{\~} \grammarterm{type-name}. +\grammarterm{computed-type-specifier} \tcode{::} \tcode{\~} \grammarterm{type-name}. \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 @@ -1679,6 +1936,32 @@ \end{itemize} and a prvalue otherwise. +\rSec3[expr.prim.pack.index]{Pack indexing expression} + +\begin{bnf} +\nontermdef{pack-index-expression}\br + id-expression \terminal{...} \terminal{[} constant-expression \terminal{]} +\end{bnf} + +\pnum +The \grammarterm{id-expression} $P$ in a \grammarterm{pack-index-expression} +shall be an \grammarterm{identifier} that denotes a pack. + +\pnum +The \grammarterm{constant-expression} shall be +a converted constant expression\iref{expr.const} of type \tcode{std::size_t} +whose value $V$, termed the index, +is such that $0 \le V < \tcode{sizeof...($P$)}$. + +\pnum +A \grammarterm{pack-index-expression} is a pack expansion\iref{temp.variadic}. + +\pnum +\begin{note} +A \grammarterm{pack-index-expression} denotes +the $V^\text{th}$ element of the pack. +\end{note} + \rSec3[expr.prim.id.dtor]{Destruction} \pnum @@ -1736,10 +2019,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} @@ -1752,8 +2036,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 @@ -1789,6 +2072,11 @@ \begin{note} Such ambiguous cases cannot have valid semantics because the constraint expression would not have type \keyword{bool}. +\begin{example} +\begin{codeblock} +auto x = [] requires T::operator int [[some_attribute]] (int) { } +\end{codeblock} +\end{example} \end{note} \pnum @@ -1808,10 +2096,10 @@ \end{note} \pnum -If a \grammarterm{lambda-declarator} does not include -a \grammarterm{parameter-declaration-clause}, -it is as if \tcode{()} were inserted -at the start of the \grammarterm{lambda-declarator}. +A \grammarterm{lambda-expression}{'s} \grammarterm{parameter-declaration-clause} +is the \grammarterm{parameter-declaration-clause} of +the \grammarterm{lambda-expression}{'s} \grammarterm{lambda-declarator}, if any, +or empty otherwise. If the \grammarterm{lambda-declarator} does not include a \grammarterm{trailing-return-type}, it is considered to be \tcode{-> \keyword{auto}}. @@ -1835,8 +2123,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} @@ -1858,15 +2147,19 @@ types of a \grammarterm{lambda-declarator} do not affect these associated namespaces and classes. \end{note} -The closure type is not an aggregate type\iref{dcl.init.aggr}. + +\pnum +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} @@ -1878,7 +2171,7 @@ inline function call operator (for a non-generic lambda) or function call operator template (for a generic lambda)\iref{over.call} whose parameters and return type -are described by the \grammarterm{lambda-expression}'s +are those of the \grammarterm{lambda-expression}{'s} \grammarterm{parameter-declaration-clause} and \grammarterm{trailing-return-type} respectively, and whose \grammarterm{template-parameter-list} consists of @@ -1929,7 +2222,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} @@ -1961,8 +2254,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. @@ -1974,7 +2268,7 @@ the corresponding \grammarterm{lambda-expression}{'s} \grammarterm{parameter-declaration-clause} is followed by \keyword{constexpr} or \keyword{consteval}, or -it satisfies the requirements for a constexpr function\iref{dcl.constexpr}. +it is constexpr-suitable\iref{dcl.constexpr}. It is an immediate function\iref{dcl.constexpr} if the corresponding \grammarterm{lambda-expression}{'s} \grammarterm{parameter-declaration-clause} is followed by \keyword{consteval}. @@ -2041,9 +2335,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 @@ -2053,9 +2393,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 @@ -2064,7 +2404,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 @@ -2128,10 +2470,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 @@ -2140,7 +2482,7 @@ if the function call operator template specialization is an immediate function. \begin{note} This will result in the implicit instantiation of the generic lambda's body. -The instantiated generic lambda's return type and parameter types are required to match +The instantiated generic lambda's return type and parameter types need to match the return type and parameter types of the pointer to function. \end{note} \begin{example} @@ -2257,7 +2599,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 @@ -2273,7 +2615,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 @@ -2298,10 +2640,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} @@ -2358,7 +2709,7 @@ return x+2; }(); // Updates \tcode{::x} to 6, and initializes \tcode{y} to 7. -auto z = [a = 42](int a) { return 1; }; // error: parameter and local variable have the same name +auto z = [a = 42](int a) { return 1; }; // error: parameter and conceptual local variable have the same name auto counter = [i=0]() mutable -> decltype(i) { // OK, returns \tcode{int} return i++; }; @@ -2391,7 +2742,7 @@ \end{itemize} If an expression potentially references a local entity -within a scope in which it is odr-usable, +within a scope in which it is odr-usable\iref{basic.def.odr}, and the expression would be potentially evaluated if the effect of any enclosing \keyword{typeid} expressions\iref{expr.typeid} were ignored, the entity is said to be \defnx{implicitly captured}{capture!implicit} @@ -2539,8 +2890,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 @@ -2570,7 +2921,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 }; @@ -2758,6 +3109,9 @@ } \end{codeblock} \end{example} + +\pnum +A fold expression is a pack expansion. \indextext{expression!fold|)}% \rSec2[expr.prim.req]{Requires expressions} @@ -2782,14 +3136,14 @@ \end{bnf} \begin{bnf} +\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} @@ -2803,8 +3157,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} @@ -2832,9 +3184,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 @@ -2846,13 +3200,19 @@ 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} \pnum The substitution of template arguments into a \grammarterm{requires-expression} -may result in the formation of invalid types or expressions in its -\grammarterm{requirement}s or the violation of the semantic constraints of those \grammarterm{requirement}s. +can result in +the formation of invalid types or expressions in the immediate context of +its \grammarterm{requirement}s\iref{temp.deduct.general} or +the violation of the semantic constraints of those \grammarterm{requirement}s. In such cases, the \grammarterm{requires-expression} evaluates to \keyword{false}; it does not cause the program to be ill-formed. The substitution and semantic constraint checking @@ -2872,7 +3232,7 @@ \begin{codeblock} template concept C = requires { - new int[-(int)sizeof(T)]; // ill-formed, no diagnostic required + new decltype((void)T{}); // ill-formed, no diagnostic required }; \end{codeblock} \end{example} @@ -2888,10 +3248,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} @@ -2920,6 +3280,8 @@ \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}. \begin{note} The enclosing \grammarterm{requires-expression} will evaluate to \keyword{false} if substitution of template arguments fails. @@ -2957,7 +3319,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: @@ -2982,6 +3346,7 @@ The immediately-declared constraint\iref{temp.param} of the \grammarterm{type-constraint} for \tcode{\keyword{decltype}((E))} shall be satisfied. +\end{itemize} \begin{example} Given concepts \tcode{C} and \tcode{D}, \begin{codeblock} @@ -3000,8 +3365,6 @@ (including in the case where $n$ is zero). \end{example} \end{itemize} -\end{itemize} - \pnum \begin{example} \begin{codeblock} @@ -3064,18 +3427,6 @@ \end{codeblock} \tcode{D} is satisfied if \tcode{sizeof(decltype (+t)) == 1}\iref{temp.constr.atomic}. \end{example} - -\pnum -A local parameter shall only appear as an unevaluated operand\iref{term.unevaluated.operand} -within the \grammarterm{constraint-expression}. -\begin{example} -\begin{codeblock} -template concept C = requires (T a) { - requires sizeof(a) == 4; // OK - requires a == 0; // error: evaluation of a constraint variable -}; -\end{codeblock} -\end{example} \indextext{expression!requires|)} \indextext{expression!primary|)} @@ -3135,12 +3486,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}. @@ -3191,25 +3542,10 @@ The postfix expression shall have function type or function pointer type. For a call to a non-member function or to a static member function, -the postfix expression shall either be an lvalue that refers to a +the postfix expression shall be either an lvalue that refers to a function (in which case the function-to-pointer standard conversion\iref{conv.func} is suppressed on the postfix expression), -or have function pointer type. - -\pnum -For a call to a non-static member function, -the postfix expression shall be an -implicit\iref{class.mfct.non.static,class.static} or explicit -class member access\iref{expr.ref} whose \grammarterm{id-expression} is a -function member name, or a pointer-to-member -expression\iref{expr.mptr.oper} selecting a function member; the call is as a member of -the class object referred to by the -object expression. In the case of an implicit class -member access, the implied object is the one pointed to by \keyword{this}. -\begin{note} -A member function call of the form \tcode{f()} is interpreted as -\tcode{(*\keyword{this}).f()} (see~\ref{class.mfct.non.static}). -\end{note} +or a prvalue of function pointer type. \pnum If the selected @@ -3251,14 +3587,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. @@ -3270,7 +3612,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 @@ -3284,9 +3628,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) @@ -3301,20 +3647,24 @@ 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 calling function. +within the context of the full-expression\iref{intro.execution} +where the function call appears. \begin{example} -The access of the constructor, conversion functions or destructor is -checked at the point of call in the calling function. If a constructor -or destructor for a function parameter throws an exception, the search -for a handler starts in the calling function; in -particular, if the function called has a \grammarterm{function-try-block}\iref{except.pre} -with a handler that can handle the exception, -this handler is not considered. +The access\iref{class.access.general} of the +constructor, conversion functions, or destructor is +checked at the point of call. If a constructor +or destructor for a function parameter throws an exception, +any \grammarterm{function-try-block}\iref{except.pre} +of the called function +with a handler that can handle the exception +is not considered. \end{example} \pnum @@ -3324,9 +3674,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 @@ -3372,6 +3734,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}% @@ -3383,7 +3757,7 @@ A function can change the values of its non-const parameters, but these changes cannot affect the values of the arguments except where a parameter is of a reference type\iref{dcl.ref}; if the reference is to -a const-qualified type, \keyword{const_cast} is required to be used to +a const-qualified type, \keyword{const_cast} needs to be used to cast away the constness in order to modify the argument's value. Where a parameter is of \keyword{const} reference type a temporary object is introduced if @@ -3408,7 +3782,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}, @@ -3423,13 +3797,13 @@ to type \tcode{\keyword{void}*}\iref{conv.ptr}. After these conversions, if the argument does not have arithmetic, enumeration, pointer, pointer-to-member, -or class type, the program is ill-formed. Passing a potentially-evaluated -argument -of a scoped enumeration type or -of a class type\iref{class} having an eligible non-trivial -copy constructor, an eligible non-trivial move constructor, -or a -non-trivial destructor\iref{special}, +or class type, the program is ill-formed. +Passing a potentially-evaluated argument +of a scoped enumeration type\iref{dcl.enum} or +of a class type\iref{class} having +an eligible non-trivial copy constructor\iref{special,class.copy.ctor}, +an eligible non-trivial move constructor, or +a non-trivial destructor\iref{class.dtor}, with no corresponding parameter, is conditionally-supported with \impldef{passing argument of class type through ellipsis} semantics. If the argument has integral or enumeration type that is subject to the integral @@ -3448,6 +3822,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)} @@ -3474,6 +3851,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 {}; @@ -3488,24 +3903,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 @@ -3522,18 +3919,7 @@ 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}, is a postfix expression. \begin{note} If the keyword \keyword{template} is used, the following unqualified name @@ -3544,8 +3930,12 @@ \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 the first option (dot), +if the \grammarterm{id-expression} names a static member or an enumerator, +the first expression is a discarded-value expression\iref{expr.context}; +if the \grammarterm{id-expression} names a non-static data member, +the first expression shall be a glvalue. +For the second option (arrow), the first expression shall be a prvalue having pointer type. The expression \tcode{E1->E2} is converted to the equivalent form \tcode{(*(E1)).E2}; the remainder of @@ -3555,6 +3945,19 @@ \tcode{(*(E1))} is an lvalue. \end{footnote} +\pnum +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}, +determines the result of the entire postfix expression. + \pnum Abbreviating \grammarterm{postfix-expression}\tcode{.}\grammarterm{id-expression} @@ -3592,7 +3995,12 @@ \pnum If \tcode{E2} is declared to have type ``reference to \tcode{T}'', then -\tcode{E1.E2} is an lvalue; the type of \tcode{E1.E2} is \tcode{T}. +\tcode{E1.E2} is an lvalue of type \tcode{T}. +If \tcode{E2} is 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} @@ -3618,6 +4026,8 @@ ``\cvqual{cq12} \cvqual{vq12} \tcode{T}''. \item If \tcode{E2} is 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} @@ -3628,8 +4038,7 @@ \tcode{E1.E2} is an lvalue. \item Otherwise (when \tcode{E2} refers to a non-static member function), -\tcode{E1.E2} is a prvalue. The expression can be used only as the -left-hand operand of a member function call\iref{class.mfct}. +\tcode{E1.E2} is a prvalue. \begin{note} Any redundant set of parentheses surrounding the expression is ignored\iref{expr.prim.paren}. @@ -3640,8 +4049,8 @@ ill-formed. \item If \tcode{E2} is a member enumerator and the type of \tcode{E2} -is \tcode{T}, the expression \tcode{E1.E2} is a prvalue. The type of -\tcode{E1.E2} is \tcode{T}. +is \tcode{T}, the expression \tcode{E1.E2} is a prvalue of type \tcode{T} +whose value is the value of the enumerator. \end{itemize} \pnum @@ -3679,8 +4088,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} @@ -3690,7 +4099,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 @@ -3705,11 +4114,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}% @@ -3785,6 +4189,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}. @@ -3800,7 +4220,8 @@ \item If, in the most derived object pointed (referred) to by \tcode{v}, \tcode{v} points (refers) to a public base class subobject of a \tcode{C} object, and if only one object of type \tcode{C} is derived -from the subobject pointed (referred) to by \tcode{v} the result points (refers) to that \tcode{C} object. +from the subobject pointed (referred) to by \tcode{v}, +the result points (refers) to that \tcode{C} object. \item Otherwise, if \tcode{v} points (refers) to a public base class subobject of the most derived object, and the type of the most @@ -3879,26 +4300,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 @@ -3974,7 +4396,7 @@ \indextext{cast!reference}% An lvalue of type ``\cvqual{cv1} \tcode{B}'', where \tcode{B} is a class type, can be cast to type ``reference to \cvqual{cv2} \tcode{D}'', where -\tcode{D} is a class derived\iref{class.derived} from \tcode{B}, +\tcode{D} is a complete class derived\iref{class.derived} from \tcode{B}, if \cvqual{cv2} is the same cv-qualification as, or greater cv-qualification than, \cvqual{cv1}. If \tcode{B} is a virtual base class of \tcode{D} @@ -4013,7 +4435,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} @@ -4041,28 +4478,8 @@ \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 +Otherwise, +the inverse of a 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}, @@ -4174,7 +4591,7 @@ exists\iref{conv.mem}, the program is ill-formed. The null member pointer value\iref{conv.mem} is converted to the null member pointer value of the destination type. If class \tcode{B} -contains the original member, or is a base or derived class of the class +contains the original member, or is a base class of the class containing the original member, the resulting pointer to member points to the original member. Otherwise, the behavior is undefined. \begin{note} @@ -4192,7 +4609,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}, @@ -4206,6 +4623,9 @@ \end{codeblock} \end{example} +\pnum +No other conversion can be performed using \keyword{static_cast}. + \rSec3[expr.reinterpret.cast]{Reinterpret cast} \pnum @@ -4262,7 +4682,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}. @@ -4284,9 +4704,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 @@ -4361,22 +4778,25 @@ \indextext{cast!reinterpret!reference}% \indextext{cast!reference}% \indextext{type pun}% -A glvalue of type \tcode{T1}, -designating an object \placeholder{x}, -can be cast to the type ``reference to \tcode{T2}'' +If \tcode{v} is a glvalue of type \tcode{T1}, +designating an object or function \placeholder{x}, +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} @@ -4390,7 +4810,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}. @@ -4401,23 +4824,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 @@ -4430,20 +4846,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} @@ -4552,13 +4970,14 @@ \pnum \indextext{expression!unary operator}% \indextext{operator!unary}% -The unary \tcode{*} operator performs \defn{indirection}: +The unary \tcode{*} operator performs \defn{indirection}. \indextext{dereferencing|see{indirection}}% -the expression to which it is applied shall be a pointer to an object -type, or a pointer to a function type and the result is an lvalue -referring to the object or function to which the expression points. If -the type of the expression is ``pointer to \tcode{T}'', the type of the -result is ``\tcode{T}''. +Its operand shall be a prvalue of type ``pointer to \tcode{T}'', +where \tcode{T} is an object or function type. +The operator yields an lvalue of type \tcode{T}. +If the operand points to an object or function, +the result denotes that object or function; +otherwise, the behavior is undefined except as specified in \ref{expr.typeid}. \begin{note} \indextext{type!incomplete}% Indirection through a pointer to an incomplete type (other than @@ -4568,14 +4987,13 @@ \end{note} \pnum -The result of each of the following unary operators is a prvalue. +Each of the following unary operators yields a prvalue. \pnum \indextext{name!address of cv-qualified}% \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} @@ -4644,19 +5062,25 @@ \pnum \indextext{operator!unary plus}% -The operand of the unary \tcode{+} operator shall have arithmetic, unscoped +The operand of the unary \tcode{+} operator shall be a prvalue of +arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument. Integral promotion is performed on integral or enumeration operands. The type of the result is the type of the promoted operand. \pnum \indextext{operator!unary minus}% -The operand of the unary \tcode{-} operator shall have arithmetic or unscoped +The operand of the unary \tcode{-} operator shall be a prvalue of +arithmetic or unscoped enumeration type and the result is the negative of its operand. Integral promotion is performed on integral or enumeration operands. The negative of an unsigned quantity is computed by subtracting its value from $2^n$, where $n$ is the number of bits in the promoted operand. The type of the result is the type of the promoted operand. +\begin{note} +The result is the two's complement of the operand +(where operand and result are considered as unsigned). +\end{note} \pnum \indextext{operator!logical negation}% @@ -4667,21 +5091,32 @@ The type of the result is \keyword{bool}. \pnum -\indextext{signed integer representation!ones' complement}% \indextext{operator!ones' complement}% -The operand of \tcode{\~{}} shall have integral or unscoped enumeration type; the -result is the ones' complement of its operand. Integral promotions are -performed. The type of the result is the type of the promoted operand. +The operand of the \tcode{\~{}} operator shall be a prvalue of +integral or unscoped enumeration type. +Integral promotions are performed. +The type of the result is the type of the promoted operand. +% FIXME: [basic.fundamental]/p5 uses $x_i$; [expr] uses $\tcode{x}_i$. +Given the coefficients $\tcode{x}_i$ +of the base-2 representation\iref{basic.fundamental} +of the promoted operand \tcode{x}, +the coefficient $\tcode{r}_i$ +of the base-2 representation of the result \tcode{r} +is 1 if $\tcode{x}_i$ is 0, and 0 otherwise. +\begin{note} +The result is the ones' complement of the operand +(where operand and result are considered as unsigned). +\end{note} There is an ambiguity in the grammar when \tcode{\~{}} is followed by -a \grammarterm{type-name} or \grammarterm{decltype-specifier}. -The ambiguity is resolved by treating \tcode{\~{}} as the unary complement +a \grammarterm{type-name} or \grammarterm{computed-type-specifier}. +The ambiguity is resolved by treating \tcode{\~{}} as the operator rather than as the start of an \grammarterm{unqualified-id} naming a destructor. \begin{note} Because the grammar does not permit an operator to follow the \tcode{.}, \tcode{->}, or \tcode{::} tokens, a \tcode{\~{}} followed by -a \grammarterm{type-name} or \grammarterm{decltype-specifier} in a +a \grammarterm{type-name} or \grammarterm{computed-type-specifier} in a member access expression or \grammarterm{qualified-id} is unambiguously parsed as a destructor name. \end{note} @@ -4691,32 +5126,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} @@ -4729,6 +5148,8 @@ The \keyword{co_await} expression is used to suspend evaluation of a coroutine\iref{dcl.fct.def.coroutine} while awaiting completion of the computation represented by the operand expression. +Suspending the evaluation of a coroutine +transfers control to its caller or resumer. \begin{bnf} \nontermdef{await-expression}\br @@ -4736,9 +5157,11 @@ \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} @@ -4748,6 +5171,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. @@ -4762,9 +5188,10 @@ of the enclosing coroutine and \tcode{P} is the type of that object. \item Unless -the \grammarterm{await-expression} was implicitly produced by a -\grammarterm{yield-expression}\iref{expr.yield}, an initial suspend point, -or a final suspend point\iref{dcl.fct.def.coroutine}, +the \grammarterm{await-expression} was implicitly produced by +a \grammarterm{yield-expression}\iref{expr.yield}, +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}. If this search is performed and finds at least one declaration, @@ -4855,6 +5282,10 @@ rethrown\iref{except.throw}. Otherwise, control flow returns to the current coroutine caller or resumer\iref{dcl.fct.def.coroutine} without exiting any scopes\iref{stmt.jump}. +\indextext{coroutine!suspend point}% +The point in the coroutine +immediately prior to control returning to its caller or resumer +is a coroutine \defn{suspend point}. \item If the result of \placeholder{await-ready} is \keyword{true}, @@ -4976,7 +5407,7 @@ is applied. \pnum -The identifier in a \tcode{\keyword{sizeof}...} expression shall name a +The \grammarterm{identifier} in a \tcode{\keyword{sizeof}...} expression shall name a pack. The \tcode{\keyword{sizeof}...} operator yields the number of elements in the pack\iref{temp.variadic}. A \tcode{\keyword{sizeof}...} expression is a pack expansion\iref{temp.variadic}. @@ -4984,7 +5415,7 @@ \begin{codeblock} template struct count { - static const std::size_t value = sizeof...(Types); + static constexpr std::size_t value = sizeof...(Types); }; \end{codeblock} \end{example} @@ -4997,7 +5428,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} @@ -5016,7 +5447,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} @@ -5028,28 +5459,29 @@ \rSec3[expr.unary.noexcept]{\tcode{noexcept} operator} -\pnum \indextext{\idxcode{noexcept}}% \indextext{expression!\idxcode{noexcept}}% -The \keyword{noexcept} operator determines whether the evaluation of its operand, -which is an unevaluated operand\iref{term.unevaluated.operand}, can throw an -exception\iref{except.throw}. \begin{bnf} \nontermdef{noexcept-expression}\br \keyword{noexcept} \terminal{(} expression \terminal{)} \end{bnf} +\pnum +The operand of the \keyword{noexcept} operator +is an unevaluated operand\iref{term.unevaluated.operand}. +If the operand is a prvalue, +the temporary materialization conversion\iref{conv.rval} is applied. + \pnum The result of the \keyword{noexcept} operator is a prvalue of type \keyword{bool}. +The result is \tcode{false} if +the full-expression of the operand is potentially-throwing\iref{except.spec}, and +\tcode{true} otherwise. \begin{note} A \grammarterm{noexcept-expression} is an integral constant expression\iref{expr.const}. \end{note} - -\pnum -The result of the \keyword{noexcept} operator is \keyword{true} -unless the \grammarterm{expression} is potentially-throwing\iref{except.spec}. \indextext{expression!unary|)} \rSec3[expr.new]{New} @@ -5064,7 +5496,7 @@ \indextext{storage management|see{\tcode{delete}}}% \indextext{\idxcode{new}}% The \grammarterm{new-expression} attempts to create an object of the -\grammarterm{type-id}\iref{dcl.name} or \grammarterm{new-type-id} to which +\grammarterm{type-id} or \grammarterm{new-type-id}\iref{dcl.name} to which it is applied. The type of that object is the \defnadj{allocated}{type}. \indextext{type!incomplete}% This type shall be a complete object type\iref{term.incomplete.type}, @@ -5116,7 +5548,9 @@ \end{bnf} \pnum -If a placeholder type\iref{dcl.spec.auto} appears in the +If a placeholder type\iref{dcl.spec.auto} or +a placeholder for a deduced class type\iref{dcl.type.class.deduct} +appears in the \grammarterm{type-specifier-seq} of a \grammarterm{new-type-id} or \grammarterm{type-id} of a \grammarterm{new-expression}, the allocated type is deduced as follows: @@ -5198,6 +5632,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 @@ -5214,7 +5657,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 @@ -5242,10 +5685,10 @@ 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 core constant expression, +if the \grammarterm{expression} is a potentially-evaluated core constant expression, the program is ill-formed; \item otherwise, an allocation function is not called; instead @@ -5264,6 +5707,21 @@ When the value of the \grammarterm{expression} is zero, the allocation function is called to allocate an array with no elements. +\pnum +If the allocated type is an array, +the \grammarterm{new-initializer} is a \grammarterm{braced-init-list}, and +the \grammarterm{expression} +is potentially-evaluated and not a core constant expression, +the semantic constraints of copy-initializing a hypothetical element of +the array from an empty initializer list +are checked\iref{dcl.init.list}. +\begin{note} +The array can contain more elements than there are +elements in the \grammarterm{braced-init-list}, +requiring initialization of the remainder of the array elements from +an empty initializer list. +\end{note} + \pnum \indextext{storage duration!dynamic}% Objects created by a \grammarterm{new-expression} have dynamic storage @@ -5308,7 +5766,7 @@ and the deallocation function's name is \tcode{\keyword{operator} \keyword{delete}[]}. \begin{note} -An implementation is required to provide default definitions for the global +An implementation is expected to provide default definitions for the global allocation functions\iref{basic.stc.dynamic,new.delete.single,new.delete.array}. A \Cpp{} program can provide alternative definitions of @@ -5339,12 +5797,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 @@ -5525,7 +5978,8 @@ \begin{note} When the allocation function returns a value other than null, it must be a pointer to a block of storage in which space for the object has been -reserved. The block of storage is assumed to be appropriately aligned +reserved. The block of storage is assumed to be +appropriately aligned\iref{basic.align} and of the requested size. The address of the created object will not necessarily be the same as that of the block if the object is an array. \end{note} @@ -5561,10 +6015,6 @@ \grammarterm{new-expression}. \pnum -If the \grammarterm{new-expression} creates an object or an array of -objects of class type, access and ambiguity control are done for the -allocation function, the deallocation function\iref{basic.stc.dynamic.deallocation}, and -the constructor\iref{class.ctor} selected for the initialization (if any). If the \grammarterm{new-expression} creates an array of objects of class type, the destructor is potentially invoked\iref{class.dtor}. @@ -5614,6 +6064,9 @@ ill-formed. For a non-placement allocation function, the normal deallocation function lookup is used to find the matching deallocation function\iref{expr.delete}. +In any case, +the matching deallocation function (if any) shall be non-deleted and +accessible from the point where the \grammarterm{new-expression} appears. \begin{example} \begin{codeblock} struct S { @@ -5669,24 +6122,18 @@ that consists of empty square brackets can follow the \keyword{delete} keyword if the \grammarterm{lambda-expression} is enclosed in parentheses. \end{footnote} -The operand shall be of pointer to object type or of class type. If of -class type, the operand is contextually implicitly converted\iref{conv} +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 @@ -5697,7 +6144,8 @@ \indextext{array!\idxcode{delete}}% In an array delete expression, the value of the operand of \keyword{delete} may be a null pointer value or a pointer value that resulted from -a previous array \grammarterm{new-expression}. +a previous array \grammarterm{new-expression} whose +allocation function was not a non-allocating form\iref{new.delete.placement}. \begin{footnote} For nonzero-length arrays, this is the same as a pointer to the first @@ -5729,15 +6177,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}% @@ -5745,9 +6188,12 @@ null pointer value and the selected deallocation function (see below) is not a destroying operator delete, -the \grammarterm{delete-expression} will invoke the +evaluating the \grammarterm{delete-expression} invokes the destructor (if any) for the object or the elements of the array being -deleted. In the case of an array, the elements will be destroyed in +deleted. +The destructor shall be accessible from the point where +the \grammarterm{delete-expression} appears. +In the case of an array, the elements are destroyed in order of decreasing address (that is, in reverse order of the completion of their constructor; see~\ref{class.base.init}). @@ -5828,8 +6274,7 @@ \end{note} \pnum -If more than one deallocation function is found, -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, @@ -5851,13 +6296,17 @@ If the type is complete and if, for an array delete expression only, the operand is a pointer to a class type with a -non-trivial destructor or a (possibly multi-dimensional) array thereof, +non-trivial destructor or a (possibly multidimensional) array thereof, the function with a parameter of type \tcode{std::size_t} is selected. \item Otherwise, it is unspecified whether a deallocation function with a parameter of type \tcode{std::size_t} is selected. \end{itemize} +Unless the deallocation function is selected +at the point of definition of the dynamic type's virtual destructor, +the selected deallocation function shall be accessible +from the point where the \grammarterm{delete-expression} appears. \pnum For a single-object delete expression, @@ -5911,10 +6360,6 @@ the behavior is undefined\iref{new.delete.single,new.delete.array}. \end{note} -\pnum -Access and ambiguity control are done for both the deallocation function -and the destructor\iref{class.dtor,class.free}. - \rSec2[expr.cast]{Explicit type conversion (cast notation)}% \indextext{expression!cast|(} @@ -5980,8 +6425,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} @@ -5992,6 +6438,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} @@ -6006,7 +6461,7 @@ inheritance relationship between the two classes. \begin{note} For example, if the classes were defined later in the translation unit, -a multi-pass compiler would be permitted to interpret a cast between +a multi-pass compiler could validly interpret a cast between pointers to the classes as if the class types were complete at the point of the cast. \end{note} @@ -6033,6 +6488,7 @@ \pnum The binary operator \tcode{.*} binds its second operand, which shall be +a prvalue of type ``pointer to member of \tcode{T}'' to its first operand, which shall be a glvalue of @@ -6042,6 +6498,7 @@ \pnum The binary operator \tcode{->*} binds its second operand, which shall be +a prvalue of type ``pointer to member of \tcode{T}'' to its first operand, which shall be of type ``pointer to \tcode{U}'' where \tcode{U} is either \tcode{T} or @@ -6149,9 +6606,9 @@ \tcode{\%} operator yields the remainder from the division of the first expression by the second. \indextext{zero!undefined division by}% -If the second operand of \tcode{/} or \tcode{\%} is zero the behavior is +If the second operand of \tcode{/} or \tcode{\%} is zero, the behavior is undefined. -For integral operands the \tcode{/} operator yields the algebraic quotient with +For integral operands, the \tcode{/} operator yields the algebraic quotient with any fractional part discarded; \begin{footnote} This is often called truncation towards zero. @@ -6165,9 +6622,14 @@ \indextext{operator!additive} \pnum -The additive operators \tcode{+} and \tcode{-} group left-to-right. The -usual arithmetic conversions\iref{expr.arith.conv} are performed for operands of arithmetic or -enumeration type. +The additive operators \tcode{+} and \tcode{-} group left-to-right. +Each operand shall be a prvalue. +If both operands have arithmetic or unscoped enumeration type, +the usual arithmetic conversions\iref{expr.arith.conv} are performed. +Otherwise, if one operand has arithmetic or unscoped enumeration type, +integral promotion is applied\iref{conv.prom} to that operand. +A converted or promoted operand is used in place of +the corresponding original operand for the remainder of this section. \indextext{operator!addition}% \indextext{addition operator|see{operator, addition}}% @@ -6184,14 +6646,14 @@ \end{bnf} \indextext{incomplete}% -For addition, either both operands shall have arithmetic or unscoped enumeration +For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to a completely-defined object -type and the other shall have integral or unscoped enumeration type. +type and the other shall have integral type. \pnum For subtraction, one of the following shall hold: \begin{itemize} -\item both operands have arithmetic or unscoped enumeration type; or +\item both operands have arithmetic type; or \item \indextext{arithmetic!pointer}% @@ -6199,7 +6661,7 @@ versions of the same completely-defined object type; or \item the left operand is a pointer to a completely-defined object type -and the right operand has integral or unscoped enumeration type. +and the right operand has integral type. \end{itemize} \pnum @@ -6215,7 +6677,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}, @@ -6234,6 +6696,11 @@ $i - j$ of \tcode{x} if $0 \le i - j \le n$. \item Otherwise, the behavior is undefined. \end{itemize} +\begin{note} +Adding a value other than $0$ or $1$ +to a pointer to a base class subobject, a member subobject, +or a complete object results in undefined behavior. +\end{note} \pnum \indextext{\idxcode{ptrdiff_t}!implementation-defined type of}% @@ -6242,7 +6709,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} @@ -6252,23 +6719,27 @@ array elements $i$ and $j$ of the same array object \tcode{x}, the expression \tcode{P - Q} has the value $i - j$. -\item Otherwise, the behavior is undefined. \begin{note} If the value $i - j$ is not in the range of representable values of type \tcode{std::ptrdiff_t}, -the behavior is undefined. +the behavior is undefined\iref{expr.pre}. \end{note} +\item Otherwise, the behavior is undefined. \end{itemize} \pnum For addition or subtraction, if the expressions \tcode{P} or \tcode{Q} have type ``pointer to \cv{}~\tcode{T}'', where \tcode{T} and the array element type are not similar\iref{conv.qual}, the behavior is undefined. -\begin{note} -In particular, a pointer to a base class cannot be used for -pointer arithmetic when the array contains objects of a derived class type. -\end{note} +\begin{example} +\begin{codeblock} +int arr[5] = {1, 2, 3, 4, 5}; +unsigned int *p = reinterpret_cast(arr + 1); +unsigned int k = *p; // OK, value of \tcode{k} is $2$\iref{conv.lval} +unsigned int *q = p + 1; // undefined behavior: \tcode{p} points to an \tcode{int}, not an \tcode{unsigned int} object +\end{codeblock} +\end{example} \rSec2[expr.shift]{Shift operators} @@ -6293,7 +6764,7 @@ shift-expression \terminal{>>} additive-expression \end{bnf} -The operands shall be of integral or unscoped enumeration type and integral +The operands shall be prvalues of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. \indextext{left shift!undefined}% @@ -6310,7 +6781,8 @@ \end{note} \pnum -The value of \tcode{E1 >> E2} is $\tcode{E1} / 2^\tcode{E2}$, rounded down. +The value of \tcode{E1 >> E2} is $\tcode{E1} / 2^\tcode{E2}$, +rounded towards negative infinity. \begin{note} \tcode{E1} is right-shifted \tcode{E2} bit positions. Right-shift on signed integral types is an arithmetic right shift, @@ -6471,13 +6943,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. @@ -6489,8 +6959,10 @@ \pnum The usual arithmetic conversions\iref{expr.arith.conv} are performed on operands of arithmetic -or enumeration type. If both operands are pointers, pointer -conversions\iref{conv.ptr} and qualification conversions\iref{conv.qual} +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} are performed to bring them to their composite pointer type\iref{expr.type}. After conversions, the operands shall have the same type. @@ -6531,6 +7003,13 @@ \tcode{q<=p}, and \tcode{q=p}, and \tcode{q>p} all yield \keyword{false}. Otherwise, the result of each of the operators is unspecified. +\begin{note} +A relational operator applied +to unequal function pointers +yields an unspecified result. +A pointer value of type ``pointer to \cv{}~\keyword{void}'' +can point to an object\iref{basic.compound}. +\end{note} \pnum If both operands (after conversions) are of arithmetic or enumeration type, each @@ -6553,17 +7032,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. @@ -6571,7 +7048,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} @@ -6720,7 +7197,7 @@ \end{bnf} \pnum -The \tcode{\^} operator groups left-to-right. +The \tcode{\caret} operator groups left-to-right. The operands shall be of integral or unscoped enumeration type. The usual arithmetic conversions\iref{expr.arith.conv} are performed. Given the coefficients $\tcode{x}_i$ and $\tcode{y}_i$ @@ -6895,13 +7372,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 @@ -6914,12 +7396,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. @@ -6927,6 +7411,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 @@ -6945,30 +7430,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. @@ -7048,19 +7535,26 @@ A \grammarterm{throw-expression} is of type \keyword{void}. \pnum -Evaluating a \grammarterm{throw-expression} with an operand throws an -exception\iref{except.throw}; the type of the exception object is determined by removing -any top-level \grammarterm{cv-qualifier}{s} from the static type of the -operand and adjusting the type -from ``array of \tcode{T}'' or function type \tcode{T} -to ``pointer to \tcode{T}''. +A \grammarterm{throw-expression} with an operand throws an +exception\iref{except.throw}. +The array-to-pointer\iref{conv.array} and function-to-pointer\iref{conv.func} +standard conversions are performed on the operand. +The type of the exception object is determined by removing +any top-level \grammarterm{cv-qualifier}{s} from the type of the +(possibly converted) operand. +The exception object is copy-initialized\iref{dcl.init.general} +from the (possibly converted) operand. \pnum \indextext{exception handling!rethrow}% A \grammarterm{throw-expression} with no operand rethrows the currently handled exception\iref{except.handle}. -The exception is reactivated with the existing exception object; +\indextext{exception handling!terminate called@\tcode{terminate} called}% +\indextext{\idxcode{terminate}!called}% +If no exception is presently being handled, +the function \tcode{std::terminate} is invoked\iref{except.terminate}. +Otherwise, the exception is reactivated with the existing exception object; no new exception object is created. The exception is no longer considered to be caught. \begin{example} @@ -7076,17 +7570,7 @@ \end{codeblock} \end{example} -\pnum -\indextext{exception handling!rethrow}% -\indextext{exception handling!terminate called@\tcode{terminate} called}% -\indextext{\idxcode{terminate}!called}% -If no exception is presently being handled, -evaluating a -\grammarterm{throw-expression} -with no operand calls -\tcode{std::\brk{}terminate()}\iref{except.terminate}. - -\rSec2[expr.ass]{Assignment and compound assignment operators}% +\rSec2[expr.assign]{Assignment and compound assignment operators}% \indextext{expression!assignment and compound assignment} \pnum @@ -7138,9 +7622,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}% @@ -7165,10 +7653,9 @@ The behavior of an expression of the form \tcode{E1 \placeholder{op}= E2} is equivalent to \tcode{E1 = E1 \placeholder{op} E2} except that \tcode{E1} is evaluated only once. -Such expressions are deprecated -if \tcode{E1} has volatile-qualified type -and \placeholder{op} is not one of the bitwise operators -\tcode{|}, \tcode{\&}, \tcode{\^}; see~\ref{depr.volatile.type}. +\begin{note} +The object designated by \tcode{E1} is accessed twice. +\end{note} For \tcode{+=} and \tcode{-=}, \tcode{E1} shall either have arithmetic type or be a pointer to a possibly cv-qualified completely-defined object type. In all other @@ -7187,17 +7674,22 @@ \end{note} \pnum -A \grammarterm{braced-init-list} may appear on the right-hand side of +A \grammarterm{braced-init-list} $B$ may appear on the right-hand side of + \begin{itemize} -\item an assignment to a scalar, in which case the initializer list shall have -at most a single element. The meaning of \tcode{x = \{v\}}, where \tcode{T} is the -scalar type of the expression \tcode{x}, is that of \tcode{x = T\{v\}}. The meaning of -\tcode{x = \{\}} is \tcode{x = T\{\}}. - -\item an assignment to an object of class type, in which case the initializer -list is passed as the argument to the assignment operator function selected by -overload resolution\iref{over.ass,over.match}. +\item +an assignment to a scalar of type \tcode{T}, in which case $B$ +shall have at most a single element. +The meaning of \tcode{x = $B$} is \tcode{x = t}, +where \tcode{t} is an invented temporary variable +declared and initialized as \tcode{T t = $B$}. + +\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.assign,over.match}. \end{itemize} + \begin{example} \begin{codeblock} complex z; @@ -7239,7 +7731,7 @@ \pnum \begin{note} In contexts where the comma token is given special meaning -(e.g. function calls\iref{expr.call}, +(e.g., function calls\iref{expr.call}, subscript expressions\iref{expr.sub}, lists of initializers\iref{dcl.init}, or \grammarterm{template-argument-list}{s}\iref{temp.names}), @@ -7276,31 +7768,153 @@ \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 - 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}. +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 +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 -it has reference or const-qualified integral or enumeration type. +it has reference or non-volatile const-qualified integral or enumeration type. \pnum A constant-initialized potentially-constant variable $V$ is @@ -7311,16 +7925,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} @@ -7340,9 +7981,20 @@ \item a control flow that passes through -a declaration of a variable with +a declaration of a block variable\iref{basic.scope.block} with static\iref{basic.stc.static} or -thread\iref{basic.stc.thread} storage duration; +thread\iref{basic.stc.thread} storage duration, +unless that variable is usable in constant expressions; +\begin{example} +\begin{codeblock} +constexpr char test() { + static const int x = 5; + static constexpr char c[] = "Hello World"; + return *(c + x); +} +static_assert(' ' == test()); +\end{codeblock} +\end{example} \item an invocation of a non-constexpr function; @@ -7356,8 +8008,7 @@ \item an invocation of an instantiated constexpr function -that fails to satisfy the requirements -for a constexpr function; +that is not constexpr-suitable; \item an invocation of a virtual function\iref{class.virtual} @@ -7368,9 +8019,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}; +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 @@ -7382,6 +8032,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 @@ -7426,7 +8079,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. @@ -7444,13 +8098,19 @@ \end{note} \item -a conversion from type \cv{}~\tcode{\keyword{void}*} to a pointer-to-object type; +a conversion +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} +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$; @@ -7462,9 +8122,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}, @@ -7482,6 +8160,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}; @@ -7493,21 +8178,24 @@ 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 \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}; @@ -7515,30 +8203,34 @@ \item a \keyword{goto} statement\iref{stmt.goto}. +\begin{note} +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 evaluation of $E$ would evaluate \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}, or +as specified in \ref{library} through \ref{\lastlibchapter} 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 @@ -7582,21 +8274,57 @@ \pnum For the purposes of determining whether an expression $E$ is a core constant expression, -the evaluation of a call to a member function of \tcode{std::allocator} +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, -does not disqualify $E$ from being a core constant expression, -even if the actual evaluation of such a call -would otherwise fail the requirements for a core constant expression. -Similarly, the evaluation of a call to -\tcode{std::construct_at} or -\tcode{std::ranges::construct_at}\iref{specialized.construct} -does not disqualify $E$ -from being a core constant expression unless -the first argument, of type \tcode{T*}, does not point -to storage allocated with \tcode{std::allocator} or -to an object whose lifetime began within the evaluation of $E$, or -the evaluation of the underlying constructor call -disqualifies $E$ from being a core constant expression. +is ignored. + +\pnum +For the purposes of determining whether $E$ is a core constant expression, +the evaluation of a call to +a trivial copy/move constructor or copy/move assignment operator of a union +is considered to copy/move the active member of the union, if any. +\begin{note} +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, @@ -7644,13 +8372,17 @@ void splash(Swim& swam) { static_assert(swam.phelps() == 28); // OK static_assert((&swam)->phelps() == 28); // OK + Swim* pswam = &swam; static_assert(pswam->phelps() == 28); // error: lvalue-to-rvalue conversion on a pointer // not usable in constant expressions + static_assert(how_many(swam) == 28); // OK static_assert(Swim().lochte() == 12); // OK + static_assert(swam.lochte() == 12); // error: invoking virtual function on reference // with constexpr-unknown dynamic type + static_assert(swam.coughlin == 12); // error: lvalue-to-rvalue conversion on an object // not usable in constant expressions } @@ -7664,13 +8396,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 multi-dimensional) array thereof, or + it is not of class type nor (possibly multidimensional) array thereof, or \item - it is of class type or (possibly multi-dimensional) array thereof, - that class type has a constexpr destructor, and + it is of class type or (possibly multidimensional) array thereof, + 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 @@ -7724,6 +8456,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}, @@ -7734,7 +8469,7 @@ 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 +as constant template arguments\iref{temp.arg}. \end{note} \indextext{contextually converted constant expression of type \tcode{bool}|see{conversion, contextual}}% @@ -7747,35 +8482,20 @@ \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 +an object or a non-immediate function, or +a prvalue core constant expression whose result object\iref{basic.lval} 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 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 - if the value is of pointer-to-member-function type, - it does not designate an immediate function, and - - \item - if the value is an object of class or array type, - each subobject satisfies these constraints for the value. +\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}, and +\item +no constituent value of pointer-to-member type designates an immediate function. \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 @@ -7789,6 +8509,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} @@ -7821,16 +8549,139 @@ \begin{itemize} \item its innermost enclosing non-block scope is -a function parameter scope of an immediate function, or +a function parameter scope of an immediate function, +\item +it is a subexpression of a manifestly constant-evaluated expression +or conversion, or \item its enclosing statement is enclosed\iref{stmt.pre} by the \grammarterm{compound-statement} of a consteval if statement\iref{stmt.if}. \end{itemize} -An expression or conversion is an \defn{immediate invocation} +An invocation is an \defn{immediate invocation} if it is a potentially-evaluated explicit or implicit invocation of an immediate function and is not in an immediate function context. -An immediate invocation shall be a constant expression. +An aggregate initialization is an immediate invocation +if it evaluates a default member initializer +that has a subexpression that is an immediate-escalating expression. + +\pnum +\indexdefn{expression!immediate-escalating}% +\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 +\begin{itemize} +\item +a potentially-evaluated \grammarterm{id-expression} +that denotes an immediate function +that is not a subexpression of an immediate invocation, or +\item +an immediate invocation that is not a constant expression +and is not a subexpression of an immediate invocation. +\end{itemize} + +\pnum +\indexdefn{immediate-escalating!function|see{function, immediate-escalating}}% +An \defnx{immediate-escalating}{function!immediate-escalating} function is +\begin{itemize} +\item +the call operator of a lambda that is not declared +with the \keyword{consteval} specifier, +\item +a defaulted special member function +that is not declared with the \keyword{consteval} specifier, or +\item +a function that results from the instantiation +of a templated entity defined with the \keyword{constexpr} specifier. +\end{itemize} +An immediate-escalating expression shall appear only +in an immediate-escalating function. + +\pnum +An \defnadj{immediate}{function} is a function or constructor that is +\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 +is \tcode{\placeholder{F}}'s function parameter scope. +\begin{tailnote} +Default member initializers used to initialize +a base or member subobject\iref{class.base.init} +are considered to be part of the function body\iref{dcl.fct.def.general}. +\end{tailnote} +\end{itemize} +\begin{example} +\begin{codeblock} +consteval int id(int i) { return i; } +constexpr char id(char c) { return c; } + +template +constexpr int f(T t) { + return t + id(t); +} + +auto a = &f; // OK, \tcode{f} is not an immediate function +auto b = &f; // error: \tcode{f} is an immediate function + +static_assert(f(3) == 6); // OK + +template +constexpr int g(T t) { // \tcode{g} is not an immediate function + return t + id(42); // because \tcode{id(42)} is already a constant +} + +template +constexpr bool is_not(T t, F f) { + return not f(t); +} + +consteval bool is_even(int i) { return i % 2 == 0; } + +static_assert(is_not(5, is_even)); // OK + +int x = 0; + +template +constexpr T h(T t = id(x)) { // \tcode{h} is not an immediate function + // \tcode{id(x)} is not evaluated when parsing the default argument\iref{dcl.fct.default,temp.inst} + return t; +} + +template +constexpr T hh() { // \tcode{hh} is an immediate function because of the invocation + return h(); // of the immediate function \tcode{id} in the default argument of \tcode{h} +} + +int i = hh(); // error: \tcode{hh()} is an immediate-escalating expression + // outside of an immediate-escalating function + +struct A { + int x; + int y = id(x); +}; + +template +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} @@ -7846,7 +8697,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} @@ -7871,7 +8725,8 @@ \end{example} \end{itemize} \begin{note} -A manifestly constant-evaluated expression +Except for a \grammarterm{static_assert-message}, +a manifestly constant-evaluated expression is evaluated even in an unevaluated operand\iref{term.unevaluated.operand}. \end{note} @@ -7901,8 +8756,7 @@ or \item -a subexpression of one of the above -that is not a subexpression of a nested unevaluated operand\iref{term.unevaluated.operand}. +a potentially-evaluated subexpression\iref{intro.execution} of one of the above. \end{itemize} \indextext{function!needed for constant evaluation}% @@ -7916,9 +8770,7 @@ that is potentially constant evaluated, or \item -a variable named by a potentially constant evaluated expression -that is either a constexpr variable or -is of non-volatile const-qualified integral type or of reference type. +a potentially-constant variable named by a potentially constant evaluated expression. \end{itemize} \indextext{expression|)} diff --git a/source/figdag.pdf b/source/figdag.pdf deleted file mode 100644 index e3d535caf2..0000000000 Binary files a/source/figdag.pdf and /dev/null differ diff --git a/source/figname.pdf b/source/figname.pdf deleted file mode 100644 index 5a603c462f..0000000000 Binary files a/source/figname.pdf and /dev/null differ diff --git a/source/fignonvirt.pdf b/source/fignonvirt.pdf deleted file mode 100644 index 3e55e71c65..0000000000 Binary files a/source/fignonvirt.pdf and /dev/null differ diff --git a/source/figvirt.pdf b/source/figvirt.pdf deleted file mode 100644 index 931e6a6097..0000000000 Binary files a/source/figvirt.pdf and /dev/null differ diff --git a/source/figvirtnonvirt.pdf b/source/figvirtnonvirt.pdf deleted file mode 100644 index ccfc2da16d..0000000000 Binary files a/source/figvirtnonvirt.pdf and /dev/null differ diff --git a/source/front.tex b/source/front.tex index ef9189eb80..5396b6397d 100644 --- a/source/front.tex +++ b/source/front.tex @@ -28,3 +28,5 @@ \let\index\oindex \setcounter{tocdepth}{5} + +\input{preface} diff --git a/source/future.tex b/source/future.tex index 093dba383e..50edea0be7 100644 --- a/source/future.tex +++ b/source/future.tex @@ -1,13 +1,11 @@ %!TEX root = std.tex \normannex{depr}{Compatibility features} -\newcommand{\requires}{\Fundesc{Requires}} - \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 @@ -18,24 +16,23 @@ An implementation may declare library names and entities described in this Clause with the \tcode{deprecated} attribute\iref{dcl.attr.deprecated}. -\rSec1[depr.arith.conv.enum]{Arithmetic conversion on enumerations} +\rSec1[depr.local]{Non-local use of TU-local entities} \pnum -The ability to apply the usual arithmetic conversions\iref{expr.arith.conv} -on operands where one is of enumeration type -and the other is of a different enumeration type -or a floating-point type +A declaration of a non-TU-local entity that is an exposure\iref{basic.link} is deprecated. \begin{note} -Three-way comparisons\iref{expr.spaceship} between such operands are ill-formed. +Such a declaration in an importable module unit is ill-formed. \end{note} \begin{example} \begin{codeblock} -enum E1 { e }; -enum E2 { f }; -bool b = e <= 3.7; // deprecated -int k = f - e; // deprecated -auto cmp = e <=> f; // error +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} @@ -58,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 @@ -95,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} @@ -104,9 +82,7 @@ brachiosaur = neck; // OK tail = brachiosaur; // OK tail = brachiosaur = neck; // deprecated -brachiosaur += neck; // deprecated -brachiosaur = brachiosaur + neck; // OK -brachiosaur |= neck; // OK, bitwise compound expression +brachiosaur += neck; // OK \end{codeblock} \end{example} @@ -139,40 +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. -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} @@ -190,2333 +143,556 @@ It is possible that future versions of \Cpp{} will specify that these implicit definitions are deleted\iref{dcl.fct.def.delete}. -\rSec1[depr.template.template]{\tcode{template} keyword before qualified names} +\rSec1[depr.static.constexpr]{Redeclaration of \tcode{static constexpr} data members} \pnum -The use of the keyword \keyword{template} -before the qualified name of a class or alias template -without a template argument list is deprecated. +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.res.on.required]{Requires paragraph} +\rSec1[depr.lit]{Literal operator function declarations using an identifier} \pnum -In addition to the elements specified in \ref{structure.specifications}, -descriptions of function semantics may also contain a \requires element -to denote the preconditions for calling a function. +A \grammarterm{literal-operator-id}\iref{over.literal} of the form +\begin{codeblock} +operator @\grammarterm{unevaluated-string}@ @\grammarterm{identifier}@ +\end{codeblock} +is deprecated. + +\rSec1[depr.template.template]{\tcode{template} keyword before qualified names} \pnum -\indextext{restriction}% -Violation of any preconditions specified in a function's \requires element -results in undefined behavior -unless the function's \throws element -specifies throwing an exception when the precondition is violated. +The use of the keyword \keyword{template} +before the qualified name of a class or alias template +without a template argument list is deprecated\iref{temp.names}. -\rSec1[depr.relops]{Relational operators}% -\indexlibraryglobal{rel_ops}% +\rSec1[depr.numeric.limits.has.denorm]{\tcode{has_denorm} members in \tcode{numeric_limits}} \pnum -The header \libheaderref{utility} has the following additions: - +The following type is defined +in addition to those specified in \libheaderref{limits}: \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&); +namespace std { + 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} \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} +\indextext{denormalized value|see{number, subnormal}}% +\indextext{value!denormalized|see{number, subnormal}}% +\indextext{subnormal number|see{number, subnormal}}% +\indextext{number!subnormal}% +The following members are defined +in addition to those specified in \ref{numeric.limits.general}: +\begin{codeblock} +static constexpr float_denorm_style has_denorm = denorm_absent; +static constexpr bool has_denorm_loss = false; +\end{codeblock} -\begin{itemdescr} \pnum -\requires -Type \tcode{T} is \oldconcept{EqualityComparable} (\tref{cpp17.equalitycomparable}). +The values of \tcode{has_denorm} and \tcode{has_denorm_loss} of +specializations of \tcode{numeric_limits} are unspecified. \pnum -\returns -\tcode{!(x == y)}. -\end{itemdescr} +The following members of the specialization \tcode{numeric_limits} are defined +in addition to those specified in \ref{numeric.special}: +\indexlibrarymember{float_denorm_style}{numeric_limits}% +\indexlibrarymember{has_denorm_loss}{numeric_limits}% +\begin{codeblock} +static constexpr float_denorm_style has_denorm = denorm_absent; +static constexpr bool has_denorm_loss = false; +\end{codeblock} -\indexlibraryglobal{operator>}% -\begin{itemdecl} -template bool operator>(const T& x, const T& y); -\end{itemdecl} +\rSec1[depr.c.macros]{Deprecated C macros} -\begin{itemdescr} \pnum -\requires -Type \tcode{T} is \oldconcept{LessThanComparable} (\tref{cpp17.lessthancomparable}). +The header \libheaderref{stdalign.h} has the following macros: +\begin{codeblock} +#define @\libxmacro{alignas_is_defined}@ 1 +#define @\libxmacro{alignof_is_defined}@ 1 +\end{codeblock} \pnum -\returns -\tcode{y < x}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator<=}}% -\begin{itemdecl} -template bool operator<=(const T& x, const T& y); -\end{itemdecl} +The header \libheaderref{stdbool.h} has the following macro: +\begin{codeblock} +#define @\libxmacro{bool_true_false_are_defined}@ 1 +\end{codeblock} -\begin{itemdescr} -\pnum -\requires -Type \tcode{T} is \oldconcept{LessThanComparable} (\tref{cpp17.lessthancomparable}). +\rSec1[depr.cerrno]{Deprecated error numbers} \pnum -\returns -\tcode{!(y < x)}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator>=}}% -\begin{itemdecl} -template bool operator>=(const T& x, const T& y); -\end{itemdecl} +The header \libheaderref{cerrno} has the following additional macros: -\begin{itemdescr} -\pnum -\requires -Type \tcode{T} is \oldconcept{LessThanComparable} (\tref{cpp17.lessthancomparable}). +\begin{codeblock} +#define @\libmacro{ENODATA}@ @\seebelow@ +#define @\libmacro{ENOSR}@ @\seebelow@ +#define @\libmacro{ENOSTR}@ @\seebelow@ +#define @\libmacro{ETIME}@ @\seebelow@ +\end{codeblock} \pnum -\returns -\tcode{!(x < y)}. -\end{itemdescr} - -\rSec1[depr.str.strstreams]{\tcode{char*} streams} - -\rSec2[depr.strstream.syn]{Header \tcode{} synopsis} +The meaning of these macros is defined by the POSIX standard. \pnum -The header \libheaderdef{strstream} -defines types that associate stream buffers with -character array objects and assist reading and writing such objects. +The following \tcode{enum errc} enumerators are defined +in addition to those specified in \ref{system.error.syn}: \begin{codeblock} -namespace std { - class strstreambuf; - class istrstream; - class ostrstream; - class strstream; -} +@\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} -\rSec2[depr.strstreambuf]{Class \tcode{strstreambuf}} +\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.meta.types]{Deprecated type traits} -\rSec3[depr.strstreambuf.general]{General} +\pnum +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} +\mandates +\tcode{Len} is not zero. +\tcode{Align} is equal to \tcode{alignof(T)} for some type \tcode{T} or +to \exposid{default-alignment}. -\rSec3[depr.strstreambuf.members]{Member functions} +\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}. -\indexlibrarymember{freeze}{strstreambuf}% -\begin{itemdecl} -void freeze(bool freezefl = true); -\end{itemdecl} +\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} -\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} +\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} -\indexlibrarymember{str}{strstreambuf}% +\indexlibraryglobal{aligned_union}% \begin{itemdecl} -char* str(); +template + struct aligned_union; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Calls -\tcode{freeze()}, -then returns the beginning pointer for the input sequence, \tcode{gbeg}. +\mandates +At least one type is provided. +Each type in the template parameter pack \tcode{Types} +is a complete object type. \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} - -\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{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{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 - }; -} -\end{codeblock} - -\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}% -\begin{itemdecl} -istrstream(const char* s, streamsize n); -istrstream(char* s, streamsize n); -\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} - -\begin{itemdescr} -\pnum -\returns -\tcode{const_cast(\&sb)}. -\end{itemdescr} - -\indexlibrarymember{str}{istrstream}% -\begin{itemdecl} -char* str(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{rdbuf()->str()}. -\end{itemdescr} - -\rSec2[depr.ostrstream]{Class \tcode{ostrstream}} - -\rSec3[depr.ostrstream.general]{General} - -\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 - }; -} -\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} - -\indexlibraryctor{ostrstream}% -\begin{itemdecl} -ostrstream(char* s, int n, ios_base::openmode mode = ios_base::out); -\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} - -\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)}. -\end{itemdescr} - -\indexlibrarymember{str}{ostrstream}% -\begin{itemdecl} -char* str(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{rdbuf()->str()}. -\end{itemdescr} - -\indexlibrarymember{pcount}{ostrstream}% -\begin{itemdecl} -int pcount() const; -\end{itemdecl} - -\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)}. -\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.default.allocator]{The default allocator} - -\pnum -The following member is defined in addition to those -specified in \ref{default.allocator}: - -\indexlibrarymember{is_always_equal}{allocator}% -\begin{codeblock} -namespace std { - template class allocator { - public: - using is_always_equal = true_type; - }; -} -\end{codeblock} - -\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: - -\indexlibraryglobal{is_literal_type}% -\begin{codeblock} -namespace std { - template struct is_pod; - template inline constexpr bool is_pod_v = is_pod::value; - template // \seebelow - struct aligned_storage; - template // \seebelow - using @\libglobal{aligned_storage_t}@ = typename aligned_storage::type; - template - struct aligned_union; - template - using @\libglobal{aligned_union_t}@ = typename aligned_union::type; -} -\end{codeblock} - -\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. - -\indexlibraryglobal{is_pod}% -\begin{itemdecl} -template struct is_pod; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\requires -\tcode{remove_all_extents_t} shall be a complete type or \cv{} \keyword{void}. - -\pnum -\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. -\indextext{POD}% -A 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 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. - -\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 -\requires \tcode{p} shall not be 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 -\requires \tcode{p} shall not be 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 -\requires \tcode{p} shall not be null. - -\pnum -\requires \tcode{mo} shall not be \tcode{memory_order::release} or \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 -\requires \tcode{p} shall not be 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 -\requires \tcode{p} shall not be null. - -\pnum -\requires \tcode{mo} shall not be \tcode{memory_order::acquire} or \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 -\requires \tcode{p} shall not be 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 -\requires \tcode{p} shall not be 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 -\requires \tcode{p} shall not be null and \tcode{v} shall not be 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 -\requires \tcode{p} shall not be null and \tcode{v} shall not be null. -The \tcode{failure} argument shall not be \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.string.capacity]{Deprecated \tcode{basic_string} capacity} - -\pnum -The following member is declared in addition to those members specified -in \ref{string.capacity}: - -\indexlibraryglobal{basic_string}% -\begin{codeblock} -namespace std { - template, - class Allocator = allocator> - class basic_string { - public: - void reserve(); - }; -} -\end{codeblock} - -\indexlibrarymember{reserve}{basic_string}% -\begin{itemdecl} -void reserve(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -After this call, \tcode{capacity()} has an unspecified value -greater than or equal to \tcode{size()}. -\begin{note} -This is a non-binding shrink to fit request. -\end{note} +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.locale.stdcvt]{Deprecated standard code conversion facets} - -\rSec2[depr.locale.stdcvt.general]{General} - -\pnum -The header \libheaderdef{codecvt} provides -code conversion facets for various character encodings. - -\rSec2[depr.codecvt.syn]{Header \tcode{} synopsis} - -\indexlibraryglobal{codecvt_mode}% -\indexlibraryglobal{codecvt_utf8}% -\indexlibraryglobal{codecvt_utf16}% -\indexlibraryglobal{codecvt_utf8_utf16}% -\begin{codeblock} -namespace std { - enum codecvt_mode { - consume_header = 4, - generate_header = 2, - little_endian = 1 - }; - - template - class codecvt_utf8 : public codecvt { - public: - explicit codecvt_utf8(size_t refs = 0); - ~codecvt_utf8(); - }; - - template - class codecvt_utf16 : public codecvt { - public: - explicit codecvt_utf16(size_t refs = 0); - ~codecvt_utf16(); - }; - - template - class codecvt_utf8_utf16 : public codecvt { - public: - explicit codecvt_utf8_utf16(size_t refs = 0); - ~codecvt_utf8_utf16(); - }; -} -\end{codeblock} - -\rSec2[depr.locale.stdcvt.req]{Requirements} - -\pnum -For each of the three code conversion facets \tcode{codecvt_utf8}, -\tcode{codecvt_utf16}, and \tcode{codecvt_utf8_utf16}: -\begin{itemize} -\item - \tcode{Elem} is the wide-character type, such as - \keyword{wchar_t}, \keyword{char16_t}, or \keyword{char32_t}. -\item - \tcode{Maxcode} is the largest wide-character code that the facet - will read or write without reporting a conversion error. -\item - If \tcode{(Mode \& consume_header)}, the facet shall consume an - initial header sequence, if present, when reading a multibyte sequence - to determine the endianness of the subsequent multibyte sequence to be read. -\item - If \tcode{(Mode \& generate_header)}, the facet shall generate an - initial header sequence when writing a multibyte sequence to advertise - the endianness of the subsequent multibyte sequence to be written. -\item - If \tcode{(Mode \& little_endian)}, the facet shall generate a - multibyte sequence in little-endian order, - as opposed to the default big-endian order. -\end{itemize} - -\pnum -\indextext{UTF-8}% -\indextext{UCS-2}% -\indextext{UTF-32}% -For the facet \tcode{codecvt_utf8}\indexlibraryglobal{codecvt_utf8}: -\begin{itemize} -\item - The facet shall convert between UTF-8 multibyte sequences - and UCS-2 or UTF-32 (depending on the size of \tcode{Elem}) - within the program. -\item - Endianness shall not affect how multibyte sequences are read or written. -\item - The multibyte sequences may be written as either a text or a binary file. -\end{itemize} - -\pnum -\indextext{UTF-16}% -\indextext{UCS-2}% -\indextext{UTF-32}% -For the facet \tcode{codecvt_utf16}\indexlibraryglobal{codecvt_utf16}: -\begin{itemize} -\item - The facet shall convert between UTF-16 multibyte sequences - and UCS-2 or UTF-32 (depending on the size of \tcode{Elem}) - within the program. -\item - Multibyte sequences shall be read or written - according to the \tcode{Mode} flag, as set out above. -\item - The multibyte sequences may be written only as a binary file. - Attempting to write to a text file produces undefined behavior. -\end{itemize} - -\pnum -\indextext{UTF-8}% -\indextext{UTF-16}% -For the facet \tcode{codecvt_utf8_utf16}\indexlibraryglobal{codecvt_utf8_utf16}: -\begin{itemize} -\item - The facet shall convert between UTF-8 multibyte sequences - and UTF-16 (one or two 16-bit codes) within the program. -\item - Endianness shall not affect how multibyte sequences are read or written. -\item - The multibyte sequences may be written as either a text or a binary file. -\end{itemize} - -\pnum -The encoding forms UTF-8, UTF-16, and UTF-32 are specified in ISO/IEC 10646. -The encoding form UCS-2 is specified in ISO/IEC 10646:2003. -\begin{footnote} -Cancelled and replaced by ISO/IEC 10646:2017. -\end{footnote} - -\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}} +\rSec1[depr.relops]{Relational operators}% +\indexlibraryglobal{rel_ops}% \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 the code -conversion facet \tcode{codecvt_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} -wstring_convert> myconv; -std::string mbstring = myconv.to_bytes(L"Hello\n"); -std::cout << mbstring; -\end{codeblock} -\end{example} +The header \libheaderref{utility} has the following additions: -\indexlibraryglobal{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 - }; +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 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} +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: -\indexlibrarymember{byte_string}{wstring_convert}% +\indexlibrary{\idxcode{operator"!=}}% \begin{itemdecl} -using byte_string = basic_string, ByteAlloc>; +template bool operator!=(const T& x, const T& y); \end{itemdecl} \begin{itemdescr} \pnum -The type shall be a synonym for \tcode{basic_string, ByteAlloc>}. -\end{itemdescr} - -\indexlibrarymember{converted}{wstring_convert}% -\begin{itemdecl} -size_t converted() const noexcept; -\end{itemdecl} +\expects +\tcode{T} meets the \oldconcept{EqualityComparable} requirements (\tref{cpp17.equalitycomparable}). -\begin{itemdescr} \pnum \returns -\tcode{cvtcount}. +\tcode{!(x == y)}. \end{itemdescr} -\indexlibrarymember{from_bytes}{wstring_convert}% +\indexlibraryglobal{operator>}% \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); +template bool operator>(const T& x, const T& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -The first member function shall convert the single-element sequence \tcode{byte} to a -wide string. The second member function shall convert the null-terminated -sequence beginning at \tcode{ptr} to a wide string. The third member function -shall convert the sequence stored in \tcode{str} to a wide string. The fourth member -function shall convert 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 -shall be set to its default value (the initial conversion state) before the -conversion begins. Otherwise it shall be left unchanged. - -\item The number of input elements successfully converted shall be stored in \tcode{cvtcount}. -\end{itemize} +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). \pnum \returns -If no conversion error occurs, the member function shall return the converted wide string. -Otherwise, if the object was constructed with a wide-error string, the -member function shall return the wide-error string. -Otherwise, the member function throws an object of class \tcode{range_error}. +\tcode{y < x}. \end{itemdescr} -\indexlibrarymember{int_type}{wstring_convert}% +\indexlibrary{\idxcode{operator<=}}% \begin{itemdecl} -using int_type = typename wide_string::traits_type::int_type; +template bool operator<=(const T& x, const T& y); \end{itemdecl} \begin{itemdescr} \pnum -The type shall be a synonym for \tcode{wide_string::traits_type::int_type}. -\end{itemdescr} +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). -\indexlibrarymember{state}{wstring_convert}% -\begin{itemdecl} -state_type state() const; -\end{itemdecl} - -\begin{itemdescr} \pnum \returns -\tcode{cvtstate}. +\tcode{!(y < x)}. \end{itemdescr} -\indexlibrarymember{state_type}{wstring_convert}% +\indexlibrary{\idxcode{operator>=}}% \begin{itemdecl} -using state_type = typename Codecvt::state_type; +template bool operator>=(const T& x, const T& y); \end{itemdecl} \begin{itemdescr} \pnum -The type shall be a synonym for \tcode{Codecvt::state_type}. -\end{itemdescr} +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). -\indexlibrarymember{to_bytes}{wstring_convert}% -\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); -\end{itemdecl} - -\begin{itemdescr} \pnum -\effects -The first member function shall convert the single-element sequence \tcode{wchar} to a byte string. -The second member function shall convert the null-terminated sequence beginning at \tcode{wptr} to -a byte string. The third member function shall convert the sequence stored in \tcode{wstr} to a -byte string. The fourth member function shall convert the sequence defined by the -range \range{first}{last} to a byte string. +\returns +\tcode{!(x < y)}. +\end{itemdescr} + +\rSec1[depr.tuple]{Tuple} \pnum -In all cases: +The header \libheaderref{tuple} has the following additions: -\begin{itemize} -\item If the \tcode{cvtstate} object was not constructed with an explicit value, it -shall be -set to its default value (the initial conversion state) before the -conversion begins. Otherwise it shall be left unchanged. -\item The number of input elements successfully converted shall be stored -in \tcode{cvtcount}. -\end{itemize} +\begin{codeblock} +namespace std { + template struct tuple_size; + template struct tuple_size; -\pnum -\returns -If no conversion error occurs, the member function shall return the converted byte string. -Otherwise, if the object was constructed with a byte-error string, the -member function shall return the byte-error string. -Otherwise, the member function shall throw an object of class \tcode{range_error}. -\end{itemdescr} + template struct tuple_element; + template struct tuple_element; +} +\end{codeblock} -\indexlibrarymember{wide_string}{wstring_convert}% \begin{itemdecl} -using wide_string = basic_string, WideAlloc>; +template struct tuple_size; +template struct tuple_size; \end{itemdecl} \begin{itemdescr} \pnum -The type shall be a synonym for \tcode{basic_string, WideAlloc>}. -\end{itemdescr} - -\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()); -\end{itemdecl} +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}. -\begin{itemdescr} \pnum -\requires -For the first and second constructors, \tcode{pcvt != nullptr}. +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 -\effects -The first constructor shall store \tcode{pcvt} in \tcode{cvtptr} and -default values in \tcode{cvtstate}, \tcode{byte_err_string}, and -\tcode{wide_err_string}. -The second constructor shall store \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 shall be retained between calls to \tcode{from_bytes} and -\tcode{to_bytes}. -The third constructor shall store \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}. +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 -The destructor shall delete \tcode{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}% \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. -\indexlibrarymember{state_type}{wbuffer_convert}% -\begin{itemdecl} -using state_type = typename Codecvt::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 -The type shall be a synonym for \tcode{Codecvt::state_type}. -\end{itemdescr} +\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: -\indexlibraryctor{wbuffer_convert}% -\begin{itemdecl} -explicit wbuffer_convert( - streambuf* bytebuf, - Codecvt* pcvt = new Codecvt, - state_type state = state_type()); -\end{itemdecl} +\begin{codeblock} +class MyIterator : + public iterator { + // code implementing \tcode{++}, etc. +}; +\end{codeblock} +\end{example} -\begin{itemdescr} -\pnum -\requires -\tcode{pcvt != nullptr}. +\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 -The destructor shall delete \tcode{cvtptr}. +\returns +\tcode{current}. \end{itemdescr} \rSec1[depr.locale.category]{Deprecated locale category facets} @@ -2524,21 +700,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 @@ -2546,14 +726,47 @@ 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} +\pnum +The header \libheaderrefx{filesystem}{fs.filesystem.syn} has the following additions: + \indexlibraryglobal{u8path}% \begin{itemdecl} template @@ -2564,23 +777,27 @@ \begin{itemdescr} \pnum -\requires The \tcode{source} and \range{first}{last} - sequences are UTF-8 encoded. The value type of \tcode{Source} - and \tcode{InputIterator} is \tcode{char} or \keyword{char8_t}. - \tcode{Source} meets the requirements specified in \ref{fs.path.req}. +\mandates +The value type of \tcode{Source} and \tcode{InputIterator} is +\tcode{char} or \keyword{char8_t}. + +\pnum +\expects +The \tcode{source} and \range{first}{last} sequences are UTF-8 encoded. +\tcode{Source} meets the requirements specified in \ref{fs.path.req}. \pnum \returns \begin{itemize} -\item If \tcode{value_type} is \tcode{char} and the current native +\item If \tcode{path::value_type} is \tcode{char} and the current native narrow encoding\iref{fs.path.type.cvt} is UTF-8, return \tcode{path(source)} or \tcode{path(first, last)}; otherwise, -\item if \tcode{value_type} is \keyword{wchar_t} and the +\item if \tcode{path::value_type} is \keyword{wchar_t} and the native wide encoding is UTF-16, or - if \tcode{value_type} is \keyword{char16_t} or \keyword{char32_t}, + if \tcode{path::value_type} is \keyword{char16_t} or \keyword{char32_t}, convert \tcode{source} or \range{first}{last} - to a temporary, \tcode{tmp}, of type \tcode{string_type} and + to a temporary, \tcode{tmp}, of type \tcode{path::string_type} and return \tcode{path(tmp)}; otherwise, \item convert \tcode{source} or \range{first}{last} @@ -2637,15 +854,18 @@ 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} \rSec2[depr.atomics.volatile]{Volatile access} \pnum -If an atomic specialization has one of the following overloads, +If an \tcode{atomic}\iref{atomics.types.generic} specialization has one of the following overloads, then that overload participates in overload resolution even if \tcode{atomic::is_always_lock_free} is \tcode{false}: \begin{codeblock} @@ -2687,13 +907,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. @@ -2707,3 +927,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 cce294040a..75705a2bab 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -6,15 +6,14 @@ \indextext{scope|(}% This document specifies requirements for implementations of the \Cpp{} programming language. The first such requirement is that -they implement the language, so this document also +an implementation implements the language, so this document also defines \Cpp{}. Other requirements and relaxations of the first requirement appear at various places within this document. \pnum \Cpp{} is a general purpose programming language based on the C -programming language as described in ISO/IEC 9899:2018 -\doccite{Programming languages --- C} (hereinafter referred to as the -\defnx{C standard}{C!standard}). \Cpp{} provides many facilities +programming language as described in \IsoC{}. +\Cpp{} provides many facilities beyond those provided by C, including additional data types, classes, templates, exceptions, namespaces, operator overloading, function name overloading, references, free store @@ -35,35 +34,21 @@ \begin{itemize} % ISO documents in numerical order. \item ISO/IEC 2382, \doccite{Information technology --- Vocabulary} -\item ISO 8601:2004, \doccite{Data elements and interchange formats --- -Information interchange --- Representation of dates and times} -\item ISO/IEC 9899:2018, \doccite{Programming languages --- C} -\item ISO/IEC/IEEE 9945:2009, \doccite{Information Technology --- Portable -Operating System Interface (POSIX -\begin{footnote} +\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 \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 10646, \doccite{Information technology --- -Universal Coded Character Set (UCS)} -\item ISO/IEC 10646:2003, -\begin{footnote} -Cancelled and replaced by ISO/IEC 10646:2017. \end{footnote} -\doccite{Information technology --- -Universal Multiple-Octet Coded Character Set (UCS)} -\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} +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} @@ -75,50 +60,18 @@ Language Specification}, Standard Ecma-262, third edition, 1999. \item -The Unicode Consortium. -Unicode Standard Annex, UAX \#44, \doccite{Unicode Character Database}. -Edited by Ken Whistler and Lauren\c{t}iu Iancu. -Available from: \url{http://www.unicode.org/reports/tr44/} -\item -The Unicode Consortium. -The Unicode Standard, \doccite{Derived Core Properties}. -Available from: \url{https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt} +The Unicode Consortium. \doccite{The Unicode Standard}. +Available from: \url{https://www.unicode.org/versions/latest/} \end{itemize} - -\pnum -The library described in ISO/IEC 9899:2018, Clause 7, -is hereinafter called the -\defnx{C standard library}{C!standard library}. -\begin{footnote} -With the qualifications noted in \ref{\firstlibchapter} -through \ref{\lastlibchapter} and in \ref{diff.library}, the C standard -library is a subset of the \Cpp{} standard library. -\end{footnote} - -\pnum -The operating system interface described in ISO/IEC 9945:2009 is -hereinafter called \defn{POSIX}. - -\pnum -The ECMAScript Language Specification described in Standard Ecma-262 is -hereinafter called \defn{ECMA-262}. \indextext{references!normative|)} -\pnum -\begin{note} -References to ISO/IEC 10646:2003 are used only -to support deprecated features\iref{depr.locale.stdcvt}. -\end{note} - \rSec0[intro.defs]{Terms and definitions} \pnum \indextext{definitions|(}% For the purposes of this document, the terms and definitions -given in ISO/IEC 2382, -the terms, definitions, and symbols -given in ISO 80000-2:2009, +given in ISO/IEC 2382, ISO 80000-2:2019, and the following apply. \pnum @@ -127,24 +80,19 @@ at the following addresses: \begin{itemize} \item ISO Online browsing platform: available at \url{https://www.iso.org/obp} -\item IEC Electropedia: available at \url{http://www.electropedia.org} +\item IEC Electropedia: available at \url{https://www.electropedia.org/} \end{itemize} -\pnum -Terms that are used only in a small portion of this document -are defined where they are used and italicized where they are -defined. - \indexdefn{access}% \definition{access}{defns.access} \defncontext{execution-time action} 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}; @@ -152,21 +100,12 @@ although they may involve accesses of scalar subobjects. \end{defnote} -\definition{arbitrary-positional stream}{defns.arbitrary.stream} -\defncontext{library} -\indexdefn{stream!arbitrary-positional}% -stream that can seek to any integral position within -the length of the stream - -\begin{defnote} -Every arbitrary-positional stream is also a repositional stream\iref{defns.repositional.stream}. -\end{defnote} - \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}% @@ -200,6 +139,15 @@ \defncontext{statement} compound statement +\indexdefn{C!standard library}% +\definition{C standard library}{defns.c.lib} +library described in \IsoC{}, Clause 7 +\begin{defnote} +With the qualifications noted in \ref{\firstlibchapter} +through \ref{\lastlibchapter} and in \ref{diff.library}, +the C standard library is a subset of the \Cpp{} standard library. +\end{defnote} + \definition{character}{defns.character} \indexdefn{character}% \defncontext{library} @@ -225,32 +173,29 @@ \defncontext{library} \indexdefn{type!character container}% class or a type used to -represent a character +represent a \termref{defns.character}{character}{} \begin{defnote} -It is used for one of the template parameters of the string, -iostream, and regular expression class templates. +It is used for one of the template parameters of \tcode{char_traits} +and the class templates which use that, +such as the string, iostream, and regular expression class templates. \end{defnote} \definition{collating element}{defns.regex.collating.element} \indexdefn{collating element}% -sequence of one or more characters within the +sequence of one or more \termref{defns.character}{character}{s} within the current locale that collate as if they were a single character \definition{component}{defns.component} \defncontext{library} \indexdefn{component}% -group of library entities directly related as members, parameters, or +group of library entities directly related as members, \termref{defns.parameter}{parameter}{s}, or return types \begin{defnote} -For example, the class template -\tcode{basic_string} -and the non-member -function templates -that operate on -strings are referred to as the -\term{string component}. +For example, the class template \tcode{basic_string} +and the non-member function templates +that operate on strings are referred to as the string component. \end{defnote} \indexdefn{behavior!conditionally-supported}% @@ -262,6 +207,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 @@ -274,24 +224,19 @@ \indexdefn{deadlock}% situation wherein one or more threads are unable to continue execution because each is -blocked waiting for one or more of the others to satisfy some condition +\termref{defns.block}{block}{ed} waiting for one or more of the others to satisfy some condition \definition{default behavior}{defns.default.behavior.impl} \indexdefn{behavior!default}% \defncontext{library implementation} specific behavior provided by the implementation, -within the scope of the required behavior +within the scope of the \termref{defns.required.behavior}{required behavior}{} \indexdefn{message!diagnostic}% \definition{diagnostic message}{defns.diagnostic} message belonging to an \impldef{diagnostic message} subset of the implementation's output messages -\definition{direct-non-list-initialization}{defns.direct.non.list.init} -\indexdefn{direct-non-list-initialization}% -direct-initialization -that is not list-initialization - \indexdefn{type!dynamic}% \definition{dynamic type}{defns.dynamic.type} \defncontext{glvalue} type of the most derived object to which the @@ -307,7 +252,18 @@ \indexdefn{type!dynamic}% \definition{dynamic type}{defns.dynamic.type.prvalue} -\defncontext{prvalue} static type of the prvalue expression +\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} @@ -318,7 +274,7 @@ are all not potentially-throwing, and either -are all constant subexpressions or +are all \termref{defns.const.subexpr}{constant subexpression}{s} or are all not constant subexpressions \begin{example} @@ -336,14 +292,14 @@ \defncontext{regular expression} \indexdefn{finite state machine}% unspecified data structure that is used to -represent a regular expression, and which permits efficient matches +represent a \termref{defns.regex.regular.expression}{regular expression}{}, and which permits efficient matches against the regular expression to be obtained \definition{format specifier}{defns.regex.format.specifier} \defncontext{regular expression} \indexdefn{format specifier}% -sequence of one or more characters that is to be -replaced with some part of a regular expression match +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} \defncontext{library} @@ -353,7 +309,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}% @@ -362,7 +318,7 @@ \indexdefn{behavior!implementation-defined}% \definition{implementation-defined behavior}{defns.impl.defined} -behavior, for a well-formed program construct and correct data, that +behavior, for a \termref{defns.well.formed}{well-formed program}{} construct and correct data, that depends on the implementation and that each implementation documents \definition{implementation-defined strict total order over pointers} @@ -372,26 +328,12 @@ \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}% -\definition{implementation limits}{defns.impl.limits} -restrictions imposed upon programs by the implementation - -\definition{iostream class templates}{defns.iostream.templates} -\defncontext{library} -templates that are declared in header \libheader{iosfwd} and -take two template arguments - -\begin{defnote} -The arguments are named \tcode{charT} and \tcode{traits}. -The argument \tcode{charT} is a character container class, and -the argument \tcode{traits} is a class -which defines additional characteristics and functions -of the character type represented by \tcode{charT} -necessary to implement the iostream class templates. -\end{defnote} +\definition{implementation limit}{defns.impl.limits} +restriction imposed upon programs by the implementation \indexdefn{behavior!locale-specific}% \definition{locale-specific behavior}{defns.locale.specific} @@ -402,7 +344,7 @@ \defncontext{regular expression} \indexdefn{matched}% \indexdefn{regular expression!matched}% -condition when a sequence of zero or more characters +condition when a sequence of zero or more \termref{defns.character}{character}{s} correspond to a sequence of characters defined by the pattern \definition{modifier function}{defns.modifier} @@ -422,11 +364,6 @@ \indexdefn{construction!move}% direct-initialization of an object of some type with an rvalue of the same type -\indexdefn{character!multibyte}% -\definition{multibyte character}{defns.multibyte} -sequence of one or more bytes representing -the code unit sequence for an encoded character of the execution character set - \indexdefn{library call!non-constant}% \definition{non-constant library call}{defns.nonconst.libcall} invocation of a library function that, @@ -438,7 +375,7 @@ \indexdefn{NTCTS}% \indexdefn{string!null-terminated character type}% sequence of values that have -character type +\termref{defns.character}{character}{} type that precede the terminating null character type value \tcode{charT()} @@ -478,10 +415,10 @@ \definition{primary equivalence class}{defns.regex.primary.equivalence.class} \defncontext{regular expression} \indexdefn{primary equivalence class}% -set of one or more characters which +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} @@ -497,7 +434,7 @@ that is not part of the \Cpp{} standard library and not defined by the implementation, or a closure type of a non-implementation-provided lambda expression, -or an instantiation of a program-defined specialization +or an instantiation of a \termref{defns.prog.def.spec}{program-defined specialization}{} \begin{defnote} Types defined by the implementation include @@ -534,7 +471,7 @@ \definition{regular expression}{defns.regex.regular.expression} pattern that selects specific strings -from a set of character strings +from a set of \termref{defns.character}{character}{} strings \definition{replacement function}{defns.replacement} \defncontext{library} @@ -548,15 +485,11 @@ definitions of all translation units\iref{basic.link}. \end{defnote} -\definition{repositional stream}{defns.repositional.stream} -\defncontext{library} -\indexdefn{stream!repositional}% -stream that can seek to a position that was previously encountered - \definition{required behavior}{defns.required.behavior} \defncontext{library} \indexdefn{behavior!required}% -description of replacement function and handler function semantics +description of \termref{defns.replacement}{replacement function}{} +and \termref{defns.handler}{handler function}{} semantics applicable to both the behavior provided by the implementation and the behavior of any such function definition in the program @@ -577,6 +510,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} @@ -605,7 +555,7 @@ parameter-type-list, enclosing namespace, return type, -\grammarterm{template-head}, +\termref{defns.signature.template.head}{signature}{} of the \grammarterm{template-head}, and trailing \grammarterm{requires-clause} (if any) @@ -616,14 +566,14 @@ parameter-type-list, return type, enclosing class, -\grammarterm{template-head}, +\termref{defns.signature.template.head}{signature}{} of the \grammarterm{template-head}, and trailing \grammarterm{requires-clause} (if any) \indexdefn{signature}% \definition{signature}{defns.signature.spec} -\defncontext{function template specialization} signature of the template of which it is a specialization -and its template arguments (whether explicitly specified or deduced) +\defncontext{function template specialization} \termref{defns.signature.templ}{signature}{} of the template of which it is a specialization +and its template \termref{defns.argument.templ}{argument}{s} (whether explicitly specified or deduced) \indexdefn{signature}% \definition{signature}{defns.signature.member} @@ -645,15 +595,23 @@ \cv-qualifiers (if any), \grammarterm{ref-qualifier} (if any), return type (if any), -\grammarterm{template-head}, +\termref{defns.signature.template.head}{signature}{} of the \grammarterm{template-head}, and trailing \grammarterm{requires-clause} (if any) \indexdefn{signature}% \definition{signature}{defns.signature.member.spec} -\defncontext{class member function template specialization} signature of the member function template +\defncontext{class member function template specialization} \termref{defns.signature.member.templ}{signature}{} of the member function template of which it is a specialization and its template arguments (whether explicitly specified or deduced) +\indexdefn{signature}% +\definition{signature}{defns.signature.template.head} +\defncontext{\grammarterm{template-head}} +template \termref{defns.parameter.templ}{parameter}{} list, +excluding template parameter names and default \termref{defns.argument.templ}{argument}{s}, +and +\grammarterm{requires-clause} (if any) + \definition{stable algorithm}{defns.stable} \defncontext{library} \indexdefn{algorithm!stable}% @@ -679,7 +637,7 @@ \definition{sub-expression}{defns.regex.subexpression} \defncontext{regular expression} \indexdefn{sub-expression!regular expression}% -subset of a regular expression that has +subset of a \termref{defns.regex.regular.expression}{regular expression}{} that has been marked by parentheses \definition{traits class}{defns.traits} @@ -690,7 +648,7 @@ \indexdefn{unblock}% \definition{unblock}{defns.unblock} -satisfy a condition that one or more blocked 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} @@ -700,21 +658,21 @@ \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 -diagnostic message), to terminating a translation or execution (with the -issuance of a diagnostic message). Many erroneous program constructs do +\termref{defns.diagnostic}{diagnostic message}{}), to terminating a translation or execution (with the +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}% \definition{unspecified behavior}{defns.unspecified} -behavior, for a well-formed program construct and correct data, that +behavior, for a \termref{defns.well.formed}{well-formed program}{} construct and correct data, that depends on the implementation \begin{defnote} @@ -787,26 +745,44 @@ \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}% -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 -shall issue at least one diagnostic message. +the implementation does not support that construct, or \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. +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} During template argument deduction and substitution, @@ -814,6 +790,20 @@ are treated differently; see~\ref{temp.deduct}. \end{note} +Furthermore, a conforming implementation +shall not accept +\begin{itemize} +\item +a preprocessing translation unit containing +a \tcode{\#error} preprocessing directive\iref{cpp.error}, +\item +a translation unit with +a \grammarterm{static_assert-declaration} that fails\iref{dcl.pre}, or +\item +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 \indextext{conformance requirements!library|(}% @@ -843,7 +833,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 @@ -852,9 +843,25 @@ 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 have extensions (including additional library functions), provided they do not alter the @@ -904,7 +911,7 @@ \pnum \indextext{behavior!implementation-defined}% Certain aspects and operations of the abstract machine are described in this -document as implementation-defined (for example, +document as implementation-defined behavior (for example, \tcode{sizeof(int)}). These constitute the parameters of the abstract machine. Each implementation shall include documentation describing its characteristics and behavior in these respects. @@ -920,7 +927,7 @@ \pnum \indextext{behavior!unspecified}% Certain other aspects and operations of the abstract machine are -described in this document as unspecified (for example, +described in this document as unspecified behavior (for example, order of evaluation of arguments in a function call\iref{expr.call}). Where possible, this document defines a set of allowable behaviors. These @@ -931,45 +938,84 @@ \pnum \indextext{behavior!undefined}% Certain other operations are described in this document as -undefined (for example, the effect of +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}\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. @@ -981,7 +1027,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. @@ -1009,7 +1055,7 @@ \pnum \indextext{notation!syntax|(}% In the syntax notation used in this document, syntactic -categories are indicated by \fakegrammarterm{italic} type, and literal words +categories are indicated by \fakegrammarterm{italic, sans-serif} type, and literal words and characters in \tcode{constant} \tcode{width} type. Alternatives are listed on separate lines except in a few cases where a long set of alternatives is marked by the phrase ``one of''. If the text of an alternative is too long to fit on a line, the text is continued on subsequent lines indented from the first one. diff --git a/source/iostreams.tex b/source/iostreams.tex index 851476a378..535596515e 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -27,7 +27,7 @@ \ref{iostreams.base} & Iostreams base classes & \tcode{} \\ \rowsep \ref{stream.buffers} & Stream buffers & \tcode{} \\ \rowsep \ref{iostream.format} & Formatting and manipulators & - \tcode{}, \tcode{}, \tcode{} \\ \rowsep + \tcode{}, \tcode{}, \tcode{}, \tcode{} \\ \rowsep \ref{string.streams} & String streams & \tcode{} \\ \rowsep \ref{span.streams} & Span-based streams & \tcode{} \\ \rowsep \ref{file.streams} & File streams & \tcode{} \\ \rowsep @@ -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} @@ -128,8 +128,9 @@ \pnum In the classes of \ref{input.output}, a template parameter with name \tcode{charT} represents a member of the set of types containing \tcode{char}, \keyword{wchar_t}, -and any other \impldef{set of character types that iostreams templates can be instantiated for} -character types that meet the requirements for a character on which any of +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. \rSec2[iostreams.threadsafety]{Thread safety} @@ -479,6 +480,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 @@ -506,6 +513,17 @@ The results of including \libheader{iostream} in a translation unit shall be as if \libheader{iostream} defined an instance of \tcode{ios_base::Init} with static storage duration. +Each \Cpp{} library module\iref{std.modules} in a hosted implementation +shall behave as if it contains an interface unit that +defines an unexported \tcode{ios_base::Init} variable with +ordered initialization\iref{basic.start.dynamic}. + +\begin{note} +As a result, the definition of that variable is appearance-ordered before +any declaration following the point of importation of a \Cpp{} library module. +Whether such a definition exists is unobservable by a program that +does not reference any of the standard iostream objects. +\end{note} \pnum Mixing operations on corresponding wide- and narrow-character streams @@ -671,11 +689,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; @@ -718,8 +740,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 { }; @@ -815,7 +837,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); @@ -828,9 +850,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} @@ -866,19 +888,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} @@ -906,7 +928,7 @@ to class \tcode{ios_base::failure} shown in this subclause. \begin{note} When \tcode{ios_base::failure} is a synonym for another type, -that type is required to provide a nested type \tcode{failure} +that type needs to provide a nested type \tcode{failure} to emulate the injected-class-name. \end{note} The class @@ -1116,8 +1138,6 @@ Init(const Init&) = default; ~Init(); Init& operator=(const Init&) = default; - private: - static int init_cnt; // \expos }; } \end{codeblock} @@ -1131,17 +1151,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(); @@ -1429,7 +1438,7 @@ \begin{itemdescr} \pnum \returns -\tcode{index} +\exposid{index} \tcode{++}. \pnum @@ -1450,20 +1459,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 @@ -1488,7 +1497,7 @@ \pnum \returns On success -\tcode{iarray[idx]}. +\tcode{\exposid{iarray}[idx]}. On failure, a valid \tcode{long\&} initialized to 0. @@ -1506,13 +1515,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 @@ -1628,6 +1637,8 @@ \rSec2[fpos]{Class template \tcode{fpos}} +\rSec3[fpos.general]{General} + \indexlibraryglobal{fpos}% \begin{codeblock} namespace std { @@ -1636,8 +1647,9 @@ // \ref{fpos.members}, members stateT state() const; void state(stateT); + private: - stateT st; // \expos + stateT @\exposid{st}@; // \expos }; } \end{codeblock} @@ -1652,7 +1664,7 @@ \begin{itemdescr} \pnum \effects -Assigns \tcode{s} to \tcode{st}. +Assigns \tcode{s} to \exposid{st}. \end{itemdescr} \indexlibrarymember{state}{fpos}% @@ -1663,7 +1675,7 @@ \begin{itemdescr} \pnum \returns -Current value of \tcode{st}. +Current value of \exposid{st}. \end{itemdescr} \rSec3[fpos.operations]{Requirements} @@ -1700,7 +1712,7 @@ of type \tcode{P} or \tcode{const P}, \item \tcode{pl} and \tcode{ql} refer to modifiable lvalues of type \tcode{P}, \item \tcode{O} refers to type \tcode{streamoff}, and -\item \tcode{o} refers to a value +\item \tcode{o} and \tcode{o2} refer to values of type \tcode{streamoff} or \tcode{const streamoff}. \end{itemize} @@ -1725,7 +1737,7 @@ & & \effects Value-initializes the state object. \br - \ensures \tcode{p == P(o)} \\ \rowsep + \ensures \tcode{p == P(o)} is \tcode{true}. \\ \rowsep \tcode{P()} & \tcode{P} & \tcode{P(0)} & @@ -1738,8 +1750,20 @@ \tcode{streamoff} & converts to \tcode{offset} & \tcode{P(O(p)) == p} \\ \rowsep +\tcode{p == q} & + \tcode{bool} & + & + \remarks For any two values \tcode{o} and \tcode{o2}, + if \tcode{p} is obtained + from \tcode{o} converted to \tcode{P} or + from a copy of such \tcode{P} value and + if \tcode{q} is obtained + from \tcode{o2} converted to \tcode{P} or + from a copy of such \tcode{P} value, + then \tcode{p == q} is \tcode{true} + only if \tcode{o == o2} is \tcode{true}. \\ \rowsep \tcode{p != q} & - convertible to \tcode{bool} & + \tcode{bool} & \tcode{!(p == q)} & \\ \rowsep \tcode{p + o} & \tcode{P} & @@ -1846,7 +1870,6 @@ void move(basic_ios&& rhs); void swap(basic_ios& rhs) noexcept; void set_rdbuf(basic_streambuf* sb); - }; } \end{codeblock} @@ -2858,6 +2881,7 @@ \indexlibraryglobal{basic_streambuf}% \begin{codeblock} namespace std { + // \ref{streambuf}, class template \tcode{basic_streambuf} template> class basic_streambuf; using streambuf = basic_streambuf; @@ -3072,7 +3096,7 @@ \pnum The class template \tcode{basic_streambuf} -serves as an abstract base class for deriving various +serves as a base class for deriving various \term{stream buffers} whose objects each control two \term{character sequences}: @@ -3488,6 +3512,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()}, @@ -3548,6 +3577,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\range{pbeg}{pend} is a valid range. + \pnum \ensures \tcode{pbeg == pbase()}, @@ -3609,7 +3642,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} @@ -3631,7 +3664,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} @@ -4113,21 +4146,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); } @@ -4143,12 +4180,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 @@ -4163,6 +4202,7 @@ template basic_ostream& flush_emit(basic_ostream& os); + // \ref{ostream.rvalue}, rvalue stream insertion template Ostream&& operator<<(Ostream&& os, const T& x); @@ -4171,6 +4211,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); @@ -4187,17 +4228,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('\\')); @@ -4228,14 +4273,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} @@ -4380,32 +4429,6 @@ They may use other public members of \tcode{istream}. -\pnum -If -\tcode{rdbuf()->sbumpc()} -or -\tcode{rdbuf()->sgetc()} -returns -\tcode{traits::eof()}, -then the input function, except as explicitly noted otherwise, completes its actions and does -\tcode{setstate(eofbit)}, -which may throw -\tcode{ios_base::failure}\iref{iostate.flags}, before returning. - -\pnum -If one of these called functions throws an exception, then unless explicitly noted otherwise, -the input function sets -\tcode{badbit} -in the error state. -If -\tcode{badbit} -is set in -\tcode{exceptions()}, -the input function -rethrows the exception without completing its actions, otherwise -it does not throw anything and proceeds as if the called function had returned -a failure indication. - \rSec4[istream.cons]{Constructors} \indexlibraryctor{basic_istream}% @@ -4462,7 +4485,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{swap(rhs)}. +Equivalent to \tcode{swap(rhs)}. \pnum \returns @@ -4490,11 +4513,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 +4615,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 +4652,7 @@ \begin{itemdescr} \pnum \returns -\tcode{ok_}. +\exposid{ok_}. \end{itemdescr} \rSec3[istream.formatted]{Formatted input functions} @@ -4636,7 +4660,10 @@ \rSec4[istream.formatted.reqmts]{Common requirements} \pnum -Each formatted input function begins execution by constructing an object of class +Each formatted input function begins execution by constructing +an object of type \tcode{ios_base::iostate}, termed the local error state, and +initializing it to \tcode{ios_base::goodbit}. +It then creates an object of class \tcode{sentry} with the \tcode{noskipws} @@ -4650,20 +4677,22 @@ \tcode{bool}, the function endeavors to obtain the requested input. +Otherwise, +if the \tcode{sentry} constructor exits by throwing an exception or +if the \tcode{sentry} object produces \tcode{false} +when converted to a value of type \tcode{bool}, +the function returns without attempting to obtain any input. +If \tcode{rdbuf()->sbumpc()} or \tcode{rdbuf()->sgetc()} +returns \tcode{traits::eof()}, then +\tcode{ios_base::eofbit} is set in the local error state and +the input function stops trying to obtain the requested input. If an exception is thrown during input then -\tcode{ios_base::badbit} -is turned on -\begin{footnote} -This is done without causing an -\tcode{ios_base::failure} -to be thrown. -\end{footnote} -in -\tcode{*this}'s -error state. -If -\tcode{(exceptions()\&badbit) != 0} -then the exception is rethrown. +\tcode{ios_base::badbit} is set in the local error state, +\tcode{*this}'s error state is set to the local error state, and +the exception is rethrown if \tcode{(exceptions() \& badbit) != 0}. +After extraction is done, the input function calls \tcode{setstate}, which +sets \tcode{*this}'s error state to the local error state, and +may throw an exception. In any case, the formatted input function destroys the \tcode{sentry} object. @@ -4694,12 +4723,11 @@ \tcode{num_get<>}\iref{locale.num.get} object to perform parsing the input stream data. These extractors behave as formatted input functions (as described in~\ref{istream.formatted.reqmts}). After a \tcode{sentry} object is constructed, the -conversion occurs as if performed by the following code fragment: +conversion occurs as if performed by the following code fragment, +where \tcode{state} represents the input function's local error state: \begin{codeblock} using numget = num_get>; -iostate err = iostate::goodbit; -use_facet(loc).get(*this, 0, *this, err, val); -setstate(err); +use_facet(loc).get(*this, 0, *this, state, val); \end{codeblock} In the above fragment, \tcode{loc} @@ -4732,18 +4760,16 @@ (using the same notation as for the preceding code fragment): \begin{codeblock} using numget = num_get>; -iostate err = ios_base::goodbit; long lval; -use_facet(loc).get(*this, 0, *this, err, lval); +use_facet(loc).get(*this, 0, *this, state, lval); if (lval < numeric_limits::min()) { - err |= ios_base::failbit; + state |= ios_base::failbit; val = numeric_limits::min(); } else if (numeric_limits::max() < lval) { - err |= ios_base::failbit; + state |= ios_base::failbit; val = numeric_limits::max(); } else val = static_cast(lval); -setstate(err); \end{codeblock} \end{itemdescr} @@ -4758,18 +4784,16 @@ (using the same notation as for the preceding code fragment): \begin{codeblock} using numget = num_get>; -iostate err = ios_base::goodbit; long lval; -use_facet(loc).get(*this, 0, *this, err, lval); +use_facet(loc).get(*this, 0, *this, state, lval); if (lval < numeric_limits::min()) { - err |= ios_base::failbit; + state |= ios_base::failbit; val = numeric_limits::min(); } else if (numeric_limits::max() < lval) { - err |= ios_base::failbit; + state |= ios_base::failbit; val = numeric_limits::max(); } else val = static_cast(lval); -setstate(err); \end{codeblock} \end{itemdescr} @@ -4807,19 +4831,17 @@ (using the same notation as for the preceding code fragment): \begin{codeblock} using numget = num_get>; -iostate err = ios_base::goodbit; FP fval; -use_facet(loc).get(*this, 0, *this, err, fval); +use_facet(loc).get(*this, 0, *this, state, fval); if (fval < -numeric_limits<@\placeholder{extended-floating-point-type}@>::max()) { - err |= ios_base::failbit; + state |= ios_base::failbit; val = -numeric_limits<@\placeholder{extended-floating-point-type}@>::max(); } else if (numeric_limits<@\placeholder{extended-floating-point-type}@>::max() < fval) { - err |= ios_base::failbit; + state |= ios_base::failbit; val = numeric_limits<@\placeholder{extended-floating-point-type}@>::max(); } else { val = static_cast<@\placeholder{extended-floating-point-type}@>(fval); } -setstate(err); \end{codeblock} \begin{note} When the extended floating-point type has @@ -4926,7 +4948,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}. @@ -4943,10 +4965,9 @@ \tcode{width(0)}. \pnum -If the function extracted no characters, it calls -\tcode{setstate(failbit)}, -which may throw -\tcode{ios_base::\brk{}failure}\iref{iostate.flags}. +If the function extracted no characters, +\tcode{ios_base::failbit} is set in the input function's local error state +before \tcode{setstate} is called. \pnum \returns @@ -4968,12 +4989,10 @@ \effects Behaves like a formatted input member (as described in~\ref{istream.formatted.reqmts}) of \tcode{in}. -After a -\tcode{sentry} -object is constructed -a character is extracted from \tcode{in}, if one is available, and stored in \tcode{c}. -Otherwise, the function calls -\tcode{in.setstate(fail\-bit)}. +A character is extracted from \tcode{in}, if one is available, and stored in \tcode{c}. +Otherwise, +\tcode{ios_base::failbit} is set in the input function's local error state +before \tcode{setstate} is called. \pnum \returns @@ -5009,18 +5028,9 @@ \end{itemize} \pnum -If the function inserts no characters, it calls -\tcode{setstate(failbit)}, -which may throw -\tcode{ios_base::\brk{}failure}\iref{iostate.flags}. -If it inserted no characters because it caught -an exception thrown while extracting characters from -\tcode{*this} -and -\tcode{failbit} -is set in -\tcode{exceptions()}\iref{iostate.flags}, -then the caught exception is rethrown. +If the function inserts no characters, +\tcode{ios_base::failbit} is set in the input function's local error state +before \tcode{setstate} is called. \pnum \returns @@ -5030,7 +5040,10 @@ \rSec3[istream.unformatted]{Unformatted input functions} \pnum -Each unformatted input function begins execution by constructing an object of class +Each unformatted input function begins execution by constructing +an object of type \tcode{ios_base::iostate}, termed the local error state, and +initializing it to \tcode{ios_base::goodbit}. +It then creates an object of class \tcode{sentry} with the default argument \tcode{noskipws} @@ -5045,7 +5058,7 @@ the function endeavors to obtain the requested input. Otherwise, if the \tcode{sentry} constructor exits by throwing an exception or if -the \tcode{sentry} object returns \tcode{false}, when converted to a value of type +the \tcode{sentry} object produces \tcode{false}, when converted to a value of type \tcode{bool}, the function returns without attempting to obtain any input. In either case the number of extracted characters is set to 0; @@ -5053,27 +5066,20 @@ an argument shall also store a null character (using \tcode{charT()}) in the first location of the array. +If \tcode{rdbuf()->sbumpc()} or \tcode{rdbuf()->sgetc()} +returns \tcode{traits::eof()}, then +\tcode{ios_base::eofbit} is set in the local error state and +the input function stops trying to obtain the requested input. If an exception is thrown during input then -\tcode{ios_base::badbit} -is turned on -\begin{footnote} -This is done without causing an -\tcode{ios_base::failure} -to be thrown. -\end{footnote} -in -\tcode{*this}'s -error state. -(Exceptions thrown from -\tcode{basic_ios<>::clear()} -are not caught or rethrown.) -If -\tcode{(exceptions()\&badbit) != 0} -then the exception is rethrown. -It also counts the number of characters extracted. -If no exception has been thrown it ends -by storing the count in a member object -and returning the value specified. +\tcode{ios_base::badbit} is set in the local error state, +\tcode{*this}'s error state is set to the local error state, and +the exception is rethrown if \tcode{(exceptions() \& badbit) != 0}. +If no exception has been thrown it +stores the number of characters extracted +in a member object. +After extraction is done, the input function calls \tcode{setstate}, which +sets \tcode{*this}'s error state to the local error state, and +may throw an exception. In any event the \tcode{sentry} object @@ -5111,10 +5117,9 @@ (as described above). After constructing a \tcode{sentry} object, extracts a character \tcode{c}, if one is available. -Otherwise, the function calls -\tcode{setstate(failbit)}, -which may throw -\tcode{ios_base::failure}\iref{iostate.flags}. +Otherwise, +\tcode{ios_base::failbit} is set in the input function's local error state +before \tcode{setstate} is called. \pnum \returns @@ -5142,10 +5147,9 @@ and \tcode{unsigned char}. \end{footnote} -Otherwise, the function calls -\tcode{setstate(failbit)} -(which may throw -\tcode{ios_base::failure}\iref{iostate.flags}). +Otherwise, +\tcode{ios_base::failbit} is set in the input function's local error state +before \tcode{setstate} is called. \pnum \returns @@ -5178,9 +5182,7 @@ \tcode{n} is less than one or \tcode{n - 1} characters are stored; \item -end-of-file occurs on the input sequence -(in which case the function calls -\tcode{setstate(eofbit)}); +end-of-file occurs on the input sequence; \item \tcode{traits::eq(c, delim)} for the next available input @@ -5189,10 +5191,9 @@ \end{itemize} \pnum -If the function stores no characters, it calls -\tcode{setstate(failbit)} -(which may throw -\tcode{ios_base::\brk{}failure}\iref{iostate.flags}). +If the function stores no characters, +\tcode{ios_base::failbit} is set in the input function's local error state +before \tcode{setstate} is called. In any case, if \tcode{n} is greater than zero it then stores a null character into the next successive location of the array. @@ -5248,10 +5249,9 @@ \end{itemize} \pnum -If the function inserts no characters, it calls -\tcode{setstate(failbit)}, -which may throw -\tcode{ios_base::\brk{}failure}\iref{iostate.flags}. +If the function inserts no characters, +\tcode{ios_base::failbit} is set in the input function's local error state +before \tcode{setstate} is called. \pnum \returns @@ -5297,9 +5297,7 @@ Characters are extracted and stored until one of the following occurs: \begin{enumerate} \item -end-of-file occurs on the input sequence -(in which case the function calls -\tcode{setstate(eofbit)}); +end-of-file occurs on the input sequence; \item \tcode{traits::eq(c, delim)} for the next available input @@ -5329,10 +5327,9 @@ \end{footnote} \pnum -If the function extracts no characters, it calls -\tcode{setstate(failbit)} -(which may throw -\tcode{ios_base::\brk{}failure}\iref{iostate.flags}). +If the function extracts no characters, +\tcode{ios_base::failbit} is set in the input function's local error state +before \tcode{setstate} is called. \begin{footnote} This implies an empty input line will not cause @@ -5407,7 +5404,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 @@ -5858,7 +5855,7 @@ \effects Move constructs from the rvalue \tcode{rhs} by constructing the \tcode{basic_istream} base class with -\tcode{move(rhs)}. +\tcode{std::move(rhs)}. \end{itemdescr} \rSec4[iostream.dest]{Destructor} @@ -5885,7 +5882,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{swap(rhs)}. +Equivalent to \tcode{swap(rhs)}. \end{itemdescr} \indexlibrarymember{swap}{basic_iostream}% @@ -6158,7 +6155,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{swap(rhs)}. +Equivalent to \tcode{swap(rhs)}. \pnum \returns @@ -6184,11 +6181,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; @@ -6229,9 +6227,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 @@ -6272,7 +6270,7 @@ \pnum \effects Returns -\tcode{ok_}. +\exposid{ok_}. \end{itemdescr} \rSec4[ostream.seeks]{Seek members} @@ -6358,7 +6356,7 @@ which can throw an exception. If an exception is thrown during output, then \tcode{ios_base::badbit} -is turned on +is set \begin{footnote} This is done without causing an \tcode{ios_base::failure} @@ -6368,7 +6366,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} @@ -6388,7 +6386,7 @@ If a formatted output function of a stream \tcode{os} determines padding, it does so as follows. Given a \tcode{charT} character sequence \tcode{seq} where -\tcode{charT} is the character type of the stream, if +\tcode{charT} is the character container type of the stream, if the length of \tcode{seq} is less than \tcode{os.width()}, then enough copies of \tcode{os.fill()} are added to this sequence as necessary to pad to a width of \tcode{os.width()} characters. If @@ -6440,9 +6438,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 @@ -6450,9 +6447,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(); @@ -6463,9 +6459,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(); @@ -6477,20 +6472,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 @@ -6547,20 +6538,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} @@ -6732,7 +6719,7 @@ of \tcode{out}. Constructs a character sequence \tcode{seq}. If \tcode{c} has type \tcode{char} -and the character type of the stream is not +and the character container type of the stream is not \tcode{char}, then \tcode{seq} consists of \tcode{out.widen(c)}; @@ -6816,11 +6803,11 @@ \effects If the ordinary literal encoding\iref{lex.charset} is UTF-8, equivalent to: \begin{codeblock} -vprint_unicode(os, fmt.@\exposid{str}@, make_format_args(std::forward(args)...)); +vprint_unicode(os, fmt.@\exposid{str}@, make_format_args(args...)); \end{codeblock} Otherwise, equivalent to: \begin{codeblock} -vprint_nonunicode(os, fmt.@\exposid{str}@, make_format_args(std::forward(args)...)); +vprint_nonunicode(os, fmt.@\exposid{str}@, make_format_args(args...)); \end{codeblock} \end{itemdescr} @@ -6835,7 +6822,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} @@ -6859,23 +6860,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. -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}). @@ -6886,7 +6896,7 @@ if invoking the native Unicode API requires transcoding, implementations should substitute invalid code units with \unicode{fffd}{replacement character} per -The Unicode Standard Version 14.0 - Core Specification, Chapter 3.9. +the Unicode Standard, Chapter 3.9 \ucode{fffd} Substitution in Conversion. \end{itemdescr} \rSec3[ostream.unformatted]{Unformatted output functions} @@ -6904,7 +6914,7 @@ to generate the requested output. If an exception is thrown during output, then \tcode{ios_base::badbit} -is turned on +is set \begin{footnote} This is done without causing an \tcode{ios_base::failure} @@ -7013,7 +7023,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 @@ -7092,7 +7102,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 @@ -7721,13 +7731,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(std::forward(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(std::forward(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} @@ -7746,6 +7762,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 @@ -7757,7 +7787,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} @@ -7775,6 +7819,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); @@ -7787,26 +7846,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. +\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 @@ -7820,7 +7885,7 @@ If invoking the native Unicode API requires transcoding, implementations should substitute invalid code units with \unicode{fffd}{replacement character} per -The Unicode Standard Version 14.0 - Core Specification, Chapter 3.9. +the Unicode Standard, Chapter 3.9 \ucode{fffd} Substitution in Conversion. \end{itemdescr} \indexlibraryglobal{vprint_nonunicode}% @@ -7837,6 +7902,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); @@ -7849,7 +7929,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 @@ -7881,6 +7964,7 @@ \indexlibraryglobal{basic_stringstream}% \begin{codeblock} namespace std { + // \ref{stringbuf}, class template \tcode{basic_stringbuf} template, class Allocator = allocator> class basic_stringbuf; @@ -7892,6 +7976,7 @@ using stringbuf = basic_stringbuf; using wstringbuf = basic_stringbuf; + // \ref{istringstream}, class template \tcode{basic_istringstream} template, class Allocator = allocator> class basic_istringstream; @@ -7903,6 +7988,7 @@ using istringstream = basic_istringstream; using wistringstream = basic_istringstream; + // \ref{ostringstream}, class template \tcode{basic_ostringstream} template, class Allocator = allocator> class basic_ostringstream; @@ -7914,6 +8000,7 @@ using ostringstream = basic_ostringstream; using wostringstream = basic_ostringstream; + // \ref{stringstream}, class template \tcode{basic_stringstream} template, class Allocator = allocator> class basic_stringstream; @@ -7975,6 +8062,13 @@ explicit basic_stringbuf( const basic_string& s, ios_base::openmode which = ios_base::in | ios_base::out); + template + explicit basic_stringbuf(const T& t, + ios_base::openmode which = ios_base::in | ios_base::out); + template + basic_stringbuf(const T& t, const Allocator& a); + template + basic_stringbuf(const T& t, ios_base::openmode which, const Allocator& a); basic_stringbuf(const basic_stringbuf&) = delete; basic_stringbuf(basic_stringbuf&& rhs); basic_stringbuf(basic_stringbuf&& rhs, const Allocator& a); @@ -7997,6 +8091,8 @@ template void str(const basic_string& s); void str(basic_string&& s); + template + void str(const T& t); protected: // \ref{stringbuf.virtuals}, overridden virtual functions @@ -8007,15 +8103,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} @@ -8036,17 +8132,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} @@ -8061,7 +8157,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} @@ -8087,14 +8183,14 @@ \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}% \begin{itemdecl} -basic_stringbuf(ios_base::openmode which, const Allocator &a); +basic_stringbuf(ios_base::openmode which, const Allocator& a); \end{itemdecl} \begin{itemdescr} @@ -8102,9 +8198,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 @@ -8122,9 +8218,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}% @@ -8132,16 +8228,16 @@ template basic_stringbuf( const basic_string& s, - ios_base::openmode which, const Allocator &a); + ios_base::openmode which, const Allocator& a); \end{itemdecl} \begin{itemdescr} \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}% @@ -8160,9 +8256,40 @@ \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}% +\begin{itemdecl} +template + explicit basic_stringbuf(const T& t, ios_base::openmode which = ios_base::in | ios_base::out); +template + basic_stringbuf(const T& t, const Allocator& a); +template + basic_stringbuf(const T& t, ios_base::openmode which, const Allocator& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{which} be \tcode{ios_base::in | ios_base::out} +for the overload with no parameter \tcode{which}, and +\tcode{a} be \tcode{Allocator()} for the overload with no parameter \tcode{a}. + +\pnum +\constraints +\tcode{is_convertible_v>} +is \tcode{true}. + +\pnum +\effects +Creates a variable \tcode{sv} as if by +\tcode{basic_string_view sv = t}, +then value-initializes the base class, +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}% @@ -8175,10 +8302,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 @@ -8250,7 +8377,7 @@ \remarks The exception specification is equivalent to:\\ \tcode{allocator_traits::propagate_on_container_swap::value ||}\\ -\tcode{allocator_traits::is_always_equal::value}. +\tcode{allocator_traits::is_always_equal::value} \end{itemdescr} \indexlibrarymember{swap}{basic_stringbuf}% @@ -8263,7 +8390,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{x.swap(y)}. +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} \rSec3[stringbuf.members]{Member functions} @@ -8283,39 +8410,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}@(); // \expos \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} @@ -8329,7 +8456,7 @@ \begin{itemdescr} \pnum \returns -\tcode{buf.get_allocator()}. +\tcode{\exposid{buf}.get_allocator()}. \end{itemdescr} \indexlibrarymember{str}{basic_stringbuf}% @@ -8356,7 +8483,7 @@ \pnum \constraints \tcode{SAlloc} is a type that -qualifies as an allocator\iref{container.requirements.general}. +qualifies as an allocator\iref{container.reqmts}. \pnum \effects @@ -8376,7 +8503,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 @@ -8402,10 +8529,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} @@ -8427,8 +8554,8 @@ \effects Equivalent to: \begin{codeblock} -buf = s; -init_buf_ptrs(); +@\exposid{buf}@ = s; +@\exposid{init-buf-ptrs}@(); \end{codeblock} \end{itemdescr} @@ -8447,8 +8574,8 @@ \effects Equivalent to: \begin{codeblock} -buf = s; -init_buf_ptrs(); +@\exposid{buf}@ = s; +@\exposid{init-buf-ptrs}@(); \end{codeblock} \end{itemdescr} @@ -8462,8 +8589,30 @@ \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} + +\indexlibrarymember{str}{basic_stringbuf}% +\begin{itemdecl} +template + void str(const T& t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_convertible_v>} +is \tcode{true}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +basic_string_view sv = t; +@\exposid{buf}@ = sv; +@\exposid{init-buf-ptrs}@(); \end{codeblock} \end{itemdescr} @@ -8522,7 +8671,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, @@ -8608,14 +8757,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. @@ -8772,6 +8921,12 @@ explicit basic_istringstream( const basic_string& s, ios_base::openmode which = ios_base::in); + template + explicit basic_istringstream(const T& t, ios_base::openmode which = ios_base::in); + template + basic_istringstream(const T& t, const Allocator& a); + template + basic_istringstream(const T& t, ios_base::openmode which, const Allocator& a); basic_istringstream(const basic_istringstream&) = delete; basic_istringstream(basic_istringstream&& rhs); @@ -8793,9 +8948,11 @@ template void str(const basic_string& s); void str(basic_string&& s); + template + void str(const T& t); private: - basic_stringbuf sb; // \expos + basic_stringbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -8811,7 +8968,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} @@ -8825,8 +8982,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} @@ -8841,8 +8998,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} @@ -8855,8 +9012,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} @@ -8871,8 +9028,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} @@ -8888,8 +9045,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} @@ -8902,14 +9059,45 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_same_v} is \tcode{false}. + \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} +\indexlibraryctor{basic_istringstream}% +\begin{itemdecl} +template + explicit basic_istringstream(const T& t, ios_base::openmode which = ios_base::in); +template + basic_istringstream(const T& t, const Allocator& a); +template + basic_istringstream(const T& t, ios_base::openmode which, const Allocator& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{which} be \tcode{ios_base::in} +for the overload with no parameter \tcode{which}, and +\tcode{a} be \tcode{Allocator()} for the overload with no parameter \tcode{a}. + +\pnum +\constraints +\tcode{is_convertible_v>} +is \tcode{true}. + +\pnum +\effects +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}% \begin{itemdecl} basic_istringstream(basic_istringstream&& rhs); @@ -8921,7 +9109,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} @@ -8938,7 +9126,7 @@ Equivalent to: \begin{codeblock} basic_istream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -8953,7 +9141,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{x.swap(y)}. +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} \rSec3[istringstream.members]{Member functions} @@ -8966,7 +9154,7 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. \end{itemdescr} \indexlibrarymember{str}{basic_istringstream}% @@ -9041,12 +9229,30 @@ \begin{itemdecl} void str(basic_string&& s); \end{itemdecl} + \begin{itemdescr} \pnum \effects Equivalent to: \tcode{rdbuf()->str(std::move(s));} \end{itemdescr} +\indexlibrarymember{str}{basic_istringstream}% +\begin{itemdecl} +template + void str(const T& t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_convertible_v>} +is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{rdbuf()->str(t);} +\end{itemdescr} + \rSec2[ostringstream]{Class template \tcode{basic_ostringstream}} \rSec3[ostringstream.general]{General} @@ -9087,6 +9293,12 @@ explicit basic_ostringstream( const basic_string& s, ios_base::openmode which = ios_base::out); + template + explicit basic_ostringstream(const T& t, ios_base::openmode which = ios_base::out); + template + basic_ostringstream(const T& t, const Allocator& a); + template + basic_ostringstream(const T& t, ios_base::openmode which, const Allocator& a); basic_ostringstream(const basic_ostringstream&) = delete; basic_ostringstream(basic_ostringstream&& rhs); @@ -9109,9 +9321,11 @@ template void str(const basic_string& s); void str(basic_string&& s); + template + void str(const T& t); private: - basic_stringbuf sb; // \expos + basic_stringbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -9127,7 +9341,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} @@ -9141,8 +9355,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} @@ -9157,8 +9371,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} @@ -9171,8 +9385,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} @@ -9187,8 +9401,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} @@ -9204,8 +9418,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} @@ -9225,11 +9439,38 @@ \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} +\indexlibraryctor{basic_ostringstream}% +\begin{itemdecl} +template + explicit basic_ostringstream(const T& t, ios_base::openmode which = ios_base::out); +template + basic_ostringstream(const T& t, const Allocator& a); +template + basic_ostringstream(const T& t, ios_base::openmode which, const Allocator& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{which} be \tcode{ios_base::out} +for the overload with no parameter \tcode{which}, and +\tcode{a} be \tcode{Allocator()} for the overload with no parameter \tcode{a}. + +\pnum +\constraints +\tcode{is_convertible_v>} +is \tcode{true}. + +\pnum +\effects +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}% \begin{itemdecl} basic_ostringstream(basic_ostringstream&& rhs); @@ -9241,7 +9482,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} @@ -9258,7 +9499,7 @@ Equivalent to: \begin{codeblock} basic_ostream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -9272,7 +9513,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{x.swap(y)}. +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} \rSec3[ostringstream.members]{Member functions} @@ -9285,7 +9526,7 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. \end{itemdescr} \indexlibrarymember{str}{basic_ostringstream}% @@ -9367,6 +9608,23 @@ Equivalent to: \tcode{rdbuf()->str(std::move(s));} \end{itemdescr} +\indexlibrarymember{str}{basic_ostringstream}% +\begin{itemdecl} +template + void str(const T& t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_convertible_v>} +is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{rdbuf()->str(t);} +\end{itemdescr} + \rSec2[stringstream]{Class template \tcode{basic_stringstream}} \rSec3[stringstream.general]{General} @@ -9407,6 +9665,13 @@ explicit basic_stringstream( const basic_string& s, ios_base::openmode which = ios_base::out | ios_base::in); + template + explicit basic_stringstream(const T& t, + ios_base::openmode which = ios_base::out | ios_base::in); + template + basic_stringstream(const T& t, const Allocator& a); + template + basic_stringstream(const T& t, ios_base::openmode which, const Allocator& a); basic_stringstream(const basic_stringstream&) = delete; basic_stringstream(basic_stringstream&& rhs); @@ -9429,9 +9694,11 @@ template void str(const basic_string& s); void str(basic_string&& s); + template + void str(const T& t); private: - basic_stringbuf sb; // \expos + basic_stringbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -9448,7 +9715,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} @@ -9462,9 +9729,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} @@ -9480,9 +9747,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} @@ -9496,8 +9763,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} @@ -9512,8 +9779,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} @@ -9529,8 +9796,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} @@ -9550,11 +9817,38 @@ \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} +\indexlibraryctor{basic_stringstream}% +\begin{itemdecl} +template + explicit basic_stringstream(const T& t, ios_base::openmode which = ios_base::out | ios_base::in); +template + basic_stringstream(const T& t, const Allocator& a); +template + basic_stringstream(const T& t, ios_base::openmode which, const Allocator& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{which} be \tcode{ios_base::out | ios_base::in} +for the overload with no parameter \tcode{which}, and +\tcode{a} be \tcode{Allocator()} for the overload with no parameter \tcode{a}. + +\pnum +\constraints +\tcode{is_convertible_v>} +is \tcode{true}. + +\pnum +\effects +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}% \begin{itemdecl} basic_stringstream(basic_stringstream&& rhs); @@ -9566,7 +9860,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} @@ -9583,7 +9877,7 @@ Equivalent to: \begin{codeblock} basic_iostream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -9597,7 +9891,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{x.swap(y)}. +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} \rSec3[stringstream.members]{Member functions} @@ -9610,7 +9904,7 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. \end{itemdescr} \indexlibrarymember{str}{basic_stringstream}% @@ -9692,6 +9986,23 @@ Equivalent to: \tcode{rdbuf()->str(std::move(s));} \end{itemdescr} +\indexlibrarymember{str}{basic_stringstream}% +\begin{itemdecl} +template + void str(const T&); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_convertible_v>} +is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{rdbuf()->str(t);} +\end{itemdescr} + \rSec1[span.streams]{Span-based streams} \rSec2[span.streams.overview]{Overview} @@ -9703,7 +10014,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 @@ -9723,6 +10034,7 @@ \indexlibraryglobal{wspanstream}% \begin{codeblock} namespace std { + // \ref{spanbuf}, class template \tcode{basic_spanbuf} template> class basic_spanbuf; @@ -9732,6 +10044,7 @@ using spanbuf = basic_spanbuf; using wspanbuf = basic_spanbuf; + // \ref{ispanstream}, class template \tcode{basic_ispanstream} template> class basic_ispanstream; @@ -9741,6 +10054,7 @@ using ispanstream = basic_ispanstream; using wispanstream = basic_ispanstream; + // \ref{ospanstream}, class template \tcode{basic_ospanstream} template> class basic_ospanstream; @@ -9750,6 +10064,7 @@ using ospanstream = basic_ospanstream; using wospanstream = basic_ospanstream; + // \ref{spanstream}, class template \tcode{basic_spanstream} template> class basic_spanstream; @@ -9803,10 +10118,11 @@ 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; + private: ios_base::openmode @\exposid{mode}@; // \expos std::span @\exposid{buf}@; // \expos -}; + }; } \end{codeblock} @@ -10037,7 +10353,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} @@ -10125,7 +10441,7 @@ template void span(ROS&& s) noexcept; private: - basic_spanbuf sb; // \expos + basic_spanbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -10148,8 +10464,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} @@ -10162,9 +10478,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}% @@ -10182,7 +10498,7 @@ \pnum \effects Let \tcode{sp} be \tcode{std::span(std::forward(s))}. -Equivalent to +Equivalent to: \begin{codeblock} basic_ispanstream(std::span(const_cast(sp.data()), sp.size())) \end{codeblock} @@ -10201,7 +10517,7 @@ Equivalent to: \begin{codeblock} basic_istream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -10229,7 +10545,7 @@ \effects Equivalent to: \begin{codeblock} -return const_cast*>(addressof(sb)); +return const_cast*>(addressof(@\exposid{sb}@)); \end{codeblock} \end{itemdescr} @@ -10271,7 +10587,7 @@ Let \tcode{sp} be \tcode{std::span(std::forward(s))}. Equivalent to: \begin{codeblock} -this->span(std::span(const_cast(sp.data()), sp.size())) +this->span(std::span(const_cast(sp.data()), sp.size())); \end{codeblock} \end{itemdescr} @@ -10309,8 +10625,9 @@ std::span span() const noexcept; void span(std::span s) noexcept; + private: - basic_spanbuf sb; // \expos + basic_spanbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -10327,8 +10644,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} @@ -10341,9 +10658,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} @@ -10359,7 +10676,7 @@ Equivalent to: \begin{codeblock} basic_ostream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -10387,7 +10704,7 @@ \effects Equivalent to: \begin{codeblock} -return const_cast*>(addressof(sb)); +return const_cast*>(addressof(@\exposid{sb}@)); \end{codeblock} \end{itemdescr} @@ -10447,8 +10764,9 @@ std::span span() const noexcept; void span(std::span s) noexcept; + private: - basic_spanbuf sb; // \expos + basic_spanbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -10465,8 +10783,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} @@ -10479,8 +10797,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} @@ -10497,7 +10815,7 @@ Equivalent to: \begin{codeblock} basic_iostream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -10525,7 +10843,7 @@ \effects Equivalent to: \begin{codeblock} -return const_cast*>(addressof(sb)); +return const_cast*>(addressof(@\exposid{sb}@)); \end{codeblock} \end{itemdescr} @@ -10574,6 +10892,7 @@ \indexlibraryglobal{basic_fstream}% \begin{codeblock} namespace std { + // \ref{filebuf}, class template \tcode{basic_filebuf} template> class basic_filebuf; @@ -10583,6 +10902,7 @@ using filebuf = basic_filebuf; using wfilebuf = basic_filebuf; + // \ref{ifstream}, class template \tcode{basic_ifstream} template> class basic_ifstream; @@ -10592,6 +10912,7 @@ using ifstream = basic_ifstream; using wifstream = basic_ifstream; + // \ref{ofstream}, class template \tcode{basic_ofstream} template> class basic_ofstream; @@ -10601,6 +10922,7 @@ using ofstream = basic_ofstream; using wofstream = basic_ofstream; + // \ref{fstream}, class template \tcode{basic_fstream} template> class basic_fstream; @@ -10633,6 +10955,26 @@ These functions enable class \tcode{path} support for systems with a wide native path character type, such as \keyword{wchar_t}. \end{note} +\rSec2[file.native]{Native handles} + +\indexlibraryglobal{native_handle_type}% + +\pnum +Several classes described in \ref{file.streams} +have a member \tcode{native_handle_type}. + +\pnum +The type \tcode{native_handle_type} represents a platform-specific +\defnadj{native}{handle} to a file. +It is trivially copyable and models \libconcept{semiregular}. + +\begin{note} +For operating systems based on POSIX, +\tcode{native_handle_type} is \keyword{int}. +For Windows-based operating systems, +\tcode{native_handle_type} is \tcode{HANDLE}. +\end{note} + \rSec2[filebuf]{Class template \tcode{basic_filebuf}} \rSec3[filebuf.general]{General} @@ -10648,6 +10990,7 @@ using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; + using native_handle_type = @\impdefx{type of \tcode{native_handle_type}}@; // see \ref{file.native} // \ref{filebuf.cons}, constructors/destructor basic_filebuf(); @@ -10665,11 +11008,10 @@ basic_filebuf* open(const char* s, ios_base::openmode mode); basic_filebuf* open(const filesystem::path::value_type* s, ios_base::openmode mode); // wide systems only; see \ref{fstream.syn} - basic_filebuf* open(const string& s, - ios_base::openmode mode); - basic_filebuf* open(const filesystem::path& s, - ios_base::openmode mode); + basic_filebuf* open(const string& s, ios_base::openmode mode); + basic_filebuf* open(const filesystem::path& s, ios_base::openmode mode); basic_filebuf* close(); + native_handle_type native_handle() const noexcept; protected: // \ref{filebuf.virtuals}, overridden virtual functions @@ -10679,16 +11021,15 @@ int_type pbackfail(int_type c = traits::eof()) override; int_type overflow (int_type c = traits::eof()) override; - basic_streambuf* setbuf(char_type* s, - streamsize n) override; + basic_streambuf* setbuf(char_type* s, streamsize n) override; + pos_type seekoff(off_type off, ios_base::seekdir way, - ios_base::openmode which - = ios_base::in | ios_base::out) override; + 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; - int sync() override; - void imbue(const locale& loc) override; + ios_base::openmode which = ios_base::in | ios_base::out) override; + + int sync() override; + void imbue(const locale& loc) override; }; } \end{codeblock} @@ -10729,6 +11070,18 @@ \tcode{fpos}. Otherwise the behavior is undefined. +\pnum +The file associated with a \tcode{basic_filebuf} has +an associated value of type \tcode{native_handle_type}, +called the native handle\iref{file.native} of that file. +This native handle can be obtained by calling +the member function \tcode{native_handle}. + +\pnum +For any opened \tcode{basic_filebuf f}, +the native handle returned by \tcode{f.native_handle()} is +invalidated when \tcode{f.close()} is called, or \tcode{f} is destroyed. + \pnum In order to support file I/O and multibyte/wide character conversion, conversions are performed using members of a facet, referred to as @@ -10851,7 +11204,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{x.swap(y)}. +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} \rSec3[filebuf.members]{Member functions} @@ -10881,7 +11234,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 @@ -11022,6 +11375,21 @@ on success, a null pointer otherwise. \end{itemdescr} +\indexlibrarymember{native_handle}{basic_filebuf}% +\begin{itemdecl} +native_handle_type native_handle() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{is_open()} is \tcode{true}. + +\pnum +\returns +The native handle associated with \tcode{*this}. +\end{itemdescr} + \rSec3[filebuf.virtuals]{Overridden virtual functions} \indexlibrarymember{showmanyc}{basic_filebuf}% @@ -11211,6 +11579,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 @@ -11296,7 +11665,7 @@ ``Write any unshift sequence'' means, if \tcode{width} -if less than zero then call +is less than zero then call \tcode{a_codecvt.unshift(state, xbuf, xbuf+XSIZE, xbuf_end)} and output the resulting unshift sequence. The function determines one of three values for the @@ -11420,6 +11789,7 @@ using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; + using native_handle_type = typename basic_filebuf::native_handle_type; // \ref{ifstream.cons}, constructors basic_ifstream(); @@ -11442,6 +11812,7 @@ // \ref{ifstream.members}, members basic_filebuf* rdbuf() const; + native_handle_type native_handle() const noexcept; bool is_open() const; void open(const char* s, ios_base::openmode mode = ios_base::in); @@ -11450,8 +11821,9 @@ void open(const string& s, ios_base::openmode mode = ios_base::in); void open(const filesystem::path& s, ios_base::openmode mode = ios_base::in); void close(); + private: - basic_filebuf sb; // \expos + basic_filebuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -11467,7 +11839,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} @@ -11481,8 +11853,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} @@ -11498,8 +11870,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)}. @@ -11516,7 +11888,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{basic_ifstream(s.c_str(), mode)}. +Equivalent to \tcode{basic_ifstream(s.c_str(), mode)}. \end{itemdescr} \indexlibraryctor{basic_ifstream}% @@ -11532,7 +11904,7 @@ \pnum \effects -Equivalent to: \tcode{basic_ifstream(s.c_str(), mode)}. +Equivalent to \tcode{basic_ifstream(s.c_str(), mode)}. \end{itemdescr} \indexlibraryctor{basic_ifstream}% @@ -11544,7 +11916,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} @@ -11561,7 +11933,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}% @@ -11573,7 +11945,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{x.swap(y)}. +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} \rSec3[ifstream.members]{Member functions} @@ -11586,7 +11958,18 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. +\end{itemdescr} + +\indexlibrarymember{native_handle}{basic_ifstream}% +\begin{itemdecl} +native_handle_type native_handle() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return rdbuf()->native_handle();} \end{itemdescr} \indexlibrarymember{is_open}{basic_ifstream}% @@ -11665,6 +12048,7 @@ using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; + using native_handle_type = typename basic_filebuf::native_handle_type; // \ref{ofstream.cons}, constructors basic_ofstream(); @@ -11687,6 +12071,7 @@ // \ref{ofstream.members}, members basic_filebuf* rdbuf() const; + native_handle_type native_handle() const noexcept; bool is_open() const; void open(const char* s, ios_base::openmode mode = ios_base::out); @@ -11695,8 +12080,9 @@ void open(const string& s, ios_base::openmode mode = ios_base::out); void open(const filesystem::path& s, ios_base::openmode mode = ios_base::out); void close(); + private: - basic_filebuf sb; // \expos + basic_filebuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -11712,7 +12098,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} @@ -11726,8 +12112,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} @@ -11743,8 +12129,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)}. @@ -11761,7 +12147,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{basic_ofstream(s.c_str(), mode)}. +Equivalent to \tcode{basic_ofstream(s.c_str(), mode)}. \end{itemdescr} \indexlibraryctor{basic_ofstream}% @@ -11777,7 +12163,7 @@ \pnum \effects -Equivalent to: \tcode{basic_ofstream(s.c_str(), mode)}. +Equivalent to \tcode{basic_ofstream(s.c_str(), mode)}. \end{itemdescr} \indexlibraryctor{basic_ofstream}% @@ -11789,7 +12175,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} @@ -11806,7 +12192,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}% @@ -11818,7 +12204,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{x.swap(y)}. +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} \rSec3[ofstream.members]{Member functions} @@ -11831,7 +12217,18 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. +\end{itemdescr} + +\indexlibrarymember{native_handle}{basic_ofstream}% +\begin{itemdecl} +native_handle_type native_handle() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return rdbuf()->native_handle();} \end{itemdescr} \indexlibrarymember{is_open}{basic_ofstream}% @@ -11908,6 +12305,7 @@ using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; + using native_handle_type = typename basic_filebuf::native_handle_type; // \ref{fstream.cons}, constructors basic_fstream(); @@ -11916,7 +12314,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); @@ -11933,13 +12331,15 @@ // \ref{fstream.members}, members basic_filebuf* rdbuf() const; + native_handle_type native_handle() const noexcept; + bool is_open() const; void open( const char* s, 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); @@ -11949,7 +12349,7 @@ void close(); private: - basic_filebuf sb; // \expos + basic_filebuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -11965,7 +12365,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} @@ -11979,9 +12379,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}% @@ -11998,9 +12398,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 @@ -12017,7 +12417,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{basic_fstream(s.c_str(), mode)}. +Equivalent to \tcode{basic_fstream(s.c_str(), mode)}. \end{itemdescr} \indexlibraryctor{basic_fstream}% @@ -12033,7 +12433,7 @@ \pnum \effects -Equivalent to: \tcode{basic_fstream(s.c_str(), mode)}. +Equivalent to \tcode{basic_fstream(s.c_str(), mode)}. \end{itemdescr} \indexlibraryctor{basic_fstream}% @@ -12045,7 +12445,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} @@ -12062,7 +12462,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}% @@ -12075,7 +12475,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{x.swap(y)}. +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} \rSec3[fstream.members]{Member functions} @@ -12088,7 +12488,18 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. +\end{itemdescr} + +\indexlibrarymember{native_handle}{basic_fstream}% +\begin{itemdecl} +native_handle_type native_handle() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return rdbuf()->native_handle();} \end{itemdescr} \indexlibrarymember{is_open}{basic_fstream}% @@ -12171,6 +12582,7 @@ #include // see \ref{ostream.syn} namespace std { + // \ref{syncstream.syncbuf}, class template \tcode{basic_syncbuf} template, class Allocator = allocator> class basic_syncbuf; @@ -12182,6 +12594,7 @@ using syncbuf = basic_syncbuf; using wsyncbuf = basic_syncbuf; + // \ref{syncstream.osyncstream}, class template \tcode{basic_osyncstream} template, class Allocator = allocator> class basic_osyncstream; @@ -12237,8 +12650,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} @@ -12248,7 +12661,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 @@ -12265,7 +12678,7 @@ \begin{itemdescr} \pnum \effects -Sets \tcode{wrapped} to \tcode{obuf}. +Sets \exposid{wrapped} to \tcode{obuf}. \pnum \ensures @@ -12399,10 +12812,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. @@ -12425,15 +12838,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}% @@ -12444,7 +12857,7 @@ \begin{itemdescr} \pnum \returns -\tcode{wrapped}. +\exposid{wrapped}. \end{itemdescr} \indexlibrarymember{get_allocator}{basic_syncbuf}% @@ -12466,7 +12879,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} @@ -12480,9 +12893,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} @@ -12539,15 +12952,15 @@ ~basic_osyncstream(); // assignment - basic_osyncstream& operator=(basic_osyncstream&&) noexcept; + basic_osyncstream& operator=(basic_osyncstream&&); // \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} @@ -12589,8 +13002,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} @@ -12613,8 +13026,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 @@ -12635,7 +13048,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)}. @@ -12680,7 +13093,7 @@ \begin{itemdescr} \pnum \returns -\tcode{sb.get_wrapped()}. +\tcode{\exposid{sb}.get_wrapped()}. \pnum \begin{example} @@ -12768,7 +13181,7 @@ \rSec3[fs.conform.9945]{POSIX conformance} \pnum -Some behavior is specified by reference to POSIX. How such behavior is actually implemented is unspecified. +Some behavior is specified by reference to POSIX\@. How such behavior is actually implemented is unspecified. \begin{note} This constitutes an ``as if'' rule allowing implementations to call native @@ -13066,22 +13479,25 @@ 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; } namespace std::ranges { template<> - inline constexpr bool enable_borrowed_range = true; + inline constexpr bool @\libspec{enable_borrowed_range}{directory_iterator}@ = true; template<> - inline constexpr bool enable_borrowed_range = true; + inline constexpr bool @\libspec{enable_borrowed_range}{recursive_directory_iterator}@ = true; template<> - inline constexpr bool enable_view = true; + inline constexpr bool @\libspec{enable_view}{directory_iterator}@ = true; template<> - inline constexpr bool enable_view = true; + inline constexpr bool @\libspec{enable_view}{recursive_directory_iterator}@ = true; } \end{codeblock} @@ -13202,7 +13618,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} @@ -13324,7 +13741,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; @@ -13546,8 +13963,8 @@ \begin{note} Some operating systems have no unambiguous way to distinguish between native format and generic format arguments. This is by design as it simplifies use for operating systems that do not require -disambiguation. An implementation for an operating system where disambiguation -is required is permitted to distinguish between the formats. +disambiguation. It is possible that an implementation for an operating system +where disambiguation is needed distinguishes between the formats. \end{note} \pnum @@ -13628,8 +14045,8 @@ \begin{note} This results in behavior identical to other C and \Cpp{} standard library functions that perform file operations using ordinary character -strings to identify paths. Changing this behavior would be surprising and error -prone. +strings to identify paths. Changing this behavior would be surprising and +error-prone. \end{note} \item \keyword{wchar_t}: The encoding is the native wide encoding. The method of conversion is unspecified. @@ -13671,14 +14088,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 @@ -13696,7 +14113,7 @@ \tcode{basic_string} or \tcode{basic_string_view}, or \item the \grammarterm{qualified-id} \tcode{iterator_traits>::value_type} is valid and -denotes a possibly \keyword{const} encoded character type\iref{temp.deduct}. +denotes a possibly const encoded character type\iref{temp.deduct}. \end{itemize} \pnum @@ -13722,7 +14139,7 @@ \begin{itemdescr} \pnum \ensures -\tcode{empty() == true}. +\tcode{empty()} is \keyword{true}. \end{itemdescr} \indexlibraryctor{path}% @@ -14078,7 +14495,7 @@ \begin{itemdescr} \pnum \ensures -\tcode{empty() == true}. +\tcode{empty()} is \tcode{true}. \end{itemdescr} \indexlibrarymember{make_preferred}{path}% @@ -14091,7 +14508,7 @@ \effects Each \grammarterm{directory-separator} of the pathname in the generic format - is converted to \grammarterm{preferred-separator}. +is converted to \grammarterm{preferred-separator}. \pnum \returns @@ -14570,7 +14987,7 @@ \indexlibrarymember{empty}{path}% \begin{itemdecl} -[[nodiscard]] bool empty() const noexcept; +bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -14868,8 +15285,8 @@ \item The \grammarterm{root-name} element, if present. \item The \grammarterm{root-directory} element, if present. \begin{note} -The generic format is required to ensure lexicographical -comparison works correctly. +It is possible that the use of the generic format is needed +to ensure correct lexicographical comparison. \end{note} \item Each successive \grammarterm{filename} element, if present. \item An empty element, if a trailing non-root \grammarterm{directory-separator} @@ -15022,6 +15439,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} @@ -15076,10 +15589,10 @@ \pnum \ensures \begin{itemize} -\item \tcode{code() == ec}, -\item \tcode{path1().empty() == true}, -\item \tcode{path2().empty() == true}, and -\item \tcode{string_view(what()).find(what_arg.c_str())} \tcode{!= string_view::npos}. +\item \tcode{code() == ec} is \tcode{true}, +\item \tcode{path1().empty()} is \tcode{true}, +\item \tcode{path2().empty()} is \tcode{true}, and +\item \tcode{string_view(what()).find(what_arg.c_str())} \tcode{!= string_view::npos} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -15092,10 +15605,10 @@ \pnum \ensures \begin{itemize} -\item \tcode{code() == ec}, +\item \tcode{code() == ec} is \tcode{true}, \item \tcode{path1()} returns a reference to the stored copy of \tcode{p1}, -\item \tcode{path2().empty() == true}, and -\item \tcode{string_view(what()).find(what_arg.c_str())} \tcode{!= string_view::npos}. +\item \tcode{path2().empty()} is \tcode{true}, and +\item \tcode{string_view(what()).find(what_arg.c_str())} \tcode{!= string_view::npos} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -15197,10 +15710,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 @@ -15208,13 +15721,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 @@ -15224,7 +15737,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} @@ -15246,42 +15759,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 sub-directories} \\ \rowsep +\ohdrx{2}{Option group controlling \tcode{copy} function effects for subdirectories} \\ \rowsep \lhdr{Constant} & \rhdr{Meaning} \\ \capsep -\tcode{none} & - (Default) Do not copy sub-directories. \\ \rowsep -\tcode{recursive} & - Recursively copy sub-directories and their contents. \\ \capsep +\tcode{\libmember{none}{copy_options}} & + (Default) Do not copy subdirectories. \\ \rowsep +\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} @@ -15300,46 +15813,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} @@ -15361,15 +15874,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} @@ -15392,11 +15905,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} @@ -15571,8 +16084,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} @@ -15591,13 +16103,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 @@ -15666,7 +16175,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. @@ -15684,7 +16193,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. @@ -15735,7 +16244,7 @@ \begin{itemdescr} \pnum \returns -\tcode{pathobject}. +\exposid{path-object}. \end{itemdescr} \indexlibrarymember{exists}{directory_entry}% @@ -15975,7 +16484,7 @@ \begin{itemdescr} \pnum \returns -\tcode{pathobject == rhs.pathobject}. +\tcode{\exposid{path-object} == rhs.\exposid{path-object}}. \end{itemdescr} \indexlibrarymember{operator<=>}{directory_entry}% @@ -15986,7 +16495,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} @@ -16016,7 +16525,7 @@ for each file in a directory or in an \impldef{type of a directory-like file} directory-like file type. \begin{note} -For iteration into sub-directories, see class \tcode{recursive_directory_iterator}\iref{fs.class.rec.dir.itr}. +For iteration into subdirectories, see class \tcode{recursive_directory_iterator}\iref{fs.class.rec.dir.itr}. \end{note} \begin{codeblock} @@ -16096,8 +16605,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 @@ -16254,7 +16761,7 @@ An object of type \tcode{recursive_directory_iterator} provides an iterator for a sequence of \tcode{directory_entry} elements representing the files in a directory or in an \impldef{type of a directory-like file} directory-like file -type, and its sub-directories. +type, and its subdirectories. \begin{codeblock} namespace std::filesystem { @@ -16587,7 +17094,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} @@ -16596,7 +17103,7 @@ \pnum These functions enable use of \tcode{recursive_directory_iterator} -with range-based for statements. +with range-based \keyword{for} statements. \indexlibrarymember{begin}{recursive_directory_iterator}% \begin{itemdecl} @@ -16782,7 +17289,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 @@ -16865,16 +17372,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 @@ -16883,10 +17390,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 @@ -16897,7 +17404,7 @@ file2 dir2 file3 -\end{codeblock} +\end{outputblock} \end{example} \end{itemdescr} @@ -16940,7 +17447,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 @@ -16955,7 +17462,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 @@ -17017,7 +17524,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 @@ -17110,7 +17617,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 @@ -17125,7 +17632,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} @@ -17151,7 +17658,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 @@ -17186,7 +17693,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 @@ -17219,7 +17726,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. @@ -17233,12 +17740,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 @@ -17256,7 +17757,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 @@ -17289,7 +17790,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} @@ -17367,7 +17868,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} @@ -17729,7 +18230,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. @@ -17749,7 +18250,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 @@ -17783,7 +18284,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} @@ -17920,7 +18421,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. @@ -17932,9 +18433,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 @@ -17954,7 +18456,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. @@ -17988,7 +18490,7 @@ \pnum \effects Renames \tcode{old_p} to \tcode{new_p}, as if by - POSIX \tcode{rename()}. + POSIX \tcode{rename}. \begin{note} \begin{itemize} @@ -18024,7 +18526,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 @@ -18079,7 +18581,7 @@ \begin{itemdescr} \pnum \effects -As if: +As if by: \begin{codeblock} error_code ec; file_status result = status(p, ec); @@ -18111,14 +18613,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} @@ -18212,9 +18714,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 @@ -18224,7 +18726,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 @@ -18293,14 +18795,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. @@ -18316,12 +18818,6 @@ \pnum \throws As specified in~\ref{fs.err.report}. - -\pnum -\remarks -Implementations should - avoid unnecessary normalization such as - when \tcode{canonical} has already been called on the entirety of \tcode{p}. \end{itemdescr} \rSec1[c.files]{C library files} @@ -18332,22 +18828,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}% @@ -18400,22 +18880,22 @@ 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{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); @@ -18470,6 +18950,13 @@ 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 @@ -18522,43 +19009,21 @@ \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}% \begin{codeblock} #include // see \ref{cstdint.syn} namespace std { using imaxdiv_t = @\seebelow@; - intmax_t imaxabs(intmax_t j); - imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom); + constexpr intmax_t imaxabs(intmax_t j); + constexpr imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom); intmax_t strtoimax(const char* nptr, char** endptr, int base); uintmax_t strtoumax(const char* nptr, char** endptr, int base); intmax_t wcstoimax(const wchar_t* nptr, wchar_t** endptr, int base); uintmax_t wcstoumax(const wchar_t* nptr, wchar_t** endptr, int base); - intmax_t abs(intmax_t); // optional, see below - imaxdiv_t div(intmax_t, intmax_t); // optional, see below + constexpr intmax_t abs(intmax_t); // optional, see below + constexpr imaxdiv_t div(intmax_t, intmax_t); // optional, see below } #define PRId@\placeholdernc{N}@ @\seebelow@ @@ -18594,28 +19059,28 @@ #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 @\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{SCNdMAX}@ @\seebelow@ +#define @\libmacro{SCNiMAX}@ @\seebelow@ +#define @\libmacro{SCNoMAX}@ @\seebelow@ +#define @\libmacro{SCNuMAX}@ @\seebelow@ +#define @\libmacro{SCNxMAX}@ @\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{SCNdPTR}@ @\seebelow@ +#define @\libmacro{SCNiPTR}@ @\seebelow@ +#define @\libmacro{SCNoPTR}@ @\seebelow@ +#define @\libmacro{SCNuPTR}@ @\seebelow@ +#define @\libmacro{SCNxPTR}@ @\seebelow@ \end{codeblock} \pnum @@ -18627,15 +19092,19 @@ 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} -intmax_t abs(intmax_t); -imaxdiv_t div(intmax_t, intmax_t); +constexpr intmax_t abs(intmax_t); +constexpr imaxdiv_t div(intmax_t, intmax_t); \end{codeblock} which shall have the same semantics as the function signatures -\tcode{intmax_t imaxabs(intmax_t)} and -\tcode{imaxdiv_t imaxdiv(intmax_t, intmax_t)}, respectively. +\tcode{constexpr intmax_t imaxabs(intmax_t)} and +\tcode{constexpr imaxdiv_t imaxdiv(intmax_t, intmax_t)}, respectively. \end{itemize} \xrefc{7.8} diff --git a/source/iterators.tex b/source/iterators.tex index cf6b9b8374..d148a6489a 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -59,7 +59,7 @@ template requires is_object_v struct iterator_traits; // freestanding template<@\exposconcept{dereferenceable}@ T> - using iter_reference_t = decltype(*declval()); // freestanding + using @\libglobal{iter_reference_t}@ = decltype(*declval()); // freestanding namespace ranges { // \ref{iterator.cust}, customization point objects @@ -76,7 +76,7 @@ requires requires(T& t) { { ranges::iter_move(t) } -> @\exposconcept{can-reference}@; } - using iter_rvalue_reference_t // freestanding + using @\libglobal{iter_rvalue_reference_t}@ // freestanding = decltype(ranges::iter_move(declval())); // \ref{iterator.concepts}, iterator concepts @@ -84,9 +84,13 @@ template concept indirectly_readable = @\seebelow@; // freestanding + // \ref{indirectcallable.traits}, indirect callable traits template<@\libconcept{indirectly_readable}@ T> - using iter_common_reference_t = // freestanding - common_reference_t, iter_value_t&>; + using @\exposidnc{indirect-value-t}@ = @\seebelow@; // \expos + + template<@\libconcept{indirectly_readable}@ T> + using @\libglobal{iter_common_reference_t}@ = // freestanding + common_reference_t, @\exposid{indirect-value-t}@>; // \ref{iterator.concept.writable}, concept \libconcept{indirectly_writable} template @@ -110,7 +114,7 @@ // \ref{iterator.concept.sizedsentinel}, concept \libconcept{sized_sentinel_for} template - inline constexpr bool disable_sized_sentinel_for = false; // freestanding + constexpr bool disable_sized_sentinel_for = false; // freestanding template concept sized_sentinel_for = @\seebelow@; // freestanding @@ -161,14 +165,15 @@ template requires (@\libconcept{indirectly_readable}@ && ...) && @\libconcept{invocable}@...> - using indirect_result_t = invoke_result_t...>; // freestanding + using @\libglobal{indirect_result_t}@ = invoke_result_t...>; // freestanding // \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} @@ -199,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} @@ -243,11 +248,11 @@ S bound); // \ref{range.iter.op.distance}, \tcode{ranges::distance} - template<@\libconcept{input_or_output_iterator}@ I, @\libconcept{sentinel_for}@ S> + template S> requires (!@\libconcept{sized_sentinel_for}@) constexpr iter_difference_t distance(I first, S last); // freestanding - template<@\libconcept{input_or_output_iterator}@ I, @\libconcept{sized_sentinel_for}@ S> - constexpr iter_difference_t distance(const I& first, const S& last); // freestanding + template> S> + constexpr iter_difference_t> distance(I&& first, S last); // freestanding template<@\libconcept{range}@ R> constexpr range_difference_t distance(R&& r); // freestanding @@ -316,9 +321,9 @@ constexpr reverse_iterator make_reverse_iterator(Iterator i); // freestanding template - requires (!@\libconcept{sized_sentinel_for}@) - inline constexpr bool disable_sized_sentinel_for, // freestanding - reverse_iterator> = true; + requires (!@\libconcept{sized_sentinel_for}@) + constexpr bool @\libspec{disable_sized_sentinel_for}{reverse_iterator}@, // freestanding + reverse_iterator> = true; // \ref{insert.iterators}, insert iterators template class back_insert_iterator; // freestanding @@ -342,31 +347,34 @@ concept @\exposconcept{constant-iterator}@ = @\seebelow@; // \expos template<@\libconcept{input_iterator}@ I> using const_iterator = @\seebelow@; // freestanding - template + template<@\libconcept{semiregular}@ S> using const_sentinel = @\seebelow@; // freestanding // \ref{const.iterators.iterator}, class template \tcode{basic_const_iterator} - template + template<@\libconcept{input_iterator}@ Iterator> class basic_const_iterator; // freestanding template U> + requires @\libconcept{input_iterator}@> struct common_type, U> { // freestanding using type = basic_const_iterator>; }; template U> + requires @\libconcept{input_iterator}@> struct common_type> { // freestanding using type = basic_const_iterator>; }; template U> + requires @\libconcept{input_iterator}@> struct common_type, basic_const_iterator> { // freestanding using type = basic_const_iterator>; }; template<@\libconcept{input_iterator}@ I> - constexpr const_iterator make_const_iterator(I it) { return it; } // freestanding + constexpr const_iterator @\libglobal{make_const_iterator}@(I it) { return it; } // freestanding - template - constexpr const_sentinel make_const_sentinel(S s) { return s; } // freestanding + template<@\libconcept{semiregular}@ S> + constexpr const_sentinel @\libglobal{make_const_sentinel}@(S s) { return s; } // freestanding // \ref{move.iterators}, move iterators and sentinels template class move_iterator; // freestanding @@ -402,6 +410,11 @@ template constexpr move_iterator make_move_iterator(Iterator i); // freestanding + template + requires (!@\libconcept{sized_sentinel_for}@) + constexpr bool @\libspec{disable_sized_sentinel_for}{move_iterator}@, // freestanding + move_iterator> = true; + template<@\libconcept{semiregular}@ S> class move_sentinel; // freestanding // \ref{iterators.common}, common iterators @@ -439,7 +452,7 @@ const istream_iterator& y); template> - class ostream_iterator; + class ostream_iterator; template> class istreambuf_iterator; @@ -487,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 @@ -503,7 +516,7 @@ \rSec1[iterator.requirements]{Iterator requirements} -\rSec2[iterator.requirements.general]{In general} +\rSec2[iterator.requirements.general]{General} \pnum \indextext{requirements!iterator}% @@ -522,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 @@ -676,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). @@ -683,8 +714,9 @@ do not specify complexity. \pnum -Destruction of a non-forward iterator may invalidate pointers and references -previously obtained from that iterator. +Destruction of an iterator may invalidate pointers and references previously +obtained from that iterator if its type does not meet the +\oldconcept{ForwardIterator} requirements and does not model \libconcept{forward_iterator}. \pnum An \defnadj{invalid}{iterator} @@ -697,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} @@ -941,7 +973,7 @@ template concept @\defexposconcept{cpp17-forward-iterator}@ = @\exposconcept{cpp17-input-iterator}@ && @\libconcept{constructible_from}@ && - is_lvalue_reference_v> && + is_reference_v> && @\libconcept{same_as}@>, typename indirectly_readable_traits::value_type> && requires(I i) { @@ -1128,12 +1160,8 @@ \item \tcode{iter_move(E)}, if \tcode{E} has class or enumeration type and \tcode{iter_move(E)} is a well-formed expression when treated as an unevaluated operand, -with overload resolution performed in a context -that does not include a declaration of \tcode{ranges::iter_move} -but does include the declaration -\begin{codeblock} -void iter_move(); -\end{codeblock} +where the meaning of \tcode{iter_move} is established as-if by performing +argument-dependent lookup only\iref{basic.lookup.argdep}. \item Otherwise, if the expression \tcode{*E} is well-formed: \begin{itemize} @@ -1163,7 +1191,7 @@ arguments. \pnum -Let \exposid{iter-exchange-move} be the exposition-only function: +Let \exposid{iter-exchange-move} be the exposition-only function template: \begin{itemdecl} template constexpr iter_value_t @\exposid{iter-exchange-move}@(X&& x, Y&& y) @@ -1198,6 +1226,11 @@ If the function selected by overload resolution does not exchange the values denoted by \tcode{E1} and \tcode{E2}, the program is ill-formed, no diagnostic required. +\begin{note} +This precludes calling unconstrained \tcode{std::iter_swap}. When the deleted +overload is viable, program-defined overloads need to be more +specialized\iref{temp.func.order} to be selected. +\end{note} \item Otherwise, if the types of \tcode{E1} and \tcode{E2} each model \libconcept{indirectly_readable}, and if the reference types of \tcode{E1} and \tcode{E2} @@ -1275,7 +1308,7 @@ \begin{codeblock} template - concept @\defexposconcept{indirectly-readable-impl}@ = + concept @\defexposconcept{indirectly-readable-impl}@ = @\itcorr[-1]@ // \expos requires(const In in) { typename iter_value_t; typename iter_reference_t; @@ -1308,19 +1341,19 @@ template concept @\deflibconcept{indirectly_writable}@ = requires(Out&& o, T&& t) { - *o = std::forward(t); // not required to be equality-preserving - *std::forward(o) = std::forward(t); // not required to be equality-preserving + *o = std::forward(t); // not required to be equality-preserving + *std::forward(o) = std::forward(t); // not required to be equality-preserving const_cast&&>(*o) = - std::forward(t); // not required to be equality-preserving + std::forward(t); // not required to be equality-preserving const_cast&&>(*std::forward(o)) = - std::forward(t); // not required to be equality-preserving + std::forward(t); // not required to be equality-preserving }; \end{codeblock} \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>}, @@ -1360,10 +1393,10 @@ \begin{codeblock} template - inline constexpr bool @\exposid{is-integer-like}@ = @\seebelow@; @\itcorr[-2]@ // \expos + constexpr bool @\exposid{is-integer-like}@ = @\seebelow@; @\itcorr[-2]@ // \expos template - inline constexpr bool @\exposid{is-signed-integer-like}@ = @\seebelow@; @\itcorr[-2]@ // \expos + constexpr bool @\exposid{is-signed-integer-like}@ = @\seebelow@; @\itcorr[-2]@ // \expos template concept @\deflibconcept{weakly_incrementable}@ = @@ -1371,14 +1404,14 @@ requires(I i) { typename iter_difference_t; requires @\exposid{is-signed-integer-like}@>; - { ++i } -> @\libconcept{same_as}@; // not required to be equality-preserving - i++; // not required to be equality-preserving + { ++i } -> @\libconcept{same_as}@; // not required to be equality-preserving + i++; // not required to be equality-preserving }; \end{codeblock} \pnum A type \tcode{I} is an \defnadj{integer-class}{type} -if it is in a set of \impldef{integer-class type} types +if it is in a set of \impldef{set of integer-class types} types that behave as integer types do, as defined below. \begin{note} An integer-class type is not necessarily a class type. @@ -1526,7 +1559,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} @@ -1538,7 +1571,7 @@ \pnum \recommended -The implementaton of an algorithm on a weakly incrementable type +The implementation of an algorithm on a weakly incrementable type should never attempt to pass through the same incrementable value twice; such an algorithm should be a single-pass algorithm. \begin{note} @@ -1573,7 +1606,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)}. @@ -1636,7 +1669,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. @@ -1681,7 +1714,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$. @@ -1694,7 +1727,7 @@ \indexlibraryglobal{disable_sized_sentinel_for}% \begin{itemdecl} template - inline constexpr bool disable_sized_sentinel_for = false; + constexpr bool disable_sized_sentinel_for = false; \end{itemdecl} \begin{itemdescr} @@ -1811,7 +1844,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 @@ -1900,7 +1933,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)}. @@ -1950,6 +1983,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, @@ -2003,11 +2037,10 @@ 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}, and -\oldconcept{Destructible} requirements\iref{utility.arg.requirements} and lvalues -of type \tcode{X} are swappable\iref{swappable.requirements}, and +\item \tcode{X} meets the \oldconcept{CopyConstructible}, \oldconcept{CopyAssignable}, \oldconcept{Swappable}, and +\oldconcept{Destructible} requirements\iref{utility.arg.requirements,swappable.requirements}, and \item \tcode{iterator_traits::difference_type} is a signed integer type or \keyword{void}, and @@ -2089,7 +2122,7 @@ & & \chdr{semantics} & \rhdr{pre-/post-condition} \\ \capsep \endhead \tcode{a != b} & - contextually convertible to \tcode{bool} & + \tcode{decltype(a != b)} models \exposconceptx{boolean-test\-able}{boolean-testable} & \tcode{!(a == b)} & \expects \orange{a}{b} is in the domain of \tcode{==}. \\ \rowsep @@ -2202,7 +2235,7 @@ \pnum A class or pointer type \tcode{X} -meets the requirements of a forward iterator if +meets the \oldconcept{ForwardIterator} requirements if \begin{itemize} \item \tcode{X} meets the \oldconcept{InputIterator} requirements\iref{input.iterators}, @@ -2229,7 +2262,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 @@ -2377,25 +2410,21 @@ \tcode{*(a + n)} & \\ \rowsep \tcode{a < b} & - contextually - convertible to \tcode{bool} & + \tcode{decltype(a < b)} models \exposconceptx{boolean-test\-able}{boolean-testable} & \effects Equivalent to: \tcode{return b - a > 0;} & \tcode{<} is a total ordering relation \\ \rowsep \tcode{a > b} & - contextually - convertible to \tcode{bool} & + \tcode{decltype(a > b)} models \exposconceptx{boolean-test\-able}{boolean-testable} & \tcode{b < a} & \tcode{>} is a total ordering relation opposite to \tcode{<}. \\ \rowsep \tcode{a >= b} & - contextually - convertible to \tcode{bool} & + \tcode{decltype(a >= b)} models \exposconceptx{boolean-test\-able}{boolean-testable} & \tcode{!(a < b)} & \\ \rowsep \tcode{a <= b} & - contextually - convertible to \tcode{bool}. & + \tcode{decltype(a <= b)} models \exposconceptx{boolean-test\-able}{boolean-testable} & \tcode{!(a > b)} & \\ \end{libreqtab4b} @@ -2407,6 +2436,21 @@ There are several concepts that group requirements of algorithms that take callable objects\iref{func.def} as arguments. +\rSec3[indirectcallable.traits]{Indirect callable traits} + +\pnum +To implement algorithms taking projections, +it is necessary to determine the projected type of an iterator's value type. +For the exposition-only alias template \exposid{indirect-value-t}, +\tcode{\exposid{indirect-value-t}} denotes +\begin{itemize} +\item +\tcode{invoke_result_t>} +if \tcode{T} names \tcode{projected}, and +\item +\tcode{iter_value_t\&} otherwise. +\end{itemize} + \rSec3[indirectcallable.indirectinvocable]{Indirect callables} \pnum @@ -2419,61 +2463,55 @@ concept @\deflibconcept{indirectly_unary_invocable}@ = @\libconcept{indirectly_readable}@ && @\libconcept{copy_constructible}@ && - @\libconcept{invocable}@&> && + @\libconcept{invocable}@> && @\libconcept{invocable}@> && - @\libconcept{invocable}@> && @\libconcept{common_reference_with}@< - invoke_result_t&>, + invoke_result_t>, invoke_result_t>>; template concept @\deflibconcept{indirectly_regular_unary_invocable}@ = @\libconcept{indirectly_readable}@ && @\libconcept{copy_constructible}@ && - @\libconcept{regular_invocable}@&> && + @\libconcept{regular_invocable}@> && @\libconcept{regular_invocable}@> && - @\libconcept{regular_invocable}@> && @\libconcept{common_reference_with}@< - invoke_result_t&>, + invoke_result_t>, invoke_result_t>>; template concept @\deflibconcept{indirect_unary_predicate}@ = @\libconcept{indirectly_readable}@ && @\libconcept{copy_constructible}@ && - @\libconcept{predicate}@&> && - @\libconcept{predicate}@> && - @\libconcept{predicate}@>; + @\libconcept{predicate}@> && + @\libconcept{predicate}@>; template concept @\deflibconcept{indirect_binary_predicate}@ = @\libconcept{indirectly_readable}@ && @\libconcept{indirectly_readable}@ && @\libconcept{copy_constructible}@ && - @\libconcept{predicate}@&, iter_value_t&> && - @\libconcept{predicate}@&, iter_reference_t> && - @\libconcept{predicate}@, iter_value_t&> && - @\libconcept{predicate}@, iter_reference_t> && - @\libconcept{predicate}@, iter_common_reference_t>; + @\libconcept{predicate}@, @\exposidnc{indirect-value-t}@> && + @\libconcept{predicate}@, iter_reference_t> && + @\libconcept{predicate}@, @\exposidnc{indirect-value-t}@> && + @\libconcept{predicate}@, iter_reference_t>; template concept @\deflibconcept{indirect_equivalence_relation}@ = @\libconcept{indirectly_readable}@ && @\libconcept{indirectly_readable}@ && @\libconcept{copy_constructible}@ && - @\libconcept{equivalence_relation}@&, iter_value_t&> && - @\libconcept{equivalence_relation}@&, iter_reference_t> && - @\libconcept{equivalence_relation}@, iter_value_t&> && - @\libconcept{equivalence_relation}@, iter_reference_t> && - @\libconcept{equivalence_relation}@, iter_common_reference_t>; + @\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>; template concept @\deflibconcept{indirect_strict_weak_order}@ = @\libconcept{indirectly_readable}@ && @\libconcept{indirectly_readable}@ && @\libconcept{copy_constructible}@ && - @\libconcept{strict_weak_order}@&, iter_value_t&> && - @\libconcept{strict_weak_order}@&, iter_reference_t> && - @\libconcept{strict_weak_order}@, iter_value_t&> && - @\libconcept{strict_weak_order}@, iter_reference_t> && - @\libconcept{strict_weak_order}@, iter_common_reference_t>; + @\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>; } \end{codeblock} @@ -2482,7 +2520,7 @@ \pnum Class template \tcode{projected} is used to constrain algorithms that accept callable objects and projections\iref{defns.projection}. -It combines a \libconcept{indirectly_readable} type \tcode{I} and +It combines an \libconcept{indirectly_readable} type \tcode{I} and a callable object type \tcode{Proj} into a new \libconcept{indirectly_readable} type whose \tcode{reference} type is the result of applying \tcode{Proj} to the \tcode{iter_reference_t} of \tcode{I}. @@ -2490,16 +2528,18 @@ \indexlibraryglobal{projected}% \begin{codeblock} namespace std { - template<@\libconcept{indirectly_readable}@ I, @\libconcept{indirectly_regular_unary_invocable}@ Proj> - struct projected { - using value_type = remove_cvref_t>; - indirect_result_t operator*() const; // \notdef + template + struct @\exposidnc{projected-impl}@ { // \expos + struct @\exposidnc{type}@ { // \expos + using value_type = remove_cvref_t>; + using difference_type = iter_difference_t; // present only if \tcode{I} + // models \libconcept{weakly_incrementable} + indirect_result_t operator*() const; // \notdef + }; }; - template<@\libconcept{weakly_incrementable}@ I, class Proj> - struct incrementable_traits> { - using difference_type = iter_difference_t; - }; + template<@\libconcept{indirectly_readable}@ I, @\libconcept{indirectly_regular_unary_invocable}@ Proj> + using projected = @\exposid{projected-impl}@::@\exposid{type}@; } \end{codeblock} @@ -2535,7 +2575,7 @@ \pnum The \libconcept{indirectly_movable} concept specifies the relationship between -a \libconcept{indirectly_readable} type and a \libconcept{indirectly_writable} type +an \libconcept{indirectly_readable} type and an \libconcept{indirectly_writable} type between which values may be moved. \begin{codeblock} @@ -2577,7 +2617,7 @@ \pnum The \libconcept{indirectly_copyable} concept specifies the relationship between -a \libconcept{indirectly_readable} type and a \libconcept{indirectly_writable} type +an \libconcept{indirectly_readable} type and an \libconcept{indirectly_writable} type between which values may be copied. \begin{codeblock} @@ -2907,32 +2947,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}} @@ -3027,7 +3043,7 @@ \rSec3[range.iter.op.distance]{\tcode{ranges::distance}} \indexlibraryglobal{distance}% \begin{itemdecl} -template<@\libconcept{input_or_output_iterator}@ I, @\libconcept{sentinel_for}@ S> +template S> requires (!@\libconcept{sized_sentinel_for}@) constexpr iter_difference_t ranges::distance(I first, S last); \end{itemdecl} @@ -3045,14 +3061,14 @@ \indexlibraryglobal{distance}% \begin{itemdecl} -template<@\libconcept{input_or_output_iterator}@ I, @\libconcept{sized_sentinel_for}@ S> - constexpr iter_difference_t ranges::distance(const I& first, const S& last); +template> S> + constexpr iter_difference_t> ranges::distance(I&& first, S last); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return last - first;} +Equivalent to: \tcode{return last - static_cast\&>(first);} \end{itemdescr} \indexlibraryglobal{distance}% @@ -3293,9 +3309,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}% @@ -3357,7 +3370,7 @@ \indexlibrarymember{base}{reverse_iterator}% \begin{itemdecl} -constexpr Iterator base() const; // explicit +constexpr Iterator base() const; \end{itemdecl} \begin{itemdescr} @@ -3411,7 +3424,7 @@ \begin{itemdescr} \pnum \returns -\tcode{current[-n-1]}. +\tcode{current[-n - 1]}. \end{itemdescr} \rSec3[reverse.iter.nav]{Navigation} @@ -3424,7 +3437,7 @@ \begin{itemdescr} \pnum \returns -\tcode{reverse_iterator(current-n)}. +\tcode{reverse_iterator(current - n)}. \end{itemdescr} \indexlibrarymember{operator-}{reverse_iterator}% @@ -3435,7 +3448,7 @@ \begin{itemdescr} \pnum \returns -\tcode{reverse_iterator(current+n)}. +\tcode{reverse_iterator(current + n)}. \end{itemdescr} \indexlibrarymember{operator++}{reverse_iterator}% @@ -3812,6 +3825,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 { @@ -3923,6 +3938,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 { @@ -4034,6 +4051,8 @@ \rSec3[insert.iterator]{Class template \tcode{insert_iterator}} +\rSec4[insert.iter.general]{General} + \indexlibraryglobal{insert_iterator}% \begin{codeblock} namespace std { @@ -4175,7 +4194,7 @@ \begin{itemdecl} template<@\libconcept{indirectly_readable}@ It> - using iter_const_reference_t = + using @\libglobal{iter_const_reference_t}@ = common_reference_t&&, iter_reference_t>; template @@ -4194,7 +4213,7 @@ \end{itemdescr} \begin{itemdecl} -template +template<@\libconcept{semiregular}@ S> using @\libglobal{const_sentinel}@ = @\seebelow@; \end{itemdecl} @@ -4210,12 +4229,18 @@ \begin{codeblock} namespace std { template - concept @\exposconcept{not-a-const-iterator}@ = @\seebelow@; + concept @\exposconcept{not-a-const-iterator}@ = @\seebelow@; // \expos + + template<@\libconcept{indirectly_readable}@ I> + using @\exposidnc{iter-const-rvalue-reference-t}@ = // \expos + common_reference_t&&, iter_rvalue_reference_t>; template<@\libconcept{input_iterator}@ Iterator> class @\libglobal{basic_const_iterator}@ { Iterator @\exposidnc{current_}@ = Iterator(); // \expos using @\exposidnc{reference}@ = iter_const_reference_t; // \expos + using @\exposidnc{rvalue-reference}@ = // \expos + @\exposid{iter-const-rvalue-reference-t}@; public: using iterator_concept = @\seebelow@; @@ -4228,16 +4253,16 @@ 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; constexpr Iterator base() &&; constexpr @\exposid{reference}@ operator*() const; - constexpr const value_type* operator->() const - requires is_lvalue_reference_v> && - @\libconcept{same_as}@>, value_type>; + constexpr const auto* operator->() const + requires is_lvalue_reference_v> && + @\libconcept{same_as}@>, value_type>; constexpr basic_const_iterator& operator++(); constexpr void operator++(int); @@ -4255,34 +4280,42 @@ requires @\libconcept{random_access_iterator}@; template<@\libconcept{sentinel_for}@ S> - friend constexpr bool operator==(const basic_const_iterator& x, const S& s); + constexpr bool operator==(const S& s) const; + + template<@\exposconcept{not-a-const-iterator}@ CI> + requires @\exposconcept{constant-iterator}@ && @\libconcept{convertible_to}@ + constexpr operator CI() const &; + template<@\exposconcept{not-a-const-iterator}@ CI> + requires @\exposconcept{constant-iterator}@ && @\libconcept{convertible_to}@ + constexpr operator CI() &&; - friend constexpr bool operator<(const basic_const_iterator& x, const basic_const_iterator& y) + constexpr bool operator<(const basic_const_iterator& y) const requires @\libconcept{random_access_iterator}@; - friend constexpr bool operator>(const basic_const_iterator& x, const basic_const_iterator& y) + constexpr bool operator>(const basic_const_iterator& y) const requires @\libconcept{random_access_iterator}@; - friend constexpr bool operator<=(const basic_const_iterator& x, - const basic_const_iterator& y) + constexpr bool operator<=(const basic_const_iterator& y) const requires @\libconcept{random_access_iterator}@; - friend constexpr bool operator>=(const basic_const_iterator& x, - const basic_const_iterator& y) + constexpr bool operator>=(const basic_const_iterator& y) const requires @\libconcept{random_access_iterator}@; - friend constexpr auto operator<=>(const basic_const_iterator& x, - const basic_const_iterator& y) + constexpr auto operator<=>(const basic_const_iterator& y) const requires @\libconcept{random_access_iterator}@ && @\libconcept{three_way_comparable}@; template<@\exposconcept{different-from}@ I> - friend constexpr bool operator<(const basic_const_iterator& x, const I& y) + constexpr bool operator<(const I& y) const requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@; template<@\exposconcept{different-from}@ I> - friend constexpr bool operator>(const basic_const_iterator& x, const I& y) + constexpr bool operator>(const I& y) const requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@; template<@\exposconcept{different-from}@ I> - friend constexpr bool operator<=(const basic_const_iterator& x, const I& y) + constexpr bool operator<=(const I& y) const requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@; template<@\exposconcept{different-from}@ I> - friend constexpr bool operator>=(const basic_const_iterator& x, const I& y) + constexpr bool operator>=(const I& y) const requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@; + template<@\exposconcept{different-from}@ I> + constexpr auto operator<=>(const I& y) const + requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@ && + @\libconcept{three_way_comparable_with}@; template<@\exposconcept{not-a-const-iterator}@ I> friend constexpr bool operator<(const I& x, const basic_const_iterator& y) requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@; @@ -4295,10 +4328,6 @@ template<@\exposconcept{not-a-const-iterator}@ I> friend constexpr bool operator>=(const I& x, const basic_const_iterator& y) requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@; - template<@\exposconcept{different-from}@ I> - friend constexpr auto operator<=>(const basic_const_iterator& x, const I& y) - requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@ && - @\libconcept{three_way_comparable_with}@; friend constexpr basic_const_iterator operator+(const basic_const_iterator& i, difference_type n) @@ -4310,10 +4339,15 @@ difference_type n) requires @\libconcept{random_access_iterator}@; template<@\libconcept{sized_sentinel_for}@ S> - friend constexpr difference_type operator-(const basic_const_iterator& x, const S& y); - template<@\libconcept{sized_sentinel_for}@ S> - requires @\exposconcept{different-from}@ + constexpr difference_type operator-(const S& y) const; + template<@\exposconcept{not-a-const-iterator}@ S> + requires @\libconcept{sized_sentinel_for}@ friend constexpr difference_type operator-(const S& x, const basic_const_iterator& y); + friend constexpr @\exposid{rvalue-reference}@ iter_move(const basic_const_iterator& i) + noexcept(noexcept(static_cast<@\exposid{rvalue-reference}@>(ranges::iter_move(i.@\exposid{current_}@)))) + { + return static_cast<@\exposid{rvalue-reference}@>(ranges::iter_move(i.@\exposid{current_}@)); + } }; } \end{codeblock} @@ -4426,7 +4460,7 @@ \indexlibrarymember{operator->}{basic_const_iterator}% \begin{itemdecl} -constexpr const value_type* operator->() const +constexpr const auto* operator->() const requires is_lvalue_reference_v> && @\libconcept{same_as}@>, value_type>; \end{itemdecl} @@ -4548,13 +4582,37 @@ \indexlibrarymember{operator==}{basic_const_iterator}% \begin{itemdecl} template<@\libconcept{sentinel_for}@ S> - friend constexpr bool operator==(const basic_const_iterator& x, const S& s); + constexpr bool operator==(const S& s) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} == s;} +Equivalent to: \tcode{return \exposid{current_} == s;} +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{not-a-const-iterator}@ CI> + requires @\exposconcept{constant-iterator}@ && @\libconcept{convertible_to}@ +constexpr operator CI() const &; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{current_}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{not-a-const-iterator}@ CI> + requires @\exposconcept{constant-iterator}@ && @\libconcept{convertible_to}@ +constexpr operator CI() &&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{std::move(\exposid{current_})}. \end{itemdescr} \indexlibrarymember{operator<}{basic_const_iterator}% @@ -4563,15 +4621,15 @@ \indexlibrarymember{operator>=}{basic_const_iterator}% \indexlibrarymember{operator<=>}{basic_const_iterator}% \begin{itemdecl} -friend constexpr bool operator<(const basic_const_iterator& x, const basic_const_iterator& y) +constexpr bool operator<(const basic_const_iterator& y) const requires @\libconcept{random_access_iterator}@; -friend constexpr bool operator>(const basic_const_iterator& x, const basic_const_iterator& y) +constexpr bool operator>(const basic_const_iterator& y) const requires @\libconcept{random_access_iterator}@; -friend constexpr bool operator<=(const basic_const_iterator& x, const basic_const_iterator& y) +constexpr bool operator<=(const basic_const_iterator& y) const requires @\libconcept{random_access_iterator}@; -friend constexpr bool operator>=(const basic_const_iterator& x, const basic_const_iterator& y) +constexpr bool operator>=(const basic_const_iterator& y) const requires @\libconcept{random_access_iterator}@; -friend constexpr auto operator<=>(const basic_const_iterator& x, const basic_const_iterator& y) +constexpr auto operator<=>(const basic_const_iterator& y) const requires @\libconcept{random_access_iterator}@ && @\libconcept{three_way_comparable}@; \end{itemdecl} @@ -4582,7 +4640,7 @@ \pnum \effects Equivalent to: -\tcode{return x.\exposid{current_} \placeholder{op} \exposid{y.current_};} +\tcode{return \exposid{current_} \placeholder{op} \exposid{y.current_};} \end{itemdescr} \indexlibrarymember{operator<}{basic_const_iterator}% @@ -4592,19 +4650,19 @@ \indexlibrarymember{operator<=>}{basic_const_iterator}% \begin{itemdecl} template<@\exposconcept{different-from}@ I> - friend constexpr bool operator<(const basic_const_iterator& x, const I& y) + constexpr bool operator<(const I& y) const requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@; template<@\exposconcept{different-from}@ I> - friend constexpr bool operator>(const basic_const_iterator& x, const I& y) + constexpr bool operator>(const I& y) const requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@; template<@\exposconcept{different-from}@ I> - friend constexpr bool operator<=(const basic_const_iterator& x, const I& y) + constexpr bool operator<=(const I& y) const requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@; template<@\exposconcept{different-from}@ I> - friend constexpr bool operator>=(const basic_const_iterator& x, const I& y) + constexpr bool operator>=(const I& y) const requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@; template<@\exposconcept{different-from}@ I> - friend constexpr auto operator<=>(const basic_const_iterator& x, const I& y) + constexpr auto operator<=>(const I& y) const requires @\libconcept{random_access_iterator}@ && @\libconcept{totally_ordered_with}@ && @\libconcept{three_way_comparable_with}@; \end{itemdecl} @@ -4614,8 +4672,8 @@ Let \tcode{\placeholder{op}} be the operator. \pnum -\returns -Equivalent to: \tcode{return x.\exposid{current_} \placeholder{op} y;} +\effects +Equivalent to: \tcode{return \exposid{current_} \placeholder{op} y;} \end{itemdescr} \indexlibrarymember{operator<}{basic_const_iterator}% @@ -4638,10 +4696,11 @@ \end{itemdecl} \begin{itemdescr} +\pnum Let \tcode{\placeholder{op}} be the operator. \pnum -\returns +\effects Equivalent to: \tcode{return x \placeholder{op} y.\exposid{current_};} \end{itemdescr} @@ -4674,19 +4733,19 @@ \indexlibrarymember{operator-}{basic_const_iterator}% \begin{itemdecl} template<@\libconcept{sized_sentinel_for}@ S> - friend constexpr difference_type operator-(const basic_const_iterator& x, const S& y); + constexpr difference_type operator-(const S& y) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} - y;} +Equivalent to: \tcode{return \exposid{current_} - y;} \end{itemdescr} \indexlibrarymember{operator-}{basic_const_iterator}% \begin{itemdecl} -template<@\libconcept{sized_sentinel_for}@ S> - requires @\exposconcept{different-from}@ +template<@\exposconcept{not-a-const-iterator}@ S> + requires @\libconcept{sized_sentinel_for}@ friend constexpr difference_type operator-(const S& x, const basic_const_iterator& y); \end{itemdecl} @@ -5231,7 +5290,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} @@ -5258,7 +5317,8 @@ @\libconcept{indirect_unary_predicate}@ Pred> requires @\libconcept{indirectly_movable}@ void move_if(I first, S last, O out, Pred pred) { - ranges::copy_if(move_iterator{first}, move_sentinel{last}, out, pred); + ranges::copy_if(move_iterator{std::move(first)}, move_sentinel{last}, + std::move(out), pred); } \end{codeblock} \end{example} @@ -5279,6 +5339,7 @@ constexpr move_sentinel& operator=(const move_sentinel& s); constexpr S base() const; + private: S last; // \expos }; @@ -5422,7 +5483,7 @@ friend constexpr iter_difference_t operator-( const common_iterator& x, const common_iterator& y); - friend constexpr iter_rvalue_reference_t iter_move(const common_iterator& i) + friend constexpr decltype(auto) iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval()))) requires @\libconcept{input_iterator}@; template<@\libconcept{indirectly_swappable}@ I2, class S2> @@ -5441,7 +5502,7 @@ template<@\libconcept{input_iterator}@ I, class S> struct iterator_traits> { using iterator_concept = @\seebelow@; - using iterator_category = @\seebelow@; + using iterator_category = @\seebelow@; // not always present using value_type = iter_value_t; using difference_type = iter_difference_t; using pointer = @\seebelow@; @@ -5453,22 +5514,25 @@ \rSec3[common.iter.types]{Associated types} \pnum -The nested \grammarterm{typedef-name}s of the specialization of -\tcode{iterator_traits} for \tcode{common_iterator} are defined as follows. +The nested \grammarterm{typedef-name} \tcode{iterator_category} of +the specialization of \tcode{iterator_traits} for \tcode{common_iterator} +is defined if and only if \tcode{iter_difference_t} is an integral type. +In that case, +\tcode{iterator_category} denotes \tcode{forward_iterator_tag} if +the \grammarterm{qualified-id} \tcode{iterator_traits::iterator_category} +is valid and denotes a type that +models \tcode{\libconcept{derived_from}}; +otherwise it denotes \tcode{input_iterator_tag}. + +\pnum +The remaining nested \grammarterm{typedef-name}s of the specialization of +\tcode{iterator_traits} for \tcode{common_iterator} are defined as follows: \begin{itemize} \item \tcode{iterator_concept} denotes \tcode{forward_iterator_tag} if \tcode{I} models \libconcept{forward_iterator}; otherwise it denotes \tcode{input_iterator_tag}. -\item -\tcode{iterator_category} denotes -\tcode{forward_iterator_tag} -if the \grammarterm{qualified-id} \tcode{iterator_traits::iter\-ator_category} -is valid and denotes a type that -models \tcode{\libconcept{derived_from}}; -otherwise it denotes \tcode{input_iterator_tag}. - \item Let \tcode{a} denote an lvalue of type \tcode{const common_iterator}. If the expression \tcode{a.operator->()} is well-formed, @@ -5546,7 +5610,7 @@ \pnum \returns -\tcode{*this} +\tcode{*this}. \end{itemdescr} \rSec3[common.iter.access]{Accessors} @@ -5761,7 +5825,7 @@ \indexlibrarymember{iter_move}{common_iterator}% \begin{itemdecl} -friend constexpr iter_rvalue_reference_t iter_move(const common_iterator& i) +friend constexpr decltype(auto) iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval()))) requires @\libconcept{input_iterator}@; \end{itemdecl} @@ -5920,7 +5984,7 @@ friend constexpr strong_ordering operator<=>( const counted_iterator& x, const counted_iterator& y); - friend constexpr iter_rvalue_reference_t iter_move(const counted_iterator& i) + friend constexpr decltype(auto) iter_move(const counted_iterator& i) noexcept(noexcept(ranges::iter_move(i.current))) requires @\libconcept{input_iterator}@; template<@\libconcept{indirectly_swappable}@ I2> @@ -6348,7 +6412,7 @@ \indexlibrarymember{iter_move}{counted_iterator}% \begin{itemdecl} -friend constexpr iter_rvalue_reference_t +friend constexpr decltype(auto) iter_move(const counted_iterator& i) noexcept(noexcept(ranges::iter_move(i.current))) requires @\libconcept{input_iterator}@; @@ -6466,7 +6530,7 @@ constexpr istream_iterator(); constexpr istream_iterator(default_sentinel_t); istream_iterator(istream_type& s); - istream_iterator(const istream_iterator& x) = default; + constexpr istream_iterator(const istream_iterator& x) noexcept(@\seebelow@); ~istream_iterator() = default; istream_iterator& operator=(const istream_iterator&) = default; @@ -6529,18 +6593,22 @@ \indexlibraryctor{istream_iterator}% \begin{itemdecl} -istream_iterator(const istream_iterator& x) = default; +constexpr istream_iterator(const istream_iterator& x) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{in_stream == x.in_stream} is \tcode{true}. +\effects +Initializes \tcode{in_stream} with \tcode{x.in_stream} and +initializes \tcode{value} with \tcode{x.value}. \pnum \remarks -If \tcode{is_trivially_copy_constructible_v} is \tcode{true}, -then this constructor is trivial. +An invocation of this constructor may be used in a core constant expression +if and only if the initialization of \tcode{value} from \tcode{x.value} +is a constant subexpression\iref{defns.const.subexpr}. +The exception specification is equivalent to +\tcode{is_nothrow_copy_constructible_v}. \end{itemdescr} \indexlibrarydtor{istream_iterator}% @@ -7172,7 +7240,10 @@ headers are included: \libheaderref{array}, \libheaderref{deque}, +\libheaderrefx{flat_map}{flat.map.syn}, +\libheaderrefx{flat_set}{flat.set.syn}, \libheaderrefx{forward_list}{forward.list.syn}, +\libheaderrefx{inplace_vector}{inplace.vector.syn}, \libheaderref{list}, \libheaderrefx{map}{associative.map.syn}, \libheaderrefx{regex}{re.syn}, @@ -7183,8 +7254,6 @@ \libheaderrefx{unordered_map}{unord.map.syn}, \libheaderrefx{unordered_set}{unord.set.syn}, and \libheaderref{vector}. -Each of these templates -is a designated customization point\iref{namespace.std}. \indexlibrary{\idxcode{begin(C\&)}}% \begin{itemdecl} @@ -7382,7 +7451,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 @@ -7392,7 +7461,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 @@ -7402,7 +7471,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 65c53124f9..1f82bd20d9 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{\onelineskip}{4\onelineskip} \setheaderspaces{*}{2\onelineskip}{*} %%-------------------------------------------------- @@ -21,7 +21,9 @@ %%-------------------------------------------------- %% If there is insufficient stretchable vertical space on a page, %% TeX will not properly consider penalties for a good page break, -%% even if \raggedbottom (default) is in effect. +%% even if \raggedbottom (default for oneside, not for twoside) +%% is in effect. +\raggedbottom \addtolength{\topskip}{0pt plus 20pt} %%-------------------------------------------------- diff --git a/source/lex.tex b/source/lex.tex index 0f33bfda64..6cf011e432 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -32,8 +32,11 @@ 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 -called a \defn{translation unit}. +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} @@ -66,7 +69,6 @@ \begin{enumerate} \item \indextext{character!source file}% -\indextext{character set!basic source}% An implementation shall support input files that are a sequence of UTF-8 code units (UTF-8 files). It may also support @@ -81,14 +83,28 @@ \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 UCS scalar values -that constitutes the sequence of elements of the translation character set. +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, +each pair of characters in the input sequence consisting of +\unicode{000d}{carriage return} followed by \unicode{000a}{line feed}, +as well as each +\unicode{000d}{carriage return} not immediately followed by a \unicode{000a}{line feed}, +is replaced by a single new-line character. 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} -(introducing new-line characters for end-of-line indicators). +\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 \indextext{line splicing}% @@ -98,14 +114,15 @@ 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. -Except for splices reverted in a raw string literal, if a splice results in -a character sequence that matches the -syntax of a \grammarterm{universal-character-name}, the behavior is -undefined. A source file that is not empty and that does not end in a new-line -character, or that ends in a splice, +\begin{note} +Line splicing can form +a \grammarterm{universal-character-name}\iref{lex.charset}. +\end{note} +A source file that is not empty and that (after splicing) +does not end in a new-line character shall be processed as if an additional new-line character were appended to the file. @@ -123,7 +140,7 @@ 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 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 unspecified. @@ -136,35 +153,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. +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 are syntactically and -semantically analyzed and translated as a translation unit. +\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 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 @@ -222,7 +244,9 @@ The program is ill-formed if any instantiation fails. -\item All external entity references are resolved. Library +\item +\indextext{linking}% +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 @@ -230,30 +254,32 @@ \indextext{translation!phases|)} \end{enumerate} -\rSec1[lex.charset]{Character sets} +\rSec1[lex.char]{Characters}% + +\rSec2[lex.charset]{Character sets} \pnum \indextext{character set|(}% The \defnadj{translation}{character set} consists of the following elements: \begin{itemize} \item -each character named by ISO/IEC 10646, -as identified by its unique UCS scalar value, and +each abstract character assigned a code point in the Unicode codespace +as specified in the Unicode Standard, and \item -a distinct character for each UCS scalar value -where no named character is assigned. +a distinct character for each Unicode scalar value +not assigned to an abstract character. \end{itemize} \begin{note} -ISO/IEC 10646 code points are integers +Unicode code points are integers in the range $[0, \mathrm{10FFFF}]$ (hexadecimal). A surrogate code point is a value in the range $[\mathrm{D800}, \mathrm{DFFF}]$ (hexadecimal). -A UCS scalar value is any code point that is not a surrogate code point. +A Unicode scalar value is any code point that is not a surrogate code point. \end{note} \pnum The \defnadj{basic}{character set} is a subset of the translation character set, -consisting of 96 characters as specified in \tref{lex.charset.basic}. +consisting of 99 characters as specified in \tref{lex.charset.basic}. \begin{note} Unicode short names are given only as a means to identifying the character; the numerical value has no other meaning in this context. @@ -270,6 +296,7 @@ \ucode{0021} & \uname{exclamation mark} & \tcode{!} \\ \ucode{0022} & \uname{quotation mark} & \tcode{"} \\ \ucode{0023} & \uname{number sign} & \tcode{\#} \\ +\ucode{0024} & \uname{dollar sign} & \tcode{\$} \\ \ucode{0025} & \uname{percent sign} & \tcode{\%} \\ \ucode{0026} & \uname{ampersand} & \tcode{\&} \\ \ucode{0027} & \uname{apostrophe} & \tcode{'} \\ @@ -288,6 +315,7 @@ \ucode{003d} & \uname{equals sign} & \tcode{=} \\ \ucode{003e} & \uname{greater-than sign} & \tcode{>} \\ \ucode{003f} & \uname{question mark} & \tcode{?} \\ +\ucode{0040} & \uname{commercial at} & \tcode{@} \\ \ucode{0041} .. \ucode{005a} & \uname{latin capital letter a .. z} & \tcode{A B C D E F G H I J K L M} \\ & & \tcode{N O P Q R S T U V W X Y Z} \\ \ucode{005b} & \uname{left square bracket} & \tcode{[} \\ @@ -295,6 +323,7 @@ \ucode{005d} & \uname{right square bracket} & \tcode{]} \\ \ucode{005e} & \uname{circumflex accent} & \tcode{\caret} \\ \ucode{005f} & \uname{low line} & \tcode{_} \\ +\ucode{0060} & \uname{grave accent} & \tcode{\`} \\ \ucode{0061} .. \ucode{007a} & \uname{latin small letter a .. z} & \tcode{a b c d e f g h i j k l m} \\ & & \tcode{n o p q r s t u v w x y z} \\ \ucode{007b} & \uname{left curly bracket} & \tcode{\{} \\ @@ -303,196 +332,10 @@ \ucode{007e} & \uname{tilde} & \tcode{\textasciitilde} \\ \end{floattable} -\pnum -The \grammarterm{universal-character-name} construct provides a way to name -other characters. - -\begin{bnf} -\nontermdef{n-char} \textnormal{one of}\br - \terminal{A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}\br - \terminal{0 1 2 3 4 5 6 7 8 9}\br - \textnormal{\unicode{002d}{hyphen-minus}}\br - \textnormal{\unicode{0020}{space}} -\end{bnf} - -\begin{bnf} -\nontermdef{n-char-sequence}\br - n-char\br - n-char-sequence n-char -\end{bnf} - -\begin{bnf} -\nontermdef{named-universal-character}\br - \terminal{\textbackslash N\{} n-char-sequence \terminal{\}} -\end{bnf} - -\begin{bnf} -\nontermdef{hex-quad}\br - hexadecimal-digit hexadecimal-digit hexadecimal-digit hexadecimal-digit -\end{bnf} - -\begin{bnf} -\nontermdef{simple-hexadecimal-digit-sequence}\br - hexadecimal-digit\br - simple-hexadecimal-digit-sequence hexadecimal-digit -\end{bnf} - -\begin{bnf} -\nontermdef{universal-character-name}\br - \terminal{\textbackslash u} hex-quad\br - \terminal{\textbackslash U} hex-quad hex-quad\br - \terminal{\textbackslash u\{} simple-hexadecimal-digit-sequence \terminal{\}}\br - named-universal-character -\end{bnf} - -\pnum -A \grammarterm{universal-character-name} -of the form \tcode{\textbackslash u} \grammarterm{hex-quad}, -\tcode{\textbackslash U} \grammarterm{hex-quad} \grammarterm{hex-quad}, or -\tcode{\textbackslash u\{\grammarterm{simple-hexadecimal-digit-sequence}\}} -designates the character in the translation character set -whose UCS scalar value is the hexadecimal number represented by -the sequence of \grammarterm{hexadecimal-digit}s -in the \grammarterm{universal-character-name}. -The program is ill-formed if that number is not a UCS scalar value. - -\pnum -A \grammarterm{universal-character-name} -that is a \grammarterm{named-universal-character} -designates the character named by its \grammarterm{n-char-sequence}. -A character is so named if the \grammarterm{n-char-sequence} is equal to -\begin{itemize} -\item -the associated character name or associated character name alias -specified in ISO/IEC 10646 subclause ``Code charts and lists of character names'' -or -\item -the control code alias given in \tref{lex.charset.ucn}. -\begin{note} -The aliases in \tref{lex.charset.ucn} are provided for control characters -which otherwise have no associated character name or character name alias. -These names are derived from -the Unicode Character Database's \tcode{NameAliases.txt}. -For historical reasons, control characters are formally unnamed. -\end{note} -\end{itemize} -\begin{note} -None of the associated character names, -associated character name aliases, or -control code aliases -have leading or trailing spaces. -\end{note} - -\begin{multicolfloattable}{Control code aliases}{lex.charset.ucn}{ll} -\unicode{0000}{null} \\ -\unicode{0001}{start of heading} \\ -\unicode{0002}{start of text} \\ -\unicode{0003}{end of text} \\ -\unicode{0004}{end of transmission} \\ -\unicode{0005}{enquiry} \\ -\unicode{0006}{acknowledge} \\ -\unicode{0007}{alert} \\ -\unicode{0008}{backspace} \\ -\unicode{0009}{character tabulation} \\ -\unicode{0009}{horizontal tabulation} \\ -\unicode{000a}{line feed} \\ -\unicode{000a}{new line} \\ -\unicode{000a}{end of line} \\ -\unicode{000b}{line tabulation} \\ -\unicode{000b}{vertical tabulation} \\ -\unicode{000c}{form feed} \\ -\unicode{000d}{carriage return} \\ -\unicode{000e}{shift out} \\ -\unicode{000e}{locking-shift one} \\ -\unicode{000f}{shift in} \\ -\unicode{000f}{locking-shift zero} \\ -\unicode{0010}{data link escape} \\ -\unicode{0011}{device control one} \\ -\unicode{0012}{device control two} \\ -\unicode{0013}{device control three} \\ -\unicode{0014}{device control four} \\ -\unicode{0015}{negative acknowledge} \\ -\unicode{0016}{synchronous idle} \\ -\unicode{0017}{end of transmission block} \\ -\unicode{0018}{cancel} \\ -\unicode{0019}{end of medium} \\ -\unicode{001a}{substitute} \\ -\unicode{001b}{escape} \\ -\unicode{001c}{information separator four} \\ -\unicode{001c}{file separator} \\ -\unicode{001d}{information separator three} \\ -\unicode{001d}{group separator} \\ -\unicode{001e}{information separator two} \\ -\unicode{001e}{record separator} \\ -\unicode{001f}{information separator one} \\ -\unicode{001f}{unit separator} \\ -\columnbreak -\unicode{007f}{delete} \\ -\unicode{0082}{break permitted here} \\ -\unicode{0083}{no break here} \\ -\unicode{0084}{index} \\ -\unicode{0085}{next line} \\ -\unicode{0086}{start of selected area} \\ -\unicode{0087}{end of selected area} \\ -\unicode{0088}{character tabulation set} \\ -\unicode{0088}{horizontal tabulation set} \\ -\unicode{0089}{character tabulation with justification} \\ -\unicode{0089}{horizontal tabulation with justification} \\ -\unicode{008a}{line tabulation set} \\ -\unicode{008a}{vertical tabulation set} \\ -\unicode{008b}{partial line forward} \\ -\unicode{008b}{partial line down} \\ -\unicode{008c}{partial line backward} \\ -\unicode{008c}{partial line up} \\ -\unicode{008d}{reverse line feed} \\ -\unicode{008d}{reverse index} \\ -\unicode{008e}{single shift two} \\ -\unicode{008e}{single-shift-2} \\ -\unicode{008f}{single shift three} \\ -\unicode{008f}{single-shift-3} \\ -\unicode{0090}{device control string} \\ -\unicode{0091}{private use one} \\ -\unicode{0091}{private use-1} \\ -\unicode{0092}{private use two} \\ -\unicode{0092}{private use-2} \\ -\unicode{0093}{set transmit state} \\ -\unicode{0094}{cancel character} \\ -\unicode{0095}{message waiting} \\ -\unicode{0096}{start of guarded area} \\ -\unicode{0096}{start of protected area} \\ -\unicode{0097}{end of guarded area} \\ -\unicode{0097}{end of protected area} \\ -\unicode{0098}{start of string} \\ -\unicode{009a}{single character introducer} \\ -\unicode{009b}{control sequence introducer} \\ -\unicode{009c}{string terminator} \\ -\unicode{009d}{operating system command} \\ -\unicode{009e}{privacy message} \\ -\unicode{009f}{application program command} \\ -\end{multicolfloattable} - -\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{note} -The alias \uname{bell} for \ucode{0007} shown in ISO 10646 -is ambiguous with \unicode{1f514}{bell}. -\end{note} \begin{floattable}{Additional control characters in the basic literal character set}{lex.charset.literal}{ll} \topline @@ -542,11 +385,114 @@ \indextext{UTF-16}% \indextext{UTF-32}% For a UTF-8, UTF-16, or UTF-32 literal, -the UCS scalar value +the implementation shall encode +the Unicode scalar value corresponding to each character of the translation character set -is encoded as specified in ISO/IEC 10646 for the respective UCS encoding form. +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}\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 \opt{n-char-sequence} +\end{bnf} + +\begin{bnf} +\nontermdef{named-universal-character}\br + \terminal{\textbackslash N\{} n-char-sequence \terminal{\}} +\end{bnf} + +\begin{bnf} +\nontermdef{hex-quad}\br + hexadecimal-digit hexadecimal-digit hexadecimal-digit hexadecimal-digit +\end{bnf} + +\begin{bnf} +\nontermdef{simple-hexadecimal-digit-sequence}\br + hexadecimal-digit \opt{simple-hexadecimal-digit-sequence} +\end{bnf} + +\begin{bnf} +\nontermdef{universal-character-name}\br + \terminal{\textbackslash u} hex-quad\br + \terminal{\textbackslash U} hex-quad hex-quad\br + \terminal{\textbackslash u\{} simple-hexadecimal-digit-sequence \terminal{\}}\br + 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}, +\tcode{\textbackslash U} \grammarterm{hex-quad} \grammarterm{hex-quad}, or +\tcode{\textbackslash u\{\grammarterm{simple-hexadecimal-digit-sequence}\}} +designates the character in the translation character set +whose Unicode scalar value is the hexadecimal number represented by +the sequence of \grammarterm{hexadecimal-digit}s +in the \grammarterm{universal-character-name}. +The program is ill-formed if that number is not a Unicode scalar value. + +\pnum +A \grammarterm{universal-character-name} +that is a \grammarterm{named-universal-character} +designates the corresponding character +in the Unicode Standard (chapter 4.8 Name) +if the \grammarterm{n-char-sequence} is equal +to its character name or +to one of its character name aliases of +type ``control'', ``correction'', or ``alternate''; +otherwise, the program is ill-formed. +\begin{note} +These aliases are listed in +the Unicode Character Database's \tcode{NameAliases.txt}. +None of these names or aliases have leading or trailing spaces. +\end{note} + +\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.pptoken]{Preprocessing tokens} \indextext{token!preprocessing|(}% @@ -566,11 +512,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. @@ -585,7 +526,7 @@ operators and punctuators, and single non-whitespace characters that do not lexically match the other preprocessing token categories. If a \unicode{0027}{apostrophe} or a \unicode{0022}{quotation mark} character -matches the last category, the behavior is undefined. +matches the last category, the program is ill-formed. If any character not in the basic character set matches the last category, the program is ill-formed. Preprocessing tokens can be separated by @@ -605,6 +546,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: @@ -634,7 +591,7 @@ except that a \grammarterm{header-name}\iref{lex.header} is only formed \begin{itemize} \item -after the \tcode{include} or \tcode{import} preprocessing token in an +after the \tcode{include} or \tcode{import} preprocessing token in a \tcode{\#include}\iref{cpp.include} or \tcode{import}\iref{cpp.import} directive, or @@ -644,6 +601,7 @@ \end{itemize} \end{itemize} +\pnum \begin{example} \begin{codeblock} #define R "x" @@ -651,17 +609,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 @@ -684,111 +631,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} -Some whitespace is -required to 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} \nontermdef{header-name}\br \terminal{<} h-char-sequence \terminal{>}\br \terminal{"} q-char-sequence \terminal{"} @@ -796,8 +643,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} @@ -807,8 +653,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} @@ -817,16 +662,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 @@ -836,12 +681,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} @@ -873,7 +718,127 @@ 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{? \ \ \ \ \ \ \ :: \ \ \ \ \ \ . \ \ \ \ \ \ \ .* \ \ \ \ \ \ -> \ \ \ \ \ \ ->* \ \ \ \ \ \~}\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}% +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.name]{Identifiers} +\indextext{XID_Start}% +\indextext{XID_Continue}% \indextext{identifier|(}% \begin{bnf} @@ -885,14 +850,14 @@ \begin{bnf} \nontermdef{identifier-start}\br nondigit\br - \textnormal{an element of the translation character set of class XID_Start} + \textnormal{an element of the translation character set with the Unicode property XID_Start} \end{bnf} \begin{bnf} \nontermdef{identifier-continue}\br digit\br nondigit\br - \textnormal{an element of the translation character set of class XID_Continue} + \textnormal{an element of the translation character set with the Unicode property XID_Continue} \end{bnf} \begin{bnf} @@ -911,8 +876,8 @@ \pnum \indextext{name!length of}% \indextext{name}% -The character classes XID_Start and XID_Continue -are Derived Core Properties as described by UAX \#44. +\begin{note} +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 @@ -923,13 +888,18 @@ place a translation limit on significant characters for external identifiers. \end{footnote} +\end{note} The program is ill-formed if an \grammarterm{identifier} does not conform to -Normalization Form C as specified in ISO/IEC 10646. +Normalization Form C as specified in the Unicode Standard. \begin{note} Identifiers are case-sensitive. \end{note} \begin{note} +\ref{uaxid} compares the requirements of \UAX{31} of the Unicode Standard +with the \Cpp{} rules for identifiers. +\end{note} +\begin{note} In translation phase 4, \grammarterm{identifier} also includes those \grammarterm{preprocessing-token}s\iref{lex.pptoken} @@ -942,6 +912,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. @@ -951,20 +923,23 @@ \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 \indextext{\idxcode{_}|see{character, underscore}}% \indextext{character!underscore!in identifier}% \indextext{reserved identifier}% -In addition, some identifiers are reserved for use by \Cpp{} +In addition, some identifiers +appearing as a \grammarterm{token} or \grammarterm{preprocessing-token} +are reserved for use by \Cpp{} implementations and shall not be used otherwise; no diagnostic is required. \begin{itemize} @@ -973,7 +948,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 @@ -1027,6 +1004,7 @@ \keyword{constinit} \\ \keyword{const_cast} \\ \keyword{continue} \\ +\keyword{contract_assert} \\ \keyword{co_await} \\ \keyword{co_return} \\ \keyword{co_yield} \\ @@ -1040,8 +1018,8 @@ \keyword{enum} \\ \keyword{explicit} \\ \keyword{export} \\ -\keyword{extern} \\ \columnbreak +\keyword{extern} \\ \keyword{false} \\ \keyword{float} \\ \keyword{for} \\ @@ -1058,8 +1036,8 @@ \keyword{nullptr} \\ \keyword{operator} \\ \keyword{private} \\ -\keyword{protected} \\ \columnbreak +\keyword{protected} \\ \keyword{public} \\ \keyword{register} \\ \keyword{reinterpret_cast} \\ @@ -1076,8 +1054,8 @@ \keyword{template} \\ \keyword{this} \\ \keyword{thread_local} \\ -\keyword{throw} \\ \columnbreak +\keyword{throw} \\ \keyword{true} \\ \keyword{try} \\ \keyword{typedef} \\ @@ -1108,47 +1086,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|(} @@ -1160,8 +1097,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} @@ -1174,6 +1110,10 @@ pointer-literal\br user-defined-literal \end{bnf} +\begin{note} +When appearing as an \grammarterm{expression}, +a literal has a type and a value category\iref{expr.prim.literal}. +\end{note} \rSec2[lex.icon]{Integer literals} @@ -1283,7 +1223,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 @@ -1326,7 +1266,6 @@ the first type in the list in \tref{lex.icon.type} corresponding to its optional \grammarterm{integer-suffix} in which its value can be represented. -An \grammarterm{integer-literal} is a prvalue. \begin{floattable}{Types of \grammarterm{integer-literal}s}{lex.icon.type}{l|l|l} \topline @@ -1406,21 +1345,27 @@ \end{floattable} \pnum -If an \grammarterm{integer-literal} +Except for \grammarterm{integer-literal}{s} containing +a \grammarterm{size-suffix}, +if the value of an \grammarterm{integer-literal} cannot be represented by any type in its list and an extended integer type\iref{basic.fundamental} can represent its value, it may have that extended integer type. If all of the types in the list for the \grammarterm{integer-literal} are signed, -the extended integer type shall be signed. +the extended integer type is signed. If all of the types in the list for the \grammarterm{integer-literal} are unsigned, -the extended integer type shall be unsigned. +the extended integer type is unsigned. If the list contains both signed and unsigned types, the extended integer type may be signed or unsigned. -A program is ill-formed -if one of its translation units contains an \grammarterm{integer-literal} -that cannot be represented by any of the allowed types. +If an \grammarterm{integer-literal} +cannot be represented by any of the allowed types, +the program is ill-formed. +\begin{note} +An \grammarterm{integer-literal} with a \tcode{z} or \tcode{Z} suffix +is ill-formed if it cannot be represented by \tcode{std::size_t}. +\end{note} \rSec2[lex.ccon]{Character literals} @@ -1437,8 +1382,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} @@ -1479,8 +1423,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} @@ -1488,13 +1431,12 @@ \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} \nontermdef{hexadecimal-escape-sequence}\br - \terminal{\textbackslash x} hexadecimal-digit\br - hexadecimal-escape-sequence hexadecimal-digit\br + \terminal{\textbackslash x} simple-hexadecimal-digit-sequence\br \terminal{\textbackslash x\{} simple-hexadecimal-digit-sequence \terminal{\}} \end{bnf} @@ -1519,61 +1461,35 @@ \indextext{type!\idxcode{char32_t}}% \indextext{wide-character}% \indextext{type!\idxcode{wchar_t}}% -A \defnx{non-encodable character literal}{literal!character!non-encodable} -is a \grammarterm{character-literal} -whose \grammarterm{c-char-sequence} consists of a single \grammarterm{c-char} -that is not a \grammarterm{numeric-escape-sequence} and -that specifies a character -that either lacks representation in the literal's associated character encoding -or that cannot be encoded as a single code unit. A \defnadj{multicharacter}{literal} is a \grammarterm{character-literal} whose \grammarterm{c-char-sequence} consists of more than one \grammarterm{c-char}. -The \grammarterm{encoding-prefix} of -a non-encodable character literal or a multicharacter literal -shall be absent. -Such \grammarterm{character-literal}s are conditionally-supported. +A multicharacter literal shall not have an \grammarterm{encoding-prefix}. +If a multicharacter literal contains a \grammarterm{c-char} +that is not encodable as a single code unit in the ordinary literal encoding, +the program is ill-formed. +Multicharacter literals are conditionally-supported. \pnum The kind of a \grammarterm{character-literal}, -its type, and its associated character encoding +its type, and its associated character encoding\iref{lex.charset} are determined by its \grammarterm{encoding-prefix} and its \grammarterm{c-char-sequence} as defined by \tref{lex.ccon.literal}. -The special cases for -non-encodable character literals and multicharacter literals -take precedence over the base kind. -\begin{note} -The associated character encoding for ordinary character literals -determines encodability, -but does not determine the value of -non-encodable ordinary character literals or -ordinary multicharacter literals. -The examples in \tref{lex.ccon.literal} -for non-encodable ordinary character literals assume that -the specified character lacks representation in -the ordinary literal encoding or -that encoding the character would require more than one code unit. -\end{note} \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} & \keyword{char} & -ordinary & +ordinary literal & \tcode{'v'} \\ \cline{2-3}\cline{5-5} & -non-encodable ordinary character literal & -\keyword{int} & -literal & -\tcode{'\textbackslash U0001F525'} \\ \cline{2-3}\cline{5-5} - & -ordinary multicharacter literal & +multicharacter literal & \keyword{int} & encoding & \tcode{'abcd'} \\ \hline @@ -1605,8 +1521,7 @@ the value of a \grammarterm{character-literal} is determined using the range of representable values of the \grammarterm{character-literal}'s type in translation phase 7. -A non-encodable character literal or a multicharacter literal -has an +A multicharacter literal has an \impldef{value of non-encodable character literal or multicharacter literal} value. The value of any other kind of \grammarterm{character-literal} @@ -1620,12 +1535,10 @@ \grammarterm{universal-character-name} is the code unit value of the specified character as encoded in the literal's associated character encoding. -\begin{note} If the specified character lacks representation in the literal's associated character encoding or if it cannot be encoded as a single code unit, -then the literal is a non-encodable character literal. -\end{note} +then the program is ill-formed. \item A \grammarterm{character-literal} with a \grammarterm{c-char-sequence} consisting of @@ -1651,7 +1564,7 @@ $v$ does not exceed the range of representable values of the corresponding unsigned type for the underlying type of the \grammarterm{character-literal}'s type, then the value is the unique value of the \grammarterm{character-literal}'s type \tcode{T} that is congruent to $v$ modulo $2^N$, where $N$ is the width of \tcode{T}. \item -Otherwise, the \grammarterm{character-literal} is ill-formed. +Otherwise, the program is ill-formed. \end{itemize} \item A \grammarterm{character-literal} with @@ -1669,7 +1582,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} @@ -1775,7 +1688,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} \\ @@ -1838,8 +1751,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} @@ -1862,8 +1774,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} @@ -1874,8 +1785,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} @@ -1897,18 +1807,20 @@ \indextext{type!\idxcode{char32_t}}% The kind of a \grammarterm{string-literal}, its type, and -its associated character encoding +its associated character encoding\iref{lex.charset} 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} & @@ -1954,7 +1866,7 @@ \pnum \begin{note} -The characters \tcode{'('} and \tcode{')'} are permitted in a +The characters \tcode{'('} and \tcode{')'} can appear in a \grammarterm{raw-string}. Thus, \tcode{R"delimiter((a|b))delimiter"} is equivalent to \tcode{"(a|b)"}. \end{note} @@ -1989,23 +1901,17 @@ \end{example} \pnum -\indextext{literal!string!narrow}% \indextext{literal!narrow-character}% Ordinary string literals and UTF-8 string literals are -also referred to as narrow string literals. +also referred to as \defnx{narrow string literals}{literal!string!narrow}. \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}. @@ -2059,18 +1965,18 @@ \pnum Evaluating a \grammarterm{string-literal} results in a string literal object with static storage duration\iref{basic.stc}. -\indextext{string!distinct}% -Whether all \grammarterm{string-literal}s are distinct (that is, are stored in -nonoverlapping objects) and whether successive evaluations of a +\begin{note} +String literal objects are potentially non-unique\iref{intro.object}. +Whether successive evaluations of a \grammarterm{string-literal} yield the same or a different object is unspecified. +\end{note} \begin{note} \indextext{literal!string!undefined change to}% The effect of attempting to modify a string literal object is undefined. \end{note} \pnum -\indextext{\idxcode{0}|seealso{zero, null}}% \indextext{\idxcode{0}!string terminator}% \indextext{\idxcode{0}!null character|see {character, null}}% String literal objects are initialized with @@ -2090,12 +1996,9 @@ is encoded to a code unit sequence using the \grammarterm{string-literal}'s associated character encoding. If a character lacks representation in the associated character encoding, -then the \grammarterm{string-literal} is conditionally-supported and -an -\impldef{code unit sequence for non-representable \grammarterm{string-literal}} -code unit sequence is encoded. +then the program is ill-formed. \begin{note} -No character lacks representation in any of the UCS encoding forms. +No character lacks representation in any Unicode encoding form. \end{note} When encoding a stateful character encoding, implementations should encode the first such sequence @@ -2134,7 +2037,7 @@ the \grammarterm{string-literal}'s array element type \tcode{T} that is congruent to $v$ modulo $2^N$, where $N$ is the width of \tcode{T}. \item -Otherwise, the \grammarterm{string-literal} is ill-formed. +Otherwise, the program is ill-formed. \end{itemize} When encoding a stateful character encoding, these sequences should have no effect on encoding state. @@ -2149,6 +2052,28 @@ what effect these sequences have on encoding state. \end{itemize} +\rSec2[lex.string.uneval]{Unevaluated strings} + +\begin{bnf} +\nontermdef{unevaluated-string}\br + string-literal +\end{bnf} + +\pnum +An \grammarterm{unevaluated-string} shall have no \grammarterm{encoding-prefix}. + +\pnum +Each \grammarterm{universal-character-name} and each \grammarterm{simple-escape-sequence} in an \grammarterm{unevaluated-string} is +replaced by the member of the translation character set it denotes. +An \grammarterm{unevaluated-string} that contains +a \grammarterm{numeric-escape-sequence} or +a \grammarterm{conditional-escape-sequence} +is ill-formed. + +\pnum +An \grammarterm{unevaluated-string} is never evaluated and +its interpretation depends on the context in which it appears. + \rSec2[lex.bool]{Boolean literals} \indextext{literal!boolean}% @@ -2161,7 +2086,7 @@ \pnum \indextext{Boolean literal}% The Boolean literals are the keywords \tcode{false} and \tcode{true}. -Such literals are prvalues and have type \tcode{bool}. +Such literals have type \tcode{bool}. \rSec2[lex.nullptr]{Pointer literals} @@ -2172,7 +2097,7 @@ \end{bnf} \pnum -The pointer literal is the keyword \keyword{nullptr}. It is a prvalue of type +The pointer literal is the keyword \keyword{nullptr}. It has type \tcode{std::nullptr_t}. \begin{note} \tcode{std::nullptr_t} is a distinct type that is neither a pointer type nor a pointer-to-member type; @@ -2252,19 +2177,19 @@ parameter type \tcode{unsigned long long}, the literal \placeholder{L} is treated as a call of the form \begin{codeblock} -operator "" @\placeholder{X}@(@\placeholder{n}@ULL) +operator ""@\placeholder{X}@(@\placeholder{n}@ULL) \end{codeblock} Otherwise, \placeholder{S} shall contain a raw literal operator or a numeric literal operator template\iref{over.literal} but not both. If \placeholder{S} contains a raw literal operator, the literal \placeholder{L} is treated as a call of the form \begin{codeblock} -operator "" @\placeholder{X}@("@\placeholder{n}@") +operator ""@\placeholder{X}@("@\placeholder{n}@") \end{codeblock} Otherwise (\placeholder{S} contains a numeric literal operator template), \placeholder{L} is treated as a call of the form \begin{codeblock} -operator "" @\placeholder{X}@<'@$c_1$@', '@$c_2$@', ... '@$c_k$@'>() +operator ""@\placeholder{X}@<'@$c_1$@', '@$c_2$@', ... '@$c_k$@'>() \end{codeblock} where \placeholder{n} is the source character sequence $c_1c_2...c_k$. \begin{note} @@ -2278,19 +2203,19 @@ with parameter type \tcode{long double}, the literal \placeholder{L} is treated as a call of the form \begin{codeblock} -operator "" @\placeholder{X}@(@\placeholder{f}@L) +operator ""@\placeholder{X}@(@\placeholder{f}@L) \end{codeblock} Otherwise, \placeholder{S} shall contain a raw literal operator or a numeric literal operator template\iref{over.literal} but not both. If \placeholder{S} contains a raw literal operator, the \grammarterm{literal} \placeholder{L} is treated as a call of the form \begin{codeblock} -operator "" @\placeholder{X}@("@\placeholder{f}@") +operator ""@\placeholder{X}@("@\placeholder{f}@") \end{codeblock} Otherwise (\placeholder{S} contains a numeric literal operator template), \placeholder{L} is treated as a call of the form \begin{codeblock} -operator "" @\placeholder{X}@<'@$c_1$@', '@$c_2$@', ... '@$c_k$@'>() +operator ""@\placeholder{X}@<'@$c_1$@', '@$c_2$@', ... '@$c_k$@'>() \end{codeblock} where \placeholder{f} is the source character sequence $c_1c_2...c_k$. \begin{note} @@ -2304,15 +2229,15 @@ 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} -operator "" @\placeholder{X}@<@\placeholder{str}{}@>() +operator ""@\placeholder{X}@<@\placeholder{str}{}@>() \end{codeblock} Otherwise, the literal \placeholder{L} is treated as a call of the form \begin{codeblock} -operator "" @\placeholder{X}@(@\placeholder{str}{}@, @\placeholder{len}{}@) +operator ""@\placeholder{X}@(@\placeholder{str}{}@, @\placeholder{len}{}@) \end{codeblock} \pnum @@ -2323,19 +2248,19 @@ literal \placeholder{L} is treated as a call of the form \begin{codeblock} -operator "" @\placeholder{X}@(@\placeholder{ch}{}@) +operator ""@\placeholder{X}@(@\placeholder{ch}{}@) \end{codeblock} \pnum \begin{example} \begin{codeblock} -long double operator "" _w(long double); -std::string operator "" _w(const char16_t*, std::size_t); -unsigned operator "" _w(const char*); +long double operator ""_w(long double); +std::string operator ""_w(const char16_t*, std::size_t); +unsigned operator ""_w(const char*); int main() { - 1.2_w; // calls \tcode{operator "" _w(1.2L)} - u"one"_w; // calls \tcode{operator "" _w(u"one", 3)} - 12_w; // calls \tcode{operator "" _w("12")} + 1.2_w; // calls \tcode{operator ""_w(1.2L)} + u"one"_w; // calls \tcode{operator ""_w(u"one", 3)} + 12_w; // calls \tcode{operator ""_w("12")} "two"_w; // error: no applicable literal operator } \end{codeblock} diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 590670d176..61fcbded40 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -32,19 +32,23 @@ \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 \IsoPosix{} is +hereinafter called \defn{POSIX}. + \pnum The language support library\iref{support} provides components that are required by certain parts of the \Cpp{} language, @@ -78,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}, @@ -87,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 @@ -106,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} @@ -118,13 +123,14 @@ strings, locales, and iterators. \pnum -The regular expressions library\iref{re} provides regular expression matching and searching. - -\pnum -The thread support library\iref{thread} provides components to create +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 @@ -140,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 @@ -150,14 +156,14 @@ if it raises a floating-point exception other than \tcode{FE_INEXACT}. The semantics of a call to a C standard library function evaluated as a core constant expression -are those specified in Annex F of the C standard +are those specified in \IsoC{}, Annex F \begin{footnote} -See also ISO/IEC 9899:2018 section 7.6. +See also \IsoC{}, 7.6. \end{footnote} to the extent applicable to the floating-point types\iref{basic.fundamental} that are parameter types of the called function. \begin{note} -Annex F specifies +\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} @@ -364,9 +370,32 @@ \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 @@ -380,12 +409,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. @@ -418,9 +452,18 @@ 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{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, @@ -478,13 +521,14 @@ implementation-defined types\iref{type.descriptions}, and member functions\iref{functions.within.classes}. -\rSec3[expos.only.func]{Exposition-only functions} +\rSec3[expos.only.entity]{Exposition-only entities, etc.} \pnum -Several function templates +Several entities and \grammarterm{typedef-name}{s} defined in \ref{\firstlibchapter} through \ref{\lastlibchapter} and \ref{depr} are only defined for the purpose of exposition. -The declaration of such a function is followed by a comment ending in \expos. +The declaration of such an entity or \grammarterm{typedef-name} +is followed by a comment ending in \expos. \pnum The following are defined for exposition only @@ -494,11 +538,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}@; @@ -515,10 +559,19 @@ }; template - using @\placeholdernc{synth-three-way-result}@ = decltype(@\placeholdernc{synth-three-way}@(declval(), declval())); + 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} @@ -546,22 +599,6 @@ \indextext{types!implementation-defined}% They are based on other types, but with added constraints. -\rSec4[expos.only.types]{Exposition-only types} - -\pnum -Several types defined in \ref{\firstlibchapter} through \ref{\lastlibchapter} -and \ref{depr} are defined for the purpose of exposition. -The declaration of such a type is followed by a comment ending in \expos. -\begin{example} -\begin{codeblock} -namespace std { - extern "C" using @\placeholdernc{some-handler}@ = int(int, void*, double); // \expos -} -\end{codeblock} -The type placeholder \tcode{\placeholder{some-handler}} can now be used to specify a function -that takes a callback parameter with C language linkage. -\end{example} - \rSec4[enumerated.types]{Enumerated types} \pnum @@ -790,6 +827,12 @@ \rSec5[multibyte.strings]{Multibyte strings} +\pnum +A \defnx{multibyte character}{character!multibyte} is +a sequence of one or more bytes representing the +code unit sequence for an encoded character of the +execution character set. + \indextext{string!null-terminated multibyte|see{\ntmbs{}}}% \pnum A \defnx{null-terminated multibyte string}{NTMBS@\ntmbs{}}, @@ -850,23 +893,39 @@ \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} -Many of the customization point objects in the library evaluate function call -expressions with an unqualified name which results in a call to a -program-defined function found by argument dependent name -lookup\iref{basic.lookup.argdep}. To preclude such an expression resulting in a -call to unconstrained functions with the same name in namespace \tcode{std}, -customization point objects specify that lookup for these expressions is -performed in a context that includes deleted overloads matching the signatures -of overloads defined in namespace \tcode{std}. When the deleted overloads are -viable, program-defined overloads need to be more specialized\iref{temp.func.order} -or more constrained\iref{temp.constr.order} to be used by a customization point -object. +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} @@ -908,32 +967,57 @@ \pnum An implementation may use any technique that provides equivalent observable behavior. -\rSec3[freestanding.entity]{Freestanding entities} +\rSec3[freestanding.item]{Freestanding items} \pnum -\indextext{entity!freestanding|see{freestanding entity}}% -A \defn{freestanding entity} is a declaration or macro definition -that is present in a freestanding implementation and a hosted implementation. +\indextext{item!freestanding|see{freestanding item}}% +A \defn{freestanding item} is +a declaration, entity, \grammarterm{typedef-name}, or macro +that is required to be present in +a freestanding implementation and a hosted implementation. \pnum Unless otherwise specified, -the requirements on freestanding entities on a freestanding implementation -are the same as the corresponding requirements in a hosted implementation. - -\pnum -In a header synopsis, entities followed with a comment -that includes \textit{freestanding} are freestanding entities. +the requirements on freestanding items for a freestanding implementation +are the same as the corresponding requirements for a hosted implementation, +except that not all of the members of those items are required to be present. + +\pnum +Function declarations and function template declarations +followed by a comment that include \textit{freestanding-deleted} are +\defnadjx{freestanding deleted}{functions}{function}. +On freestanding implementations, +it is \impldef{whether a freestanding deleted function is a deleted function} +whether each entity introduced by a freestanding deleted function +is a deleted function\iref{dcl.fct.def.delete} or +whether the requirements are the same as +the corresponding requirements for a hosted implementation. +\begin{note} +Deleted definitions reduce the chance of overload resolution silently changing +when migrating from a freestanding implementation to a hosted implementation. +\end{note} \begin{example} \begin{codeblock} -#define NULL @\seebelow@ // freestanding +double abs(double j); // freestanding-deleted \end{codeblock} \end{example} \pnum -If a header synopsis begins with a comment -that includes \textit{all freestanding}, -then all of the declarations and macro definitions in the header synopsis -are freestanding entities. +\indextext{declaration!freestanding item}% +A declaration in a synopsis is a freestanding item if +\begin{itemize} +\item it is followed by a comment that includes \textit{freestanding}, +\item it is followed by a comment that includes \textit{freestanding-deleted}, or +\item the header synopsis begins with a comment +that includes \textit{freestanding} and +the declaration is not followed by a comment that includes \textit{hosted}. +\begin{note} +Declarations followed by \textit{hosted} in freestanding headers are +not freestanding items. +As a result, looking up the name of such functions can vary +between hosted and freestanding implementations. +\end{note} +\end{itemize} \begin{example} \begin{codeblock} // all freestanding @@ -942,17 +1026,63 @@ \end{example} \pnum -Deduction guides for freestanding entity class templates are freestanding entities. - -\pnum -Enclosing namespaces of freestanding entities are freestanding entities. +\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 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, +\item an enumerator of a freestanding item, +\item a deduction guide of a freestanding item, +\item an enclosing namespace of a freestanding item, +\item a friend of a freestanding item, +\item denoted by a \grammarterm{typedef-name} that is a freestanding item, or +\item denoted by an alias template that is a freestanding item. +\end{itemize} \pnum -Friends of freestanding entities are freestanding entities. +\indextext{macro!freestanding item}% +A macro is a freestanding item if it is defined in a header synopsis and +\begin{itemize} +\item the definition is followed by a comment +that includes \textit{freestanding}, or +\item the header synopsis begins with a comment +that includes \textit{freestanding} and +the definition is not followed by a comment that includes \textit{hosted}. +\end{itemize} +\begin{example} +\begin{codeblock} +#define NULL @\seebelow@ // freestanding +\end{codeblock} +\end{example} \pnum -Entities denoted by freestanding entity \grammarterm{typedef-name}{s} and -freestanding entity alias templates are freestanding entities. +\begin{note} +Freestanding annotations follow some additional exposition conventions +that do not impose any additional normative requirements. +Header synopses that begin with a comment containing "all freestanding" +contain no hosted items and no freestanding deleted functions. +Header synopses that begin with a comment containing "mostly freestanding" +contain at least one hosted item or freestanding deleted function. +Classes and class templates followed by a comment +containing "partially freestanding" +contain at least one hosted item or freestanding deleted function. +\end{note} +\begin{example} +\begin{codeblock} +template struct array; // partially freestanding +template +struct array { + 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 +}; +\end{codeblock} +\end{example} \rSec1[requirements]{Library-wide requirements} @@ -1018,8 +1148,11 @@ \end{footnote} \pnum -Whenever an unqualified name other than \tcode{swap} is used -in the specification of a declaration \tcode{D} +Whenever an unqualified name other than +\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}, its meaning is established as-if by performing unqualified name lookup\iref{basic.lookup.unqual} @@ -1040,6 +1173,13 @@ The meaning of the unqualified name \tcode{swap} is established 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}, +\tcode{from_stream}, and +\tcode{submdspan_mapping} +are established +as-if by performing argument-dependent lookup\iref{basic.lookup.argdep}. + \rSec3[headers]{Headers} @@ -1068,27 +1208,31 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\columnbreak \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\columnbreak \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ +\tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1097,6 +1241,7 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1115,11 +1260,13 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1133,14 +1280,14 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1251,7 +1398,7 @@ \end{footnote} \pnum -\ref{support.c.headers}, C standard library headers, describes the effects of using +Subclause \ref{support.c.headers} describes the effects of using the \tcode{\placeholder{name}.h} (C header) form in a \Cpp{} program. \begin{footnote} The @@ -1262,7 +1409,7 @@ \end{footnote} \pnum -Annex K of the C standard describes a large number of functions, +\IsoC{}, Annex K describes a large number of functions, with associated types and macros, which ``promote safer, more secure programming'' than many of the traditional C library functions. @@ -1283,7 +1430,7 @@ that may be declared in some header. These names are also subject to the restrictions of~\ref{macro.names}. -\begin{multicolfloattable}{C standard Annex K names}{c.annex.k.names} +\begin{multicolfloattable}{Names from \IsoC{}, Annex K}{c.annex.k.names} {llll} \tcode{abort_handler_s} \\ \tcode{asctime_s} \\ @@ -1382,16 +1529,25 @@ \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}). +the \Cpp{} headers for C library facilities~(\tref{headers.cpp.c}), +except the explicitly excluded declarations +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 is attached. \begin{note} -Implementations are required to ensure that mixing +Conforming implementations ensure that mixing \tcode{\#include} and \tcode{import} does not result in conflicting attachments\iref{basic.link}. \end{note} @@ -1438,46 +1594,84 @@ include at least the headers shown in \tref{headers.cpp.fs}. \begin{libsumtab}{\Cpp{} headers for freestanding implementations}{headers.cpp.fs} -\ref{support.types} & Types & \tcode{} \\ \rowsep +\ref{support.types} & Common definitions & \tcode{} \\ \rowsep +\ref{cstdlib.syn} & C standard library & \tcode{} \\ \rowsep \ref{support.limits} & Implementation properties & - \tcode{}, \tcode{}, \tcode{}, \tcode{} \\ \rowsep -\ref{cstdint} & Integer types & \tcode{} \\ \rowsep -\ref{support.start.term} & Start and termination & \tcode{} \\ \rowsep + \tcode{}, \tcode{}, \tcode{}, \\ + & & \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{bit} & Bit manipulation & \tcode{} \\ \rowsep -\ref{atomics} & Atomics & \tcode{} \\ \rowsep +\ref{ratio} & Compile-time rational arithmetic & \tcode{} \\ \rowsep \ref{utility} & Utility components & \tcode{} \\ \rowsep \ref{tuple} & Tuples & \tcode{} \\ \rowsep -\ref{memory} & Memory & \tcode{} \\ \rowsep +\ref{optional} & Optional objects & \tcode{} \\ \rowsep +\ref{variant} & Variants & \tcode{} \\ \rowsep +\ref{expected} & Expected objects & \tcode{} \\ \rowsep \ref{function.objects} & Function objects & \tcode{} \\ \rowsep -\ref{ratio} & Compile-time rational arithmetic & \tcode{} \\ \rowsep +\ref{bit} & 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{} \\ +\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 \end{libsumtab} \pnum For each of the headers listed in \tref{headers.cpp.fs}, a freestanding implementation provides at least -the freestanding entities\iref{freestanding.entity} declared in the header. -\indextext{implementation!freestanding|)}% - -\pnum +the freestanding items\iref{freestanding.item} declared in the header. + +\pnum +The \defnadj{hosted}{library facilities} are +the set of facilities described in this document +that are required for hosted implementations, +but not required for freestanding implementations. +A freestanding implementation provides +a (possibly empty) implementation-defined subset of +the hosted library facilities. +Unless otherwise specified, the requirements on +each declaration, entity, \grammarterm{typedef-name}, and macro +provided in this way are the same as +the corresponding requirements for a hosted implementation, +except that not all of the members of the namespaces are required to be present. + +\pnum +A freestanding implementation provides +deleted definitions\iref{dcl.fct.def.delete} for +a (possibly empty) implementation-defined subset of +the namespace-scope functions and function templates +from the hosted library facilities. \begin{note} -Throwing a standard library provided exception -is not observably different from \tcode{terminate()} -if the implementation does not -unwind the stack during exception handling\iref{except.handle} and -the user's program contains no catch blocks. +An implementation can provide a deleted definition +so that the result of overload resolution does not silently change +when migrating a program from a freestanding implementation to +a hosted implementation. \end{note} +\indextext{implementation!freestanding|)}% \rSec2[using]{Using the library} @@ -1553,8 +1747,7 @@ \begin{footnote} The only reliable way to declare an object or function signature from the C standard library is by including the header that -declares it, notwithstanding the latitude granted in 7.1.4 of the C -Standard. +declares it, notwithstanding the latitude granted in \IsoC{}, 7.1.4. \end{footnote} \pnum @@ -1590,16 +1783,25 @@ The template definitions in the \Cpp{} standard library refer to various named requirements whose details are set out in Tables~\ref{tab:cpp17.equalitycomparable}--\ref{tab:cpp17.destructible}. -In these tables, \tcode{T} is an object or reference type to be -supplied by a \Cpp{} program instantiating a template; +In these tables, +\begin{itemize} +\item +\tcode{T} denotes an object or reference type to be +supplied by a \Cpp{} program instantiating a template, +\item \tcode{a}, \tcode{b}, and -\tcode{c} are values of type (possibly \keyword{const}) \tcode{T}; -\tcode{s} and \tcode{t} are modifiable lvalues of type \tcode{T}; -\tcode{u} denotes an identifier; -\tcode{rv} is an rvalue of type \tcode{T}; -and \tcode{v} is an lvalue of type (possibly \keyword{const}) \tcode{T} or an rvalue of -type \tcode{const T}. +\tcode{c} denote values of type (possibly const) \tcode{T}, +\item +\tcode{s} and \tcode{t} denote modifiable lvalues of type \tcode{T}, +\item +\tcode{u} denotes an identifier, +\item +\tcode{rv} denotes an rvalue of type \tcode{T}, and +\item +\tcode{v} denotes an lvalue of type (possibly const) \tcode{T} or an +rvalue of type \tcode{const T}. +\end{itemize} \pnum In general, a default constructor is not required. Certain container class @@ -1612,7 +1814,7 @@ \topline \hdstyle{Expression} & \hdstyle{Return type} & \rhdr{Requirement} \\ \capsep \tcode{a == b} & -convertible to \tcode{bool} & +\tcode{decltype(a == b)} models \exposconceptx{boolean-testa\-ble}{boolean-testable} & \tcode{==} is an equivalence relation, that is, it has the following properties: \begin{itemize} @@ -1630,7 +1832,7 @@ \topline \hdstyle{Expression} & \hdstyle{Return type} & \hdstyle{Requirement} \\ \capsep \tcode{a < b} & -convertible to \tcode{bool} & +\tcode{decltype(a < b)} models \exposconceptx{boolean-testa\-ble}{boolean-testable} & \tcode{<} is a strict weak ordering relation\iref{alg.sorting} \\ \end{oldconcepttable} @@ -1716,7 +1918,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 @@ -1756,9 +1958,13 @@ An rvalue or lvalue \tcode{t} is \defn{swappable} if and only if \tcode{t} is swappable with any rvalue or lvalue, respectively, of type \tcode{T}. +\pnum +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. @@ -1779,7 +1985,7 @@ // for rvalues and lvalues } -// Preconditions: lvalues of \tcode{T} are swappable. +// Preconditions: \tcode{T} meets the \oldconcept{Swappable} requirements. template void lv_swap(T& t1, T& t2) { using std::swap; @@ -1814,13 +2020,11 @@ \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}, -and \oldconcept{Destructible} requirements, - -\item lvalues of type \tcode{P} are swappable\iref{swappable.requirements}, +\oldconcept{Swappable}, and \oldconcept{Destructible} requirements, \item the expressions shown in \tref{cpp17.nullablepointer} are valid and have the indicated semantics, and @@ -1831,10 +2035,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 @@ -1849,11 +2053,11 @@ \pnum In \tref{cpp17.nullablepointer}, \tcode{u} denotes an identifier, \tcode{t} denotes a non-\keyword{const} lvalue of type \tcode{P}, \tcode{a} and \tcode{b} -denote values of type (possibly \keyword{const}) \tcode{P}, and \tcode{np} denotes -a value of type (possibly \keyword{const}) \tcode{std::nullptr_t}. +denote values of type (possibly const) \tcode{P}, and \tcode{np} denotes +a value of type (possibly const) \tcode{std::nullptr_t}. \begin{oldconcepttable}{NullablePointer}{}{cpp17.nullablepointer} -{lll} +{lx{2in}l} \topline \lhdr{Expression} & \chdr{Return type} & \rhdr{Operational semantics} \\ \capsep \tcode{P u(np);}\br & @@ -1872,17 +2076,17 @@ \ensures \tcode{t == nullptr} \\ \rowsep \tcode{a != b} & - contextually convertible to \tcode{bool} & + \tcode{decltype(a != b)} models \exposconcept{boolean-testable} & \tcode{!(a == b)} \\ \rowsep \tcode{a == np} & - contextually convertible to \tcode{bool} & + \tcode{decltype(a == np)} and \tcode{decltype(np == a)} each model \exposconcept{boolean-testable} & \tcode{a == P()} \\ \tcode{np == a} & & \\ \rowsep \tcode{a != np} & - contextually convertible to \tcode{bool} & + \tcode{decltype(a != np)} and \tcode{decltype(np != a)} each model \exposconcept{boolean-testable} & \tcode{!(a == np)} \\ \tcode{np != a} & & @@ -1892,7 +2096,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 @@ -1903,9 +2107,9 @@ \pnum Given \tcode{Key} is an argument type for function objects of type \tcode{H}, in -\tref{cpp17.hash} \tcode{h} is a value of type (possibly \keyword{const}) \tcode{H}, +\tref{cpp17.hash} \tcode{h} is a value of type (possibly const) \tcode{H}, \tcode{u} is an lvalue of type \tcode{Key}, and \tcode{k} is a value of a type convertible to -(possibly \keyword{const}) \tcode{Key}. +(possibly const) \tcode{Key}. \begin{oldconcepttable}{Hash}{}{cpp17.hash} {llp{.55\hsize}} @@ -1940,13 +2144,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 @@ -1986,7 +2190,7 @@ \item \tcode{y} denotes a value of type \tcode{XX::const_void_pointer} obtained by conversion from a result value of \tcode{YY::allocate}, or else -a value of type (possibly \tcode{const}) \tcode{std::nullptr_t}, +a value of type (possibly const) \tcode{std::nullptr_t}, \item \tcode{n} denotes a value of type \tcode{XX::size_type}, \item @@ -2006,9 +2210,10 @@ given type or expression is specified. Within the standard library \tcode{allocator_traits} template, an optional requirement that is not supplied by an allocator is -replaced by the specified default type or expression. A user specialization of -\tcode{allocator_traits} may provide different defaults and may provide -defaults for different requirements than the primary template. +replaced by the specified default type or expression. +\begin{note} +There are no program-defined specializations of \tcode{allocator_traits}. +\end{note} \begin{itemdecl} typename X::pointer @@ -2027,11 +2232,11 @@ \begin{itemdescr} \pnum \mandates -\tcode{X::pointer} is convertible to \tcode{X::const_pointer}. +\tcode{XX::pointer} is convertible to \tcode{XX::const_pointer}. \pnum \remarks -Default: \tcode{pointer_traits::rebind} +Default: \tcode{pointer_traits::rebind} \end{itemdescr} \begin{itemdecl} @@ -2042,13 +2247,13 @@ \begin{itemdescr} \pnum \mandates -\tcode{X::pointer} is convertible to \tcode{X::void_pointer}. -\tcode{X::void_pointer} and \tcode{Y::void_pointer} are the same type. +\tcode{XX::pointer} is convertible to \tcode{XX::void_pointer}. +\tcode{XX::void_pointer} and \tcode{YY::void_pointer} are the same type. \pnum \remarks Default: -\tcode{pointer_traits::rebind} +\tcode{pointer_traits::rebind} \end{itemdescr} \begin{itemdecl} @@ -2059,15 +2264,15 @@ \begin{itemdescr} \pnum \mandates -\tcode{X::pointer}, \tcode{X::const_pointer}, and \tcode{X::void_pointer} -are convertible to \tcode{X::const_void_pointer}. -\tcode{X::const_void_pointer} and \tcode{Y::const_void_pointer} +\tcode{XX::pointer}, \tcode{XX::const_pointer}, and \tcode{XX::void_pointer} +are convertible to \tcode{XX::const_void_pointer}. +\tcode{XX::const_void_pointer} and \tcode{YY::const_void_pointer} are the same type. \pnum \remarks Default: -\tcode{pointer_traits::rebind} +\tcode{pointer_traits::rebind} \end{itemdescr} \begin{itemdecl} @@ -2093,7 +2298,7 @@ \pnum \remarks Default: -\tcode{make_unsigned_t} +\tcode{make_unsigned_t} \end{itemdescr} \begin{itemdecl} @@ -2109,11 +2314,11 @@ \pnum \remarks Default: -\tcode{pointer_traits::difference_type} +\tcode{pointer_traits::difference_type} \end{itemdescr} \begin{itemdecl} -typename X::template rebind::other +typename X::rebind::other \end{itemdecl} \begin{itemdescr} @@ -2124,7 +2329,7 @@ \pnum \ensures For all \tcode{U} (including \tcode{T}), -\tcode{Y::template rebind::other} is \tcode{X}. +\tcode{YY::rebind_alloc} is \tcode{X}. \pnum \remarks @@ -2210,41 +2415,41 @@ \end{itemdescr} \begin{itemdecl} -static_cast(w) +static_cast(w) \end{itemdecl} \begin{itemdescr} \pnum \result -\tcode{X::pointer} +\tcode{XX::pointer} \pnum \ensures -\tcode{static_cast(w) == p}. +\tcode{static_cast(w) == p}. \end{itemdescr} \begin{itemdecl} -static_cast(x) +static_cast(x) \end{itemdecl} \begin{itemdescr} \pnum \result -\tcode{X::const_pointer} +\tcode{XX::const_pointer} \pnum \ensures -\tcode{static_cast(x) == q}. +\tcode{static_cast(x) == q}. \end{itemdescr} \begin{itemdecl} -pointer_traits::pointer_to(r) +pointer_traits::pointer_to(r) \end{itemdecl} \begin{itemdescr} \pnum \result -\tcode{X::pointer} +\tcode{XX::pointer} \pnum \ensures @@ -2258,7 +2463,7 @@ \begin{itemdescr} \pnum \result -\tcode{X::pointer} +\tcode{XX::pointer} \pnum \effects @@ -2296,7 +2501,7 @@ \begin{itemdescr} \pnum \result -\tcode{X::pointer} +\tcode{XX::pointer} \pnum \effects @@ -2315,11 +2520,11 @@ \begin{itemdescr} \pnum \result -\tcode{allocation_result} +\tcode{allocation_result} \pnum \returns -\tcode{allocation_result\{ptr, count\}} +\tcode{allocation_result\{ptr, count\}} where \tcode{ptr} is memory allocated for an array of \tcode{count} \tcode{T} and such an object is created but array elements are not constructed, such that $\tcode{count} \geq \tcode{n}$. @@ -2331,10 +2536,7 @@ \pnum \remarks -An allocator need not support \tcode{allocate_at_least}, -but no default is provided in \tcode{allocator_traits}. -If an allocator has an \tcode{allocate_at_least} member, -it shall satisfy the requirements. +Default: \tcode{\{a.allocate(n), n\}}. \end{itemdescr} \begin{itemdecl} @@ -2377,11 +2579,11 @@ \begin{itemdescr} \pnum \result -\tcode{X::size_type} +\tcode{XX::size_type} \pnum \returns -The largest value that can meaningfully be passed to \tcode{X::allocate()}. +The largest value \tcode{n} that can meaningfully be passed to \tcode{a.allocate(n)}. \pnum \remarks @@ -2438,7 +2640,7 @@ \pnum \returns -\tcode{a == Y::rebind::other(b)}. +\tcode{a == YY::rebind_alloc(b)}. \end{itemdescr} \begin{itemdecl} @@ -2514,7 +2716,7 @@ \end{itemdescr} \begin{itemdecl} -a.construct(c, args) +a.construct(c, args...) \end{itemdecl} \begin{itemdescr} @@ -2626,7 +2828,7 @@ \tcode{true_type} only if an allocator of type \tcode{X} should be swapped when the client container is swapped; if so, -lvalues of type \tcode{X} shall be swappable\iref{swappable.requirements} and +\tcode{X} shall meet the \oldconcept{Swappable} requirements\iref{swappable.requirements} and the \tcode{swap} operation shall not throw exceptions. \pnum @@ -2646,7 +2848,7 @@ \pnum \returns \tcode{true_type} only if the expression \tcode{a1 == a2} is guaranteed -to be \tcode{true} for any two (possibly \tcode{const}) values +to be \tcode{true} for any two (possibly const) values \tcode{a1}, \tcode{a2} of type \tcode{X}. \pnum @@ -2657,43 +2859,43 @@ \pnum An allocator type \tcode{X} shall meet the \oldconcept{CopyConstructible} requirements (\tref{cpp17.copyconstructible}). -The \tcode{X::pointer}, \tcode{X::const_pointer}, \tcode{X::void_pointer}, and -\tcode{X::const_void_pointer} types shall meet the +The \tcode{XX::pointer}, \tcode{XX::const_pointer}, \tcode{XX::void_pointer}, and +\tcode{XX::const_void_pointer} types shall meet the \oldconcept{Nullable\-Pointer} requirements (\tref{cpp17.nullablepointer}). No constructor, comparison operator function, copy operation, move operation, or swap operation on -these pointer types shall exit via an exception. \tcode{X::pointer} and \tcode{X::const_pointer} shall also +these pointer types shall exit via an exception. \tcode{XX::pointer} and \tcode{XX::const_pointer} shall also meet the requirements for a \oldconcept{RandomAccessIterator}\iref{random.access.iterators} and -the additional requirement that, when \tcode{a} and \tcode{(a + n)} are +the additional requirement that, when \tcode{p} and \tcode{(p + n)} are dereferenceable pointer values for some integral value \tcode{n}, \begin{codeblock} -addressof(*(a + n)) == addressof(*a) + n +addressof(*(p + n)) == addressof(*p) + n \end{codeblock} is \tcode{true}. \pnum Let \tcode{x1} and \tcode{x2} denote objects of (possibly different) types -\tcode{X::void_pointer}, \tcode{X::const_void_pointer}, \tcode{X::pointer}, -or \tcode{X::const_pointer}. Then, \tcode{x1} and \tcode{x2} are +\tcode{XX::void_pointer}, \tcode{XX::const_void_pointer}, \tcode{XX::pointer}, +or \tcode{XX::const_pointer}. Then, \tcode{x1} and \tcode{x2} are \defn{equivalently-valued} pointer values, if and only if both \tcode{x1} and \tcode{x2} can be explicitly converted to the two corresponding objects \tcode{px1} and \tcode{px2} -of type \tcode{X::const_pointer}, using a sequence of \keyword{static_cast}s +of type \tcode{XX::const_pointer}, using a sequence of \keyword{static_cast}s using only these four types, and the expression \tcode{px1 == px2} evaluates to \tcode{true}. \pnum -Let \tcode{w1} and \tcode{w2} denote objects of type \tcode{X::void_pointer}. +Let \tcode{w1} and \tcode{w2} denote objects of type \tcode{XX::void_pointer}. Then for the expressions \begin{codeblock} w1 == w2 w1 != w2 \end{codeblock} either or both objects may be replaced by an equivalently-valued object of type -\tcode{X::const_void_pointer} with no change in semantics. +\tcode{XX::const_void_pointer} with no change in semantics. \pnum -Let \tcode{p1} and \tcode{p2} denote objects of type \tcode{X::pointer}. +Let \tcode{p1} and \tcode{p2} denote objects of type \tcode{XX::pointer}. Then for the expressions \begin{codeblock} p1 == p2 @@ -2705,7 +2907,7 @@ p1 - p2 \end{codeblock} either or both objects may be replaced by an equivalently-valued object of type -\tcode{X::const_pointer} with no change in semantics. +\tcode{XX::const_pointer} with no change in semantics. \pnum An allocator may constrain the types on which it can be instantiated and the @@ -2736,14 +2938,30 @@ template SimpleAllocator(const SimpleAllocator& other); - [[nodiscard]] T* allocate(std::size_t n); + T* allocate(std::size_t n); void deallocate(T* p, std::size_t n); - bool operator==(const SimpleAllocator&) const; + template bool operator==(const SimpleAllocator& rhs) const; }; \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 @@ -2786,10 +3004,11 @@ any standard library class template to namespace \tcode{std} provided that -(a) the added declaration -depends on at least one program-defined type -and -(b) the specialization meets the standard library requirements +\begin{itemize} +\item the added declaration +depends on at least one program-defined type, and + +\item the specialization meets the standard library requirements for the original template. \begin{footnote} Any @@ -2797,12 +3016,17 @@ must be prepared to work adequately with any user-supplied specialization that meets the minimum requirements of this document. \end{footnote} +\end{itemize} \pnum The behavior of a \Cpp{} program is undefined if it declares an explicit or partial specialization of any standard library variable template, except where explicitly permitted by the specification of that variable template. +\begin{note} +The requirements on an explicit or partial specialization +are stated by each variable template that grants such permission. +\end{note} \pnum The behavior of a \Cpp{} program is undefined if it declares @@ -2823,10 +3047,12 @@ A program may explicitly instantiate a class template defined in the standard library only if the declaration -(a) depends on the name of at least one program-defined type -and -(b) the instantiation meets the standard library requirements for the +\begin{itemize} +\item depends on the name of at least one program-defined type, and + +\item the instantiation meets the standard library requirements for the original template. +\end{itemize} \pnum Let \tcode{\placeholder{F}} denote @@ -2856,53 +3082,6 @@ either a standard library non-static member function\iref{member.functions} or an instantiation of a standard library member function template. -\pnum -Other than in namespace \tcode{std} -or in a namespace -within namespace \tcode{std}, -a program may provide -an overload for any library function template -designated as a \defn{customization point}, -provided that -(a) -the overload's declaration depends -on at least one user-defined type -and -(b) -the overload meets the standard library requirements -for the customization point. -\begin{footnote} -Any library customization point -must be prepared -to work adequately -with any user-defined overload -that meets the minimum requirements -of this document. -Therefore -an implementation can elect, -under the as-if rule\iref{intro.execution}, -to provide any customization point -in the form -of an instantiated function object\iref{function.objects} -even though the customization point's specification -is in the form -of a function template. -The template parameters -of each such function object -and the function parameters -and return type -of the object's \tcode{operator()} -must match those -of the corresponding customization point's specification. -\end{footnote} -\begin{note} -This permits -a (qualified or unqualified) call -to the customization point -to invoke the most appropriate overload -for the given arguments. -\end{note} - \pnum A translation unit shall not declare namespace \tcode{std} to be an inline namespace\iref{namespace.def}. @@ -2914,7 +3093,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} @@ -2954,82 +3133,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{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{declare_no_pointers} \tcode{declare_no_pointers}, -\item \indexlibraryzombie{declare_reachable} \tcode{declare_reachable}, -\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{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{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{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} @@ -3138,6 +3367,10 @@ \pnum Literal suffix identifiers\iref{over.literal} that do not start with an underscore are reserved for future standardization. +Literal suffix identifiers that contain a double underscore +\tcode{\unun} +\indextext{character!underscore}% +are reserved for use by \Cpp{} implementations. \rSec3[alt.headers]{Headers} @@ -3163,65 +3396,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} @@ -3260,8 +3441,8 @@ \end{itemize} \pnum -Calling the \tcode{set_*} and \tcode{get_*} functions shall not incur a data race. A call to -any of the \tcode{set_*} functions shall synchronize with subsequent calls to the same +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 \tcode{set_*} function and to the corresponding \tcode{get_*} function. \rSec3[res.on.functions]{Other functions} @@ -3278,7 +3459,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. @@ -3336,7 +3517,7 @@ \item If a function argument is bound to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument, -except that the argument passed to a move-assignment operator may be +except that the argument passed to a move assignment operator may be a reference to \tcode{*this}\iref{lib.types.movedfrom}. \begin{note} If the type of a parameter is a forwarding reference\iref{temp.deduct.call} @@ -3406,12 +3587,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} @@ -3525,8 +3712,8 @@ provided by an implementation. \begin{note} In particular, -an implementation is not allowed to provide -an additional declaration of that function or function template +a conforming implementation does not provide +any additional declarations of that function or function template at namespace scope. \end{note} \begin{note} @@ -3631,6 +3818,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 @@ -3692,14 +3901,13 @@ 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% \indextext{specifications!C standard library exception}% \begin{footnote} -That is, the C -library functions can all be treated as if they +That is, the C standard library functions can all be treated as if they are marked \keyword{noexcept}. This allows implementations to make performance optimizations based on the absence of exceptions at runtime. @@ -3717,7 +3925,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 @@ -3745,6 +3953,15 @@ 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 @@ -3772,7 +3989,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 e3b86f6ca1..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}, @@ -25,10 +14,12 @@ \item% Nesting levels of conditional inclusion\iref{cpp.cond} [256]. \item% -Pointer\iref{dcl.ptr}, array\iref{dcl.array}, and function\iref{dcl.fct} declarators -(in any combination) -modifying a class, arithmetic, -or incomplete type in a declaration [256]. +Pointer\iref{dcl.ptr}, +pointer-to-member\iref{dcl.mptr}, +array\iref{dcl.array}, and +function\iref{dcl.fct} +declarators (in any combination) +modifying a type in a declaration [256]. \item% Nesting levels of parenthesized expressions\iref{expr.prim.paren} within a full-expression [256]. \item% @@ -130,5 +121,7 @@ Handlers per try block\iref{except.handle} [256]. \item% Number of placeholders\iref{func.bind.place} [10]. +\item% +Number of hazard-protectable possibly-reclaimable objects\iref{saferecl.hp.general} [256]. \end{itemize} diff --git a/source/locales.tex b/source/locales.tex deleted file mode 100644 index 788abc1be0..0000000000 --- a/source/locales.tex +++ /dev/null @@ -1,4622 +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{} \\ -\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: - // types - class facet; - class id; - 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; - - // 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; - template locale combine(const locale& other) const; - - // locale operations - string name() const; - - bool operator==(const locale& other) const; - - template - bool operator()(const basic_string& s1, - const basic_string& s2) const; - - // 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 types -that iostreams templates can be instantiated for} -character types -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 -The same as \tcode{locale(std_name.c_str())}. -\end{itemdescr} - -\indexlibraryctor{locale}% -\begin{itemdecl} -locale(const locale& other, const char* std_name, category); -\end{itemdecl} - -\begin{itemdescr} -\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 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 cat); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The same as \tcode{locale(other, std_name.c_str(), cat)}. -\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 -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 -\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 -The resulting locale has a name if and only if -the first two arguments 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} - -\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) 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 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} diff --git a/source/macros.tex b/source/macros.tex index 295267bf98..ec88684fcd 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. %%-------------------------------------------------- @@ -61,9 +59,10 @@ \def\stopindexescape#1\doneindexescape{} %%-------------------------------------------------- -%% Cross references. +%% Cross-references. %%-------------------------------------------------- \newcommand{\addxref}[1]{% + \hypertarget{#1}{}% \glossary[xrefindex]{\indexescape{#1}}{(\ref{\indexescape{#1}})}% } @@ -77,12 +76,12 @@ % Set the xref label for a clause to be "Clause n", not just "n". \makeatletter -\newcommand{\customlabel}[2]{% -\@bsphack \begingroup \protected@edef \@currentlabel {\protect \M@TitleReference{#2}{\M@currentTitle}}\MNR@label{#1}\endgroup \@esphack% +\newcommand{\customlabel}[3]{% +\@bsphack \protected@write\@auxout{}{\string\newlabel{#1}{{#3}{\thepage}{}{#2.\thechapter}{}}} \@esphack% } \makeatother -\newcommand{\clauselabel}[1]{\customlabel{#1}{Clause \thechapter}} -\newcommand{\annexlabel}[1]{\customlabel{#1}{Annex \thechapter}} +\newcommand{\clauselabel}[1]{\customlabel{#1}{chapter}{Clause \thechapter}} +\newcommand{\annexlabel}[1]{\customlabel{#1}{appendix}{Annex \thechapter}} % Use prefix "Annex" in the table of contents \newcommand{\annexnumberlinebox}[2]{Annex #2\space} @@ -92,6 +91,7 @@ % defines a first-level section whose name is "Scope" and whose short % tag is intro.scope. The square brackets are mandatory. \def\Sec#1[#2]#3{% +\addxref{#2}% \ifcase#1\let\s=\chapter\let\l=\clauselabel \or\let\s=\section\let\l=\label \or\let\s=\subsection\let\l=\label @@ -99,7 +99,7 @@ \or\let\s=\paragraph\let\l=\label \or\let\s=\subparagraph\let\l=\label \fi% -\s[#3]{#3\hfill[#2]}\l{#2}\addxref{#2}% +\s[#3]{#3\hfill[#2]}\l{#2}% } % A convenience feature (mostly for the convenience of the Project @@ -118,6 +118,11 @@ \addtocounter{SectionDepth}{\value{SectionDepthBase}} \Sec{\arabic{SectionDepth}}[#2]{#3}} +%%-------------------------------------------------- +% Bibliography +%%-------------------------------------------------- +\newcommand{\supercite}[1]{\textsuperscript{\cite{#1}}} + %%-------------------------------------------------- % Indexing %%-------------------------------------------------- @@ -140,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% @@ -175,7 +180,7 @@ % This command uses the "cooked" \indeximpldef command to emit index % entries; thus they only work for simple index entries that do not contain % special indexing instructions. -\newcommand{\impldef}[1]{\indeximpldef{#1}implementation-defined} +\newcommand{\impldef}[1]{\indeximpldef{#1}imple\-men\-ta\-tion-defined} % \impldefplain passes the argument directly to the index, allowing you to % use special indexing instructions (!, @, |). \newcommand{\impldefplain}[1]{\index[impldefindex]{#1}implementation-defined} @@ -191,25 +196,37 @@ \newcommand{\idxxname}[1]{__#1@\xname{#1}} % library index entries -\newcommand{\indexlibrarymisc}[2]{\indexlibrary{\idxcode{#1}!#2}} \newcommand{\indexlibraryglobal}[1]{\indexlibrary{\idxcode{#1}}} -\newcommand{\indexlibraryctor}[1]{\indexlibrarymisc{#1}{constructor}} -\newcommand{\indexlibrarydtor}[1]{\indexlibrarymisc{#1}{destructor}} +\newcommand{\indexlibrarymisc}[2]{\indexlibrary{#1!#2}} +\newcommand{\indexlibraryctor} [1]{\indexlibrarymisc{\idxcode{#1}}{constructor}} +\newcommand{\indexlibrarydtor} [1]{\indexlibrarymisc{\idxcode{#1}}{destructor}} +\newcommand{\indexlibraryzombie}[1]{\indexlibrarymisc{\idxcode{#1}}{zombie}} % class member library index -\newcommand{\indexlibrarymemberx}[2]{\indexlibrarymisc{#1}{\idxcode{#2}}} -\newcommand{\indexlibrarymember}[2]{\indexlibrarymemberx{#1}{#2}\indexlibrarymemberx{#2}{#1}} -\newcommand{\indexlibraryzombie}[1]{\indexlibrarymisc{#1}{zombie}} +\newcommand{\indexlibraryboth}[2]{\indexlibrarymisc{#1}{#2}\indexlibrarymisc{#2}{#1}} +\newcommand{\indexlibrarymember}[2]{\indexlibraryboth{\idxcode{#1}}{\idxcode{#2}}} +\newcommand{\indexlibrarymemberexpos}[2]{\indexlibraryboth{\idxcode{#1}}{#2@\exposid{#2}}} +\newcommand{\indexlibrarymemberx}[2]{\indexlibrarymisc{\idxcode{#1}}{\idxcode{#2}}} \newcommand{\libglobal}[1]{\indexlibraryglobal{#1}#1} \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}} @@ -217,7 +234,7 @@ % General code style %%-------------------------------------------------- \newcommand{\CodeStyle}{\ttfamily} -\newcommand{\CodeStylex}[1]{\texttt{#1}} +\newcommand{\CodeStylex}[1]{\texttt{\protect\frenchspacing #1}} \definecolor{grammar-gray}{gray}{0.2} @@ -251,6 +268,13 @@ % Usage: \defnadjx{scalar}{types}{type} \newcommand{\defnadjx}[3]{\indextext{#1 #3|see{#3, #1}}\indexdefn{#3!#1}\textit{#1 #2}} +% Macros used for the grammar of std::format format specifications. +% FIXME: For now, keep the format grammar productions out of the index, since +% they conflict with the main grammar. +% Consider renaming these en masse (to fmt-* ?) to avoid this problem. +\newcommand{\fmtnontermdef}[1]{{\BnfNontermshape#1\itcorr}\textnormal{:}} +\newcommand{\fmtgrammarterm}[1]{\gterm{#1}} + %%-------------------------------------------------- %% allow line break if needed for justification %%-------------------------------------------------- @@ -265,6 +289,13 @@ \newcommand{\CppXIV}{\Cpp{} 2014} \newcommand{\CppXVII}{\Cpp{} 2017} \newcommand{\CppXX}{\Cpp{} 2020} +\newcommand{\CppXXIII}{\Cpp{} 2023} +\newcommand{\CppXXVI}{\Cpp{} 2026} +\newcommand{\IsoCUndated}{ISO/IEC 9899} +\newcommand{\IsoC}{\IsoCUndated{}:2018} +\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)}} @@ -297,11 +328,13 @@ \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}} -{\end{tail#1}\small\par} % \small\par is for C++20 post-DIS compatibility +% \small\par is for C++20 post-DIS compatibility +{\end{tail#1}\small\par\penalty -200} + } \newnoteenvironment{note}{Note \arabic{note}}{end note} @@ -331,6 +364,7 @@ \newcommand{\constraints}{\Fundesc{Constraints}} \newcommand{\mandates}{\Fundesc{Mandates}} \newcommand{\expects}{\Fundesc{Preconditions}} +\newcommand{\hardexpects}{\Fundesc{Hardened preconditions}} \newcommand{\effects}{\Fundesc{Effects}} \newcommand{\ensures}{\Fundesc{Postconditions}} \newcommand{\returns}{\Fundesc{Returns}} @@ -341,15 +375,15 @@ \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{} ISO C #1} +%% Cross-reference +\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 \ExplSyntaxOn @@ -404,6 +438,7 @@ } \newcommand{\uname}[1]{\textsc{#1}} \newcommand{\unicode}[2]{\ucode{#1} \uname{#2}} +\newcommand{\UAX}[1]{\texorpdfstring{UAX~\textsmaller[1]{\raisebox{0.35ex}{\#}}#1}{UAX \##1}} \newcommand{\NTS}[1]{\textsc{#1}} \newcommand{\ntbs}{\NTS{ntbs}} \newcommand{\ntmbs}{\NTS{ntmbs}} @@ -519,6 +554,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. @@ -554,22 +592,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}{} @@ -589,6 +611,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 %%-------------------------------------------------- @@ -603,9 +636,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 @@ -632,7 +665,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} @@ -656,7 +699,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 @@ -667,7 +715,7 @@ \end{bnfbase} } -\newenvironment{bnf} +\newenvironment{ncbnf} { \begin{bnfbase} \begin{bnflist} @@ -679,6 +727,7 @@ \end{bnfbase} } +% The regex grammar is never copied. \newenvironment{ncrebnf} { \begin{bnfbase} @@ -692,28 +741,32 @@ \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 %%-------------------------------------------------- -% usage: \begin{importgraphic}{CAPTION}{TAG}{FILE} +% usage: \begin{importgraphic}{CAPTION}{TAG}{FILE}\end{importgraphic} +% \importexample[VERTICAL OFFESET]{FILE} +% +% The filename is relative to the source/assets directory. \newenvironment{importgraphic}[3] {% \newcommand{\cptn}{#1} \newcommand{\lbl}{#2} \begin{figure}[htp]\centering% -\includegraphics[scale=.35]{#3} +\includegraphics[scale=.35]{assets/#3} } { \caption{\cptn \quad [fig:\lbl]}\label{fig:\lbl}% \end{figure}} +\newcommand{\importexample}[2][-0.9pt]{\raisebox{#1}{\includegraphics{assets/#2}}} + %%-------------------------------------------------- %% Definitions section for "Terms and definitions" %%-------------------------------------------------- diff --git a/source/memory.tex b/source/memory.tex index 9dc24f3078..dfa3087c95 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,30 +83,35 @@ // \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 - T* start_lifetime_as(void* p) noexcept; + T* start_lifetime_as(void* p) noexcept; // freestanding template - const T* start_lifetime_as(const void* p) noexcept; + const T* start_lifetime_as(const void* p) noexcept; // freestanding template - volatile T* start_lifetime_as(volatile void* p) noexcept; + volatile T* start_lifetime_as(volatile void* p) noexcept; // freestanding template - const volatile T* start_lifetime_as(const volatile void* p) noexcept; + const volatile T* start_lifetime_as(const volatile void* p) noexcept; // freestanding template - T* start_lifetime_as_array(void* p, size_t n) noexcept; + T* start_lifetime_as_array(void* p, size_t n) noexcept; // freestanding template - const T* start_lifetime_as_array(const void* p, size_t n) noexcept; + const T* start_lifetime_as_array(const void* p, size_t n) noexcept; // freestanding template - volatile T* start_lifetime_as_array(volatile void* p, size_t n) noexcept; + volatile T* start_lifetime_as_array(volatile void* p, size_t n) noexcept; // freestanding template - const volatile T* start_lifetime_as_array(const volatile void* p, size_t n) noexcept; + 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 { // freestanding - explicit allocator_arg_t() = default; // freestanding - }; + struct allocator_arg_t { explicit allocator_arg_t() = default; }; // freestanding inline constexpr allocator_arg_t allocator_arg{}; // freestanding // \ref{allocator.uses}, \tcode{uses_allocator} @@ -113,7 +119,7 @@ // \ref{allocator.uses.trait}, \tcode{uses_allocator} template - inline constexpr bool @\libglobal{uses_allocator_v}@ = uses_allocator::value; // freestanding + constexpr bool @\libglobal{uses_allocator_v}@ = uses_allocator::value; // freestanding // \ref{allocator.uses.construction}, uses-allocator construction template @@ -140,6 +146,9 @@ template constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding const pair&& pr) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding + P&& p) noexcept; template constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding U&& u) noexcept; @@ -152,16 +161,12 @@ // \ref{allocator.traits}, allocator traits template struct allocator_traits; // freestanding - template + template struct allocation_result { // freestanding Pointer ptr; - size_t count; + SizeType count; }; - template - [[nodiscard]] constexpr allocation_result::pointer> - allocate_at_least(Allocator& a, size_t n); // freestanding - // \ref{default.allocator}, the default allocator template class allocator; template @@ -187,76 +192,83 @@ concept @\exposconcept{nothrow-forward-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 - 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 - 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 { @@ -265,39 +277,41 @@ 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 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 - 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 @@ -305,11 +319,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); // 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 @@ -317,37 +331,40 @@ 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 - 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); } // \ref{specialized.construct}, \tcode{construct_at} @@ -366,14 +383,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> @@ -551,6 +569,12 @@ // \ref{util.smartptr.ownerless}, class template \tcode{owner_less} template struct owner_less; + // \ref{util.smartptr.owner.hash}, struct \tcode{owner_hash} + struct owner_hash; + + // \ref{util.smartptr.owner.equal}, struct \tcode{owner_equal} + struct owner_equal; + // \ref{util.smartptr.enab}, class template \tcode{enable_shared_from_this} template class enable_shared_from_this; @@ -566,19 +590,35 @@ // \ref{out.ptr.t}, class template \tcode{out_ptr_t} template - class out_ptr_t; + class out_ptr_t; // freestanding // \ref{out.ptr}, function template \tcode{out_ptr} template - auto out_ptr(Smart& s, Args&&... args); + auto out_ptr(Smart& s, Args&&... args); // freestanding // \ref{inout.ptr.t}, class template \tcode{inout_ptr_t} template - class inout_ptr_t; + class inout_ptr_t; // freestanding // \ref{inout.ptr}, function template \tcode{inout_ptr} template - auto inout_ptr(Smart& s, Args&&... args); + 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} @@ -594,13 +634,7 @@ \begin{codeblock} namespace std { template struct pointer_traits { - using pointer = Ptr; - using element_type = @\seebelow@; - using difference_type = @\seebelow@; - - template using rebind = @\seebelow@; - - static pointer pointer_to(@\seebelow@ r); + @\seebelow@; }; template struct pointer_traits { @@ -617,6 +651,46 @@ \rSec3[pointer.traits.types]{Member types} +\pnum +The definitions in this subclause make use of +the following exposition-only class template and concept: +\begin{codeblock} +template +struct @\exposid{ptr-traits-elem}@ // \expos +{ }; + +template requires requires { typename T::element_type; } +struct @\exposid{ptr-traits-elem}@ +{ using type = typename T::element_type; }; + +template class SomePointer, class T, class... Args> + requires (!requires { typename SomePointer::element_type; }) +struct @\exposid{ptr-traits-elem}@> +{ using type = T; }; + +template + concept @\defexposconcept{has-elem-type}@ = // \expos + requires { typename @\exposid{ptr-traits-elem}@::type; } +\end{codeblock} + +\pnum +If \tcode{Ptr} satisfies \exposconcept{has-elem-type}, +a specialization \tcode{pointer_traits} +generated from the \tcode{pointer_traits} primary template +has the following members +as well as those described in~\ref{pointer.traits.functions}; +otherwise, such a specialization has no members by any of those names. + +\indexlibrarymember{pointer}{pointer_traits}% +\begin{itemdecl} +using pointer = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Ptr}. +\end{itemdescr} + \indexlibrarymember{element_type}{pointer_traits}% \begin{itemdecl} using element_type = @\seebelow@; @@ -624,12 +698,7 @@ \begin{itemdescr} \pnum -\ctype \tcode{Ptr::element_type} if -the \grammarterm{qualified-id} \tcode{Ptr::element_type} is valid and denotes a -type\iref{temp.deduct}; otherwise, \tcode{T} if -\tcode{Ptr} is a class template instantiation of the form \tcode{SomePointer}, -where \tcode{Args} is zero or more type arguments; otherwise, the specialization is -ill-formed. +\ctype \tcode{typename \exposid{ptr-traits-elem}::type}. \end{itemdescr} \indexlibrarymember{difference_type}{pointer_traits}% @@ -697,6 +766,8 @@ \pnum Specializations of \tcode{pointer_traits} may define the member declared in this subclause to customize the behavior of the standard library. +A specialization generated from the \tcode{pointer_traits} primary template +has no member by this name. \indexlibrarymember{to_address}{pointer_traits}% \begin{itemdecl} @@ -794,7 +865,7 @@ \indexlibraryglobal{assume_aligned}% \begin{itemdecl} template - [[nodiscard]] constexpr T* assume_aligned(T* ptr); + constexpr T* assume_aligned(T* ptr); \end{itemdecl} \begin{itemdescr} @@ -804,9 +875,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 @@ -818,17 +889,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}% @@ -846,7 +939,8 @@ \begin{itemdescr} \pnum \mandates -\tcode{T} is an implicit-lifetime type\iref{basic.types.general}. +\tcode{T} is an implicit-lifetime type\iref{term.implicit.lifetime.type} +and not an incomplete type\iref{term.incomplete.type}. \pnum \expects @@ -866,7 +960,7 @@ The object representation of \placeholder{a} is the contents of the storage prior to the call to \tcode{start_lifetime_as}. The value of each created object \placeholder{o} -of trivially-copyable type \tcode{U} +of trivially copyable type\iref{term.trivially.copyable.type} \tcode{U} is determined in the same manner as for a call to \tcode{bit_cast(E)}\iref{bit.cast}, where \tcode{E} is an lvalue of type \tcode{U} denoting \placeholder{o}, @@ -895,15 +989,156 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{T} is a complete type. + \pnum \expects -\tcode{n > 0} is \tcode{true}. +\tcode{p} is suitably aligned for an array of \tcode{T} or is null. +\tcode{n <= size_t(-1) / sizeof(T)} is \tcode{true}. +If \tcode{n > 0} is \tcode{true}, +\range{(char*)p}{(char*)p + (n * sizeof(T))} denotes +a region of allocated storage that is +a subset of the region of storage +reachable through\iref{basic.compound} \tcode{p}. \pnum \effects -Equivalent to: -\tcode{return *start_lifetime_as(p);} +If \tcode{n > 0} is \tcode{true}, +equivalent to +\tcode{start_lifetime_as(p)} where \tcode{U} is the type ``array of \tcode{n} \tcode{T}''. +Otherwise, there are no effects. + +\pnum +\returns +A pointer to the first element of the created array, +if any; +otherwise, +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} @@ -1012,18 +1247,18 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is not a specialization of \tcode{pair}. +\tcode{remove_cv_t} is not a specialization of \tcode{pair}. \pnum \returns A \tcode{tuple} value determined as follows: \begin{itemize} \item - If \tcode{uses_allocator_v} is \tcode{false} and - \tcode{is_constructible_v} is \tcode{true}, + If \tcode{uses_allocator_v, Alloc>} is \tcode{false} and + \tcode{is_constructible_v} is \tcode{true}, return \tcode{forward_as_tuple(std::forward(args)...)}. \item - Otherwise, if \tcode{uses_allocator_v} is \tcode{true} and + Otherwise, if \tcode{uses_allocator_v, Alloc>} is \tcode{true} and \tcode{is_constructible_v} is \tcode{true}, return @@ -1032,7 +1267,7 @@ allocator_arg, alloc, std::forward(args)...) \end{codeblock} \item - Otherwise, if \tcode{uses_allocator_v} is \tcode{true} and + Otherwise, if \tcode{uses_allocator_v, Alloc>} is \tcode{true} and \tcode{is_constructible_v} is \tcode{true}, return \tcode{forward_as_tuple(std::forward(args)..., alloc)}. \item @@ -1053,13 +1288,17 @@ \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{T1} be \tcode{T::first_type}. +Let \tcode{T2} be \tcode{T::second_type}. + \pnum \constraints -\tcode{T} is a specialization of \tcode{pair}. +\tcode{remove_cv_t} is a specialization of \tcode{pair}. \pnum \effects -For \tcode{T} specified as \tcode{pair}, equivalent to: +Equivalent to: \begin{codeblock} return make_tuple( piecewise_construct, @@ -1083,7 +1322,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is a specialization of \tcode{pair}. +\tcode{remove_cv_t} is a specialization of \tcode{pair}. \pnum \effects @@ -1104,7 +1343,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is a specialization of \tcode{pair}. +\tcode{remove_cv_t} is a specialization of \tcode{pair}. \pnum \effects @@ -1129,7 +1368,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is a specialization of \tcode{pair}. +\tcode{remove_cv_t} is a specialization of \tcode{pair}. \pnum \effects @@ -1154,7 +1393,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is a specialization of \tcode{pair}. +\tcode{remove_cv_t} is a specialization of \tcode{pair}. \pnum \effects @@ -1166,6 +1405,28 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, P&& p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{remove_cv_t} is a specialization of \tcode{pair} and +\tcode{remove_cvref_t

} is not a specialization of \tcode{ranges::subrange}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return uses_allocator_construction_args(alloc, piecewise_construct, + forward_as_tuple(get<0>(std::forward

(p))), + forward_as_tuple(get<1>(std::forward

(p)))); +\end{codeblock} +\end{itemdescr} + \indexlibraryglobal{uses_allocator_construction_args}% \begin{itemdecl} template @@ -1182,9 +1443,15 @@ \pnum \constraints -\tcode{T} is a specialization of \tcode{pair}, and +\tcode{remove_cv_t} is a specialization of \tcode{pair}, and either: +\begin{itemize} +\item +\tcode{remove_cvref_t} is a specialization of \tcode{ranges::subrange}, or +\item +\tcode{U} does not satisfy \exposconcept{pair-like} and the expression \tcode{\exposid{FUN}(u)} is not well-formed when considered as an unevaluated operand. +\end{itemize} \pnum Let \exposid{pair-constructor} be an exposition-only class defined as follows: @@ -1264,6 +1531,9 @@ Thus, it is always possible to create a derived class from an allocator. \end{note} +If a program declares +an explicit or partial specialization of \tcode{allocator_traits}, +the program is ill-formed, no diagnostic required. \indexlibraryglobal{allocator_traits}% \begin{codeblock} @@ -1289,9 +1559,10 @@ template using rebind_alloc = @\seebelow@; template using rebind_traits = allocator_traits>; - [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n); - [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n, - const_void_pointer hint); + static constexpr 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); @@ -1458,7 +1729,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} @@ -1469,7 +1740,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} @@ -1478,6 +1749,18 @@ \tcode{a.allocate(n, hint)} if that expression is well-formed; otherwise, \tcode{a.allocate(n)}. \end{itemdescr} +\indexlibrarymember{allocate_at_least}{allocator_traits}% +\begin{itemdecl} +static constexpr allocation_result allocate_at_least(Alloc& a, size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{a.allocate_at_least(n)} if that expression is well-formed; +otherwise, \tcode{\{a.allocate(n), n\}}. +\end{itemdescr} + \indexlibrarymember{deallocate}{allocator_traits}% \begin{itemdecl} static constexpr void deallocate(Alloc& a, pointer p, size_type n); @@ -1529,7 +1812,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}% @@ -1551,19 +1834,6 @@ the template parameters, data members, and special members specified above. It has no base classes or members other than those specified. -\begin{itemdecl} -template -[[nodiscard]] constexpr allocation_result::pointer> - allocate_at_least(Allocator& a, size_t n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{a.allocate_at_least(n)} if that expression is well-formed; -otherwise, \tcode{\{a.allocate(n), n\}}. -\end{itemdescr} - \rSec2[default.allocator]{The default allocator} \rSec3[default.allocator.general]{General} @@ -1581,7 +1851,7 @@ \begin{codeblock} namespace std { template class allocator { - public: + public: using value_type = T; using size_type = size_t; using difference_type = ptrdiff_t; @@ -1593,8 +1863,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); }; } @@ -1615,7 +1885,7 @@ \indexlibrarymember{allocate}{allocator}% \begin{itemdecl} -[[nodiscard]] constexpr T* allocate(size_t n); +constexpr T* allocate(size_t n); \end{itemdecl} \begin{itemdescr} @@ -1645,7 +1915,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} @@ -1843,7 +2113,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) @@ -1994,6 +2264,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 @@ -2344,9 +2622,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 @@ -2687,7 +2969,7 @@ \indexlibrarymember{reset}{unique_ptr}% \begin{itemdecl} -constexpr template void reset(U p) noexcept; +template constexpr void reset(U p) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3139,6 +3421,11 @@ bool owner_before(const shared_ptr& b) const noexcept; template 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; + template + bool owner_equal(const weak_ptr& b) const noexcept; }; template @@ -3178,7 +3465,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 @@ -3196,10 +3483,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}% @@ -3745,14 +4032,45 @@ \returns An unspecified value such that \begin{itemize} -\item \tcode{x.owner_before(y)} defines a strict weak ordering as defined in~\ref{alg.sorting}; - -\item under the equivalence relation defined by \tcode{owner_before}, -\tcode{!a.owner_before(b) \&\& !b.owner_before(a)}, two \tcode{shared_ptr} or -\tcode{weak_ptr} instances are equivalent if and only if they share ownership or -are both empty. +\item +\tcode{owner_before(b)} defines a strict weak ordering as defined in~\ref{alg.sorting}; +\item +\tcode{!owner_before(b) \&\& !b.owner_before(*this)} is \tcode{true} +if and only if \tcode{owner_equal(b)} is \tcode{true}. \end{itemize} +\end{itemdescr} + +\indexlibrarymember{owner_hash}{shared_ptr}% +\begin{itemdecl} +size_t owner_hash() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An unspecified value such that, +for any object \tcode{x} where \tcode{owner_equal(x)} is \tcode{true}, +\tcode{owner_hash() == x.owner_hash()} is \tcode{true}. +\end{itemdescr} +\indexlibrarymember{owner_equal}{shared_ptr}% +\begin{itemdecl} +template + bool owner_equal(const shared_ptr& b) const noexcept; +template + bool owner_equal(const weak_ptr& b) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if and only if +\tcode{*this} and \tcode{b} share ownership or are both empty. +Otherwise returns \tcode{false}. + +\pnum +\remarks +\tcode{owner_equal} is an equivalence relation. \end{itemdescr} \rSec4[util.smartptr.shared.create]{Creation} @@ -3844,15 +4162,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, @@ -3863,13 +4181,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 @@ -3886,18 +4204,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 @@ -4183,7 +4503,7 @@ \pnum \returns \begin{codeblock} -compare_three_way()(a.get(), static_cast::element_type*>(nullptr). +compare_three_way()(a.get(), static_cast::element_type*>(nullptr)) \end{codeblock} \end{itemdescr} @@ -4228,7 +4548,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} @@ -4265,7 +4585,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} @@ -4294,7 +4614,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} @@ -4323,7 +4643,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} @@ -4423,6 +4743,11 @@ bool owner_before(const shared_ptr& b) const noexcept; template 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; + template + bool owner_equal(const weak_ptr& b) const noexcept; }; template @@ -4623,15 +4948,45 @@ \returns An unspecified value such that \begin{itemize} -\item \tcode{x.owner_before(y)} defines a strict weak ordering as defined in~\ref{alg.sorting}; +\item \tcode{owner_before(b)} defines a strict weak ordering as defined in~\ref{alg.sorting}; -\item under the equivalence relation defined by \tcode{owner_before}, -\tcode{!a.owner_before(b) \&\& !b.owner_before(a)}, two \tcode{shared_ptr} or -\tcode{weak_ptr} instances are equivalent if and only if they share ownership or are -both empty. +\item \tcode{!owner_before(b) \&\& !b.owner_before(*this)} is \tcode{true} +if and only if \tcode{owner_equal(b)} is \tcode{true}. \end{itemize} \end{itemdescr} +\indexlibrarymember{owner_hash}{weak_ptr}% +\begin{itemdecl} +size_t owner_hash() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An unspecified value such that, +for any object \tcode{x} where \tcode{owner_equal(x)} is \tcode{true}, +\tcode{owner_hash() == x.owner_hash()} is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{owner_equal}{weak_ptr}% +\begin{itemdecl} +template + bool owner_equal(const shared_ptr& b) const noexcept; +template + bool owner_equal(const weak_ptr& b) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if and only if +\tcode{*this} and \tcode{b} share ownership or are both empty. +Otherwise returns \tcode{false}. + +\pnum +\remarks +\tcode{owner_equal} is an equivalence relation. +\end{itemdescr} \rSec4[util.smartptr.weak.spec]{Specialized algorithms} @@ -4694,31 +5049,117 @@ \item \tcode{operator()} defines a strict weak ordering as defined in~\ref{alg.sorting}; \item -two \tcode{shared_ptr} or \tcode{weak_ptr} instances are equivalent -under the equivalence relation defined by \tcode{operator()}, -\tcode{!operator()(a, b) \&\& !operator()(b, a)}, -if and only if they share ownership or are both empty. +\tcode{!operator()(a, b) \&\& !operator()(b, a)} is \tcode{true} +if and only if \tcode{a.owner_equal(b)} is \tcode{true}. \end{itemize} \end{note} -\rSec3[util.smartptr.enab]{Class template \tcode{enable_shared_from_this}} +\rSec3[util.smartptr.owner.hash]{Struct \tcode{owner_hash}} \pnum -\indexlibraryglobal{enable_shared_from_this}% -A class \tcode{T} can inherit from \tcode{enable_shared_from_this} -to inherit the \tcode{shared_from_this} member functions that obtain -a \tcode{shared_ptr} instance pointing to \tcode{*this}. +The class \tcode{owner_hash} provides ownership-based hashing. -\pnum -\begin{example} +\indexlibraryglobal{owner_hash}% \begin{codeblock} -struct X: public enable_shared_from_this { }; +namespace std { + struct owner_hash { + template + size_t operator()(const shared_ptr&) const noexcept; -int main() { - shared_ptr p(new X); - shared_ptr q = p->shared_from_this(); - assert(p == q); - assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership + template + size_t operator()(const weak_ptr&) const noexcept; + + using is_transparent = @\unspec@; + }; +} +\end{codeblock} + +\indexlibrarymember{operator()}{owner_hash}% +\begin{itemdecl} +template + size_t operator()(const shared_ptr& x) const noexcept; +template + size_t operator()(const weak_ptr& x) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.owner_hash()}. + +\pnum +\begin{note} +For any object \tcode{y} where \tcode{x.owner_equal(y)} is \tcode{true}, +\tcode{x.owner_hash() == y.owner_hash()} is \tcode{true}. +\end{note} +\end{itemdescr} + +\rSec3[util.smartptr.owner.equal]{Struct \tcode{owner_equal}} + +\pnum +The class \tcode{owner_equal} provides +ownership-based mixed equality comparisons of shared and weak pointers. + +\indexlibraryglobal{owner_equal}% +\begin{codeblock} +namespace std { + struct owner_equal { + template + bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; + template + bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + template + bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + template + bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + + using is_transparent = @\unspec@; + }; +} +\end{codeblock} + +\indexlibrarymember{operator()}{owner_equal}% +\begin{itemdecl} +template + 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; +template + 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; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.owner_equal(y)}. + +\pnum +\begin{note} +\tcode{x.owner_equal(y)} is \tcode{true} +if and only if \tcode{x} and \tcode{y} share ownership or are both empty. +\end{note} +\end{itemdescr} + +\rSec3[util.smartptr.enab]{Class template \tcode{enable_shared_from_this}} + +\pnum +\indexlibraryglobal{enable_shared_from_this}% +A class \tcode{T} can inherit from \tcode{enable_shared_from_this} +to inherit the \tcode{shared_from_this} member functions that obtain +a \tcode{shared_ptr} instance pointing to \tcode{*this}. + +\pnum +\begin{example} +\begin{codeblock} +struct X: public enable_shared_from_this { }; + +int main() { + shared_ptr p(new X); + shared_ptr q = p->shared_from_this(); + assert(p == q); + assert(p.owner_equal(q)); // \tcode{p} and \tcode{q} share ownership } \end{codeblock} \end{example} @@ -4739,7 +5180,7 @@ weak_ptr weak_from_this() const noexcept; private: - mutable weak_ptr weak_this; // \expos + mutable weak_ptr @\exposid{weak-this}@; // \expos }; } \end{codeblock} @@ -4757,7 +5198,7 @@ \begin{itemdescr} \pnum \effects -Value-initializes \tcode{weak_this}. +Value-initializes \exposid{weak-this}. \end{itemdescr} \indexlibrarymember{operator=}{enable_shared_from_this}% @@ -4772,7 +5213,7 @@ \pnum \begin{note} -\tcode{weak_this} is not changed. +\exposid{weak-this} is not changed. \end{note} \end{itemdescr} @@ -4786,7 +5227,7 @@ \begin{itemdescr} \pnum \returns -\tcode{shared_ptr(weak_this)}. +\tcode{shared_ptr(\exposid{weak-this})}. \end{itemdescr} \indexlibraryglobal{weak_ptr}% @@ -4799,7 +5240,7 @@ \begin{itemdescr} \pnum \returns -\tcode{weak_this}. +\exposid{weak-this}. \end{itemdescr} \rSec2[util.smartptr.hash]{Smart pointer hash support} @@ -4926,6 +5367,26 @@ Initializes \tcode{s} with \tcode{smart}, \tcode{a} with \tcode{std::forward(args)...}, and value-initializes \tcode{p}. +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} +if the expression \tcode{s.reset()} is well-formed; + +\item +otherwise, +\begin{codeblock} +s = Smart(); +\end{codeblock} +if \tcode{is_constructible_v} is \tcode{true}; + +\item +otherwise, the program is ill-formed. +\end{itemize} \pnum \begin{note} @@ -5184,18 +5645,16 @@ % pretend to \item that there is real text here, but undo the vertical spacing \mbox{}\vspace{-\baselineskip}\vspace{-\parskip} \begin{codeblock} -if (p) { - apply([&](auto&&... args) { - s = Smart( static_cast(p), std::forward(args)...); }, std::move(a)); -} +apply([&](auto&&... args) { + s = Smart(static_cast(p), std::forward(args)...); }, std::move(a)); \end{codeblock} if \tcode{is_pointer_v} is \tcode{true}; \item otherwise, \begin{codeblock} +@\exposid{release-statement}@; if (p) { apply([&](auto&&... args) { - @\exposid{release-statement}@; s.reset(static_cast(p), std::forward(args)...); }, std::move(a)); } \end{codeblock} @@ -5205,9 +5664,9 @@ \item otherwise, \begin{codeblock} +@\exposid{release-statement}@; if (p) { apply([&](auto&&... args) { - @\exposid{release-statement}@; s = Smart(static_cast(p), std::forward(args)...); }, std::move(a)); } \end{codeblock} @@ -5291,205 +5750,1757 @@ \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.asgn}, 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} -\rSec3[mem.res.public]{Public member functions} +\pnum +The following element applies to all functions in~\ref{indirect.ctor}: -\indexlibrarydtor{memory_resource}% +\begin{itemdescr} +\pnum +\throws +Nothing unless \tcode{allocator_traits::allocate} or +\tcode{allocator_traits::construct} throws. +\end{itemdescr} + +\indexlibraryctor{indirect}% \begin{itemdecl} -~memory_resource(); +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 -Destroys this \tcode{memory_resource}. +Constructs an owned object of type \tcode{T} with an empty argument list, +using the allocator \exposid{alloc}. \end{itemdescr} -\indexlibrarymember{allocate}{memory_resource}% +\indexlibraryctor{indirect}% \begin{itemdecl} -[[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align); +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 -Allocates storage by calling \tcode{do_allocate(bytes, alignment)} and -implicitly creates objects within the allocated region of storage. +\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 -\returns -A pointer to a suitable created object\iref{intro.object} -in the allocated region of storage. +\mandates +\tcode{is_copy_constructible_v} is \tcode{true}. \pnum -\throws -What and when the call to \tcode{do_allocate} throws. +\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} -\indexlibrarymember{deallocate}{memory_resource}% +\indexlibraryctor{indirect}% \begin{itemdecl} -void deallocate(void* p, size_t bytes, size_t alignment = max_align); +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 -Equivalent to \tcode{do_deallocate(p, bytes, alignment)}. +\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} -\indexlibrarymember{is_equal}{memory_resource}% +\indexlibraryctor{indirect}% \begin{itemdecl} -bool is_equal(const memory_resource& other) const noexcept; +constexpr indirect(indirect&& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return do_is_equal(other);} -\end{itemdescr} +\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} -\rSec3[mem.res.private]{Private virtual member functions} - -\indexlibrarymember{do_allocate}{memory_resource}% +\indexlibraryctor{indirect}% \begin{itemdecl} -virtual void* do_allocate(size_t bytes, size_t alignment) = 0; +constexpr indirect(allocator_arg_t, const Allocator& a, indirect&& other) + noexcept(allocator_traits::is_always_equal::value); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{alignment} is a power of two. +\mandates +If \tcode{allocator_traits::is_always_equal::value} is \tcode{false} +then \tcode{T} is a complete type. \pnum -\returns -A derived class shall implement this function to -return a pointer to allocated storage\iref{basic.stc.dynamic.allocation} -with a size of at least \tcode{bytes}, -aligned to the specified \tcode{alignment}. +\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 -\throws -A derived class implementation shall throw an appropriate exception if it is unable to allocate memory with the requested size and alignment. +\ensures +\tcode{other} is valueless. \end{itemdescr} -\indexlibrarymember{do_deallocate}{memory_resource}% +\indexlibraryctor{indirect}% \begin{itemdecl} -virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; +template + constexpr explicit indirect(U&& u); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{p} was returned from a prior call to \tcode{allocate(bytes, alignment)} -on a memory resource equal to \tcode{*this}, -and the storage at \tcode{p} has not yet been deallocated. +\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 -A derived class shall implement this function to dispose of allocated storage. - -\pnum -\throws -Nothing. +Constructs an owned object of type \tcode{T} with \tcode{std::forward(u)}, +using the allocator \exposid{alloc}. \end{itemdescr} -\indexlibrarymember{do_is_equal}{memory_resource}% +\indexlibraryctor{indirect}% \begin{itemdecl} -virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; +template + constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u); \end{itemdecl} \begin{itemdescr} \pnum -\returns -A derived class shall implement this function to return \tcode{true} if memory allocated from \keyword{this} can be deallocated from \tcode{other} and vice-versa, -otherwise \tcode{false}. -\begin{note} -It is possible that the most-derived type of \tcode{other} does not match the type of \keyword{this}. -For a derived class \tcode{D}, an implementation of this function -can immediately return \tcode{false} -if \tcode{dynamic_cast(\&other) == nullptr}. -\end{note} -\end{itemdescr} +\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} -\rSec3[mem.res.eq]{Equality} +\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} -\indexlibrarymember{operator==}{memory_resource}% +\indexlibraryctor{indirect}% \begin{itemdecl} -bool operator==(const memory_resource& a, const memory_resource& b) noexcept; +template + constexpr explicit indirect(in_place_t, Us&&... us); \end{itemdecl} \begin{itemdescr} \pnum -\returns +\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.asgn]{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 contained value +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.asgn}, 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{U} 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{U} 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.asgn]{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} + + +\rSec3[mem.res.public]{Public member functions} + +\indexlibrarydtor{memory_resource}% +\begin{itemdecl} +~memory_resource(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Destroys this \tcode{memory_resource}. +\end{itemdescr} + +\indexlibrarymember{allocate}{memory_resource}% +\begin{itemdecl} +void* allocate(size_t bytes, size_t alignment = max_align); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Allocates storage by calling \tcode{do_allocate(bytes, alignment)} and +implicitly creates objects within the allocated region of storage. + +\pnum +\returns +A pointer to a suitable created object\iref{intro.object} +in the allocated region of storage. + +\pnum +\throws +What and when the call to \tcode{do_allocate} throws. +\end{itemdescr} + +\indexlibrarymember{deallocate}{memory_resource}% +\begin{itemdecl} +void deallocate(void* p, size_t bytes, size_t alignment = max_align); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{do_deallocate(p, bytes, alignment)}. +\end{itemdescr} + +\indexlibrarymember{is_equal}{memory_resource}% +\begin{itemdecl} +bool is_equal(const memory_resource& other) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return do_is_equal(other);} +\end{itemdescr} + + +\rSec3[mem.res.private]{Private virtual member functions} + +\indexlibrarymember{do_allocate}{memory_resource}% +\begin{itemdecl} +virtual void* do_allocate(size_t bytes, size_t alignment) = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{alignment} is a power of two. + +\pnum +\returns +A derived class shall implement this function to +return a pointer to allocated storage\iref{basic.stc.dynamic.allocation} +with a size of at least \tcode{bytes}, +aligned to the specified \tcode{alignment}. + +\pnum +\throws +A derived class implementation shall throw an appropriate exception if it is unable to allocate memory with the requested size and alignment. +\end{itemdescr} + +\indexlibrarymember{do_deallocate}{memory_resource}% +\begin{itemdecl} +virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{p} was returned from a prior call to \tcode{allocate(bytes, alignment)} +on a memory resource equal to \tcode{*this}, +and the storage at \tcode{p} has not yet been deallocated. + +\pnum +\effects +A derived class shall implement this function to dispose of allocated storage. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{do_is_equal}{memory_resource}% +\begin{itemdecl} +virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A derived class shall implement this function to return \tcode{true} if memory allocated from \tcode{*this} can be deallocated from \tcode{other} and vice-versa, +otherwise \tcode{false}. +\begin{note} +It is possible that the most-derived type of \tcode{other} does not match the type of \tcode{*this}. +For a derived class \tcode{D}, an implementation of this function +can immediately return \tcode{false} +if \tcode{dynamic_cast(\&other) == nullptr}. +\end{note} +\end{itemdescr} + +\rSec3[mem.res.eq]{Equality} + +\indexlibrarymember{operator==}{memory_resource}% +\begin{itemdecl} +bool operator==(const memory_resource& a, const memory_resource& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns \tcode{\&a == \&b || a.is_equal(b)}. \end{itemdescr} @@ -5535,19 +7546,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; @@ -5614,7 +7628,7 @@ \indexlibrarymember{allocate}{polymorphic_allocator}% \begin{itemdecl} -[[nodiscard]] Tp* allocate(size_t n); +Tp* allocate(size_t n); \end{itemdecl} \begin{itemdescr} @@ -5651,7 +7665,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} @@ -5682,7 +7696,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} @@ -5722,7 +7736,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} @@ -5758,7 +7772,7 @@ \effects Equivalent to: \begin{codeblock} -allocator_traits::destroy(*this, p); +destroy(p); deallocate_object(p); \end{codeblock} \end{itemdescr} @@ -5788,6 +7802,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; @@ -6043,7 +8069,7 @@ is greater than an \impldef{largest supported value to configure the maximum number of blocks to replenish a pool} limit, that limit is used instead. The implementation -may choose to use a smaller value than is specified in this field and +may choose to use a smaller value than is specified in this member and may use different values for different pools. \end{itemdescr} @@ -6062,7 +8088,7 @@ is greater than an \impldef{largest supported value to configure the largest allocation satisfied directly by a pool} limit, that limit is used instead. The implementation may choose a pass-through threshold -larger than specified in this field. +larger than specified in this member. \end{itemdescr} \rSec3[mem.res.pool.ctor]{Constructors and destructors} @@ -6342,8 +8368,8 @@ \pnum \begin{note} The memory is released back to \tcode{upstream_rsrc} -even if some blocks that were allocated from \keyword{this} -have not been deallocated from \keyword{this}. +even if some blocks that were allocated from \tcode{*this} +have not been deallocated from \tcode{*this}. \end{note} \end{itemdescr} @@ -6523,8 +8549,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; @@ -6756,7 +8782,7 @@ \indexlibrarymember{allocate}{scoped_allocator_adaptor}% \begin{itemdecl} -[[nodiscard]] pointer allocate(size_type n); +pointer allocate(size_type n); \end{itemdecl} \begin{itemdescr} @@ -6767,7 +8793,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 11f69c16e7..95d2635ed3 100644 --- a/source/meta.tex +++ b/source/meta.tex @@ -15,7 +15,7 @@ \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 +59,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 +138,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 +160,9 @@ 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{meta.unary.cat}, primary type categories template struct is_void; @@ -192,8 +192,9 @@ // \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; @@ -244,6 +245,9 @@ template struct is_nothrow_swappable; template struct is_nothrow_destructible; + template struct is_nothrow_relocatable; + + template struct is_implicit_lifetime; template struct has_virtual_destructor; @@ -260,6 +264,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; @@ -352,10 +357,10 @@ using @\libglobal{remove_cvref_t}@ = typename remove_cvref::type; template using @\libglobal{decay_t}@ = typename decay::type; - template - using @\libglobal{enable_if_t}@ = typename enable_if::type; - template - using @\libglobal{conditional_t}@ = typename conditional::type; + template + using @\libglobal{enable_if_t}@ = typename enable_if::type; + template + using @\libglobal{conditional_t}@ = typename conditional::type; template using @\libglobal{common_type_t}@ = typename common_type::type; template @@ -378,198 +383,206 @@ // \ref{meta.unary.cat}, primary type categories template - inline constexpr bool @\libglobal{is_void_v}@ = is_void::value; + constexpr bool @\libglobal{is_void_v}@ = is_void::value; template - inline constexpr bool @\libglobal{is_null_pointer_v}@ = is_null_pointer::value; + constexpr bool @\libglobal{is_null_pointer_v}@ = is_null_pointer::value; template - inline constexpr bool @\libglobal{is_integral_v}@ = is_integral::value; + constexpr bool @\libglobal{is_integral_v}@ = is_integral::value; template - inline constexpr bool @\libglobal{is_floating_point_v}@ = is_floating_point::value; + constexpr bool @\libglobal{is_floating_point_v}@ = is_floating_point::value; template - inline constexpr bool @\libglobal{is_array_v}@ = is_array::value; + constexpr bool @\libglobal{is_array_v}@ = is_array::value; template - inline constexpr bool @\libglobal{is_pointer_v}@ = is_pointer::value; + constexpr bool @\libglobal{is_pointer_v}@ = is_pointer::value; template - inline constexpr bool @\libglobal{is_lvalue_reference_v}@ = is_lvalue_reference::value; + constexpr bool @\libglobal{is_lvalue_reference_v}@ = is_lvalue_reference::value; template - inline constexpr bool @\libglobal{is_rvalue_reference_v}@ = is_rvalue_reference::value; + constexpr bool @\libglobal{is_rvalue_reference_v}@ = is_rvalue_reference::value; template - inline constexpr bool @\libglobal{is_member_object_pointer_v}@ = is_member_object_pointer::value; + constexpr bool @\libglobal{is_member_object_pointer_v}@ = is_member_object_pointer::value; template - inline constexpr bool @\libglobal{is_member_function_pointer_v}@ = is_member_function_pointer::value; + constexpr bool @\libglobal{is_member_function_pointer_v}@ = is_member_function_pointer::value; template - inline constexpr bool @\libglobal{is_enum_v}@ = is_enum::value; + constexpr bool @\libglobal{is_enum_v}@ = is_enum::value; template - inline constexpr bool @\libglobal{is_union_v}@ = is_union::value; + constexpr bool @\libglobal{is_union_v}@ = is_union::value; template - inline constexpr bool @\libglobal{is_class_v}@ = is_class::value; + constexpr bool @\libglobal{is_class_v}@ = is_class::value; template - inline constexpr bool @\libglobal{is_function_v}@ = is_function::value; + constexpr bool @\libglobal{is_function_v}@ = is_function::value; // \ref{meta.unary.comp}, composite type categories template - inline constexpr bool @\libglobal{is_reference_v}@ = is_reference::value; + constexpr bool @\libglobal{is_reference_v}@ = is_reference::value; template - inline constexpr bool @\libglobal{is_arithmetic_v}@ = is_arithmetic::value; + constexpr bool @\libglobal{is_arithmetic_v}@ = is_arithmetic::value; template - inline constexpr bool @\libglobal{is_fundamental_v}@ = is_fundamental::value; + constexpr bool @\libglobal{is_fundamental_v}@ = is_fundamental::value; template - inline constexpr bool @\libglobal{is_object_v}@ = is_object::value; + constexpr bool @\libglobal{is_object_v}@ = is_object::value; template - inline constexpr bool @\libglobal{is_scalar_v}@ = is_scalar::value; + constexpr bool @\libglobal{is_scalar_v}@ = is_scalar::value; template - inline constexpr bool @\libglobal{is_compound_v}@ = is_compound::value; + constexpr bool @\libglobal{is_compound_v}@ = is_compound::value; template - inline constexpr bool @\libglobal{is_member_pointer_v}@ = is_member_pointer::value; + constexpr bool @\libglobal{is_member_pointer_v}@ = is_member_pointer::value; // \ref{meta.unary.prop}, type properties template - inline constexpr bool @\libglobal{is_const_v}@ = is_const::value; + constexpr bool @\libglobal{is_const_v}@ = is_const::value; template - inline constexpr bool @\libglobal{is_volatile_v}@ = is_volatile::value; + constexpr bool @\libglobal{is_volatile_v}@ = is_volatile::value; template - inline constexpr bool @\libglobal{is_trivial_v}@ = is_trivial::value; + constexpr bool @\libglobal{is_trivially_copyable_v}@ = is_trivially_copyable::value; template - inline constexpr bool @\libglobal{is_trivially_copyable_v}@ = is_trivially_copyable::value; + constexpr bool @\libglobal{is_trivially_relocatable_v}@ = is_trivially_relocatable::value; template - inline constexpr bool @\libglobal{is_standard_layout_v}@ = is_standard_layout::value; + constexpr bool @\libglobal{is_standard_layout_v}@ = is_standard_layout::value; template - inline constexpr bool @\libglobal{is_empty_v}@ = is_empty::value; + constexpr bool @\libglobal{is_empty_v}@ = is_empty::value; template - inline constexpr bool @\libglobal{is_polymorphic_v}@ = is_polymorphic::value; + constexpr bool @\libglobal{is_polymorphic_v}@ = is_polymorphic::value; template - inline constexpr bool @\libglobal{is_abstract_v}@ = is_abstract::value; + constexpr bool @\libglobal{is_abstract_v}@ = is_abstract::value; template - inline constexpr bool @\libglobal{is_final_v}@ = is_final::value; + constexpr bool @\libglobal{is_final_v}@ = is_final::value; template - inline constexpr bool @\libglobal{is_aggregate_v}@ = is_aggregate::value; + constexpr bool @\libglobal{is_aggregate_v}@ = is_aggregate::value; template - inline constexpr bool @\libglobal{is_signed_v}@ = is_signed::value; + constexpr bool @\libglobal{is_signed_v}@ = is_signed::value; template - inline constexpr bool @\libglobal{is_unsigned_v}@ = is_unsigned::value; + constexpr bool @\libglobal{is_unsigned_v}@ = is_unsigned::value; template - inline constexpr bool @\libglobal{is_bounded_array_v}@ = is_bounded_array::value; + constexpr bool @\libglobal{is_bounded_array_v}@ = is_bounded_array::value; template - inline constexpr bool @\libglobal{is_unbounded_array_v}@ = is_unbounded_array::value; + constexpr bool @\libglobal{is_unbounded_array_v}@ = is_unbounded_array::value; template - inline constexpr bool @\libglobal{is_scoped_enum_v}@ = is_scoped_enum::value; + constexpr bool @\libglobal{is_scoped_enum_v}@ = is_scoped_enum::value; template - inline constexpr bool @\libglobal{is_constructible_v}@ = is_constructible::value; + constexpr bool @\libglobal{is_constructible_v}@ = is_constructible::value; template - inline constexpr bool @\libglobal{is_default_constructible_v}@ = is_default_constructible::value; + constexpr bool @\libglobal{is_default_constructible_v}@ = is_default_constructible::value; template - inline constexpr bool @\libglobal{is_copy_constructible_v}@ = is_copy_constructible::value; + constexpr bool @\libglobal{is_copy_constructible_v}@ = is_copy_constructible::value; template - inline constexpr bool @\libglobal{is_move_constructible_v}@ = is_move_constructible::value; + constexpr bool @\libglobal{is_move_constructible_v}@ = is_move_constructible::value; template - inline constexpr bool @\libglobal{is_assignable_v}@ = is_assignable::value; + constexpr bool @\libglobal{is_assignable_v}@ = is_assignable::value; template - inline constexpr bool @\libglobal{is_copy_assignable_v}@ = is_copy_assignable::value; + constexpr bool @\libglobal{is_copy_assignable_v}@ = is_copy_assignable::value; template - inline constexpr bool @\libglobal{is_move_assignable_v}@ = is_move_assignable::value; + constexpr bool @\libglobal{is_move_assignable_v}@ = is_move_assignable::value; template - inline constexpr bool @\libglobal{is_swappable_with_v}@ = is_swappable_with::value; + constexpr bool @\libglobal{is_swappable_with_v}@ = is_swappable_with::value; template - inline constexpr bool @\libglobal{is_swappable_v}@ = is_swappable::value; + constexpr bool @\libglobal{is_swappable_v}@ = is_swappable::value; template - inline constexpr bool @\libglobal{is_destructible_v}@ = is_destructible::value; + constexpr bool @\libglobal{is_destructible_v}@ = is_destructible::value; template - inline constexpr bool is_trivially_constructible_v + constexpr bool is_trivially_constructible_v = is_trivially_constructible::value; template - inline constexpr bool is_trivially_default_constructible_v + constexpr bool is_trivially_default_constructible_v = is_trivially_default_constructible::value; template - inline constexpr bool is_trivially_copy_constructible_v + constexpr bool is_trivially_copy_constructible_v = is_trivially_copy_constructible::value; template - inline constexpr bool is_trivially_move_constructible_v + constexpr bool is_trivially_move_constructible_v = is_trivially_move_constructible::value; template - inline constexpr bool @\libglobal{is_trivially_assignable_v}@ = is_trivially_assignable::value; + constexpr bool @\libglobal{is_trivially_assignable_v}@ = is_trivially_assignable::value; template - inline constexpr bool is_trivially_copy_assignable_v + constexpr bool is_trivially_copy_assignable_v = is_trivially_copy_assignable::value; template - inline constexpr bool is_trivially_move_assignable_v + constexpr bool is_trivially_move_assignable_v = is_trivially_move_assignable::value; template - inline constexpr bool @\libglobal{is_trivially_destructible_v}@ = is_trivially_destructible::value; + constexpr bool @\libglobal{is_trivially_destructible_v}@ = is_trivially_destructible::value; template - inline constexpr bool is_nothrow_constructible_v + constexpr bool is_nothrow_constructible_v = is_nothrow_constructible::value; template - inline constexpr bool is_nothrow_default_constructible_v + constexpr bool is_nothrow_default_constructible_v = is_nothrow_default_constructible::value; template - inline constexpr bool is_nothrow_copy_constructible_v + constexpr bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible::value; template - inline constexpr bool is_nothrow_move_constructible_v + constexpr bool is_nothrow_move_constructible_v = is_nothrow_move_constructible::value; template - inline constexpr bool @\libglobal{is_nothrow_assignable_v}@ = is_nothrow_assignable::value; + constexpr bool @\libglobal{is_nothrow_assignable_v}@ = is_nothrow_assignable::value; template - inline constexpr bool @\libglobal{is_nothrow_copy_assignable_v}@ = is_nothrow_copy_assignable::value; + constexpr bool @\libglobal{is_nothrow_copy_assignable_v}@ = is_nothrow_copy_assignable::value; template - inline constexpr bool @\libglobal{is_nothrow_move_assignable_v}@ = is_nothrow_move_assignable::value; + constexpr bool @\libglobal{is_nothrow_move_assignable_v}@ = is_nothrow_move_assignable::value; template - inline constexpr bool @\libglobal{is_nothrow_swappable_with_v}@ = is_nothrow_swappable_with::value; + constexpr bool @\libglobal{is_nothrow_swappable_with_v}@ = is_nothrow_swappable_with::value; + template + constexpr bool @\libglobal{is_nothrow_swappable_v}@ = is_nothrow_swappable::value; + template + constexpr bool @\libglobal{is_nothrow_destructible_v}@ = is_nothrow_destructible::value; template - inline constexpr bool @\libglobal{is_nothrow_swappable_v}@ = is_nothrow_swappable::value; + constexpr bool @\libglobal{is_nothrow_relocatable_v}@ = is_nothrow_relocatable::value; template - inline constexpr bool @\libglobal{is_nothrow_destructible_v}@ = is_nothrow_destructible::value; + constexpr bool @\libglobal{is_implicit_lifetime_v}@ = is_implicit_lifetime::value; template - inline constexpr bool @\libglobal{has_virtual_destructor_v}@ = has_virtual_destructor::value; + constexpr bool @\libglobal{is_replaceable_v}@ = is_replaceable::value; template - inline constexpr bool has_unique_object_representations_v + constexpr bool @\libglobal{has_virtual_destructor_v}@ = has_virtual_destructor::value; + template + constexpr bool has_unique_object_representations_v = has_unique_object_representations::value; template - inline constexpr bool @\libglobal{reference_constructs_from_temporary_v}@ + constexpr bool @\libglobal{reference_constructs_from_temporary_v}@ = reference_constructs_from_temporary::value; template - inline constexpr bool @\libglobal{reference_converts_from_temporary_v}@ + constexpr bool @\libglobal{reference_converts_from_temporary_v}@ = reference_converts_from_temporary::value; // \ref{meta.unary.prop.query}, type property queries template - inline constexpr size_t @\libglobal{alignment_of_v}@ = alignment_of::value; + constexpr size_t @\libglobal{alignment_of_v}@ = alignment_of::value; template - inline constexpr size_t @\libglobal{rank_v}@ = rank::value; + constexpr size_t @\libglobal{rank_v}@ = rank::value; template - inline constexpr size_t @\libglobal{extent_v}@ = extent::value; + constexpr size_t @\libglobal{extent_v}@ = extent::value; // \ref{meta.rel}, type relations template - inline constexpr bool @\libglobal{is_same_v}@ = is_same::value; + constexpr bool @\libglobal{is_same_v}@ = is_same::value; + template + constexpr bool @\libglobal{is_base_of_v}@ = is_base_of::value; template - inline constexpr bool @\libglobal{is_base_of_v}@ = is_base_of::value; + constexpr bool @\libglobal{is_virtual_base_of_v}@ = is_virtual_base_of::value; template - inline constexpr bool @\libglobal{is_convertible_v}@ = is_convertible::value; + constexpr bool @\libglobal{is_convertible_v}@ = is_convertible::value; template - inline constexpr bool @\libglobal{is_nothrow_convertible_v}@ = is_nothrow_convertible::value; + constexpr bool @\libglobal{is_nothrow_convertible_v}@ = is_nothrow_convertible::value; template - inline constexpr bool @\libglobal{is_layout_compatible_v}@ = is_layout_compatible::value; + constexpr bool @\libglobal{is_layout_compatible_v}@ = is_layout_compatible::value; template - inline constexpr bool is_pointer_interconvertible_base_of_v + constexpr bool is_pointer_interconvertible_base_of_v = is_pointer_interconvertible_base_of::value; template - inline constexpr bool @\libglobal{is_invocable_v}@ = is_invocable::value; + constexpr bool @\libglobal{is_invocable_v}@ = is_invocable::value; template - inline constexpr bool @\libglobal{is_invocable_r_v}@ = is_invocable_r::value; + constexpr bool @\libglobal{is_invocable_r_v}@ = is_invocable_r::value; template - inline constexpr bool @\libglobal{is_nothrow_invocable_v}@ = is_nothrow_invocable::value; + constexpr bool @\libglobal{is_nothrow_invocable_v}@ = is_nothrow_invocable::value; template - inline constexpr bool is_nothrow_invocable_r_v + constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r::value; // \ref{meta.logical}, logical operator traits template - inline constexpr bool @\libglobal{conjunction_v}@ = conjunction::value; + constexpr bool @\libglobal{conjunction_v}@ = conjunction::value; template - inline constexpr bool @\libglobal{disjunction_v}@ = disjunction::value; + constexpr bool @\libglobal{disjunction_v}@ = disjunction::value; template - inline constexpr bool @\libglobal{negation_v}@ = negation::value; + constexpr bool @\libglobal{negation_v}@ = negation::value; // \ref{meta.member}, member relationships template @@ -579,6 +592,7 @@ // \ref{meta.const.eval}, constant evaluation context constexpr bool is_constant_evaluated() noexcept; + consteval bool is_within_lifetime(const auto*) noexcept; } \end{codeblock} @@ -587,7 +601,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; @@ -599,7 +613,6 @@ } \end{codeblock} -\indexlibraryglobal{integral_constant}% \indexlibraryglobal{bool_constant}% \indexlibraryglobal{true_type}% \indexlibraryglobal{false_type}% @@ -629,7 +642,8 @@ \rSec3[meta.unary.cat]{Primary type categories} \pnum -The primary type categories correspond to the descriptions given in +The primary type categories specified in \tref{meta.unary.cat} +correspond to the descriptions given in subclause~\ref{basic.types} of the \Cpp{} standard. \pnum @@ -715,8 +729,9 @@ \rSec3[meta.unary.comp]{Composite type traits} \pnum -These templates provide convenient compositions of the primary type -categories, corresponding to the descriptions given in subclause~\ref{basic.types}. +The templates specified in \tref{meta.unary.comp} +provide convenient compositions of the primary type categories, +corresponding to the descriptions given in subclause~\ref{basic.types}. \pnum For any given type \tcode{T}, the result of applying one of these templates to @@ -763,8 +778,8 @@ \rSec3[meta.unary.prop]{Type properties} \pnum -These templates provide access to some of the more important -properties of types. +The templates specified in \tref{meta.unary.prop} +provide access to some of the more important properties of types. \pnum It is unspecified whether the library defines any full or partial @@ -823,13 +838,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;} & @@ -837,6 +845,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;} & @@ -868,7 +890,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 @@ -881,7 +903,7 @@ \tcode{template}\br \tcode{struct is_aggregate;} & \tcode{T} is an aggregate type\iref{dcl.init.aggr} & - \tcode{remove_all_extents_t} shall be a complete type or \cv~\keyword{void}. \\ \rowsep + \tcode{T} shall be an array type, a complete type, or \cv~\keyword{void}. \\ \rowsep \indexlibrary{\idxcode{is_signed}!class}% \tcode{template}\br @@ -1199,6 +1221,23 @@ \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;} & + \tcode{T} is an implicit-lifetime type\iref{term.implicit.lifetime.type}. & + \tcode{T} shall be an array type, + a complete type, or \cv{}~\keyword{void}. \\ \rowsep + \indexlibraryglobal{has_virtual_destructor}% \tcode{template}\br \tcode{struct has_virtual_destructor;} & @@ -1211,25 +1250,52 @@ 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 \tcode{struct reference_constructs_from_temporary;} & - \tcode{conjunction_v, is_constructible>} - is \tcode{true}, and - the initialization \tcode{T t(\exposidnc{VAL});} binds \tcode{t} to - a temporary object whose lifetime is extended\iref{class.temporary}. & + \tcode{T} is a reference type, and + the initialization \tcode{T t(\exposidnc{VAL});} is + well-formed and binds \tcode{t} to + a temporary object whose lifetime is extended\iref{class.temporary}. + Access checking is performed as if in + a context unrelated to \tcode{T} and \tcode{U}. + Only the validity of the immediate context of + the variable initialization is considered. + \begin{tailnote} + The initialization can result in effects such as + the instantiation of class template specializations and + function template specializations, + the generation of implicitly-defined functions, and so on. + Such effects are not in the ``immediate context'' and + can result in the program being ill-formed. + \end{tailnote} +& \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep \indexlibraryglobal{reference_converts_from_temporary}% \tcode{template}\br \tcode{struct reference_converts_from_temporary;} & - \tcode{conjunction_v, is_convertible>} is \tcode{true}, - and the initialization \tcode{T t = \exposidnc{VAL};} binds \tcode{t} to - a temporary object whose lifetime is extended\iref{class.temporary}. & + \tcode{T} is a reference type, and + the initialization \tcode{T t = \exposidnc{VAL};} + is well-formed and binds \tcode{t} to + a temporary object whose lifetime is extended\iref{class.temporary}. + Access checking is performed as if in + a context unrelated to \tcode{T} and \tcode{U}. + Only the validity of the immediate context of + the variable initialization is considered. + \begin{tailnote} + The initialization can result in effects such as + the instantiation of class template specializations and + function template specializations, + the generation of implicitly-defined functions, and so on. + Such effects are not in the ``immediate context'' and + can result in the program being ill-formed. + \end{tailnote} +& \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep @@ -1300,16 +1366,18 @@ \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 have the same object representation, where -two objects of array or non-union class type are considered to have the same value +\begin{itemize} +\item two objects of array or non-union class type are considered to have the same value if their respective sequences of direct subobjects have the same values, and -two objects of union type are considered to have the same value +\item two objects of union type are considered to have the same value if they have the same active member and the corresponding members have the same value. \end{itemize} +\end{itemize} The set of scalar types for which this condition holds is \impldef{which scalar types have unique object representations}. \begin{note} @@ -1320,8 +1388,8 @@ \rSec2[meta.unary.prop.query]{Type property queries} \pnum -This subclause contains templates that may be used to query -properties of types at compile time. +The templates specified in \tref{meta.unary.prop.query} +may be used to query properties of types at compile time. \begin{libreqtab2a}{Type property queries}{meta.unary.prop.query} \\ \topline @@ -1364,9 +1432,9 @@ \begin{example} \begin{codeblock} // the following assertions hold: -assert(rank_v == 0); -assert(rank_v == 1); -assert(rank_v == 2); +static_assert(rank_v == 0); +static_assert(rank_v == 1); +static_assert(rank_v == 2); \end{codeblock} \end{example} @@ -1374,22 +1442,22 @@ \begin{example} \begin{codeblock} // the following assertions hold: -assert(extent_v == 0); -assert(extent_v == 2); -assert(extent_v == 2); -assert(extent_v == 0); -assert((extent_v) == 0); -assert((extent_v) == 0); -assert((extent_v) == 4); -assert((extent_v) == 4); +static_assert(extent_v == 0); +static_assert(extent_v == 2); +static_assert(extent_v == 2); +static_assert(extent_v == 0); +static_assert(extent_v == 0); +static_assert(extent_v == 0); +static_assert(extent_v == 4); +static_assert(extent_v == 4); \end{codeblock} \end{example} \rSec2[meta.rel]{Relationships between types} \pnum -This subclause contains templates that may be used to query -relationships between types at compile time. +The templates specified in \tref{meta.rel} +may be used to query relationships between types at compile time. \pnum Each of these templates shall be a @@ -1420,15 +1488,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;} & @@ -1443,7 +1527,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 @@ -1471,7 +1555,7 @@ \indexlibraryglobal{is_invocable}% \tcode{template}\br \tcode{struct is_invocable;} & - The expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + The expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)}\iref{func.require} is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand} & \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} shall be complete types, \cv{}~\keyword{void}, or @@ -1576,6 +1660,10 @@ \rSec3[meta.trans.cv]{Const-volatile modifications} +\pnum +The templates specified in \tref{meta.trans.cv} +add or remove cv-qualifications\iref{basic.type.qualifier}. + \begin{libreqtab2a}{Const-volatile modifications}{meta.trans.cv} \\ \topline \lhdr{Template} & \rhdr{Comments} \\ \capsep @@ -1644,6 +1732,10 @@ \rSec3[meta.trans.ref]{Reference modifications} +\pnum +The templates specified in \tref{meta.trans.ref} +add or remove references. + \begin{libreqtab2a}{Reference modifications}{meta.trans.ref} \\ \topline \lhdr{Template} & \rhdr{Comments} \\ \capsep @@ -1686,6 +1778,11 @@ \end{libreqtab2a} \rSec3[meta.trans.sign]{Sign modifications} + +\pnum +The templates specified in \tref{meta.trans.sign} +convert an integer type to its corresponding signed or unsigned type. + \begin{libreqtab2a}{Sign modifications}{meta.trans.sign} \\ \topline \lhdr{Template} & \rhdr{Comments} \\ \capsep @@ -1729,6 +1826,11 @@ \end{libreqtab2a} \rSec3[meta.trans.arr]{Array modifications} + +\pnum +The templates specified in \tref{meta.trans.arr} +modify array types. + \begin{libreqtab2a}{Array modifications}{meta.trans.arr} \\ \topline \lhdr{Template} & \rhdr{Comments} \\ \capsep @@ -1754,7 +1856,7 @@ \indexlibraryglobal{remove_all_extents}% \tcode{template\br struct remove_all_extents;} & - If \tcode{T} is ``multi-dimensional array of \tcode{U}'', the resulting member + If \tcode{T} is ``multidimensional array of \tcode{U}'', the resulting member typedef \tcode{type} denotes \tcode{U}, otherwise \tcode{T}. \\ \end{libreqtab2a} @@ -1762,10 +1864,10 @@ \begin{example} \begin{codeblock} // the following assertions hold: -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int[3]>)); -assert((is_same_v, int[3]>)); +static_assert(is_same_v, int>); +static_assert(is_same_v, int>); +static_assert(is_same_v, int[3]>); +static_assert(is_same_v, int[3]>); \end{codeblock} \end{example} @@ -1773,14 +1875,19 @@ \begin{example} \begin{codeblock} // the following assertions hold: -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int>)); +static_assert(is_same_v, int>); +static_assert(is_same_v, int>); +static_assert(is_same_v, int>); +static_assert(is_same_v, int>); \end{codeblock} \end{example} \rSec3[meta.trans.ptr]{Pointer modifications} + +\pnum +The templates specified in \tref{meta.trans.ptr} +add or remove pointers. + \begin{libreqtab2a}{Pointer modifications}{meta.trans.ptr} \\ \topline \lhdr{Template} & \rhdr{Comments} \\ \capsep @@ -1809,6 +1916,10 @@ \rSec3[meta.trans.other]{Other transformations} +\pnum +The templates specified in \tref{meta.trans.other} +perform other modifications of a type. + \begin{libreqtab2a}{Other transformations}{meta.trans.other} \\ \topline \lhdr{Template} & \rhdr{Comments} \\ \capsep @@ -1818,21 +1929,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 @@ -1848,8 +1956,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 @@ -1857,39 +1964,36 @@ \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}; @@ -1898,9 +2002,9 @@ \tcode{template}\br - \tcode{struct invoke_result;} + \tcode{struct \libglobal{invoke_result};} & - If the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + If the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)}\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(), declval()...))}; @@ -1919,8 +2023,7 @@ are complete types, \cv{}~\keyword{void}, or arrays of unknown bound.\\ \rowsep -\indexlibraryglobal{unwrap_reference}% -\tcode{template} \tcode{struct unwrap_reference;} +\tcode{template} \tcode{struct \libglobal{unwrap_reference};} & If \tcode{T} is a specialization \tcode{reference_wrapper} for some type \tcode{X}, @@ -1928,8 +2031,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>}.\\ @@ -1995,7 +2097,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: @@ -2049,7 +2150,7 @@ \end{itemize} \pnum -Note B: Notwithstanding the provisions of \ref{meta.type.synop}, and +Notwithstanding the provisions of \ref{meta.type.synop}, and pursuant to \ref{namespace.std}, a program may specialize \tcode{common_type} for types \tcode{T1} and \tcode{T2} such that @@ -2069,7 +2170,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} @@ -2082,9 +2183,11 @@ \item Otherwise, if \tcode{sizeof...(T)} is two, let \tcode{T1} and \tcode{T2} denote the two types in the pack \tcode{T}. Then \begin{itemize} - \item If \tcode{T1} and \tcode{T2} are reference types and - \tcode{\placeholdernc{COMMON-REF}(T1, T2)} is well-formed, then the member - typedef \tcode{type} denotes that type. + \item Let \tcode{R} be \tcode{\placeholdernc{COMMON-REF}(T1, T2)}. + If \tcode{T1} and \tcode{T2} are reference types, + \tcode{R} is well-formed, and + \tcode{is_convertible_v, add_pointer_t> \&\& is_convertible_v, add_pointer_t>} is \tcode{true}, + then the member typedef \tcode{type} denotes \tcode{R}. \item Otherwise, if \tcode{basic_common_reference, remove_cvref_t, @@ -2113,7 +2216,7 @@ \end{itemize} \pnum -Note D: Notwithstanding the provisions of \ref{meta.type.synop}, and +Notwithstanding the provisions of \ref{meta.type.synop}, and pursuant to \ref{namespace.std}, a program may partially specialize \tcode{basic_common_reference} for types \tcode{T} and \tcode{U} such that @@ -2359,6 +2462,8 @@ \end{note} \rSec2[meta.const.eval]{Constant evaluation context} + +\indexlibraryglobal{is_constant_evaluated}% \begin{itemdecl} constexpr bool is_constant_evaluated() noexcept; \end{itemdecl} @@ -2389,9 +2494,63 @@ \end{example} \end{itemdescr} +\indexlibraryglobal{is_within_lifetime}% +\begin{itemdecl} +consteval bool is_within_lifetime(const auto* p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{p} is a pointer to an object that is +within its lifetime\iref{basic.life}; otherwise, \tcode{false}. + +\pnum +\remarks +During the evaluation of an expression \tcode{E} as a core constant expression, +a call to this function is ill-formed +unless \tcode{p} points to an object that is usable +in constant expressions or +whose complete object's lifetime began within \tcode{E}. + +\pnum +\begin{example} +\begin{codeblock} +struct OptBool { + union { bool b; char c; }; + + // note: this assumes common implementation properties for \tcode{bool} and \tcode{char}: + // * \tcode{sizeof(bool) == sizeof(char)}, and + // * the value representations for \tcode{true} and \tcode{false} are distinct + // from the value representation for \tcode{2} + constexpr OptBool() : c(2) { } + constexpr OptBool(bool b) : b(b) { } + + constexpr auto has_value() const -> bool { + if consteval { + return std::is_within_lifetime(&b); // during constant evaluation, cannot read from \tcode{c} + } else { + return c != 2; // during runtime, must read from \tcode{c} + } + } + + constexpr auto operator*() const -> const bool& { + return b; + } +}; + +constexpr OptBool disengaged; +constexpr OptBool engaged(true); +static_assert(!disengaged.has_value()); +static_assert(engaged.has_value()); +static_assert(*engaged); +\end{codeblock} +\end{example} +\end{itemdescr} + \rSec1[ratio]{Compile-time rational arithmetic} -\rSec2[ratio.general]{In general} +\rSec2[ratio.general]{General} \pnum \indexlibraryglobal{ratio}% @@ -2430,39 +2589,43 @@ template struct ratio_greater_equal; template - inline constexpr bool @\libglobal{ratio_equal_v}@ = ratio_equal::value; + constexpr bool @\libglobal{ratio_equal_v}@ = ratio_equal::value; template - inline constexpr bool @\libglobal{ratio_not_equal_v}@ = ratio_not_equal::value; + constexpr bool @\libglobal{ratio_not_equal_v}@ = ratio_not_equal::value; template - inline constexpr bool @\libglobal{ratio_less_v}@ = ratio_less::value; + constexpr bool @\libglobal{ratio_less_v}@ = ratio_less::value; template - inline constexpr bool @\libglobal{ratio_less_equal_v}@ = ratio_less_equal::value; + constexpr bool @\libglobal{ratio_less_equal_v}@ = ratio_less_equal::value; template - inline constexpr bool @\libglobal{ratio_greater_v}@ = ratio_greater::value; + constexpr bool @\libglobal{ratio_greater_v}@ = ratio_greater::value; template - inline constexpr bool @\libglobal{ratio_greater_equal_v}@ = ratio_greater_equal::value; + constexpr bool @\libglobal{ratio_greater_equal_v}@ = ratio_greater_equal::value; // \ref{ratio.si}, convenience SI typedefs - using yocto = ratio<1, 1'000'000'000'000'000'000'000'000>; // see below - using zepto = ratio<1, 1'000'000'000'000'000'000'000>; // see below - using atto = ratio<1, 1'000'000'000'000'000'000>; - using femto = ratio<1, 1'000'000'000'000'000>; - using pico = ratio<1, 1'000'000'000'000>; - using nano = ratio<1, 1'000'000'000>; - using micro = ratio<1, 1'000'000>; - using milli = ratio<1, 1'000>; - using centi = ratio<1, 100>; - using deci = ratio<1, 10>; - using deca = ratio< 10, 1>; - using hecto = ratio< 100, 1>; - using kilo = ratio< 1'000, 1>; - using mega = ratio< 1'000'000, 1>; - using giga = ratio< 1'000'000'000, 1>; - using tera = ratio< 1'000'000'000'000, 1>; - using peta = ratio< 1'000'000'000'000'000, 1>; - using exa = ratio< 1'000'000'000'000'000'000, 1>; - using zetta = ratio< 1'000'000'000'000'000'000'000, 1>; // see below - using yotta = ratio<1'000'000'000'000'000'000'000'000, 1>; // see below + using @\libglobal{quecto}@ = ratio<1, 1'000'000'000'000'000'000'000'000'000'000>; // \seebelow + using @\libglobal{ronto}@ = ratio<1, 1'000'000'000'000'000'000'000'000'000>; // \seebelow + using @\libglobal{yocto}@ = ratio<1, 1'000'000'000'000'000'000'000'000>; // \seebelow + using @\libglobal{zepto}@ = ratio<1, 1'000'000'000'000'000'000'000>; // \seebelow + using @\libglobal{atto}@ = ratio<1, 1'000'000'000'000'000'000>; + using @\libglobal{femto}@ = ratio<1, 1'000'000'000'000'000>; + using @\libglobal{pico}@ = ratio<1, 1'000'000'000'000>; + using @\libglobal{nano}@ = ratio<1, 1'000'000'000>; + using @\libglobal{micro}@ = ratio<1, 1'000'000>; + using @\libglobal{milli}@ = ratio<1, 1'000>; + using @\libglobal{centi}@ = ratio<1, 100>; + using @\libglobal{deci}@ = ratio<1, 10>; + using @\libglobal{deca}@ = ratio< 10, 1>; + using @\libglobal{hecto}@ = ratio< 100, 1>; + using @\libglobal{kilo}@ = ratio< 1'000, 1>; + using @\libglobal{mega}@ = ratio< 1'000'000, 1>; + using @\libglobal{giga}@ = ratio< 1'000'000'000, 1>; + using @\libglobal{tera}@ = ratio< 1'000'000'000'000, 1>; + using @\libglobal{peta}@ = ratio< 1'000'000'000'000'000, 1>; + using @\libglobal{exa}@ = ratio< 1'000'000'000'000'000'000, 1>; + using @\libglobal{zetta}@ = ratio< 1'000'000'000'000'000'000'000, 1>; // \seebelow + using @\libglobal{yotta}@ = ratio< 1'000'000'000'000'000'000'000'000, 1>; // \seebelow + using @\libglobal{ronna}@ = ratio< 1'000'000'000'000'000'000'000'000'000, 1>; // \seebelow + using @\libglobal{quetta}@ = ratio<1'000'000'000'000'000'000'000'000'000'000, 1>; // \seebelow } \end{codeblockdigitsep} @@ -2498,7 +2661,7 @@ \tcode{N} and \tcode{D}: \begin{itemize} -\item \tcode{num} shall have the value \tcode{sign(N) * sign(D) * abs(N) / gcd}. +\item \tcode{num} shall have the value \tcode{$\operatorname{sgn}(\tcode{N})$ * $\operatorname{sgn}(\tcode{D})$ * abs(N) / gcd}. \item \tcode{den} shall have the value \tcode{abs(D) / gcd}. \end{itemize} @@ -2624,8 +2787,20 @@ \rSec2[ratio.si]{SI types for \tcode{ratio}} \pnum -For each of the \grammarterm{typedef-name}{s} \tcode{yocto}, \tcode{zepto}, -\tcode{zetta}, and \tcode{yotta}, if both of the constants used in its +\indexlibraryglobal{quecto}% +\indexlibraryglobal{ronto}% +\indexlibraryglobal{yocto}% +\indexlibraryglobal{zepto}% +\indexlibraryglobal{zetta}% +\indexlibraryglobal{yotta}% +\indexlibraryglobal{ronna}% +\indexlibraryglobal{quetta}% +For each of the \grammarterm{typedef-name}{s} +\tcode{quecto}, \tcode{ronto}, +\tcode{yocto}, \tcode{zepto}, +\tcode{zetta}, \tcode{yotta}, +\tcode{ronna}, and \tcode{quetta}, +if both of the constants used in its specification are representable by \tcode{intmax_t}, the typedef is defined; if either of the constants is not representable by \tcode{intmax_t}, the typedef is not defined. diff --git a/source/modules.tex b/source/modules.tex index 3701762ced..a0386b38ca 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -196,7 +196,7 @@ \begin{bnf} \nontermdef{export-declaration}\br - \keyword{export} declaration\br + \keyword{export} name-declaration\br \keyword{export} \terminal{\{} \opt{declaration-seq} \terminal{\}}\br export-keyword module-import-declaration \end{bnf} @@ -209,10 +209,12 @@ or a \grammarterm{private-module-fragment}. An \grammarterm{export-declaration} has the declarative effects of its -\grammarterm{declaration}, +\grammarterm{name-declaration}, \grammarterm{declaration-seq} (if any), or \grammarterm{module-import-declaration}. -The \grammarterm{declaration} or \grammarterm{declaration-seq} of +The \grammarterm{name-declaration} of an \grammarterm{export-declaration} +shall not declare a partial specialization\iref{temp.decls.general}. +The \grammarterm{declaration-seq} of an \grammarterm{export-declaration} shall not contain an \grammarterm{export-declaration} or \grammarterm{module-import-declaration}. @@ -232,10 +234,7 @@ \end{itemize} \pnum -An exported declaration -that is not a \grammarterm{module-import-declaration} -shall declare at least one name. -If the declaration is not within a header unit, +If an exported declaration is not within a header unit, it shall not declare a name with internal linkage. \pnum @@ -249,17 +248,14 @@ #include "a.h" // error: declaration of \tcode{x} is not in the // purview of a module interface unit export module M; -export namespace {} // error: does not introduce any names -export namespace { - int a1; // error: export of name with internal linkage -} +export namespace {} // error: namespace has internal linkage namespace { export int a2; // error: export of name with internal linkage } export static int b; // error: b explicitly declared static export int f(); // OK export namespace N { } // OK -export using namespace N; // error: does not declare a name +export using namespace N; // OK \end{codeblocktu} \end{example} @@ -316,7 +312,7 @@ A redeclaration of an entity $X$ is implicitly exported if $X$ was introduced by an exported declaration; -otherwise it shall not be exported. +otherwise it shall not be exported unless it is a namespace. \begin{example} \begin{codeblock} export module M; @@ -324,6 +320,12 @@ typedef S S; export typedef S S; // OK, does not redeclare an entity export struct S; // error: exported declaration follows non-exported declaration +namespace N { // external linkage, attached to global module, not exported + void f(); +} +namespace N { // OK, exported namespace redeclaring non-exported namespace + export void g(); +} \end{codeblock} \end{example} @@ -386,9 +388,10 @@ \begin{example} \begin{codeblock} export module M; +int g; export namespace N { int x; // OK - static_assert(1 == 1); // error: does not declare a name + using ::g; // error: \tcode{::g} has module linkage } \end{codeblock} \end{example} @@ -451,6 +454,8 @@ to the source file or header nominated by \tcode{H}, which shall not contain a \grammarterm{module-declaration}. \begin{note} +A header unit is a separate translation unit with +an independent set of defined macros. All declarations within a header unit are implicitly exported\iref{module.interface}, and are attached to the global module\iref{module.unit}. @@ -516,6 +521,13 @@ \end{footnote} These rules can in turn lead to the importation of yet more translation units. +\begin{note} +Such indirect importation does not make macros available, +because a translation unit is +a sequence of tokens in translation phase 7\iref{lex.phases}. +Macros can be made available by directly importing header units +as described in \ref{cpp.import}. +\end{note} \pnum A module implementation unit shall not be exported. @@ -587,7 +599,7 @@ \pnum A declaration $D$ is \defn{decl-reachable} from a declaration $S$ -in the same translation unit if: +in the same translation unit if \begin{itemize} \item $D$ does not declare a function or function template and @@ -633,14 +645,13 @@ \item $D$ is decl-reachable from $M$, or \item -$D$ redeclares the entity declared by $M$ or -$M$ redeclares the entity declared by $D$, +$D$ and $M$ declare the same entity, and $D$ neither is a friend declaration nor inhabits a block scope, or \item $D$ declares a namespace $N$ and $M$ is a member of $N$, or \item -one of $M$ and $D$ declares a class or class template $C$ +one of $D$ and $M$ declares a class or class template $C$ and the other declares a member or friend of $C$, or \item one of $D$ and $M$ declares an enumeration $E$ @@ -653,11 +664,14 @@ \end{footnote} or \item -one of $M$ and $D$ declares a template and the other declares +one of $D$ and $M$ declares a template and the other declares a partial or explicit specialization or an implicit or explicit instantiation of that template, or \item -one of $M$ and $D$ declares a class or enumeration type +$M$ declares a class template +and $D$ is a deduction guide for that template, or +\item +one of $D$ and $M$ declares a class or enumeration type and the other introduces a typedef name for linkage purposes for that type. \end{itemize} \end{itemize} @@ -1048,7 +1062,6 @@ \end{codeblocktu} \begin{codeblocktu}{Translation unit \#5} -module X; import M; B b3; // error: no reachable definition of \tcode{struct B} void g() { f(); } // error: no reachable definition of \tcode{struct B} @@ -1069,7 +1082,6 @@ \end{codeblocktu} \begin{codeblocktu}{Translation unit \#2} -module B; import A; Y y; // OK, definition of \tcode{X} is reachable X x; // error: \tcode{X} not visible to unqualified lookup diff --git a/source/numerics.tex b/source/numerics.tex index 514319824d..5d2ee0f222 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -17,14 +17,16 @@ as summarized in \tref{numerics.summary}. \begin{libsumtab}{Numerics library summary}{numerics.summary} -\ref{numeric.requirements} & Requirements & \\ \rowsep -\ref{cfenv} & Floating-point environment & \tcode{} \\ \rowsep -\ref{complex.numbers} & Complex numbers & \tcode{} \\ \rowsep -\ref{rand} & Random number generation & \tcode{} \\ \rowsep -\ref{numarray} & Numeric arrays & \tcode{} \\ \rowsep -\ref{c.math} & Mathematical functions for floating-point types & - \tcode{}, \tcode{} \\ \rowsep -\ref{numbers} & Numbers & \tcode{} \\ +\ref{numeric.requirements} & Requirements & \\ \rowsep +\ref{cfenv} & Floating-point environment & \tcode{} \\ \rowsep +\ref{complex.numbers} & Complex numbers & \tcode{} \\ \rowsep +\ref{rand} & Random number generation & \tcode{} \\ \rowsep +\ref{numarray} & Numeric arrays & \tcode{} \\ \rowsep +\ref{c.math} & Mathematical functions for + floating-point types & \tcode{}, \tcode{} \\ \rowsep +\ref{numbers} & Numbers & \tcode{} \\ \rowsep +\ref{linalg} & Linear algebra & \tcode{} \\ \rowsep +\ref{simd} & Data-parallel types & \tcode{} \\ \end{libsumtab} \rSec1[numeric.requirements]{Numeric type requirements} @@ -96,36 +98,25 @@ \indexlibraryglobal{feholdexcept}% \indexlibraryglobal{fesetenv}% \indexlibraryglobal{feupdateenv}% -\indexlibraryglobal{FE_ALL_EXCEPT}% -\indexlibraryglobal{FE_DIVBYZERO}% -\indexlibraryglobal{FE_INEXACT}% -\indexlibraryglobal{FE_INVALID}% -\indexlibraryglobal{FE_OVERFLOW}% -\indexlibraryglobal{FE_UNDERFLOW}% -\indexlibraryglobal{FE_DOWNWARD}% -\indexlibraryglobal{FE_TONEAREST}% -\indexlibraryglobal{FE_TOWARDZERO}% -\indexlibraryglobal{FE_UPWARD}% -\indexlibraryglobal{FE_DFL_ENV}% -\begin{codeblock} -#define FE_ALL_EXCEPT @\seebelow@ -#define FE_DIVBYZERO @\seebelow@ // optional -#define FE_INEXACT @\seebelow@ // optional -#define FE_INVALID @\seebelow@ // optional -#define FE_OVERFLOW @\seebelow@ // optional -#define FE_UNDERFLOW @\seebelow@ // optional - -#define FE_DOWNWARD @\seebelow@ // optional -#define FE_TONEAREST @\seebelow@ // optional -#define FE_TOWARDZERO @\seebelow@ // optional -#define FE_UPWARD @\seebelow@ // optional - -#define FE_DFL_ENV @\seebelow@ +\begin{codeblock} +#define @\libmacro{FE_ALL_EXCEPT}@ @\seebelow@ +#define @\libmacro{FE_DIVBYZERO}@ @\seebelow@ // optional +#define @\libmacro{FE_INEXACT}@ @\seebelow@ // optional +#define @\libmacro{FE_INVALID}@ @\seebelow@ // optional +#define @\libmacro{FE_OVERFLOW}@ @\seebelow@ // optional +#define @\libmacro{FE_UNDERFLOW}@ @\seebelow@ // optional + +#define @\libmacro{FE_DOWNWARD}@ @\seebelow@ // optional +#define @\libmacro{FE_TONEAREST}@ @\seebelow@ // optional +#define @\libmacro{FE_TOWARDZERO}@ @\seebelow@ // optional +#define @\libmacro{FE_UPWARD}@ @\seebelow@ // optional + +#define @\libmacro{FE_DFL_ENV}@ @\seebelow@ namespace std { // types using fenv_t = @\textit{object type}@; - using fexcept_t = @\textit{integer type}@; + using fexcept_t = @\textit{object type}@; // functions int feclearexcept(int except); @@ -194,7 +185,7 @@ that is not a cv-unqualified floating-point type\iref{basic.fundamental} is unspecified. Specializations of \tcode{complex} for cv-unqualified floating-point types -are trivially-copyable literal types\iref{term.literal.type}. +are trivially copyable literal types\iref{term.literal.type}. \pnum If the result of a function is not mathematically defined or not in @@ -211,8 +202,8 @@ Moreover, if \tcode{a} is an expression of type \cv{}~\tcode{complex*} and the expression \tcode{a[i]} is well-defined for an integer expression \tcode{i}, then: \begin{itemize} -\item \tcode{reinterpret_cast<\cv{} T*>(a)[2*i]} designates the real part of \tcode{a[i]}, and -\item \tcode{reinterpret_cast<\cv{} T*>(a)[2*i + 1]} designates the imaginary part of \tcode{a[i]}. +\item \tcode{reinterpret_cast<\cv{} T*>(a)[2 * i]} designates the real part of \tcode{a[i]}, and +\item \tcode{reinterpret_cast<\cv{} T*>(a)[2 * i + 1]} designates the imaginary part of \tcode{a[i]}. \end{itemize} \rSec2[complex.syn]{Header \tcode{} synopsis} @@ -256,49 +247,63 @@ template constexpr T real(const complex&); template constexpr T imag(const complex&); - template T abs(const complex&); - template T arg(const complex&); + template constexpr T abs(const complex&); + template constexpr T arg(const complex&); template constexpr T norm(const complex&); template constexpr complex conj(const complex&); - template complex proj(const complex&); - template complex polar(const T&, const T& = T()); + template constexpr complex proj(const complex&); + template constexpr complex polar(const T&, const T& = T()); // \ref{complex.transcendentals}, transcendentals - template complex acos(const complex&); - template complex asin(const complex&); - template complex atan(const complex&); - - template complex acosh(const complex&); - template complex asinh(const complex&); - template complex atanh(const complex&); - - template complex cos (const complex&); - template complex cosh (const complex&); - template complex exp (const complex&); - template complex log (const complex&); - template complex log10(const complex&); - - template complex pow (const complex&, const T&); - template complex pow (const complex&, const complex&); - template complex pow (const T&, const complex&); - - template complex sin (const complex&); - template complex sinh (const complex&); - template complex sqrt (const complex&); - template complex tan (const complex&); - template complex tanh (const complex&); + template constexpr complex acos(const complex&); + template constexpr complex asin(const complex&); + template constexpr complex atan(const complex&); + + template constexpr complex acosh(const complex&); + template constexpr complex asinh(const complex&); + template constexpr complex atanh(const complex&); + + template constexpr complex cos (const complex&); + template constexpr complex cosh (const complex&); + template constexpr complex exp (const complex&); + template constexpr complex log (const complex&); + template constexpr complex log10(const complex&); + + template constexpr complex pow (const complex&, const T&); + template constexpr complex pow (const complex&, const complex&); + template constexpr complex pow (const T&, const complex&); + + template constexpr complex sin (const complex&); + template constexpr complex sinh (const complex&); + template constexpr complex sqrt (const complex&); + template constexpr complex tan (const complex&); + template constexpr complex tanh (const complex&); + + // \ref{complex.tuple}, tuple interface + template struct tuple_size; + template struct tuple_element; + template struct tuple_size>; + template struct tuple_element>; + template + constexpr T& get(complex&) noexcept; + template + constexpr T&& get(complex&&) noexcept; + template + constexpr const T& get(const complex&) noexcept; + template + constexpr const T&& get(const complex&&) noexcept; // \ref{complex.literals}, complex literals inline namespace literals { - inline namespace complex_literals { - constexpr complex operator""il(long double); - constexpr complex operator""il(unsigned long long); - constexpr complex operator""i(long double); - constexpr complex operator""i(unsigned long long); - constexpr complex operator""if(long double); - constexpr complex operator""if(unsigned long long); - } + inline namespace complex_literals { + constexpr complex operator""il(long double); + constexpr complex operator""il(unsigned long long); + constexpr complex operator""i(long double); + constexpr complex operator""i(unsigned long long); + constexpr complex operator""if(long double); + constexpr complex operator""if(unsigned long long); + } } } \end{codeblock} @@ -500,6 +505,23 @@ \tcode{*this}. \end{itemdescr} +\indexlibrarymember{operator=}{complex}% +\begin{itemdecl} +template constexpr complex& operator=(const complex& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Assigns the value \tcode{rhs.real()} to the real part and +the value \tcode{rhs.imag()} to the imaginary part +of the complex value \tcode{*this}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \indexlibrarymember{operator+=}{complex}% \begin{itemdecl} template constexpr complex& operator+=(const complex& rhs); @@ -768,7 +790,7 @@ \indexlibrarymember{abs}{complex}% \begin{itemdecl} -template T abs(const complex& x); +template constexpr T abs(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -779,7 +801,7 @@ \indexlibrarymember{arg}{complex}% \begin{itemdecl} -template T arg(const complex& x); +template constexpr T arg(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -812,7 +834,7 @@ \indexlibrarymember{proj}{complex}% \begin{itemdecl} -template complex proj(const complex& x); +template constexpr complex proj(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -828,7 +850,7 @@ \indexlibrarymember{polar}{complex}% \begin{itemdecl} -template complex polar(const T& rho, const T& theta = T()); +template constexpr complex polar(const T& rho, const T& theta = T()); \end{itemdecl} \begin{itemdescr} @@ -850,7 +872,7 @@ \indexlibrarymember{acos}{complex}% \indexlibrarymember{cacos}{complex}% \begin{itemdecl} -template complex acos(const complex& x); +template constexpr complex acos(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -867,7 +889,7 @@ \indexlibrarymember{asin}{complex}% \indexlibrarymember{casin}{complex}% \begin{itemdecl} -template complex asin(const complex& x); +template constexpr complex asin(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -884,7 +906,7 @@ \indexlibrarymember{atan}{complex}% \indexlibrarymember{catan}{complex}% \begin{itemdecl} -template complex atan(const complex& x); +template constexpr complex atan(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -901,7 +923,7 @@ \indexlibrarymember{acosh}{complex}% \indexlibrarymember{cacosh}{complex}% \begin{itemdecl} -template complex acosh(const complex& x); +template constexpr complex acosh(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -918,7 +940,7 @@ \indexlibrarymember{asinh}{complex}% \indexlibrarymember{casinh}{complex}% \begin{itemdecl} -template complex asinh(const complex& x); +template constexpr complex asinh(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -935,7 +957,7 @@ \indexlibrarymember{atanh}{complex}% \indexlibrarymember{catanh}{complex}% \begin{itemdecl} -template complex atanh(const complex& x); +template constexpr complex atanh(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -951,7 +973,7 @@ \indexlibrarymember{cos}{complex}% \begin{itemdecl} -template complex cos(const complex& x); +template constexpr complex cos(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -962,7 +984,7 @@ \indexlibrarymember{cosh}{complex}% \begin{itemdecl} -template complex cosh(const complex& x); +template constexpr complex cosh(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -973,7 +995,7 @@ \indexlibrarymember{exp}{complex}% \begin{itemdecl} -template complex exp(const complex& x); +template constexpr complex exp(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -984,7 +1006,7 @@ \indexlibrarymember{log}{complex}% \begin{itemdecl} -template complex log(const complex& x); +template constexpr complex log(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -1004,7 +1026,7 @@ \indexlibrarymember{log10}{complex}% \begin{itemdecl} -template complex log10(const complex& x); +template constexpr complex log10(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -1020,9 +1042,9 @@ \indexlibrarymember{pow}{complex}% \begin{itemdecl} -template complex pow(const complex& x, const complex& y); -template complex pow(const complex& x, const T& y); -template complex pow(const T& x, const complex& y); +template constexpr complex pow(const complex& x, const complex& y); +template constexpr complex pow(const complex& x, const T& y); +template constexpr complex pow(const T& x, const complex& y); \end{itemdecl} \begin{itemdescr} @@ -1042,7 +1064,7 @@ \indexlibrarymember{sin}{complex}% \begin{itemdecl} -template complex sin(const complex& x); +template constexpr complex sin(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -1053,7 +1075,7 @@ \indexlibrarymember{sinh}{complex}% \begin{itemdecl} -template complex sinh(const complex& x); +template constexpr complex sinh(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -1064,7 +1086,7 @@ \indexlibrarymember{sqrt}{complex}% \begin{itemdecl} -template complex sqrt(const complex& x); +template constexpr complex sqrt(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -1084,7 +1106,7 @@ \indexlibrarymember{tan}{complex}% \begin{itemdecl} -template complex tan(const complex& x); +template constexpr complex tan(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -1095,7 +1117,7 @@ \indexlibrarymember{tanh}{complex}% \begin{itemdecl} -template complex tanh(const complex& x); +template constexpr complex tanh(const complex& x); \end{itemdecl} \begin{itemdescr} @@ -1104,6 +1126,49 @@ The complex hyperbolic tangent of \tcode{x}. \end{itemdescr} +\rSec2[complex.tuple]{Tuple interface} + +\indexlibraryglobal{tuple_size}% +\indexlibraryglobal{tuple_element}% +\begin{itemdecl} +template +struct tuple_size> : integral_constant {}; + +template +struct tuple_element> { + using type = T; +}; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{I < 2} is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{get}{complex}% +\begin{itemdecl} +template + constexpr T& get(complex& z) noexcept; +template + constexpr T&& get(complex&& z) noexcept; +template + constexpr const T& get(const complex& z) noexcept; +template + constexpr const T&& get(const complex&& z) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{I < 2} is \tcode{true}. + +\pnum +\returns +A reference to the real part of \tcode{z} if \tcode{I == 0} is \tcode{true}, +otherwise a reference to the imaginary part of \tcode{z}. +\end{itemdescr} + \rSec2[cmplx.over]{Additional overloads} \pnum @@ -1112,17 +1177,16 @@ \indexlibraryglobal{imag}% \indexlibraryglobal{norm}% \indexlibraryglobal{real}% -The following function templates shall have additional overloads: +The following function templates have additional constexpr overloads: \begin{codeblock} arg norm conj proj imag real \end{codeblock} -where \tcode{norm}, \tcode{conj}, \tcode{imag}, and \tcode{real} are \keyword{constexpr} overloads. \pnum \indextext{overloads!floating-point}% -The additional overloads shall be sufficient to ensure: +The additional constexpr overloads are sufficient to ensure: \begin{itemize} \item If the argument has a floating-point type \tcode{T}, @@ -1134,11 +1198,13 @@ \pnum \indexlibraryglobal{pow}% -Function template \tcode{pow} has additional overloads sufficient to ensure, +Function template \tcode{pow} has additional constexpr overloads sufficient to ensure, for a call with one argument of type \tcode{complex} and the other argument of type \tcode{T2} or \tcode{complex}, -both arguments are effectively cast to \tcode{complex>}. -If \tcode{common_type_t} is not well-formed, +both arguments are effectively cast to \tcode{complex>}, +where \tcode{T3} is +\tcode{double} if \tcode{T2} is an integer type and \tcode{T2} otherwise. +If \tcode{common_type_t} is not well-formed, then the program is ill-formed. \rSec2[complex.literals]{Suffixes for complex number literals} @@ -1306,11 +1372,11 @@ namespace std { // \ref{rand.req.urng}, uniform random bit generator requirements template - concept uniform_random_bit_generator = @\seebelow@; + concept uniform_random_bit_generator = @\seebelow@; // freestanding // \ref{rand.eng.lcong}, class template \tcode{linear_congruential_engine} template - class linear_congruential_engine; + class linear_congruential_engine; // partially freestanding // \ref{rand.eng.mers}, class template \tcode{mersenne_twister_engine} template - class subtract_with_carry_engine; + class subtract_with_carry_engine; // partially freestanding // \ref{rand.adapt.disc}, class template \tcode{discard_block_engine} template - class discard_block_engine; + class discard_block_engine; // partially freestanding // \ref{rand.adapt.ibits}, class template \tcode{independent_bits_engine} template - class independent_bits_engine; + class independent_bits_engine; // partially freestanding // \ref{rand.adapt.shuf}, class template \tcode{shuffle_order_engine} template class shuffle_order_engine; + // \ref{rand.eng.philox}, class template \tcode{philox_engine} + template + class philox_engine; + // \ref{rand.predef}, engines and engine adaptors with predefined parameters - using minstd_rand0 = @\seebelow@; - using minstd_rand = @\seebelow@; - using mt19937 = @\seebelow@; - using mt19937_64 = @\seebelow@; - using ranlux24_base = @\seebelow@; - using ranlux48_base = @\seebelow@; - using ranlux24 = @\seebelow@; - using ranlux48 = @\seebelow@; + using minstd_rand0 = @\seebelow@; // freestanding + using minstd_rand = @\seebelow@; // freestanding + using mt19937 = @\seebelow@; // freestanding + using mt19937_64 = @\seebelow@; // freestanding + using ranlux24_base = @\seebelow@; // freestanding + using ranlux48_base = @\seebelow@; // freestanding + using ranlux24 = @\seebelow@; // freestanding + using ranlux48 = @\seebelow@; // freestanding using knuth_b = @\seebelow@; + using philox4x32 = @\seebelow@; + using philox4x64 = @\seebelow@; using default_random_engine = @\seebelow@; @@ -1355,12 +1427,35 @@ class seed_seq; // \ref{rand.util.canonical}, function template \tcode{generate_canonical} - template + template RealType generate_canonical(URBG& g); + namespace ranges { + // \ref{alg.rand.generate}, \tcode{generate_random} + template + requires @\libconcept{output_range}@> && + @\libconcept{uniform_random_bit_generator}@> + constexpr borrowed_iterator_t generate_random(R&& r, G&& g); + + template> O, @\libconcept{sentinel_for}@ S> + requires @\libconcept{uniform_random_bit_generator}@> + constexpr O generate_random(O first, S last, G&& g); + + template + requires @\libconcept{output_range}@> && @\libconcept{invocable}@ && + @\libconcept{uniform_random_bit_generator}@> && + is_arithmetic_v> + constexpr borrowed_iterator_t generate_random(R&& r, G&& g, D&& d); + + template> O, @\libconcept{sentinel_for}@ S> + requires @\libconcept{invocable}@ && @\libconcept{uniform_random_bit_generator}@> && + is_arithmetic_v> + constexpr O generate_random(O first, S last, G&& g, D&& d); + } + // \ref{rand.dist.uni.int}, class template \tcode{uniform_int_distribution} template - class uniform_int_distribution; + class uniform_int_distribution; // partially freestanding // \ref{rand.dist.uni.real}, class template \tcode{uniform_real_distribution} template @@ -1461,7 +1556,7 @@ \rSec3[rand.req.genl]{General requirements}% \pnum -Throughout this subclause \ref{rand}, +Throughout \ref{rand}, the effect of instantiating a template: \begin{itemize} \item @@ -1521,7 +1616,7 @@ \end{itemize} \pnum -Throughout this subclause \ref{rand}, +Throughout \ref{rand}, phrases of the form ``\tcode{x} is an iterator of a specific kind'' shall be interpreted as equivalent to the more formal requirement that ``\tcode{x} is a value @@ -1529,7 +1624,7 @@ of the specified iterator type''. \pnum -Throughout this subclause \ref{rand}, +Throughout \ref{rand}, any constructor that can be called with a single argument and that meets a requirement specified in this subclause shall be declared \keyword{explicit}. @@ -1564,16 +1659,16 @@ in \tref{rand.req.seedseq} are valid and have the indicated semantics, and if \tcode{S} also meets all other requirements -of this subclause \ref{rand.req.seedseq}. -In that Table and throughout this subclause: +of \ref{rand.req.seedseq}. +In \tref{rand.req.seedseq} and throughout this subclause: \begin{itemize} \item \tcode{T} is the type named by \tcode{S}'s associated \tcode{result_type}; \item - \tcode{q} is a value of \tcode{S} + \tcode{q} is a value of type \tcode{S} and - \tcode{r} is a possibly const value of \tcode{S}; + \tcode{r} is a value of type \tcode{S} or \tcode{const S}; \item \tcode{ib} and \tcode{ie} are input iterators with an unsigned integer \tcode{value_type} of at least 32 bits; @@ -1584,7 +1679,7 @@ \tcode{ob} is an output iterator; and \item - \tcode{il} is a value of \tcode{initializer_list}. + \tcode{il} is a value of type \tcode{initializer_list}. \end{itemize} @@ -1610,7 +1705,7 @@ & \tcode{T} & \tcode{T} is an unsigned integer type\iref{basic.fundamental} of at least 32 bits. - & compile-time + & \\ \rowsep \tcode{S()}% & @@ -1780,8 +1875,8 @@ in \tref{rand.req.eng} are valid and have the indicated semantics, and if \tcode{E} also meets all other requirements -of this subclause \ref{rand.req.eng}. -In that Table and throughout this subclause: +of \ref{rand.req.eng}. +In \tref{rand.req.eng} and throughout this subclause: \begin{itemize} \item \tcode{T} is the type named by @@ -1789,7 +1884,7 @@ \item \tcode{e} is a value of \tcode{E}, \tcode{v} is an lvalue of \tcode{E}, - \tcode{x} and \tcode{y} are (possibly \keyword{const}) values of \tcode{E}; + \tcode{x} and \tcode{y} are (possibly const) values of \tcode{E}; \item \tcode{s} is a value of \tcode{T}; \item @@ -1819,7 +1914,8 @@ & \rhdr{Complexity} \\ \capsep \endfirsthead -\hline +\continuedcaption\\ +\topline \lhdr{Expression} & \chdr{Return type} & \chdr{Pre/post-condition} @@ -1925,51 +2021,6 @@ & \tcode{bool} & \tcode{!(x == y)}. & \bigoh{$\text{size of state}$} - \\ \rowsep -\tcode{os << x}% - & reference to the type of \tcode{os} - & With \tcode{os.}\textit{fmtflags} set to - \tcode{ios_base::dec|ios_base::left} - and the fill character set to the space character, - writes to \tcode{os} - the textual representation - of \tcode{x}'s current state. - In the output, - adjacent numbers are separated - by one or more space characters. - - \ensures The \tcode{os.}\textit{fmtflags} and fill character are unchanged. - & \bigoh{$\text{size of state}$} - \\ \rowsep -\tcode{is >> v}% - & reference to the type of \tcode{is} - & With \tcode{is.fmtflags} - set to \tcode{ios_base::dec}, - sets \tcode{v}'s state - as determined by reading its textual representation from \tcode{is}. - If bad input is encountered, - ensures that \tcode{v}'s state is unchanged by the operation - and - calls \tcode{is.setstate(ios_base::failbit)} - (which may throw \tcode{ios_base::failure}\iref{iostate.flags}). - If a textual representation written via \tcode{os << x} - was subsequently read via \tcode{is >> v}, - then \tcode{x == v} - provided that there have been no intervening invocations - of \tcode{x} or of \tcode{v}. - - \expects - \tcode{is} provides a textual representation - that was previously written - using an output stream - whose imbued locale - was the same as that of \tcode{is}, - and whose type's template specialization arguments - \tcode{charT} and \tcode{traits} - were respectively the same as those of \tcode{is}. - - \ensures The \tcode{is.}\textit{fmtflags} are unchanged. - & \bigoh{$\text{size of state}$} \\ \end{libreqtab4d} @@ -1980,6 +2031,93 @@ These operations shall each be of complexity no worse than \bigoh{\text{size of state}}. +\pnum +On hosted implementations, +the following expressions are well-formed and have the specified semantics. + +\begin{itemdecl} +os << x +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +With \tcode{os.\placeholdernc{fmtflags}} set to +\tcode{ios_base::dec|ios_base::left} +and the fill character set to the space character, +writes to \tcode{os} +the textual representation +of \tcode{x}'s current state. +In the output, +adjacent numbers are separated +by one or more space characters. + +\pnum +\ensures +The \tcode{os.\placeholdernc{fmtflags}} and fill character are unchanged. + +\pnum +\result +reference to the type of \tcode{os}. + +\pnum +\returns +\tcode{os}. + +\pnum +\complexity +\bigoh{$\text{size of state}$} +\end{itemdescr} + +\begin{itemdecl} +is >> v +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{is} provides a textual representation +that was previously written +using an output stream +whose imbued locale +was the same as that of \tcode{is}, +and whose type's template specialization arguments +\tcode{charT} and \tcode{traits} +were respectively the same as those of \tcode{is}. + +\pnum +\effects +With \tcode{is.\placeholdernc{fmtflags}} +set to \tcode{ios_base::dec}, +sets \tcode{v}'s state +as determined by reading its textual representation from \tcode{is}. +If bad input is encountered, +ensures that \tcode{v}'s state is unchanged by the operation +and +calls \tcode{is.setstate(ios_base::failbit)} +(which may throw \tcode{ios_base::failure}\iref{iostate.flags}). +If a textual representation written via \tcode{os << x} +was subsequently read via \tcode{is >> v}, +then \tcode{x == v} +provided that there have been no intervening invocations +of \tcode{x} or of \tcode{v}. + +\pnum +\ensures +The \tcode{is.\placeholdernc{fmtflags}} are unchanged. + +\pnum +\result +reference to the type of \tcode{is}. + +\pnum +\returns +\tcode{is}. + +\pnum +\complexity +\bigoh{$\text{size of state}$} +\end{itemdescr} \indextext{requirements!random number engine|)} \indextext{random number engine!requirements|)}% @@ -2159,8 +2297,8 @@ are valid and have the indicated semantics, and if \tcode{D} and its associated types also meet all other requirements -of this subclause \ref{rand.req.dist}. -In that Table and throughout this subclause, +of \ref{rand.req.dist}. +In \tref{rand.req.dist} and throughout this subclause, \begin{itemize} \item \tcode{T} is the type named by @@ -2172,7 +2310,7 @@ \tcode{d} is a value of \tcode{D}, and - \tcode{x} and \tcode{y} are (possibly \keyword{const}) values of \tcode{D}; + \tcode{x} and \tcode{y} are (possibly const) values of \tcode{D}; \item \tcode{glb} and \tcode{lub} are values of \tcode{T} @@ -2181,7 +2319,7 @@ on the values potentially returned by \tcode{d}'s \tcode{operator()}, as determined by the current values of \tcode{d}'s parameters; \item - \tcode{p} is a (possibly \keyword{const}) value of \tcode{P}; + \tcode{p} is a (possibly const) value of \tcode{P}; \item \tcode{g}, \tcode{g1}, and \tcode{g2} are lvalues of a type meeting the requirements @@ -2207,7 +2345,8 @@ & \rhdr{Complexity} \\ \capsep \endfirsthead -\hline +\continuedcaption\\ +\topline \lhdr{Expression} & \chdr{Return type} & \chdr{Pre/post-condition} @@ -2217,12 +2356,12 @@ \tcode{D::result_type} & \tcode{T} & \tcode{T} is an arithmetic type\iref{basic.fundamental}. - & compile-time + & \\ \rowsep \tcode{D::param_type} & \tcode{P} & - & compile-time + & \\ \rowsep \tcode{D()}% & @@ -2311,35 +2450,6 @@ & \tcode{bool} & \tcode{!(x == y)}. & same as \tcode{x == y}. - \\ \rowsep -\tcode{os << x} - & reference to the type of \tcode{os} - & Writes to \tcode{os} a textual representation - for the parameters and the additional internal data of \tcode{x}. - - \ensures The \tcode{os.}\textit{fmtflags} and fill character are unchanged. - & - \\ \rowsep -\tcode{is >> d} - & reference to the type of \tcode{is} - & Restores from \tcode{is} - the parameters and additional internal data of the lvalue \tcode{d}. - If bad input is encountered, - ensures that \tcode{d} is unchanged by the operation - and - calls \tcode{is.setstate(ios_base::failbit)} - (which may throw \tcode{ios_base::failure}\iref{iostate.flags}). - - \expects - \tcode{is} provides a textual representation - that was previously written - using an \tcode{os} whose imbued locale - and whose type's template specialization arguments - \tcode{charT} and \tcode{traits} - were the same as those of \tcode{is}. - - \ensures The \tcode{is.}\textit{fmtflags} are unchanged. - & \\ \end{libreqtab4d} @@ -2370,7 +2480,7 @@ It is unspecified whether \tcode{D::param_type} is declared as a (nested) \keyword{class} or via a \keyword{typedef}. -In this subclause \ref{rand}, +In \ref{rand}, declarations of \tcode{D::param_type} are in the form of \keyword{typedef}s for convenience of exposition only. @@ -2400,6 +2510,70 @@ using distribution_type = D; \end{codeblock} +\pnum +On hosted implementations, +the following expressions are well-formed and have the specified semantics. + +\begin{itemdecl} +os << x +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Writes to \tcode{os} a textual representation +for the parameters and the additional internal data of \tcode{x}. + +\pnum +\ensures +The \tcode{os.\placeholdernc{fmtflags}} and fill character are unchanged. + +\pnum +\result +reference to the type of \tcode{os}. + +\pnum +\returns +\tcode{os}. +\end{itemdescr} + +\begin{itemdecl} +is >> d +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{is} provides a textual representation +that was previously written +using an \tcode{os} whose imbued locale +and whose type's template specialization arguments +\tcode{charT} and \tcode{traits} +were the same as those of \tcode{is}. + +\pnum +\effects +Restores from \tcode{is} +the parameters and additional internal data of the lvalue \tcode{d}. +If bad input is encountered, +ensures that \tcode{d} is unchanged by the operation +and +calls \tcode{is.setstate(ios_base::failbit)} +(which may throw \tcode{ios_base::failure}\iref{iostate.flags}). + +\pnum +\ensures +The \tcode{is.\placeholdernc{fmtflags}} are unchanged. + +\pnum +\result +reference to the type of \tcode{is}. + +\pnum +\returns +\tcode{is}. +\end{itemdescr} + \indextext{requirements!random number distribution|)}% \indextext{random number distribution!requirements|)}% \indextext{random number generation!requirements|)} @@ -2458,7 +2632,7 @@ \pnum Each template specified in \ref{rand.eng} requires one or more relationships, -involving the value(s) of its non-type template parameter(s), to hold. +involving the value(s) of its constant template parameter(s), to hold. A program instantiating any of these templates is ill-formed if any such required relationship fails to hold. @@ -2543,10 +2717,12 @@ // inserters and extractors template friend basic_ostream& - operator<<(basic_ostream& os, const linear_congruential_engine& x); + operator<<(basic_ostream& os, // hosted + const linear_congruential_engine& x); template friend basic_istream& - operator>>(basic_istream& is, linear_congruential_engine& x); + operator>>(basic_istream& is, // hosted + linear_congruential_engine& x); }; } \end{codeblock} @@ -2555,7 +2731,7 @@ If the template parameter \tcode{m} is $0$, the modulus $m$ -used throughout this subclause~\ref{rand.eng.lcong} +used throughout \ref{rand.eng.lcong} is \tcode{numeric_limits::max()} plus $1$. \begin{note} $m$ need not be representable @@ -2723,10 +2899,12 @@ // inserters and extractors template friend basic_ostream& - operator<<(basic_ostream& os, const mersenne_twister_engine& x); + operator<<(basic_ostream& os, // hosted + const mersenne_twister_engine& x); template friend basic_istream& - operator>>(basic_istream& is, mersenne_twister_engine& x); + operator>>(basic_istream& is, // hosted + mersenne_twister_engine& x); }; } \end{codeblock} @@ -2742,12 +2920,12 @@ \tcode{t <= w}, \tcode{l <= w}, \tcode{w <= numeric_limits::digits}, - \tcode{a <= (1u< explicit subtract_with_carry_engine(Sseq& q); - void seed(result_type value = default_seed); + void seed(result_type value = 0u); template void seed(Sseq& q); // equality operators @@ -2889,10 +3067,12 @@ // inserters and extractors template friend basic_ostream& - operator<<(basic_ostream& os, const subtract_with_carry_engine& x); + operator<<(basic_ostream& os, // hosted + const subtract_with_carry_engine& x); template friend basic_istream& - operator>>(basic_istream& is, subtract_with_carry_engine& x); + operator>>(basic_istream& is, // hosted + subtract_with_carry_engine& x); }; } \end{codeblock} @@ -2930,8 +3110,8 @@ first construct \tcode{e}, a \tcode{linear_congruential_engine} object, as if by the following definition: \begin{codeblock} -linear_congruential_engine e(value == 0u ? default_seed : value); +linear_congruential_engine e( + value == 0u ? default_seed : static_cast(value % 2147483563u)); \end{codeblock} Then, to set each $X_k$, obtain new values $z_0, \dotsc, z_{n-1}$ @@ -2966,119 +3146,350 @@ otherwise sets $c$ to $0$. \end{itemdescr} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%% Engine adaptors class templates subclause -%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -\rSec2[rand.adapt]{Random number engine adaptor class templates} +% philox_engine engine: -\rSec3[rand.adapt.general]{In general} +\rSec3[rand.eng.philox]{Class template \tcode{philox_engine}}% +\indexlibraryglobal{philox_engine}% \pnum -Each type instantiated -from a class template specified in this subclause~\ref{rand.adapt} -meets the requirements -of a random number engine adaptor\iref{rand.req.adapt} type. +A \tcode{philox_engine} random number engine produces +unsigned integer random numbers in the interval \range{0}{$m$}, +where $m = 2^w$ and +the template parameter $w$ defines the range of the produced numbers. +The state of a \tcode{philox_engine} object consists of +a sequence $X$ of $n$ unsigned integer values of width $w$, +a sequence $K$ of $n/2$ values of \tcode{result_type}, +a sequence $Y$ of $n$ values of \tcode{result_type}, and +a scalar $i$, where +\begin{itemize} +\item +$X$ is the interpretation of the unsigned integer \term{counter} value +$Z \cedef \sum_{j = 0}^{n - 1} X_j \cdot 2^{wj}$ of $n \cdot w$ bits, +\item +$K$ are keys, which are generated once from the seed (see constructors below) +and remain constant unless the \tcode{seed} function\iref{rand.req.eng} is invoked, +\item +$Y$ stores a batch of output values, and +\item +$i$ is an index for an element of the sequence $Y$. +\end{itemize} \pnum -Except where specified otherwise, -the complexity of each function -specified in this subclause~\ref{rand.adapt} -is constant. +The generation algorithm returns $Y_i$, +the value stored in the $i^{th}$ element of $Y$ after applying +the transition algorithm. \pnum -Except where specified otherwise, -no function described in this subclause~\ref{rand.adapt} -throws an exception. +The state transition is performed as if by the following algorithm: +\begin{codeblock} +@$i$@ = @$i$@ + 1 +if (@$i$@ == @$n$@) { + @$Y$@ = Philox(@$K$@, @$X$@) // \seebelow + @$Z$@ = @$Z$@ + 1 + @$i$@ = 0 +} +\end{codeblock} \pnum -Every function described in this subclause~\ref{rand.adapt} -that has a function parameter \tcode{q} of type \tcode{Sseq\&} -for a template type parameter named \tcode{Sseq} -that is different from type \tcode{seed_seq} -throws what and when the invocation of \tcode{q.generate} throws. +The \tcode{Philox} function maps the length-$n/2$ sequence $K$ and +the length-$n$ sequence $X$ into a length-$n$ output sequence $Y$. +Philox applies an $r$-round substitution-permutation network to the values in $X$. +A single round of the generation algorithm performs the following steps: +\begin{itemize} +\item +The output sequence $X'$ of the previous round +($X$ in case of the first round) +is permuted to obtain the intermediate state $V$: +\begin{codeblock} +@$V_j = X'_{f_n(j)}$@ +\end{codeblock} +where $j = 0, \dotsc, n - 1$ and +$f_n(j)$ is defined in \tref{rand.eng.philox.f}. + +\begin{floattable}{Values for the word permutation $\bm{f}_{\bm{n}}\bm{(j)}$}{rand.eng.philox.f} +{l|l|l|l|l|l} +\topline + \multicolumn{2}{|c|}{$\bm{f}_{\bm{n}}\bm{(j)}$} & \multicolumn{4}{c|}{$\bm{j}$} \\ \cline{3-6} + \multicolumn{2}{|c|}{} + & 0 & 1 & 2 & 3 \\ \hline + $\bm{n} $ & 2 & 0 & 1 & \multicolumn{2}{c|}{} \\ \cline{2-6} + & 4 & 2 & 1 & 0 & 3 \\ \cline{2-6} +\end{floattable} +\begin{note} +For $n = 2$ the sequence is not permuted. +\end{note} -\pnum -Descriptions are provided in this subclause~\ref{rand.adapt} -only for adaptor operations -that are not described in subclause~\ref{rand.req.adapt} -or for operations where there is additional semantic information. -In particular, -declarations for copy constructors, -for copy assignment operators, -for streaming operators, -and for equality and inequality operators -are not shown in the synopses. +\item +The following computations are applied to the elements of the $V$ sequence: +\begin{codeblock} +@$X_{2k + 0} = \mulhi(V_{2k}, M_{k}, w) \xor \mathit{key}^q_k \xor V_{2k + 1}$@ +@$X_{2k + 1} = \mullo(V_{2k}, M_{k}, w)$@ +\end{codeblock} +where: + \begin{itemize} + \item + $\mullo(\tcode{a}, \tcode{b}, \tcode{w})$ is + the low half of the modular multiplication of \tcode{a} and \tcode{b}: + $(\tcode{a} \cdot \tcode{b}) \mod 2^w$, -\pnum -Each template specified in this subclause~\ref{rand.adapt} -requires one or more relationships, -involving the value(s) of its non-type template parameter(s), to hold. -A program instantiating any of these templates -is ill-formed -if any such required relationship fails to hold. + \item + $\mulhi(\tcode{a}, \tcode{b}, \tcode{w})$ is + the high half of the modular multiplication of \tcode{a} and \tcode{b}: + $(\left\lfloor (\tcode{a} \cdot \tcode{b}) / 2^w \right\rfloor)$, -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% discard_block_engine engine adaptor: + \item + $k = 0, \dotsc, n/2 - 1$ is the index in the sequences, -\rSec3[rand.adapt.disc]{Class template \tcode{discard_block_engine}}% -\indexlibraryglobal{discard_block_engine}% + \item + $q = 0, \dotsc, r - 1$ is the index of the round, -\pnum -A \tcode{discard_block_engine} random number engine adaptor -produces random numbers -selected from those produced by some base engine $e$. -The state \state{x}{i} -of a \tcode{discard_block_engine} engine adaptor object \tcode{x} -consists of the state \state{e}{i} of its base engine \tcode{e} -and an additional integer $n$. -The size of the state is - the size of $e$'s state plus $1$. + \item + $\mathit{key}^q_k$ is the $k^\text{th}$ round key for round $q$, + $\mathit{key}^q_k \cedef (K_k + q \cdot C_k) \mod 2^w$, -\pnum -The transition algorithm -discards all but $r > 0$ values -from each block of $p \geq r$ values delivered by $e$. -The state transition is performed as follows: -If $n \geq r$, - advance the state of \tcode{e} from \state{e}{i} to \state{e}{i+p-r} - and set $n$ to $0$. -In any case, - then increment $n$ - and advance \tcode{e}'s then-current state \state{e}{j} - to \state{e}{j+1}. + \item + $K_k$ are the elements of the key sequence $K$, + + \item + $M_k$ is \tcode{multipliers[$k$]}, and + + \item + $C_k$ is \tcode{round_consts[$k$]}. + \end{itemize} +\end{itemize} \pnum -The generation algorithm -yields the value returned by the last invocation of \tcode{e()} - while advancing \tcode{e}'s state as described above. +After $r$ applications of the single-round function, +\tcode{Philox} returns the sequence $Y = X'$. -\indexlibraryglobal{discard_block_engine}% -\indexlibrarymember{result_type}{discard_block_engine}% +\indexlibraryglobal{philox_engine}% +\indexlibrarymember{result_type}{philox_engine}% \begin{codeblock} namespace std { - template - class discard_block_engine { + template + class philox_engine { + static constexpr size_t @\exposid{array-size}@ = n / 2; // \expos public: // types - using result_type = typename Engine::result_type; + using result_type = UIntType; // engine characteristics - static constexpr size_t block_size = p; - static constexpr size_t used_block = r; - static constexpr result_type min() { return Engine::min(); } - static constexpr result_type max() { return Engine::max(); } + static constexpr size_t word_size = w; + static constexpr size_t word_count = n; + static constexpr size_t round_count = r; + static constexpr array multipliers; + static constexpr array}@ round_consts; + static constexpr result_type min() { return 0; } + static constexpr result_type max() { return m - 1; } + static constexpr result_type default_seed = 20111115u; // constructors and seeding functions - discard_block_engine(); - explicit discard_block_engine(const Engine& e); - explicit discard_block_engine(Engine&& e); + philox_engine() : philox_engine(default_seed) {} + explicit philox_engine(result_type value); + template explicit philox_engine(Sseq& q); + void seed(result_type value = default_seed); + template void seed(Sseq& q); + + void set_counter(const array& counter); + + // equality operators + friend bool operator==(const philox_engine& x, const philox_engine& y); + + // generating functions + result_type operator()(); + void discard(unsigned long long z); + + // inserters and extractors + template + friend basic_ostream& + operator<<(basic_ostream& os, const philox_engine& x); + template + friend basic_istream& + operator>>(basic_istream& is, philox_engine& x); + }; +} +\end{codeblock} + +\pnum +\mandates +\begin{itemize} +\item \tcode{sizeof...(consts) == n} is \tcode{true}, and +\item \tcode{n == 2 || n == 4} is \tcode{true}, and +\item \tcode{0 < r} is \tcode{true}, and +\item \tcode{0 < w \&\& w <= numeric_limits::digits} is \tcode{true}. +\end{itemize} + +\pnum +The template parameter pack \tcode{consts} represents +the $M_k$ and $C_k$ constants which are grouped as follows: +$[ M_0, C_0, M_1, C_1, M_2, C_2, \dotsc, M_{n/2 - 1}, C_{n/2 - 1} ]$. + +\pnum +The textual representation consists of the values of +$K_0, \dotsc, K_{n/2 - 1}, X_{0}, \dotsc, X_{n - 1}, i$, in that order. +\begin{note} +The stream extraction operator can reconstruct $Y$ from $K$ and $X$, as needed. +\end{note} + +\indexlibraryctor{philox_engine} +\begin{itemdecl} +explicit philox_engine(result_type value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Sets the $K_0$ element of sequence $K$ to $\tcode{value} \mod 2^w$. +All elements of sequences $X$ and $K$ (except $K_0$) are set to \tcode{0}. +The value of $i$ is set to $n - 1$. +\end{itemdescr} + +\indexlibraryctor{philox_engine} +\begin{itemdecl} +template explicit philox_engine(Sseq& q); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +With $p = \left\lceil w / 32 \right\rceil$ and +an array (or equivalent) \tcode{a} of length $(n/2) \cdot p$, +invokes \tcode{q.generate(a + 0, a + n / 2 * $p$)} and +then iteratively for $k = 0, \dotsc, n/2 - 1$, +sets $K_k$ to +$\left(\sum_{j = 0}^{p - 1} a_{k p + j} \cdot 2^{32j} \right) \mod 2^w$. +All elements of sequence $X$ are set to \tcode{0}. +The value of $i$ is set to $n - 1$. +\end{itemdescr} + +\indexlibrarymember{set_counter}{philox_engine}% +\begin{itemdecl} +void set_counter(const array& c); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +For $j = 0, \dotsc, n - 1$ sets $X_j$ to $C_{n - 1 - j} \mod 2^w$. +The value of $i$ is set to $n - 1$. +\begin{note} +The counter is the value $Z$ introduced at the beginning of this subclause. +\end{note} +\end{itemdescr} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Engine adaptors class templates subclause +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\rSec2[rand.adapt]{Random number engine adaptor class templates} + +\rSec3[rand.adapt.general]{General} + +\pnum +Each type instantiated +from a class template specified in \ref{rand.adapt} +meets the requirements +of a random number engine adaptor\iref{rand.req.adapt} type. + +\pnum +Except where specified otherwise, +the complexity of each function +specified in \ref{rand.adapt} +is constant. + +\pnum +Except where specified otherwise, +no function described in \ref{rand.adapt} +throws an exception. + +\pnum +Every function described in \ref{rand.adapt} +that has a function parameter \tcode{q} of type \tcode{Sseq\&} +for a template type parameter named \tcode{Sseq} +that is different from type \tcode{seed_seq} +throws what and when the invocation of \tcode{q.generate} throws. + +\pnum +Descriptions are provided in \ref{rand.adapt} +only for adaptor operations +that are not described in subclause~\ref{rand.req.adapt} +or for operations where there is additional semantic information. +In particular, +declarations for copy constructors, +for copy assignment operators, +for streaming operators, +and for equality and inequality operators +are not shown in the synopses. + +\pnum +Each template specified in \ref{rand.adapt} +requires one or more relationships, +involving the value(s) of its constant template parameter(s), to hold. +A program instantiating any of these templates +is ill-formed +if any such required relationship fails to hold. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% discard_block_engine engine adaptor: + +\rSec3[rand.adapt.disc]{Class template \tcode{discard_block_engine}}% +\indexlibraryglobal{discard_block_engine}% + +\pnum +A \tcode{discard_block_engine} random number engine adaptor +produces random numbers +selected from those produced by some base engine $e$. +The state \state{x}{i} +of a \tcode{discard_block_engine} engine adaptor object \tcode{x} +consists of the state \state{e}{i} of its base engine \tcode{e} +and an additional integer $n$. +The size of the state is + the size of $e$'s state plus $1$. + +\pnum +The transition algorithm +discards all but $r > 0$ values +from each block of $p \geq r$ values delivered by $e$. +The state transition is performed as follows: +If $n \geq r$, + advance the state of \tcode{e} from \state{e}{i} to \state{e}{i+p-r} + and set $n$ to $0$. +In any case, + then increment $n$ + and advance \tcode{e}'s then-current state \state{e}{j} + to \state{e}{j+1}. + +\pnum +The generation algorithm +yields the value returned by the last invocation of \tcode{e()} + while advancing \tcode{e}'s state as described above. + +\indexlibraryglobal{discard_block_engine}% +\indexlibrarymember{result_type}{discard_block_engine}% +\begin{codeblock} +namespace std { + template + class discard_block_engine { + public: + // types + using result_type = typename Engine::result_type; + + // engine characteristics + static constexpr size_t block_size = p; + static constexpr size_t used_block = r; + static constexpr result_type min() { return Engine::min(); } + static constexpr result_type max() { return Engine::max(); } + + // constructors and seeding functions + discard_block_engine(); + explicit discard_block_engine(const Engine& e); + explicit discard_block_engine(Engine&& e); explicit discard_block_engine(result_type s); template explicit discard_block_engine(Sseq& q); void seed(); @@ -3098,10 +3509,10 @@ // inserters and extractors template friend basic_ostream& - operator<<(basic_ostream& os, const discard_block_engine& x); + operator<<(basic_ostream& os, const discard_block_engine& x); // hosted template friend basic_istream& - operator>>(basic_istream& is, discard_block_engine& x); + operator>>(basic_istream& is, discard_block_engine& x); // hosted private: Engine e; // \expos @@ -3213,7 +3624,8 @@ \indexlibraryglobal{independent_bits_engine}% \indexlibrarymember{result_type}{independent_bits_engine}% \begin{codeblock} -template +namespace std { + template class independent_bits_engine { public: // types @@ -3246,14 +3658,15 @@ // inserters and extractors template friend basic_ostream& - operator<<(basic_ostream& os, const independent_bits_engine& x); + operator<<(basic_ostream& os, const independent_bits_engine& x); // hosted template friend basic_istream& - operator>>(basic_istream& is, independent_bits_engine& x); + operator>>(basic_istream& is, independent_bits_engine& x); // hosted private: Engine e; // \expos }; +} \end{codeblock}% \pnum @@ -3380,7 +3793,7 @@ each constructor% \indexlibraryctor{shuffle_order_engine} that is not a copy constructor -initializes $\tcode{V[0]}, \dotsc, \tcode{V[k-1]}$ and $Y$, +initializes $\tcode{V[0]}, \dotsc, \tcode{V[k - 1]}$ and $Y$, in that order, with values returned by successive invocations of \tcode{e()}.% \indextext{random number generation!engines|)} @@ -3565,6 +3978,36 @@ need not generate identical sequences across implementations. \end{note} \end{itemdescr}% + +\indexlibraryglobal{philox4x32}% +\begin{itemdecl} +using philox4x32 = + philox_engine; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\required +The $10000^\text{th}$ consecutive invocation +a default-constructed object of type \tcode{philox4x32} +produces the value $1955073260$. +\end{itemdescr}% + +\indexlibraryglobal{philox4x64}% +\begin{itemdecl} +using philox4x64 = + philox_engine; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\required +The $10000^\text{th}$ consecutive invocation +a default-constructed object of type \tcode{philox4x64} +produces the value $3409172418970261260$. +\end{itemdescr}% \indextext{random number generation!predefined engines and adaptors|)}% \indextext{random number engine adaptor!with predefined parameters|)}% \indextext{random number engine!with predefined parameters|)} @@ -3615,7 +4058,7 @@ // property functions double entropy() const noexcept; - @\textit{// no copy functions}@ + // no copy functions random_device(const random_device&) = delete; void operator=(const random_device&) = delete; }; @@ -3955,28 +4398,46 @@ \indexlibraryglobal{generate_canonical}% \begin{itemdecl} -template +template RealType generate_canonical(URBG& g); \end{itemdecl} \begin{itemdescr} +\pnum +Let +\begin{itemize} +\item $r$ be \tcode{numeric_limits::radix}, +\item $R$ be $\tcode{g.max()} - \tcode{g.min()} + 1$, +\item $d$ be the smaller of + \tcode{digits} and \tcode{numeric_limits::digits}, + \begin{footnote} + $d$ is introduced to avoid any attempt + to produce more bits of randomness + than can be held in \tcode{RealType}. + \end{footnote} +\item $k$ be the smallest integer such that $R^k \ge r^d$, and +\item $x$ be $\left\lfloor R^k / r^d \right\rfloor$. +\end{itemize} +An \defn{attempt} is $k$ invocations of \tcode{g()} +to obtain values $g_0, \dotsc, g_{k-1}$, respectively, +and the calculation of a quantity $S$ given by \eqref{rand.gencanonical}: +\begin{formula}{rand.gencanonical} +S = \sum_{i=0}^{k-1} (g_i - \tcode{g.min()}) \cdot R^i +\end{formula} + \pnum \effects - Invokes \tcode{g()} $k$ times - to obtain values $g_0, \dotsc, g_{k-1}$, respectively. - Calculates a quantity - \[ - S = \sum_{i=0}^{k-1} (g_i - \tcode{g.min()}) - \cdot R^i - \] - using arithmetic of type - \tcode{RealType}. +Attempts are made until $S < xr^d$. +\begin{note} +When $R$ is a power of $r$, precisely one attempt is made. +\end{note} \pnum \returns -$S / R^k$. +$\left\lfloor S / x \right\rfloor / r^d$. \begin{note} -$0 \leq S / R^k < 1$. +The return value $c$ satisfies +$0 \leq c < 1$. \end{note} \pnum @@ -3985,21 +4446,7 @@ \pnum \complexity -Exactly - $k = \max(1, \left\lceil b / \log_2 R \right\rceil)$ - invocations - of \tcode{g}, - where $b$ -\begin{footnote} -$b$ is introduced - to avoid any attempt - to produce more bits of randomness - than can be held in \tcode{RealType}. -\end{footnote} - is the lesser of \tcode{numeric_limits::digits} - and \tcode{bits}, - and - $R$ is the value of $\tcode{g.max()} - \tcode{g.min()} + 1$. +Exactly $k$ invocations of \tcode{g} per attempt. \pnum \begin{note} @@ -4012,6 +4459,13 @@ into a value that can be delivered by a random number distribution. \end{note} + +\pnum +\begin{note} +When $R$ is a power of $r$, +an implementation can avoid using an arithmetic type that is wider +than the output when computing $S$. +\end{note} \end{itemdescr} \indextext{random number generation!utilities|)} @@ -4029,16 +4483,16 @@ \rSec2[rand.dist]{Random number distribution class templates}% \indextext{random number generation!distributions|(} -\rSec3[rand.dist.general]{In general} +\rSec3[rand.dist.general]{General} \pnum Each type instantiated -from a class template specified in this subclause~\ref{rand.dist} +from a class template specified in \ref{rand.dist} meets the requirements of a random number distribution\iref{rand.req.dist} type. \pnum -Descriptions are provided in this subclause~\ref{rand.dist} +Descriptions are provided in \ref{rand.dist} only for distribution operations that are not described in \ref{rand.req.dist} or for operations where there is additional semantic information. @@ -4082,8 +4536,11 @@ produces random integers $i$, $a \leq i \leq b$, distributed according to -the constant discrete probability function% -\[ P(i\,|\,a,b) = 1 / (b - a + 1) \text{ .} \] +the constant discrete probability function in \eqref{rand.dist.uni.int}. + +\begin{formula}{rand.dist.uni.int} +P(i\,|\,a,b) = 1 / (b - a + 1) +\end{formula} \indexlibraryglobal{uniform_int_distribution}% \indexlibrarymember{result_type}{uniform_int_distribution}% @@ -4122,10 +4579,12 @@ // inserters and extractors template friend basic_ostream& - operator<<(basic_ostream& os, const uniform_int_distribution& x); + operator<<(basic_ostream& os, // hosted + const uniform_int_distribution& x); template friend basic_istream& - operator>>(basic_istream& is, uniform_int_distribution& x); + operator>>(basic_istream& is, // hosted + uniform_int_distribution& x); }; } \end{codeblock} @@ -4182,8 +4641,10 @@ produces random numbers $x$, $a \leq x < b$, distributed according to -the constant probability density function% -\[ p(x\,|\,a,b) = 1 / (b - a) \text{ .} \] +the constant probability density function in \eqref{rand.dist.uni.real}. +\begin{formula}{rand.dist.uni.real} +p(x\,|\,a,b) = 1 / (b - a) +\end{formula} \begin{note} This implies that $p(x\,|\,a,b)$ is undefined when \tcode{a == b}. \end{note} @@ -4300,12 +4761,13 @@ A \tcode{bernoulli_distribution} random number distribution produces \tcode{bool} values $b$ distributed according to -the discrete probability function -\[ P(b\,|\,p) = \left\{ \begin{array}{ll} - p & \text{ if $b = \tcode{true}$, or} \\ - 1 - p & \text{ if $b = \tcode{false}$.} +the discrete probability function in \eqref{rand.dist.bern.bernoulli}. +\begin{formula}{rand.dist.bern.bernoulli} +P(b\,|\,p) = \left\{ \begin{array}{ll} + p & \text{ if $b = \tcode{true}$} \\ + 1 - p & \text{ if $b = \tcode{false}$} \end{array}\right. -\] +\end{formula} \indexlibraryglobal{bernoulli_distribution}% \indexlibrarymember{result_type}{bernoulli_distribution}% @@ -4389,8 +4851,11 @@ A \tcode{binomial_distribution} random number distribution produces integer values $i \geq 0$ distributed according to -the discrete probability function% -\[ P(i\,|\,t,p) = \binom{t}{i} \cdot p^i \cdot (1-p)^{t-i} \text{ .} \] +the discrete probability function in \eqref{rand.dist.bern.bin}. + +\begin{formula}{rand.dist.bern.bin} +P(i\,|\,t,p) = \binom{t}{i} \cdot p^i \cdot (1-p)^{t-i} +\end{formula} \indexlibraryglobal{binomial_distribution}% \indexlibrarymember{result_type}{binomial_distribution}% @@ -4487,8 +4952,10 @@ A \tcode{geometric_distribution} random number distribution produces integer values $i \geq 0$ distributed according to -the discrete probability function -\[ P(i\,|\,p) = p \cdot (1-p)^{i} \text{ .} \] +the discrete probability function in \eqref{rand.dist.bern.geo}. +\begin{formula}{rand.dist.bern.geo} +P(i\,|\,p) = p \cdot (1-p)^{i} +\end{formula} \indexlibraryglobal{geometric_distribution}% \indexlibrarymember{result_type}{geometric_distribution}% @@ -4574,8 +5041,10 @@ A \tcode{negative_binomial_distribution} random number distribution produces random integers $i \geq 0$ distributed according to -the discrete probability function -\[ P(i\,|\,k,p) = \binom{k+i-1}{i} \cdot p^k \cdot (1-p)^i \text{ .} \] +the discrete probability function in \eqref{rand.dist.bern.negbin}. +\begin{formula}{rand.dist.bern.negbin} +P(i\,|\,k,p) = \binom{k+i-1}{i} \cdot p^k \cdot (1-p)^i +\end{formula} \begin{note} This implies that $P(i\,|\,k,p)$ is undefined when \tcode{p == 1}. \end{note} @@ -4691,18 +5160,19 @@ A \tcode{poisson_distribution} random number distribution produces integer values $i \geq 0$ distributed according to -the discrete probability function -\[ P(i\,|\,\mu) = \frac{e^{-\mu} \mu^{i}}{i\,!} \text{ .} \] +the discrete probability function in \eqref{rand.dist.pois.poisson}. +\begin{formula}{rand.dist.pois.poisson} +P(i\,|\,\mu) = \frac{e^{-\mu} \mu^{i}}{i\,!} +\end{formula} The distribution parameter $\mu$ -is also known as this distribution's \term{mean}% -. +is also known as this distribution's \term{mean}. \indexlibraryglobal{poisson_distribution}% \indexlibrarymember{result_type}{poisson_distribution}% \begin{codeblock} -template - class poisson_distribution - { +namespace std { + template + class poisson_distribution { public: // types using result_type = IntType; @@ -4738,6 +5208,7 @@ friend basic_istream& operator>>(basic_istream& is, poisson_distribution& x); }; +} \end{codeblock} \indexlibraryctor{poisson_distribution}% @@ -4777,8 +5248,10 @@ An \tcode{exponential_distribution} random number distribution produces random numbers $x > 0$ distributed according to -the probability density function% -\[ p(x\,|\,\lambda) = \lambda e^{-\lambda x} \text{ .} \] +the probability density function in \eqref{rand.dist.pois.exp}. +\begin{formula}{rand.dist.pois.exp} +p(x\,|\,\lambda) = \lambda e^{-\lambda x} +\end{formula} \indexlibraryglobal{exponential_distribution}% \indexlibrarymember{result_type}{exponential_distribution}% @@ -4862,10 +5335,11 @@ A \tcode{gamma_distribution} random number distribution produces random numbers $x > 0$ distributed according to -the probability density function% -\[ p(x\,|\,\alpha,\beta) = +the probability density function in \eqref{rand.dist.pois.gamma}. +\begin{formula}{rand.dist.pois.gamma} +p(x\,|\,\alpha,\beta) = \frac{e^{-x/\beta}}{\beta^{\alpha} \cdot \Gamma(\alpha)} \, \cdot \, x^{\, \alpha-1} - \text{ .} \] +\end{formula} \indexlibraryglobal{gamma_distribution}% \indexlibrarymember{result_type}{gamma_distribution}% @@ -4964,11 +5438,12 @@ A \tcode{weibull_distribution} random number distribution produces random numbers $x \geq 0$ distributed according to -the probability density function% -\[ p(x\,|\,a,b) = \frac{a}{b} +the probability density function in \eqref{rand.dist.pois.weibull}. +\begin{formula}{rand.dist.pois.weibull} +p(x\,|\,a,b) = \frac{a}{b} \cdot \left(\frac{x}{b}\right)^{a-1} \cdot \, \exp\left( -\left(\frac{x}{b}\right)^a\right) - \text{ .} \] +\end{formula} \indexlibraryglobal{weibull_distribution}% \indexlibrarymember{result_type}{weibull_distribution}% @@ -5066,7 +5541,7 @@ An \tcode{extreme_value_distribution} random number distribution produces random numbers $x$ distributed according to -the probability density function +the probability density function in \eqref{rand.dist.pois.extreme}. \begin{footnote} The distribution corresponding to this probability density function @@ -5077,9 +5552,10 @@ or the Fisher-Tippett Type I distribution. \end{footnote} -\[ p(x\,|\,a,b) = \frac{1}{b} +\begin{formula}{rand.dist.pois.extreme} +p(x\,|\,a,b) = \frac{1}{b} \cdot \exp\left(\frac{a-x}{b} - \exp\left(\frac{a-x}{b}\right)\right) - \text{ .} \] +\end{formula} \indexlibraryglobal{extreme_value_distribution}% \indexlibrarymember{result_type}{extreme_value_distribution}% @@ -5191,8 +5667,8 @@ A \tcode{normal_distribution} random number distribution produces random numbers $x$ distributed according to -the probability density function% -\[% +the probability density function in \eqref{rand.dist.norm.normal}. +\begin{formula}{rand.dist.norm.normal} p(x\,|\,\mu,\sigma) = \frac{1}{\sigma \sqrt{2\pi}} \cdot @@ -5201,8 +5677,7 @@ {2 \sigma^2} \right) } - \text{ .} -\] +\end{formula} The distribution parameters $\mu$ and $\sigma$ are also known as this distribution's \term{mean} and \term{standard deviation}. @@ -5304,10 +5779,11 @@ A \tcode{lognormal_distribution} random number distribution produces random numbers $x > 0$ distributed according to -the probability density function% -\[ p(x\,|\,m,s) = \frac{1}{s x \sqrt{2 \pi}} +the probability density function in \eqref{rand.dist.norm.lognormal}. +\begin{formula}{rand.dist.norm.lognormal} +p(x\,|\,m,s) = \frac{1}{s x \sqrt{2 \pi}} \cdot \exp{\left(-\frac{(\ln{x} - m)^2}{2 s^2}\right)} - \text{ .} \] +\end{formula} \indexlibraryglobal{lognormal_distribution}% \indexlibrarymember{result_type}{lognormal_distribution}% @@ -5406,8 +5882,10 @@ A \tcode{chi_squared_distribution} random number distribution produces random numbers $x > 0$ distributed according to -the probability density function% -\[ p(x\,|\,n) = \frac{x^{(n/2)-1} \cdot e^{-x/2}}{\Gamma(n/2) \cdot 2^{n/2}} \text{ .} \] +the probability density function in \eqref{rand.dist.norm.chisq}. +\begin{formula}{rand.dist.norm.chisq} +p(x\,|\,n) = \frac{x^{(n/2)-1} \cdot e^{-x/2}}{\Gamma(n/2) \cdot 2^{n/2}} +\end{formula} \indexlibraryglobal{chi_squared_distribution}% \indexlibrarymember{result_type}{chi_squared_distribution}% @@ -5492,8 +5970,10 @@ A \tcode{cauchy_distribution} random number distribution produces random numbers $x$ distributed according to -the probability density function% -\[ p(x\,|\,a,b) = \left(\pi b \left(1 + \left(\frac{x-a}{b} \right)^2 \, \right)\right)^{-1} \text{ .} \] +the probability density function in \eqref{rand.dist.norm.cauchy}. +\begin{formula}{rand.dist.norm.cauchy} +p(x\,|\,a,b) = \left(\pi b \left(1 + \left(\frac{x-a}{b} \right)^2 \, \right)\right)^{-1} +\end{formula} \indexlibraryglobal{cauchy_distribution}% \indexlibrarymember{result_type}{cauchy_distribution}% @@ -5592,12 +6072,13 @@ A \tcode{fisher_f_distribution} random number distribution produces random numbers $x \ge 0$ distributed according to -the probability density function% -\[ p(x\,|\,m,n) = \frac{\Gamma\big((m+n)/2\big)}{\Gamma(m/2) \; \Gamma(n/2)} +the probability density function in \eqref{rand.dist.norm.f}. +\begin{formula}{rand.dist.norm.f} +p(x\,|\,m,n) = \frac{\Gamma\big((m+n)/2\big)}{\Gamma(m/2) \; \Gamma(n/2)} \cdot \left(\frac{m}{n}\right)^{m/2} \cdot x^{(m/2)-1} \cdot \left(1 + \frac{m x}{n}\right)^{-(m + n)/2} - \text{ .} \] +\end{formula} \indexlibraryglobal{fisher_f_distribution}% \indexlibrarymember{result_type}{fisher_distribution}% @@ -5696,11 +6177,12 @@ A \tcode{student_t_distribution} random number distribution produces random numbers $x$ distributed according to -the probability density function% -\[ p(x\,|\,n) = \frac{1}{\sqrt{n \pi}} +the probability density function in \eqref{rand.dist.norm.t}. +\begin{formula}{rand.dist.norm.t} +p(x\,|\,n) = \frac{1}{\sqrt{n \pi}} \cdot \frac{\Gamma\big((n+1)/2\big)}{\Gamma(n/2)} \cdot \left(1 + \frac{x^2}{n} \right)^{-(n+1)/2} - \text{ .} \] +\end{formula} \indexlibraryglobal{student_t_distribution}% \indexlibrarymember{result_type}{student_t_distribution}% @@ -5799,8 +6281,10 @@ A \tcode{discrete_distribution} random number distribution produces random integers $i$, $0 \leq i < n$, distributed according to -the discrete probability function% -\[ P(i \,|\, p_0, \dotsc, p_{n-1}) = p_i \text{ .} \] +the discrete probability function in \eqref{rand.dist.samp.discrete}. +\begin{formula}{rand.dist.samp.discrete} +P(i \,|\, p_0, \dotsc, p_{n-1}) = p_i +\end{formula} \pnum Unless specified otherwise, @@ -5901,7 +6385,7 @@ \pnum \effects Constructs a \tcode{discrete_distribution} object -with probabilities given by the formula above. +with probabilities given by the \eqref{rand.dist.samp.discrete}. \end{itemdescr} @@ -5978,9 +6462,11 @@ $b_0 \leq x < b_n$, uniformly distributed over each subinterval $[ b_i, b_{i+1} )$ -according to the probability density function -\[ p(x \,|\, b_0, \dotsc, b_n, \; \rho_0, \dotsc, \rho_{n-1}) = \rho_i - \text{ , for $b_i \le x < b_{i+1}$.} \] +according to the probability density function in \eqref{rand.dist.samp.pconst}. +\begin{formula}{rand.dist.samp.pconst} +p(x \,|\, b_0, \dotsc, b_n, \; \rho_0, \dotsc, \rho_{n-1}) = \rho_i + \text{ , for $b_i \le x < b_{i+1}$} +\end{formula} \pnum The $n + 1$ distribution parameters $b_i$, @@ -6069,8 +6555,8 @@ \indexlibraryctor{piecewise_constant_distribution}% \begin{itemdecl} template - piecewise_constant_distribution(InputIteratorB firstB, InputIteratorB lastB, - InputIteratorW firstW); + piecewise_constant_distribution(InputIteratorB firstB, InputIteratorB lastB, + InputIteratorW firstW); \end{itemdecl} \begin{itemdescr} @@ -6111,7 +6597,7 @@ \indexlibraryctor{piecewise_constant_distribution}% \begin{itemdecl} template - piecewise_constant_distribution(initializer_list bl, UnaryOperation fw); + piecewise_constant_distribution(initializer_list bl, UnaryOperation fw); \end{itemdecl} \begin{itemdescr} @@ -6145,7 +6631,7 @@ \indexlibraryctor{piecewise_constant_distribution}% \begin{itemdecl} template - piecewise_constant_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw); + piecewise_constant_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw); \end{itemdecl} \begin{itemdescr} @@ -6214,11 +6700,13 @@ $b_0 \leq x < b_n$, distributed over each subinterval $[b_i, b_{i+1})$ -according to the probability density function -\[ p(x \,|\, b_0, \dotsc, b_n, \; \rho_0, \dotsc, \rho_n) +according to the probability density function in \eqref{rand.dist.samp.plinear}. +\begin{formula}{rand.dist.samp.plinear} +p(x \,|\, b_0, \dotsc, b_n, \; \rho_0, \dotsc, \rho_n) = \rho_{i} \cdot {\frac{b_{i+1} - x}{b_{i+1} - b_i}} + \rho_{i+1} \cdot {\frac{x - b_i}{b_{i+1} - b_i}} - \text{ , for $b_i \le x < b_{i+1}$.} \] + \text{ , for $b_i \le x < b_{i+1}$.} +\end{formula} \pnum The $n + 1$ distribution parameters $b_i$, @@ -6302,14 +6790,19 @@ \indexlibraryctor{piecewise_linear_distribution} \begin{itemdecl} template - piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB, - InputIteratorW firstW); + piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB, + InputIteratorW firstW); \end{itemdecl} \begin{itemdescr} \pnum \mandates -\tcode{is_invocable_r_v} is \tcode{true}. +Both of +\begin{itemize} +\item{\tcode{is_convertible_v::value_type, double>}} +\item{\tcode{is_convertible_v::value_type, double>}} +\end{itemize} +are \tcode{true}. \pnum \expects @@ -6339,7 +6832,7 @@ \indexlibraryctor{piecewise_linear_distribution}% \begin{itemdecl} template - piecewise_linear_distribution(initializer_list bl, UnaryOperation fw); + piecewise_linear_distribution(initializer_list bl, UnaryOperation fw); \end{itemdecl} \begin{itemdescr} @@ -6373,7 +6866,7 @@ \indexlibraryctor{piecewise_linear_distribution}% \begin{itemdecl} template - piecewise_linear_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw); + piecewise_linear_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw); \end{itemdecl} \begin{itemdescr} @@ -7082,13 +7575,13 @@ \indexlibrarymember{operator[]}{valarray}% \begin{itemdecl} -const T& operator[](size_t n) const; +const T& operator[](size_t n) const; T& operator[](size_t n); \end{itemdecl} \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{n < size()} is \tcode{true}. \pnum @@ -8711,23 +9204,6 @@ \rSec2[cmath.syn]{Header \tcode{} synopsis} \indexheader{cmath}% -\indexlibraryglobal{FP_FAST_FMA}% -\indexlibraryglobal{FP_FAST_FMAF}% -\indexlibraryglobal{FP_FAST_FMAL}% -\indexlibraryglobal{FP_ILOGB0}% -\indexlibraryglobal{FP_ILOGBNAN}% -\indexlibraryglobal{FP_INFINITE}% -\indexlibraryglobal{FP_NAN}% -\indexlibraryglobal{FP_NORMAL}% -\indexlibraryglobal{FP_SUBNORMAL}% -\indexlibraryglobal{FP_ZERO}% -\indexlibraryglobal{HUGE_VAL}% -\indexlibraryglobal{HUGE_VALF}% -\indexlibraryglobal{HUGE_VALL}% -\indexlibraryglobal{INFINITY}% -\indexlibraryglobal{MATH_ERREXCEPT}% -\indexlibraryglobal{MATH_ERRNO}% -\indexlibraryglobal{NAN}% \indexlibraryglobal{abs}% \indexlibraryglobal{acos}% \indexlibraryglobal{acosf}% @@ -8856,7 +9332,6 @@ \indexlibraryglobal{lround}% \indexlibraryglobal{lroundf}% \indexlibraryglobal{lroundl}% -\indexlibraryglobal{math_errhandling}% \indexlibraryglobal{modf}% \indexlibraryglobal{modff}% \indexlibraryglobal{modfl}% @@ -8916,398 +9391,396 @@ \indexlibraryglobal{truncf}% \indexlibraryglobal{truncl}% \begin{codeblock} +#define @\libmacro{HUGE_VAL}@ @\seebelow@ +#define @\libmacro{HUGE_VALF}@ @\seebelow@ +#define @\libmacro{HUGE_VALL}@ @\seebelow@ +#define @\libmacro{INFINITY}@ @\seebelow@ +#define @\libmacro{NAN}@ @\seebelow@ +#define @\libmacro{FP_INFINITE}@ @\seebelow@ +#define @\libmacro{FP_NAN}@ @\seebelow@ +#define @\libmacro{FP_NORMAL}@ @\seebelow@ +#define @\libmacro{FP_SUBNORMAL}@ @\seebelow@ +#define @\libmacro{FP_ZERO}@ @\seebelow@ +#define @\libmacro{FP_FAST_FMA}@ @\seebelow@ +#define @\libmacro{FP_FAST_FMAF}@ @\seebelow@ +#define @\libmacro{FP_FAST_FMAL}@ @\seebelow@ +#define @\libmacro{FP_ILOGB0}@ @\seebelow@ +#define @\libmacro{FP_ILOGBNAN}@ @\seebelow@ +#define @\libmacro{MATH_ERRNO}@ @\seebelow@ +#define @\libmacro{MATH_ERREXCEPT}@ @\seebelow@ + +#define @\libmacro{math_errhandling}@ @\seebelow@ + namespace std { using float_t = @\seebelow@; using double_t = @\seebelow@; -} - -#define HUGE_VAL @\seebelow@ -#define HUGE_VALF @\seebelow@ -#define HUGE_VALL @\seebelow@ -#define INFINITY @\seebelow@ -#define NAN @\seebelow@ -#define FP_INFINITE @\seebelow@ -#define FP_NAN @\seebelow@ -#define FP_NORMAL @\seebelow@ -#define FP_SUBNORMAL @\seebelow@ -#define FP_ZERO @\seebelow@ -#define FP_FAST_FMA @\seebelow@ -#define FP_FAST_FMAF @\seebelow@ -#define FP_FAST_FMAL @\seebelow@ -#define FP_ILOGB0 @\seebelow@ -#define FP_ILOGBNAN @\seebelow@ -#define MATH_ERRNO @\seebelow@ -#define MATH_ERREXCEPT @\seebelow@ - -#define math_errhandling @\seebelow@ -namespace std { - @\placeholder{floating-point-type}@ acos(@\placeholder{floating-point-type}@ x); - float acosf(float x); - long double acosl(long double x); + constexpr @\placeholdernc{floating-point-type}@ acos(@\placeholdernc{floating-point-type}@ x); + constexpr float acosf(float x); + constexpr long double acosl(long double x); - @\placeholder{floating-point-type}@ asin(@\placeholder{floating-point-type}@ x); - float asinf(float x); - long double asinl(long double x); + constexpr @\placeholdernc{floating-point-type}@ asin(@\placeholdernc{floating-point-type}@ x); + constexpr float asinf(float x); + constexpr long double asinl(long double x); - @\placeholder{floating-point-type}@ atan(@\placeholder{floating-point-type}@ x); - float atanf(float x); - long double atanl(long double x); + constexpr @\placeholdernc{floating-point-type}@ atan(@\placeholdernc{floating-point-type}@ x); + constexpr float atanf(float x); + constexpr long double atanl(long double x); - @\placeholder{floating-point-type}@ atan2(@\placeholder{floating-point-type}@ y, @\placeholder{floating-point-type}@ x); - float atan2f(float y, float x); - long double atan2l(long double y, long double x); + constexpr @\placeholdernc{floating-point-type}@ atan2(@\placeholdernc{floating-point-type}@ y, @\placeholdernc{floating-point-type}@ x); + constexpr float atan2f(float y, float x); + constexpr long double atan2l(long double y, long double x); - @\placeholder{floating-point-type}@ cos(@\placeholder{floating-point-type}@ x); - float cosf(float x); - long double cosl(long double x); + constexpr @\placeholdernc{floating-point-type}@ cos(@\placeholdernc{floating-point-type}@ x); + constexpr float cosf(float x); + constexpr long double cosl(long double x); - @\placeholder{floating-point-type}@ sin(@\placeholder{floating-point-type}@ x); - float sinf(float x); - long double sinl(long double x); + constexpr @\placeholdernc{floating-point-type}@ sin(@\placeholdernc{floating-point-type}@ x); + constexpr float sinf(float x); + constexpr long double sinl(long double x); - @\placeholder{floating-point-type}@ tan(@\placeholder{floating-point-type}@ x); - float tanf(float x); - long double tanl(long double x); + constexpr @\placeholdernc{floating-point-type}@ tan(@\placeholdernc{floating-point-type}@ x); + constexpr float tanf(float x); + constexpr long double tanl(long double x); - @\placeholder{floating-point-type}@ acosh(@\placeholder{floating-point-type}@ x); - float acoshf(float x); - long double acoshl(long double x); + constexpr @\placeholdernc{floating-point-type}@ acosh(@\placeholdernc{floating-point-type}@ x); + constexpr float acoshf(float x); + constexpr long double acoshl(long double x); - @\placeholder{floating-point-type}@ asinh(@\placeholder{floating-point-type}@ x); - float asinhf(float x); - long double asinhl(long double x); + constexpr @\placeholdernc{floating-point-type}@ asinh(@\placeholdernc{floating-point-type}@ x); + constexpr float asinhf(float x); + constexpr long double asinhl(long double x); - @\placeholder{floating-point-type}@ atanh(@\placeholder{floating-point-type}@ x); - float atanhf(float x); - long double atanhl(long double x); + constexpr @\placeholdernc{floating-point-type}@ atanh(@\placeholdernc{floating-point-type}@ x); + constexpr float atanhf(float x); + constexpr long double atanhl(long double x); - @\placeholder{floating-point-type}@ cosh(@\placeholder{floating-point-type}@ x); - float coshf(float x); - long double coshl(long double x); + constexpr @\placeholdernc{floating-point-type}@ cosh(@\placeholdernc{floating-point-type}@ x); + constexpr float coshf(float x); + constexpr long double coshl(long double x); - @\placeholder{floating-point-type}@ sinh(@\placeholder{floating-point-type}@ x); - float sinhf(float x); - long double sinhl(long double x); + constexpr @\placeholdernc{floating-point-type}@ sinh(@\placeholdernc{floating-point-type}@ x); + constexpr float sinhf(float x); + constexpr long double sinhl(long double x); - @\placeholder{floating-point-type}@ tanh(@\placeholder{floating-point-type}@ x); - float tanhf(float x); - long double tanhl(long double x); + constexpr @\placeholdernc{floating-point-type}@ tanh(@\placeholdernc{floating-point-type}@ x); + constexpr float tanhf(float x); + constexpr long double tanhl(long double x); - @\placeholder{floating-point-type}@ exp(@\placeholder{floating-point-type}@ x); - float expf(float x); - long double expl(long double x); + constexpr @\placeholdernc{floating-point-type}@ exp(@\placeholdernc{floating-point-type}@ x); + constexpr float expf(float x); + constexpr long double expl(long double x); - @\placeholder{floating-point-type}@ exp2(@\placeholder{floating-point-type}@ x); - float exp2f(float x); - long double exp2l(long double x); + constexpr @\placeholdernc{floating-point-type}@ exp2(@\placeholdernc{floating-point-type}@ x); + constexpr float exp2f(float x); + constexpr long double exp2l(long double x); - @\placeholder{floating-point-type}@ expm1(@\placeholder{floating-point-type}@ x); - float expm1f(float x); - long double expm1l(long double x); + constexpr @\placeholdernc{floating-point-type}@ expm1(@\placeholdernc{floating-point-type}@ x); + constexpr float expm1f(float x); + constexpr long double expm1l(long double x); - constexpr @\placeholder{floating-point-type}@ frexp(@\placeholder{floating-point-type}@ value, int* exp); - constexpr float frexpf(float value, int* exp); - constexpr long double frexpl(long double value, int* exp); + constexpr @\placeholdernc{floating-point-type}@ frexp(@\placeholdernc{floating-point-type}@ value, int* exp); + constexpr float frexpf(float value, int* exp); + constexpr long double frexpl(long double value, int* exp); - constexpr int ilogb(@\placeholder{floating-point-type}@ x); + constexpr int ilogb(@\placeholdernc{floating-point-type}@ x); constexpr int ilogbf(float x); constexpr int ilogbl(long double x); - constexpr @\placeholder{floating-point-type}@ ldexp(@\placeholder{floating-point-type}@ x, int exp); - constexpr float ldexpf(float x, int exp); - constexpr long double ldexpl(long double x, int exp); + constexpr @\placeholdernc{floating-point-type}@ ldexp(@\placeholdernc{floating-point-type}@ x, int exp); + constexpr float ldexpf(float x, int exp); + constexpr long double ldexpl(long double x, int exp); - @\placeholder{floating-point-type}@ log(@\placeholder{floating-point-type}@ x); - float logf(float x); - long double logl(long double x); + constexpr @\placeholdernc{floating-point-type}@ log(@\placeholdernc{floating-point-type}@ x); + constexpr float logf(float x); + constexpr long double logl(long double x); - @\placeholder{floating-point-type}@ log10(@\placeholder{floating-point-type}@ x); - float log10f(float x); - long double log10l(long double x); + constexpr @\placeholdernc{floating-point-type}@ log10(@\placeholdernc{floating-point-type}@ x); + constexpr float log10f(float x); + constexpr long double log10l(long double x); - @\placeholder{floating-point-type}@ log1p(@\placeholder{floating-point-type}@ x); - float log1pf(float x); - long double log1pl(long double x); + constexpr @\placeholdernc{floating-point-type}@ log1p(@\placeholdernc{floating-point-type}@ x); + constexpr float log1pf(float x); + constexpr long double log1pl(long double x); - @\placeholder{floating-point-type}@ log2(@\placeholder{floating-point-type}@ x); - float log2f(float x); - long double log2l(long double x); + constexpr @\placeholdernc{floating-point-type}@ log2(@\placeholdernc{floating-point-type}@ x); + constexpr float log2f(float x); + constexpr long double log2l(long double x); - constexpr @\placeholder{floating-point-type}@ logb(@\placeholder{floating-point-type}@ x); - constexpr float logbf(float x); - constexpr long double logbl(long double x); + constexpr @\placeholdernc{floating-point-type}@ logb(@\placeholdernc{floating-point-type}@ x); + constexpr float logbf(float x); + constexpr long double logbl(long double x); - constexpr @\placeholder{floating-point-type}@ modf(@\placeholder{floating-point-type}@ value, @\placeholder{floating-point-type}@* iptr); - constexpr float modff(float value, float* iptr); - constexpr long double modfl(long double value, long double* iptr); + constexpr @\placeholdernc{floating-point-type}@ modf(@\placeholdernc{floating-point-type}@ value, @\placeholdernc{floating-point-type}@* iptr); + constexpr float modff(float value, float* iptr); + constexpr long double modfl(long double value, long double* iptr); - constexpr @\placeholder{floating-point-type}@ scalbn(@\placeholder{floating-point-type}@ x, int n); - constexpr float scalbnf(float x, int n); - constexpr long double scalbnl(long double x, int n); + constexpr @\placeholdernc{floating-point-type}@ scalbn(@\placeholdernc{floating-point-type}@ x, int n); + constexpr float scalbnf(float x, int n); + constexpr long double scalbnl(long double x, int n); - constexpr @\placeholder{floating-point-type}@ scalbln(@\placeholder{floating-point-type}@ x, long int n); - constexpr float scalblnf(float x, long int n); - constexpr long double scalblnl(long double x, long int n); + constexpr @\placeholdernc{floating-point-type}@ scalbln(@\placeholdernc{floating-point-type}@ x, long int n); + constexpr float scalblnf(float x, long int n); + constexpr long double scalblnl(long double x, long int n); - @\placeholder{floating-point-type}@ cbrt(@\placeholder{floating-point-type}@ x); - float cbrtf(float x); - long double cbrtl(long double x); + constexpr @\placeholdernc{floating-point-type}@ cbrt(@\placeholdernc{floating-point-type}@ x); + constexpr float cbrtf(float x); + constexpr long double cbrtl(long double x); // \ref{c.math.abs}, absolute values - constexpr int abs(int j); - constexpr long int abs(long int j); - constexpr long long int abs(long long int j); - constexpr @\placeholder{floating-point-type}@ abs(@\placeholder{floating-point-type}@ j); + constexpr int abs(int j); // freestanding + constexpr long int abs(long int j); // freestanding + constexpr long long int abs(long long int j); // freestanding + constexpr @\placeholdernc{floating-point-type}@ abs(@\placeholdernc{floating-point-type}@ j); // freestanding-deleted - constexpr @\placeholder{floating-point-type}@ fabs(@\placeholder{floating-point-type}@ x); - constexpr float fabsf(float x); - constexpr long double fabsl(long double x); + constexpr @\placeholdernc{floating-point-type}@ fabs(@\placeholdernc{floating-point-type}@ x); + constexpr float fabsf(float x); + constexpr long double fabsl(long double x); - @\placeholder{floating-point-type}@ hypot(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - float hypotf(float x, float y); - long double hypotl(long double x, long double y); + constexpr @\placeholdernc{floating-point-type}@ hypot(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr float hypotf(float x, float y); + constexpr long double hypotl(long double x, long double y); // \ref{c.math.hypot3}, three-dimensional hypotenuse - @\placeholder{floating-point-type}@ hypot(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y, - @\placeholder{floating-point-type}@ z); + constexpr @\placeholdernc{floating-point-type}@ hypot(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y, + @\placeholdernc{floating-point-type}@ z); - @\placeholder{floating-point-type}@ pow(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - float powf(float x, float y); - long double powl(long double x, long double y); + constexpr @\placeholdernc{floating-point-type}@ pow(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr float powf(float x, float y); + constexpr long double powl(long double x, long double y); - @\placeholder{floating-point-type}@ sqrt(@\placeholder{floating-point-type}@ x); - float sqrtf(float x); - long double sqrtl(long double x); + constexpr @\placeholdernc{floating-point-type}@ sqrt(@\placeholdernc{floating-point-type}@ x); + constexpr float sqrtf(float x); + constexpr long double sqrtl(long double x); - @\placeholder{floating-point-type}@ erf(@\placeholder{floating-point-type}@ x); - float erff(float x); - long double erfl(long double x); + constexpr @\placeholdernc{floating-point-type}@ erf(@\placeholdernc{floating-point-type}@ x); + constexpr float erff(float x); + constexpr long double erfl(long double x); - @\placeholder{floating-point-type}@ erfc(@\placeholder{floating-point-type}@ x); - float erfcf(float x); - long double erfcl(long double x); + constexpr @\placeholdernc{floating-point-type}@ erfc(@\placeholdernc{floating-point-type}@ x); + constexpr float erfcf(float x); + constexpr long double erfcl(long double x); - @\placeholder{floating-point-type}@ lgamma(@\placeholder{floating-point-type}@ x); - float lgammaf(float x); - long double lgammal(long double x); + constexpr @\placeholdernc{floating-point-type}@ lgamma(@\placeholdernc{floating-point-type}@ x); + constexpr float lgammaf(float x); + constexpr long double lgammal(long double x); - @\placeholder{floating-point-type}@ tgamma(@\placeholder{floating-point-type}@ x); - float tgammaf(float x); - long double tgammal(long double x); + constexpr @\placeholdernc{floating-point-type}@ tgamma(@\placeholdernc{floating-point-type}@ x); + constexpr float tgammaf(float x); + constexpr long double tgammal(long double x); - constexpr @\placeholder{floating-point-type}@ ceil(@\placeholder{floating-point-type}@ x); - constexpr float ceilf(float x); - constexpr long double ceill(long double x); + constexpr @\placeholdernc{floating-point-type}@ ceil(@\placeholdernc{floating-point-type}@ x); + constexpr float ceilf(float x); + constexpr long double ceill(long double x); - constexpr @\placeholder{floating-point-type}@ floor(@\placeholder{floating-point-type}@ x); - constexpr float floorf(float x); - constexpr long double floorl(long double x); + constexpr @\placeholdernc{floating-point-type}@ floor(@\placeholdernc{floating-point-type}@ x); + constexpr float floorf(float x); + constexpr long double floorl(long double x); - @\placeholder{floating-point-type}@ nearbyint(@\placeholder{floating-point-type}@ x); - float nearbyintf(float x); - long double nearbyintl(long double x); + @\placeholdernc{floating-point-type}@ nearbyint(@\placeholdernc{floating-point-type}@ x); + float nearbyintf(float x); + long double nearbyintl(long double x); - @\placeholder{floating-point-type}@ rint(@\placeholder{floating-point-type}@ x); - float rintf(float x); - long double rintl(long double x); + @\placeholdernc{floating-point-type}@ rint(@\placeholdernc{floating-point-type}@ x); + float rintf(float x); + long double rintl(long double x); - long int lrint(@\placeholder{floating-point-type}@ x); + long int lrint(@\placeholdernc{floating-point-type}@ x); long int lrintf(float x); long int lrintl(long double x); - long long int llrint(@\placeholder{floating-point-type}@ x); + long long int llrint(@\placeholdernc{floating-point-type}@ x); long long int llrintf(float x); long long int llrintl(long double x); - constexpr @\placeholder{floating-point-type}@ round(@\placeholder{floating-point-type}@ x); - constexpr float roundf(float x); - constexpr long double roundl(long double x); + constexpr @\placeholdernc{floating-point-type}@ round(@\placeholdernc{floating-point-type}@ x); + constexpr float roundf(float x); + constexpr long double roundl(long double x); - constexpr long int lround(@\placeholder{floating-point-type}@ x); + constexpr long int lround(@\placeholdernc{floating-point-type}@ x); constexpr long int lroundf(float x); constexpr long int lroundl(long double x); - constexpr long long int llround(@\placeholder{floating-point-type}@ x); + constexpr long long int llround(@\placeholdernc{floating-point-type}@ x); constexpr long long int llroundf(float x); constexpr long long int llroundl(long double x); - constexpr @\placeholder{floating-point-type}@ trunc(@\placeholder{floating-point-type}@ x); - constexpr float truncf(float x); - constexpr long double truncl(long double x); + constexpr @\placeholdernc{floating-point-type}@ trunc(@\placeholdernc{floating-point-type}@ x); + constexpr float truncf(float x); + constexpr long double truncl(long double x); - constexpr @\placeholder{floating-point-type}@ fmod(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr float fmodf(float x, float y); - constexpr long double fmodl(long double x, long double y); + constexpr @\placeholdernc{floating-point-type}@ fmod(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr float fmodf(float x, float y); + constexpr long double fmodl(long double x, long double y); - constexpr @\placeholder{floating-point-type}@ remainder(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr float remainderf(float x, float y); - constexpr long double remainderl(long double x, long double y); + constexpr @\placeholdernc{floating-point-type}@ remainder(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr float remainderf(float x, float y); + constexpr long double remainderl(long double x, long double y); - constexpr @\placeholder{floating-point-type}@ remquo(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y, int* quo); - constexpr float remquof(float x, float y, int* quo); - constexpr long double remquol(long double x, long double y, int* quo); + constexpr @\placeholdernc{floating-point-type}@ remquo(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y, int* quo); + constexpr float remquof(float x, float y, int* quo); + constexpr long double remquol(long double x, long double y, int* quo); - constexpr @\placeholder{floating-point-type}@ copysign(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr float copysignf(float x, float y); - constexpr long double copysignl(long double x, long double y); + constexpr @\placeholdernc{floating-point-type}@ copysign(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr float copysignf(float x, float y); + constexpr long double copysignl(long double x, long double y); - double nan(const char* tagp); - float nanf(const char* tagp); + double nan(const char* tagp); + float nanf(const char* tagp); long double nanl(const char* tagp); - constexpr @\placeholder{floating-point-type}@ nextafter(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr float nextafterf(float x, float y); - constexpr long double nextafterl(long double x, long double y); + constexpr @\placeholdernc{floating-point-type}@ nextafter(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr float nextafterf(float x, float y); + constexpr long double nextafterl(long double x, long double y); - constexpr @\placeholder{floating-point-type}@ nexttoward(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr float nexttowardf(float x, long double y); - constexpr long double nexttowardl(long double x, long double y); + constexpr @\placeholdernc{floating-point-type}@ nexttoward(@\placeholdernc{floating-point-type}@ x, long double y); + constexpr float nexttowardf(float x, long double y); + constexpr long double nexttowardl(long double x, long double y); - constexpr @\placeholder{floating-point-type}@ fdim(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr float fdimf(float x, float y); - constexpr long double fdiml(long double x, long double y); + constexpr @\placeholdernc{floating-point-type}@ fdim(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr float fdimf(float x, float y); + constexpr long double fdiml(long double x, long double y); - constexpr @\placeholder{floating-point-type}@ fmax(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr float fmaxf(float x, float y); - constexpr long double fmaxl(long double x, long double y); + constexpr @\placeholdernc{floating-point-type}@ fmax(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr float fmaxf(float x, float y); + constexpr long double fmaxl(long double x, long double y); - constexpr @\placeholder{floating-point-type}@ fmin(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr float fminf(float x, float y); - constexpr long double fminl(long double x, long double y); + constexpr @\placeholdernc{floating-point-type}@ fmin(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr float fminf(float x, float y); + constexpr long double fminl(long double x, long double y); - constexpr @\placeholder{floating-point-type}@ fma(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y, - @\placeholder{floating-point-type}@ z); - constexpr float fmaf(float x, float y, float z); - constexpr long double fmal(long double x, long double y, long double z); + constexpr @\placeholdernc{floating-point-type}@ fma(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y, + @\placeholdernc{floating-point-type}@ z); + constexpr float fmaf(float x, float y, float z); + constexpr long double fmal(long double x, long double y, long double z); // \ref{c.math.lerp}, linear interpolation - constexpr @\placeholder{floating-point-type}@ lerp(@\placeholder{floating-point-type}@ a, @\placeholder{floating-point-type}@ b, - @\placeholder{floating-point-type}@ t) noexcept; + constexpr @\placeholdernc{floating-point-type}@ lerp(@\placeholdernc{floating-point-type}@ a, @\placeholdernc{floating-point-type}@ b, + @\placeholdernc{floating-point-type}@ t) noexcept; // \ref{c.math.fpclass}, classification / comparison functions - constexpr int fpclassify(@\placeholder{floating-point-type}@ x); - constexpr bool isfinite(@\placeholder{floating-point-type}@ x); - constexpr bool isinf(@\placeholder{floating-point-type}@ x); - constexpr bool isnan(@\placeholder{floating-point-type}@ x); - constexpr bool isnormal(@\placeholder{floating-point-type}@ x); - constexpr bool signbit(@\placeholder{floating-point-type}@ x); - constexpr bool isgreater(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr bool isgreaterequal(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr bool isless(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr bool islessequal(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr bool islessgreater(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - constexpr bool isunordered(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); + constexpr int fpclassify(@\placeholdernc{floating-point-type}@ x); + constexpr bool isfinite(@\placeholdernc{floating-point-type}@ x); + constexpr bool isinf(@\placeholdernc{floating-point-type}@ x); + constexpr bool isnan(@\placeholdernc{floating-point-type}@ x); + constexpr bool isnormal(@\placeholdernc{floating-point-type}@ x); + constexpr bool signbit(@\placeholdernc{floating-point-type}@ x); + constexpr bool isgreater(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr bool isgreaterequal(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr bool isless(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr bool islessequal(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr bool islessgreater(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr bool isunordered(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); // \ref{sf.cmath}, mathematical special functions // \ref{sf.cmath.assoc.laguerre}, associated Laguerre polynomials - @\placeholder{floating-point-type}@ assoc_laguerre(unsigned n, unsigned m, @\placeholder{floating-point-type}@ x); - float assoc_laguerref(unsigned n, unsigned m, float x); - long double assoc_laguerrel(unsigned n, unsigned m, long double x); + @\placeholdernc{floating-point-type}@ assoc_laguerre(unsigned n, unsigned m, @\placeholdernc{floating-point-type}@ x); + float assoc_laguerref(unsigned n, unsigned m, float x); + long double assoc_laguerrel(unsigned n, unsigned m, long double x); // \ref{sf.cmath.assoc.legendre}, associated Legendre functions - @\placeholder{floating-point-type}@ assoc_legendre(unsigned l, unsigned m, @\placeholder{floating-point-type}@ x); - float assoc_legendref(unsigned l, unsigned m, float x); - long double assoc_legendrel(unsigned l, unsigned m, long double x); + @\placeholdernc{floating-point-type}@ assoc_legendre(unsigned l, unsigned m, @\placeholdernc{floating-point-type}@ x); + float assoc_legendref(unsigned l, unsigned m, float x); + long double assoc_legendrel(unsigned l, unsigned m, long double x); // \ref{sf.cmath.beta}, beta function - @\placeholder{floating-point-type}@ beta(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y); - float betaf(float x, float y); - long double betal(long double x, long double y); + @\placeholdernc{floating-point-type}@ beta(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + float betaf(float x, float y); + long double betal(long double x, long double y); // \ref{sf.cmath.comp.ellint.1}, complete elliptic integral of the first kind - @\placeholder{floating-point-type}@ comp_ellint_1(@\placeholder{floating-point-type}@ k); - float comp_ellint_1f(float k); - long double comp_ellint_1l(long double k); + @\placeholdernc{floating-point-type}@ comp_ellint_1(@\placeholdernc{floating-point-type}@ k); + float comp_ellint_1f(float k); + long double comp_ellint_1l(long double k); // \ref{sf.cmath.comp.ellint.2}, complete elliptic integral of the second kind - @\placeholder{floating-point-type}@ comp_ellint_2(@\placeholder{floating-point-type}@ k); - float comp_ellint_2f(float k); - long double comp_ellint_2l(long double k); + @\placeholdernc{floating-point-type}@ comp_ellint_2(@\placeholdernc{floating-point-type}@ k); + float comp_ellint_2f(float k); + long double comp_ellint_2l(long double k); // \ref{sf.cmath.comp.ellint.3}, complete elliptic integral of the third kind - @\placeholder{floating-point-type}@ comp_ellint_3(@\placeholder{floating-point-type}@ k, @\placeholder{floating-point-type}@ nu); - float comp_ellint_3f(float k, float nu); - long double comp_ellint_3l(long double k, long double nu); + @\placeholdernc{floating-point-type}@ comp_ellint_3(@\placeholdernc{floating-point-type}@ k, @\placeholdernc{floating-point-type}@ nu); + float comp_ellint_3f(float k, float nu); + long double comp_ellint_3l(long double k, long double nu); // \ref{sf.cmath.cyl.bessel.i}, regular modified cylindrical Bessel functions - @\placeholder{floating-point-type}@ cyl_bessel_i(@\placeholder{floating-point-type}@ nu, @\placeholder{floating-point-type}@ x); - float cyl_bessel_if(float nu, float x); - long double cyl_bessel_il(long double nu, long double x); + @\placeholdernc{floating-point-type}@ cyl_bessel_i(@\placeholdernc{floating-point-type}@ nu, @\placeholdernc{floating-point-type}@ x); + float cyl_bessel_if(float nu, float x); + long double cyl_bessel_il(long double nu, long double x); // \ref{sf.cmath.cyl.bessel.j}, cylindrical Bessel functions of the first kind - @\placeholder{floating-point-type}@ cyl_bessel_j(@\placeholder{floating-point-type}@ nu, @\placeholder{floating-point-type}@ x); - float cyl_bessel_jf(float nu, float x); - long double cyl_bessel_jl(long double nu, long double x); + @\placeholdernc{floating-point-type}@ cyl_bessel_j(@\placeholdernc{floating-point-type}@ nu, @\placeholdernc{floating-point-type}@ x); + float cyl_bessel_jf(float nu, float x); + long double cyl_bessel_jl(long double nu, long double x); // \ref{sf.cmath.cyl.bessel.k}, irregular modified cylindrical Bessel functions - @\placeholder{floating-point-type}@ cyl_bessel_k(@\placeholder{floating-point-type}@ nu, @\placeholder{floating-point-type}@ x); - float cyl_bessel_kf(float nu, float x); - long double cyl_bessel_kl(long double nu, long double x); + @\placeholdernc{floating-point-type}@ cyl_bessel_k(@\placeholdernc{floating-point-type}@ nu, @\placeholdernc{floating-point-type}@ x); + float cyl_bessel_kf(float nu, float x); + long double cyl_bessel_kl(long double nu, long double x); // \ref{sf.cmath.cyl.neumann}, cylindrical Neumann functions // cylindrical Bessel functions of the second kind - @\placeholder{floating-point-type}@ cyl_neumann(@\placeholder{floating-point-type}@ nu, @\placeholder{floating-point-type}@ x); - float cyl_neumannf(float nu, float x); - long double cyl_neumannl(long double nu, long double x); + @\placeholdernc{floating-point-type}@ cyl_neumann(@\placeholdernc{floating-point-type}@ nu, @\placeholdernc{floating-point-type}@ x); + float cyl_neumannf(float nu, float x); + long double cyl_neumannl(long double nu, long double x); // \ref{sf.cmath.ellint.1}, incomplete elliptic integral of the first kind - @\placeholder{floating-point-type}@ ellint_1(@\placeholder{floating-point-type}@ k, @\placeholder{floating-point-type}@ phi); - float ellint_1f(float k, float phi); - long double ellint_1l(long double k, long double phi); + @\placeholdernc{floating-point-type}@ ellint_1(@\placeholdernc{floating-point-type}@ k, @\placeholdernc{floating-point-type}@ phi); + float ellint_1f(float k, float phi); + long double ellint_1l(long double k, long double phi); // \ref{sf.cmath.ellint.2}, incomplete elliptic integral of the second kind - @\placeholder{floating-point-type}@ ellint_2(@\placeholder{floating-point-type}@ k, @\placeholder{floating-point-type}@ phi); - float ellint_2f(float k, float phi); - long double ellint_2l(long double k, long double phi); + @\placeholdernc{floating-point-type}@ ellint_2(@\placeholdernc{floating-point-type}@ k, @\placeholdernc{floating-point-type}@ phi); + float ellint_2f(float k, float phi); + long double ellint_2l(long double k, long double phi); // \ref{sf.cmath.ellint.3}, incomplete elliptic integral of the third kind - @\placeholder{floating-point-type}@ ellint_3(@\placeholder{floating-point-type}@ k, @\placeholder{floating-point-type}@ nu, - @\placeholder{floating-point-type}@ phi); - float ellint_3f(float k, float nu, float phi); - long double ellint_3l(long double k, long double nu, long double phi); + @\placeholdernc{floating-point-type}@ ellint_3(@\placeholdernc{floating-point-type}@ k, @\placeholdernc{floating-point-type}@ nu, + @\placeholdernc{floating-point-type}@ phi); + float ellint_3f(float k, float nu, float phi); + long double ellint_3l(long double k, long double nu, long double phi); // \ref{sf.cmath.expint}, exponential integral - @\placeholder{floating-point-type}@ expint(@\placeholder{floating-point-type}@ x); - float expintf(float x); - long double expintl(long double x); + @\placeholdernc{floating-point-type}@ expint(@\placeholdernc{floating-point-type}@ x); + float expintf(float x); + long double expintl(long double x); // \ref{sf.cmath.hermite}, Hermite polynomials - @\placeholder{floating-point-type}@ hermite(unsigned n, @\placeholder{floating-point-type}@ x); - float hermitef(unsigned n, float x); - long double hermitel(unsigned n, long double x); + @\placeholdernc{floating-point-type}@ hermite(unsigned n, @\placeholdernc{floating-point-type}@ x); + float hermitef(unsigned n, float x); + long double hermitel(unsigned n, long double x); // \ref{sf.cmath.laguerre}, Laguerre polynomials - @\placeholder{floating-point-type}@ laguerre(unsigned n, @\placeholder{floating-point-type}@ x); - float laguerref(unsigned n, float x); - long double laguerrel(unsigned n, long double x); + @\placeholdernc{floating-point-type}@ laguerre(unsigned n, @\placeholdernc{floating-point-type}@ x); + float laguerref(unsigned n, float x); + long double laguerrel(unsigned n, long double x); // \ref{sf.cmath.legendre}, Legendre polynomials - @\placeholder{floating-point-type}@ legendre(unsigned l, @\placeholder{floating-point-type}@ x); - float legendref(unsigned l, float x); - long double legendrel(unsigned l, long double x); + @\placeholdernc{floating-point-type}@ legendre(unsigned l, @\placeholdernc{floating-point-type}@ x); + float legendref(unsigned l, float x); + long double legendrel(unsigned l, long double x); // \ref{sf.cmath.riemann.zeta}, Riemann zeta function - @\placeholder{floating-point-type}@ riemann_zeta(@\placeholder{floating-point-type}@ x); - float riemann_zetaf(float x); - long double riemann_zetal(long double x); + @\placeholdernc{floating-point-type}@ riemann_zeta(@\placeholdernc{floating-point-type}@ x); + float riemann_zetaf(float x); + long double riemann_zetal(long double x); // \ref{sf.cmath.sph.bessel}, spherical Bessel functions of the first kind - @\placeholder{floating-point-type}@ sph_bessel(unsigned n, @\placeholder{floating-point-type}@ x); - float sph_besself(unsigned n, float x); - long double sph_bessell(unsigned n, long double x); + @\placeholdernc{floating-point-type}@ sph_bessel(unsigned n, @\placeholdernc{floating-point-type}@ x); + float sph_besself(unsigned n, float x); + long double sph_bessell(unsigned n, long double x); // \ref{sf.cmath.sph.legendre}, spherical associated Legendre functions - @\placeholder{floating-point-type}@ sph_legendre(unsigned l, unsigned m, @\placeholder{floating-point-type}@ theta); - float sph_legendref(unsigned l, unsigned m, float theta); - long double sph_legendrel(unsigned l, unsigned m, long double theta); + @\placeholdernc{floating-point-type}@ sph_legendre(unsigned l, unsigned m, @\placeholdernc{floating-point-type}@ theta); + float sph_legendref(unsigned l, unsigned m, float theta); + long double sph_legendrel(unsigned l, unsigned m, long double theta); // \ref{sf.cmath.sph.neumann}, spherical Neumann functions; // spherical Bessel functions of the second kind - @\placeholder{floating-point-type}@ sph_neumann(unsigned n, @\placeholder{floating-point-type}@ x); - float sph_neumannf(unsigned n, float x); - long double sph_neumannl(unsigned n, long double x); + @\placeholdernc{floating-point-type}@ sph_neumann(unsigned n, @\placeholdernc{floating-point-type}@ x); + float sph_neumannf(unsigned n, float x); + long double sph_neumannl(unsigned n, long double x); } \end{codeblock} @@ -9349,6 +9822,11 @@ a usable candidate\iref{over.match.general} from the overloads provided by the implementation. +\pnum +An invocation of \tcode{nexttoward} is ill-formed if +the argument corresponding to the \placeholder{floating-point-type} parameter +has extended floating-point type. + \xrefc{7.12} \rSec2[c.math.abs]{Absolute values} @@ -9381,7 +9859,8 @@ if \tcode{X} cannot be converted to \tcode{int} by integral promotion\iref{conv.prom}, the program is ill-formed. \begin{note} -Arguments that can be promoted to \tcode{int} are permitted for compatibility with C. +Allowing arguments that can be promoted to \tcode{int} +provides compatibility with C. \end{note} \end{itemdescr} @@ -9401,7 +9880,8 @@ \indexlibrary{\idxcode{hypot}!3-argument form}% \begin{itemdecl} -@\placeholder{floating-point-type}@ hypot(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y, double z); +constexpr @\placeholder{floating-point-type}@ hypot(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y, + @\placeholder{floating-point-type}@ z); \end{itemdecl} \begin{itemdescr} @@ -9526,13 +10006,17 @@ \pnum \returns -\[ \mathsf{L}_n^m(x) = - (-1)^m \frac{\mathsf{d} ^ m}{\mathsf{d}x ^ m} \, \mathsf{L}_{n+m}(x) - \text{ ,\quad for $x \ge 0$,} \] -where +$\mathsf{L}_n^m(x)$, +where $\mathsf{L}_n^m$ is given by \eqref{sf.cmath.assoc.laguerre}, +$\mathsf{L}_{n+m}$ is given by \eqref{sf.cmath.laguerre}, $n$ is \tcode{n}, $m$ is \tcode{m}, and $x$ is \tcode{x}. +\begin{formula}{sf.cmath.assoc.laguerre} +\mathsf{L}_n^m(x) = + (-1)^m \frac{\mathsf{d} ^ m}{\mathsf{d}x ^ m} \, \mathsf{L}_{n+m}(x) + \text{ ,\quad for $x \ge 0$} +\end{formula} \pnum \remarks @@ -9564,13 +10048,17 @@ \pnum \returns -\[ \mathsf{P}_\ell^m(x) = (1 - x^2) ^ {m/2} \: - \frac{\mathsf{d} ^ m}{\mathsf{d}x ^ m} \, \mathsf{P}_\ell(x) - \text{ ,\quad for $|x| \le 1$,} \] -where -$l$ is \tcode{l}, +$\mathsf{P}_\ell^m(x)$, +where $\mathsf{P}_\ell^m$ is given by \eqref{sf.cmath.assoc.legendre}, +$\mathsf{P}_\ell$ is given by \eqref{sf.cmath.legendre}, +$\ell$ is \tcode{l}, $m$ is \tcode{m}, and $x$ is \tcode{x}. +\begin{formula}{sf.cmath.assoc.legendre} +\mathsf{P}_\ell^m(x) = (1 - x^2) ^ {m/2} \: + \frac{\mathsf{d} ^ m}{\mathsf{d}x ^ m} \, \mathsf{P}_\ell(x) + \text{ ,\quad for $|x| \le 1$} +\end{formula} \pnum \remarks @@ -9601,11 +10089,14 @@ \pnum \returns -\[ \mathsf{B}(x, y) = \frac{\Gamma(x) \, \Gamma(y)}{\Gamma(x + y)} - \text{ ,\quad for $x > 0$,\, $y > 0$,} \] -where +$\mathsf{B}(x, y)$, +where $\mathsf{B}$ is given by \eqref{sf.cmath.beta}, $x$ is \tcode{x} and $y$ is \tcode{y}. +\begin{formula}{sf.cmath.beta} +\mathsf{B}(x, y) = \frac{\Gamma(x) \, \Gamma(y)}{\Gamma(x + y)} + \text{ ,\quad for $x > 0$,\, $y > 0$} +\end{formula} \end{itemdescr} \rSec3[sf.cmath.comp.ellint.1]{Complete elliptic integral of the first kind}% @@ -9630,9 +10121,12 @@ \pnum \returns -\[ \mathsf{K}(k) = \mathsf{F}(k, \pi / 2) \text{ ,\quad for $|k| \le 1$,} \] -where +$\mathsf{K}(k)$, +where $\mathsf{K}$ is given by \eqref{sf.cmath.comp.ellint.1} and $k$ is \tcode{k}. +\begin{formula}{sf.cmath.comp.ellint.1} +\mathsf{K}(k) = \mathsf{F}(k, \pi / 2) \text{ ,\quad for $|k| \le 1$} +\end{formula} \pnum See also \ref{sf.cmath.ellint.1}. @@ -9660,9 +10154,12 @@ \pnum \returns -\[ \mathsf{E}(k) = \mathsf{E}(k, \pi / 2) \text{ ,\quad for $|k| \le 1$,} \] -where +$\mathsf{E}(k)$, +where $\mathsf{E}$ is given by \eqref{sf.cmath.comp.ellint.2} and $k$ is \tcode{k}. +\begin{formula}{sf.cmath.comp.ellint.2} +\mathsf{E}(k) = \mathsf{E}(k, \pi / 2) \text{ ,\quad for $|k| \le 1$} +\end{formula} \pnum See also \ref{sf.cmath.ellint.2}. @@ -9690,10 +10187,13 @@ \pnum \returns -\[ \mathsf{\Pi}(\nu, k) = \mathsf{\Pi}(\nu, k, \pi / 2) \text{ ,\quad for $|k| \le 1$,} \] -where -$k$ is \tcode{k} and +$\mathsf{\Pi}(\nu, k)$, +where $\mathsf{\Pi}$ is given by \eqref{sf.cmath.comp.ellint.3}, +$k$ is \tcode{k}, and $\nu$ is \tcode{nu}. +\begin{formula}{sf.cmath.comp.ellint.3} +\mathsf{\Pi}(\nu, k) = \mathsf{\Pi}(\nu, k, \pi / 2) \text{ ,\quad for $|k| \le 1$} +\end{formula} \pnum See also \ref{sf.cmath.ellint.3}. @@ -9704,7 +10204,7 @@ \indexlibraryglobal{cyl_bessel_if}% \indexlibraryglobal{cyl_bessel_il}% \indextext{Bessel functions!$\mathsf{I}_\nu$}% -\indextext{I nu@$\mathsf{I}_\nu$ (Bessell functions)}% +\indextext{I nu@$\mathsf{I}_\nu$ (Bessel functions)}% \begin{itemdecl} @\placeholder{floating-point-type}@ cyl_bessel_i(@\placeholder{floating-point-type}@ nu, @\placeholder{floating-point-type}@ x); float cyl_bessel_if(float nu, float x); @@ -9721,13 +10221,16 @@ \pnum \returns -\[ \mathsf{I}_\nu(x) = +$\mathsf{I}_\nu(x)$, +where $\mathsf{I}_\nu$ is given by \eqref{sf.cmath.cyl.bessel.i}, +$\nu$ is \tcode{nu}, and +$x$ is \tcode{x}. +\begin{formula}{sf.cmath.cyl.bessel.i} +\mathsf{I}_\nu(x) = \mathrm{i}^{-\nu} \mathsf{J}_\nu(\mathrm{i}x) = \sum_{k=0}^\infty \frac{(x/2)^{\nu+2k}}{k! \: \Gamma(\nu+k+1)} - \text{ ,\quad for $x \ge 0$,} \] -where -$\nu$ is \tcode{nu} and -$x$ is \tcode{x}. + \text{ ,\quad for $x \ge 0$} +\end{formula} \pnum \remarks @@ -9744,7 +10247,7 @@ \indexlibraryglobal{cyl_bessel_jf}% \indexlibraryglobal{cyl_bessel_jl}% \indextext{Bessel functions!$\mathsf{J}_\nu$}% -\indextext{J nu@$\mathsf{J}_\nu$ (Bessell functions)}% +\indextext{J nu@$\mathsf{J}_\nu$ (Bessel functions)}% \begin{itemdecl} @\placeholder{floating-point-type}@ cyl_bessel_j(@\placeholder{floating-point-type}@ nu, @\placeholder{floating-point-type}@ x); float cyl_bessel_jf(float nu, float x); @@ -9762,12 +10265,15 @@ \pnum \returns -\[ \mathsf{J}_\nu(x) = - \sum_{k=0}^\infty \frac{(-1)^k (x/2)^{\nu+2k}}{k! \: \Gamma(\nu+k+1)} - \text{ ,\quad for $x \ge 0$,} \] -where -$\nu$ is \tcode{nu} and +$\mathsf{J}_\nu(x)$, +where $\mathsf{J}_\nu$ is given by \eqref{sf.cmath.cyl.bessel.j}, +$\nu$ is \tcode{nu}, and $x$ is \tcode{x}. +\begin{formula}{sf.cmath.cyl.bessel.j} +\mathsf{J}_\nu(x) = + \sum_{k=0}^\infty \frac{(-1)^k (x/2)^{\nu+2k}}{k! \: \Gamma(\nu+k+1)} + \text{ ,\quad for $x \ge 0$} +\end{formula} \pnum \remarks @@ -9781,7 +10287,7 @@ \indexlibraryglobal{cyl_bessel_kf}% \indexlibraryglobal{cyl_bessel_kl}% \indextext{Bessel functions!$\mathsf{K}_\nu$}% -\indextext{K nu@$\mathsf{K}_\nu$ (Bessell functions)}% +\indextext{K nu@$\mathsf{K}_\nu$ (Bessel functions)}% \begin{itemdecl} @\placeholder{floating-point-type}@ cyl_bessel_k(@\placeholder{floating-point-type}@ nu, @\placeholder{floating-point-type}@ x); float cyl_bessel_kf(float nu, float x); @@ -9799,7 +10305,11 @@ \pnum \returns -\[% +$\mathsf{K}_\nu(x)$, +where $\mathsf{K}_\nu$ is given by \eqref{sf.cmath.cyl.bessel.k}, +$\nu$ is \tcode{nu}, and +$x$ is \tcode{x}. +\begin{formula}{sf.cmath.cyl.bessel.k} \mathsf{K}_\nu(x) = (\pi/2)\mathrm{i}^{\nu+1} ( \mathsf{J}_\nu(\mathrm{i}x) + \mathrm{i} \mathsf{N}_\nu(\mathrm{i}x) @@ -9821,10 +10331,7 @@ & \mbox{for $x \ge 0$ and integral $\nu$} \end{array} \right. -\] -where -$\nu$ is \tcode{nu} and -$x$ is \tcode{x}. +\end{formula} \pnum \remarks @@ -9860,7 +10367,11 @@ \pnum \returns -\[% +$\mathsf{N}_\nu(x)$, +where $\mathsf{N}_\nu$ is given by \eqref{sf.cmath.cyl.neumann}, +$\nu$ is \tcode{nu}, and +$x$ is \tcode{x}. +\begin{formula}{sf.cmath.cyl.neumann} \mathsf{N}_\nu(x) = \left\{ \begin{array}{cl} @@ -9876,10 +10387,7 @@ & \mbox{for $x \ge 0$ and integral $\nu$} \end{array} \right. -\] -where -$\nu$ is \tcode{nu} and -$x$ is \tcode{x}. +\end{formula} \pnum \remarks @@ -9913,12 +10421,15 @@ \pnum \returns -\[ \mathsf{F}(k, \phi) = - \int_0^\phi \! \frac{\mathsf{d}\theta}{\sqrt{1 - k^2 \sin^2 \theta}} - \text{ ,\quad for $|k| \le 1$,} \] -where -$k$ is \tcode{k} and +$\mathsf{F}(k, \phi)$, +where $\mathsf{F}$ is given by \eqref{sf.cmath.ellint.1}, +$k$ is \tcode{k}, and $\phi$ is \tcode{phi}. +\begin{formula}{sf.cmath.ellint.1} +\mathsf{F}(k, \phi) = + \int_0^\phi \! \frac{\mathsf{d}\theta}{\sqrt{1 - k^2 \sin^2 \theta}} + \text{ ,\quad for $|k| \le 1$} +\end{formula} \end{itemdescr} \rSec3[sf.cmath.ellint.2]{Incomplete elliptic integral of the second kind}% @@ -9943,11 +10454,14 @@ \pnum \returns -\[ \mathsf{E}(k, \phi) = \int_0^\phi \! \sqrt{1 - k^2 \sin^2 \theta} \, \mathsf{d}\theta - \text{ ,\quad for $|k| \le 1$,} \] -where -$k$ is \tcode{k} and +$\mathsf{E}(k, \phi)$, +where $\mathsf{E}$ is given by \eqref{sf.cmath.ellint.2}, +$k$ is \tcode{k}, and $\phi$ is \tcode{phi}. +\begin{formula}{sf.cmath.ellint.2} +\mathsf{E}(k, \phi) = \int_0^\phi \! \sqrt{1 - k^2 \sin^2 \theta} \, \mathsf{d}\theta + \text{ ,\quad for $|k| \le 1$} +\end{formula} \end{itemdescr} \rSec3[sf.cmath.ellint.3]{Incomplete elliptic integral of the third kind}% @@ -9974,12 +10488,15 @@ \pnum \returns -\[ \mathsf{\Pi}(\nu, k, \phi) = \int_0^\phi \! - \frac{ \mathsf{d}\theta }{ (1 - \nu \, \sin^2 \theta) \sqrt{1 - k^2 \sin^2 \theta} } \text{ ,\quad for $|k| \le 1$,} \] -where +$\mathsf{\Pi}(\nu, k, \phi)$, +where $\mathsf{\Pi}$ is given by \eqref{sf.cmath.ellint.3}, $\nu$ is \tcode{nu}, $k$ is \tcode{k}, and $\phi$ is \tcode{phi}. +\begin{formula}{sf.cmath.ellint.3} +\mathsf{\Pi}(\nu, k, \phi) = \int_0^\phi \! + \frac{ \mathsf{d}\theta }{ (1 - \nu \, \sin^2 \theta) \sqrt{1 - k^2 \sin^2 \theta} } \text{ ,\quad for $|k| \le 1$} +\end{formula} \end{itemdescr} \rSec3[sf.cmath.expint]{Exponential integral}% @@ -10004,15 +10521,14 @@ \pnum \returns -\[% +$\mathsf{Ei}(x)$, +where $\mathsf{Ei}$ is given by \eqref{sf.cmath.expint} and +$x$ is \tcode{x}. +\begin{formula}{sf.cmath.expint} \mathsf{Ei}(x) = - \int_{-x}^\infty \frac{e^{-t}} {t } \, \mathsf{d}t -\; -\] -where -$x$ is \tcode{x}. - +\end{formula} \end{itemdescr} \rSec3[sf.cmath.hermite]{Hermite polynomials}% @@ -10036,15 +10552,15 @@ \pnum \returns -\[% +$\mathsf{H}_n(x)$, +where $\mathsf{H}_n$ is given by \eqref{sf.cmath.hermite}, +$n$ is \tcode{n}, and +$x$ is \tcode{x}. +\begin{formula}{sf.cmath.hermite} \mathsf{H}_n(x) = (-1)^n e^{x^2} \frac{ \mathsf{d} ^n} { \mathsf{d}x^n} \, e^{-x^2} -\; -\] -where -$n$ is \tcode{n} and -$x$ is \tcode{x}. +\end{formula} \pnum \remarks @@ -10074,12 +10590,15 @@ \pnum \returns -\[ \mathsf{L}_n(x) = +$\mathsf{L}_n(x)$, +where $\mathsf{L}_n$ is given by \eqref{sf.cmath.laguerre}, +$n$ is \tcode{n}, and +$x$ is \tcode{x}. +\begin{formula}{sf.cmath.laguerre} +\mathsf{L}_n(x) = \frac{e^x}{n!} \frac{\mathsf{d}^n}{\mathsf{d}x^n} \, (x^n e^{-x}) - \text{ ,\quad for $x \ge 0$,} \] -where -$n$ is \tcode{n} and -$x$ is \tcode{x}. + \text{ ,\quad for $x \ge 0$} +\end{formula} \pnum \remarks @@ -10109,13 +10628,16 @@ \pnum \returns -\[ \mathsf{P}_\ell(x) = +$\mathsf{P}_\ell(x)$, +where $\mathsf{P}_\ell$ is given by \eqref{sf.cmath.legendre}, +$l$ is \tcode{l}, and +$x$ is \tcode{x}. +\begin{formula}{sf.cmath.legendre} +\mathsf{P}_\ell(x) = \frac{1}{2^\ell \, \ell!} \frac{\mathsf{d}^\ell}{\mathsf{d}x^\ell} \, (x^2 - 1) ^ \ell - \text{ ,\quad for $|x| \le 1$,} \] -where -$l$ is \tcode{l} and -$x$ is \tcode{x}. + \text{ ,\quad for $|x| \le 1$} +\end{formula} \pnum \remarks @@ -10145,7 +10667,10 @@ \pnum \returns -\[% +$\mathsf{\zeta}(x)$, +where $\mathsf{\zeta}$ is given by \eqref{sf.cmath.riemann.zeta} and +$x$ is \tcode{x}. +\begin{formula}{sf.cmath.riemann.zeta} \mathsf{\zeta}(x) = \left\{ \begin{array}{cl} @@ -10166,10 +10691,7 @@ & \mbox{for $x < 0$} \end{array} \right. -\; -\] -where -$x$ is \tcode{x}. +\end{formula} \end{itemdescr} \rSec3[sf.cmath.sph.bessel]{Spherical Bessel functions of the first kind}% @@ -10194,10 +10716,13 @@ \pnum \returns -\[ \mathsf{j}_n(x) = (\pi/2x)^{1\!/\!2} \mathsf{J}_{n + 1\!/\!2}(x) \text{ ,\quad for $x \ge 0$,} \] -where -$n$ is \tcode{n} and +$\mathsf{j}_n(x)$, +where $\mathsf{j}_n$ is given by \eqref{sf.cmath.sph.bessel}, +$n$ is \tcode{n}, and $x$ is \tcode{x}. +\begin{formula}{sf.cmath.sph.bessel} +\mathsf{j}_n(x) = (\pi/2x)^{1\!/\!2} \mathsf{J}_{n + 1\!/\!2}(x) \text{ ,\quad for $x \ge 0$} +\end{formula} \pnum \remarks @@ -10231,17 +10756,17 @@ \pnum \returns -\[ \mathsf{Y}_\ell^m(\theta, 0) \] -where -\[ \mathsf{Y}_\ell^m(\theta, \phi) = - (-1)^m \left[\frac{(2 \ell + 1)}{4 \pi} \frac{(\ell - m)!}{(\ell + m)!}\right]^{1/2} - \mathsf{P}_\ell^m (\cos\theta) e^{i m \phi} - \text{ ,\quad for $|m| \le \ell$,} -\] -and +$\mathsf{Y}_\ell^m(\theta, 0)$, +where $\mathsf{Y}_\ell^m$ is given by \eqref{sf.cmath.sph.legendre}, $l$ is \tcode{l}, $m$ is \tcode{m}, and $\theta$ is \tcode{theta}. +\begin{formula}{sf.cmath.sph.legendre} +\mathsf{Y}_\ell^m(\theta, \phi) = + (-1)^m \left[\frac{(2 \ell + 1)}{4 \pi} \frac{(\ell - m)!}{(\ell + m)!}\right]^{1/2} + \mathsf{P}_\ell^m (\cos\theta) e^{i m \phi} + \text{ ,\quad for $|m| \le \ell$} +\end{formula} \pnum \remarks @@ -10276,11 +10801,14 @@ \pnum \returns -\[ \mathsf{n}_n(x) = (\pi/2x)^{1\!/\!2} \mathsf{N}_{n + 1\!/\!2}(x) - \text{ ,\quad for $x \ge 0$,} \] -where -$n$ is \tcode{n} and +$\mathsf{n}_n(x)$, +where $\mathsf{n}_n$ is given by \eqref{sf.cmath.sph.neumann}, +$n$ is \tcode{n}, and $x$ is \tcode{x}. +\begin{formula}{sf.cmath.sph.neumann} +\mathsf{n}_n(x) = (\pi/2x)^{1\!/\!2} \mathsf{N}_{n + 1\!/\!2}(x) + \text{ ,\quad for $x \ge 0$} +\end{formula} \pnum \remarks @@ -10301,47 +10829,47 @@ \indexheader{numbers}% \begin{codeblock} namespace std::numbers { - template inline constexpr T e_v = @\unspec@; - template inline constexpr T log2e_v = @\unspec@; - template inline constexpr T log10e_v = @\unspec@; - template inline constexpr T pi_v = @\unspec@; - template inline constexpr T inv_pi_v = @\unspec@; - template inline constexpr T inv_sqrtpi_v = @\unspec@; - template inline constexpr T ln2_v = @\unspec@; - template inline constexpr T ln10_v = @\unspec@; - template inline constexpr T sqrt2_v = @\unspec@; - template inline constexpr T sqrt3_v = @\unspec@; - template inline constexpr T inv_sqrt3_v = @\unspec@; - template inline constexpr T egamma_v = @\unspec@; - template inline constexpr T phi_v = @\unspec@; - - template<@\libconcept{floating_point}@ T> inline constexpr T e_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T log2e_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T log10e_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T pi_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T inv_pi_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T inv_sqrtpi_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T ln2_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T ln10_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T sqrt2_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T sqrt3_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T inv_sqrt3_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T egamma_v = @\seebelow@; - template<@\libconcept{floating_point}@ T> inline constexpr T phi_v = @\seebelow@; - - inline constexpr double e = e_v; - inline constexpr double log2e = log2e_v; - inline constexpr double log10e = log10e_v; - inline constexpr double pi = pi_v; - inline constexpr double inv_pi = inv_pi_v; - inline constexpr double inv_sqrtpi = inv_sqrtpi_v; - inline constexpr double ln2 = ln2_v; - inline constexpr double ln10 = ln10_v; - inline constexpr double sqrt2 = sqrt2_v; - inline constexpr double sqrt3 = sqrt3_v; - inline constexpr double inv_sqrt3 = inv_sqrt3_v; - inline constexpr double egamma = egamma_v; - inline constexpr double phi = phi_v; + template constexpr T @\libglobal{e_v}@ = @\unspec@; + template constexpr T @\libglobal{log2e_v}@ = @\unspec@; + template constexpr T @\libglobal{log10e_v}@ = @\unspec@; + template constexpr T @\libglobal{pi_v}@ = @\unspec@; + template constexpr T @\libglobal{inv_pi_v}@ = @\unspec@; + template constexpr T @\libglobal{inv_sqrtpi_v}@ = @\unspec@; + template constexpr T @\libglobal{ln2_v}@ = @\unspec@; + template constexpr T @\libglobal{ln10_v}@ = @\unspec@; + template constexpr T @\libglobal{sqrt2_v}@ = @\unspec@; + template constexpr T @\libglobal{sqrt3_v}@ = @\unspec@; + template constexpr T @\libglobal{inv_sqrt3_v}@ = @\unspec@; + template constexpr T @\libglobal{egamma_v}@ = @\unspec@; + template constexpr T @\libglobal{phi_v}@ = @\unspec@; + + template<@\libconcept{floating_point}@ T> constexpr T e_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T log2e_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T log10e_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T pi_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T inv_pi_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T inv_sqrtpi_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T ln2_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T ln10_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T sqrt2_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T sqrt3_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T inv_sqrt3_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T egamma_v = @\seebelow@; + template<@\libconcept{floating_point}@ T> constexpr T phi_v = @\seebelow@; + + inline constexpr double @\libglobal{e}@ = e_v; + inline constexpr double @\libglobal{log2e}@ = log2e_v; + inline constexpr double @\libglobal{log10e}@ = log10e_v; + inline constexpr double @\libglobal{pi}@ = pi_v; + inline constexpr double @\libglobal{inv_pi}@ = inv_pi_v; + inline constexpr double @\libglobal{inv_sqrtpi}@ = inv_sqrtpi_v; + inline constexpr double @\libglobal{ln2}@ = ln2_v; + inline constexpr double @\libglobal{ln10}@ = ln10_v; + inline constexpr double @\libglobal{sqrt2}@ = sqrt2_v; + inline constexpr double @\libglobal{sqrt3}@ = sqrt3_v; + inline constexpr double @\libglobal{inv_sqrt3}@ = inv_sqrt3_v; + inline constexpr double @\libglobal{egamma}@ = egamma_v; + inline constexpr double @\libglobal{phi}@ = phi_v; } \end{codeblock} @@ -10375,3 +10903,8691 @@ \pnum A program that instantiates a primary template of a mathematical constant variable template is ill-formed. + +\rSec1[linalg]{Basic linear algebra algorithms} + +\rSec2[linalg.overview]{Overview} + +\pnum +Subclause \ref{linalg} defines basic linear algebra algorithms. +The algorithms that access the elements of arrays +view those elements through \tcode{mdspan}\iref{views.multidim}. + +\rSec2[linalg.syn]{Header \tcode{} synopsis} + +\indexheader{linalg}% +\begin{codeblock} +namespace std::linalg { + // \ref{linalg.tags.order}, storage order tags + struct column_major_t; + inline constexpr column_major_t column_major; + struct row_major_t; + inline constexpr row_major_t row_major; + + // \ref{linalg.tags.triangle}, triangle tags + struct upper_triangle_t; + inline constexpr upper_triangle_t upper_triangle; + struct lower_triangle_t; + inline constexpr lower_triangle_t lower_triangle; + + // \ref{linalg.tags.diagonal}, diagonal tags + struct implicit_unit_diagonal_t; + inline constexpr implicit_unit_diagonal_t implicit_unit_diagonal; + struct explicit_diagonal_t; + inline constexpr explicit_diagonal_t explicit_diagonal; + + // \ref{linalg.layout.packed}, class template layout_blas_packed + template + class layout_blas_packed; + + // \ref{linalg.helpers}, exposition-only helpers + + // \ref{linalg.helpers.concepts}, linear algebra argument concepts + template + constexpr bool @\exposid{is-mdspan}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{in-vector}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{out-vector}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{inout-vector}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{in-matrix}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{out-matrix}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{inout-matrix}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{possibly-packed-inout-matrix}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{in-object}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{out-object}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{inout-object}@ = @\seebelow@; // \expos + + // \ref{linalg.scaled}, scaled in-place transformation + + // \ref{linalg.scaled.scaledaccessor}, class template \tcode{scaled_accessor} + template + class scaled_accessor; + + // \ref{linalg.scaled.scaled}, function template \tcode{scaled} + template + constexpr auto scaled(ScalingFactor alpha, mdspan x); + + // \ref{linalg.conj}, conjugated in-place transformation + + // \ref{linalg.conj.conjugatedaccessor}, class template \tcode{conjugated_accessor} + template + class conjugated_accessor; + + // \ref{linalg.conj.conjugated}, function template \tcode{conjugated} + template + constexpr auto conjugated(mdspan a); + + // \ref{linalg.transp}, transpose in-place transformation + + // \ref{linalg.transp.layout.transpose}, class template \tcode{layout_transpose} + template + class layout_transpose; + + // \ref{linalg.transp.transposed}, function template \tcode{transposed} + template + constexpr auto transposed(mdspan a); + + // \ref{linalg.conjtransposed}, conjugated transpose in-place transformation + template + constexpr auto conjugate_transposed(mdspan a); + + // \ref{linalg.algs.blas1}, BLAS 1 algorithms + + // \ref{linalg.algs.blas1.givens}, Givens rotations + + // \ref{linalg.algs.blas1.givens.lartg}, compute Givens rotation + + template + struct setup_givens_rotation_result { + Real c; + Real s; + Real r; + }; + template + struct setup_givens_rotation_result> { + Real c; + complex s; + complex r; + }; + + template + setup_givens_rotation_result setup_givens_rotation(Real a, Real b) noexcept; + + template + setup_givens_rotation_result> + setup_givens_rotation(complex a, complex b) noexcept; + + // \ref{linalg.algs.blas1.givens.rot}, apply computed Givens rotation + template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real> + void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s); + template + void apply_givens_rotation(ExecutionPolicy&& exec, + InOutVec1 x, InOutVec2 y, Real c, Real s); + template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real> + void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex s); + template + void apply_givens_rotation(ExecutionPolicy&& exec, + InOutVec1 x, InOutVec2 y, Real c, complex s); + + // \ref{linalg.algs.blas1.swap}, swap elements + template<@\exposconcept{inout-object}@ InOutObj1, @\exposconcept{inout-object}@ InOutObj2> + void swap_elements(InOutObj1 x, InOutObj2 y); + template + void swap_elements(ExecutionPolicy&& exec, + InOutObj1 x, InOutObj2 y); + + // \ref{linalg.algs.blas1.scal}, multiply elements by scalar + template + void scale(Scalar alpha, InOutObj x); + template + void scale(ExecutionPolicy&& exec, + Scalar alpha, InOutObj x); + + // \ref{linalg.algs.blas1.copy}, copy elements + template<@\exposconcept{in-object}@ InObj, @\exposconcept{out-object}@ OutObj> + void copy(InObj x, OutObj y); + template + void copy(ExecutionPolicy&& exec, + InObj x, OutObj y); + + // \ref{linalg.algs.blas1.add}, add elementwise + template<@\exposconcept{in-object}@ InObj1, @\exposconcept{in-object}@ InObj2, @\exposconcept{out-object}@ OutObj> + void add(InObj1 x, InObj2 y, OutObj z); + template + void add(ExecutionPolicy&& exec, + InObj1 x, InObj2 y, OutObj z); + + // \ref{linalg.algs.blas1.dot}, dot product of two vectors + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> + Scalar dot(InVec1 v1, InVec2 v2, Scalar init); + template + Scalar dot(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2, Scalar init); + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2> + auto dot(InVec1 v1, InVec2 v2); + template + auto dot(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2); + + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> + Scalar dotc(InVec1 v1, InVec2 v2, Scalar init); + template + Scalar dotc(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2, Scalar init); + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2> + auto dotc(InVec1 v1, InVec2 v2); + template + auto dotc(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2); + + // \ref{linalg.algs.blas1.ssq}, scaled sum of squares of a vector's elements + template + struct sum_of_squares_result { + Scalar scaling_factor; + Scalar scaled_sum_of_squares; + }; + template<@\exposconcept{in-vector}@ InVec, class Scalar> + sum_of_squares_result + vector_sum_of_squares(InVec v, sum_of_squares_result init); + template + sum_of_squares_result + vector_sum_of_squares(ExecutionPolicy&& exec, + InVec v, sum_of_squares_result init); + + // \ref{linalg.algs.blas1.nrm2}, Euclidean norm of a vector + template<@\exposconcept{in-vector}@ InVec, class Scalar> + Scalar vector_two_norm(InVec v, Scalar init); + template + Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init); + template<@\exposconcept{in-vector}@ InVec> + auto vector_two_norm(InVec v); + template + auto vector_two_norm(ExecutionPolicy&& exec, InVec v); + + // \ref{linalg.algs.blas1.asum}, sum of absolute values of vector elements + template<@\exposconcept{in-vector}@ InVec, class Scalar> + Scalar vector_abs_sum(InVec v, Scalar init); + template + Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init); + template<@\exposconcept{in-vector}@ InVec> + auto vector_abs_sum(InVec v); + template + auto vector_abs_sum(ExecutionPolicy&& exec, InVec v); + + // \ref{linalg.algs.blas1.iamax}, index of maximum absolute value of vector elements + template<@\exposconcept{in-vector}@ InVec> + typename InVec::extents_type vector_idx_abs_max(InVec v); + template + typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v); + + // \ref{linalg.algs.blas1.matfrobnorm}, Frobenius norm of a matrix + template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_frob_norm(InMat A, Scalar init); + template + Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init); + template<@\exposconcept{in-matrix}@ InMat> + auto matrix_frob_norm(InMat A); + template + auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A); + + // \ref{linalg.algs.blas1.matonenorm}, one norm of a matrix + template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_one_norm(InMat A, Scalar init); + template + Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init); + template<@\exposconcept{in-matrix}@ InMat> + auto matrix_one_norm(InMat A); + template + auto matrix_one_norm(ExecutionPolicy&& exec, InMat A); + + // \ref{linalg.algs.blas1.matinfnorm}, infinity norm of a matrix + template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_inf_norm(InMat A, Scalar init); + template + Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init); + template<@\exposconcept{in-matrix}@ InMat> + auto matrix_inf_norm(InMat A); + template + auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A); + + // \ref{linalg.algs.blas2}, BLAS 2 algorithms + + // \ref{linalg.algs.blas2.gemv}, general matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void matrix_vector_product(InMat A, InVec x, OutVec y); + template + void matrix_vector_product(ExecutionPolicy&& exec, + InMat A, InVec x, OutVec y); + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z); + template + void matrix_vector_product(ExecutionPolicy&& exec, + InMat A, InVec1 x, InVec2 y, OutVec z); + + // \ref{linalg.algs.blas2.symv}, symmetric matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); + template + void symmetric_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec x, OutVec y); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{out-vector}@ OutVec> + void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); + template + void symmetric_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); + + // \ref{linalg.algs.blas2.hemv}, Hermitian matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); + template + void hermitian_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec x, OutVec y); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{out-vector}@ OutVec> + void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); + template + void hermitian_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); + + // \ref{linalg.algs.blas2.trmv}, triangular matrix-vector product + + // Overwriting triangular matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec, + @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec x, + OutVec y); + template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InVec x, + OutVec y); + + // In-place triangular matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y); + template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutVec y); + + // Updating triangular matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, + InVec1 x, InVec2 y, OutVec z); + template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InVec1 x, InVec2 y, OutVec z); + + // \ref{linalg.algs.blas2.trsv}, solve a triangular linear system + + // Solve a triangular linear system, not in place + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec, class BinaryDivideOp> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x, BinaryDivideOp divide); + template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x); + template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x); + + // Solve a triangular linear system, in place + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-vector}@ InOutVec, class BinaryDivideOp> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, + InOutVec b, BinaryDivideOp divide); + template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutVec b, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b); + template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutVec b); + + // \ref{linalg.algs.blas2.rank1}, nonsymmetric rank-1 matrix update + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{inout-matrix}@ InOutMat> + void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A); + template + void matrix_rank_1_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A); + + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{inout-matrix}@ InOutMat> + void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A); + template + void matrix_rank_1_update_c(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A); + + // \ref{linalg.algs.blas2.symherrank1}, symmetric or Hermitian rank-1 matrix update + template + void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); + template + void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InOutMat A, Triangle t); + template<@\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); + template + void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, + InVec x, InOutMat A, Triangle t); + + template + void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); + template + void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InOutMat A, Triangle t); + template<@\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); + template + void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, + InVec x, InOutMat A, Triangle t); + + // \ref{linalg.algs.blas2.rank2}, symmetric and Hermitian rank-2 matrix updates + + // symmetric rank-2 matrix update + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); + template + void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A, Triangle t); + + // Hermitian rank-2 matrix update + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); + template + void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A, Triangle t); + + // \ref{linalg.algs.blas3}, BLAS 3 algorithms + + // \ref{linalg.algs.blas3.gemm}, general matrix-matrix product + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void matrix_product(InMat1 A, InMat2 B, OutMat C); + template + void matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, OutMat C); + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C); + template + void matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InMat3 E, OutMat C); + + // \ref{linalg.algs.blas3.xxmm}, symmetric, Hermitian, and triangular matrix-matrix product + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); + template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); + template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); + template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); + template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); + template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage, + @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); + template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, + OutMat C); + template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, + OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, + OutMat C); + template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, + OutMat C); + + // \ref{linalg.algs.blas3.trmm}, in-place triangular matrix-matrix product + + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); + template + void triangular_matrix_left_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutMat C); + + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); + template + void triangular_matrix_right_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutMat C); + + // \ref{linalg.algs.blas3.rankk}, rank-k update of a symmetric or Hermitian matrix + + // rank-k symmetric matrix update + template + void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); + template + void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, + Scalar alpha, InMat A, InOutMat C, Triangle t); + + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); + template + void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, + InMat A, InOutMat C, Triangle t); + + // rank-k Hermitian matrix update + template + void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); + template + void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, + Scalar alpha, InMat A, InOutMat C, Triangle t); + + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); + template + void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, + InMat A, InOutMat C, Triangle t); + + // \ref{linalg.algs.blas3.rank2k}, rank-2k update of a symmetric or Hermitian matrix + + // rank-2k symmetric matrix update + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); + template + void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InOutMat C, Triangle t); + + // rank-2k Hermitian matrix update + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); + template + void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InOutMat C, Triangle t); + + // \ref{linalg.algs.blas3.trsm}, solve multiple triangular linear systems + + // solve multiple triangular systems on the left, not-in-place + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp> + void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); + template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); + template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); + + // solve multiple triangular systems on the right, not-in-place + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp> + void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); + template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); + template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); + + // solve multiple triangular systems on the left, in-place + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp> + void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); + template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B); + template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B); + + // solve multiple triangular systems on the right, in-place + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp> + void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); + template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B); + template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B); +} +\end{codeblock} + +\rSec2[linalg.general]{General} + +\pnum +For the effects of all functions in \ref{linalg}, +when the effects are described as +``computes $R = E$'' or ``compute $R = E$'' +(for some $R$ and mathematical expression $E$), +the following apply: +\begin{itemize} +\item +$E$ has + the conventional mathematical meaning as written. +\item +The pattern $x^T$ should be read as + ``the transpose of $x$.'' +\item +The pattern $x^H$ should be read as + ``the conjugate transpose of $x$.'' +\item +When $R$ is the same name as a function parameter + whose type is a template parameter with \tcode{Out} in its name, + the intent is that the result of the computation + is written to the elements of the function parameter \tcode{R}. +\end{itemize} + +\pnum +Some of the functions and types in \ref{linalg} distinguish between +the ``rows'' and the ``columns'' of a matrix. +For a matrix \tcode{A} and a multidimensional index \tcode{i, j} in \tcode{A.extents()}, +\begin{itemize} +\item +\term{row} \tcode{i} of \tcode{A} is the set of elements \tcode{A[i, k1]} + for all \tcode{k1} such that \tcode{i, k1} is in \tcode{A.extents()}; and +\item +\term{column} \tcode{j} of \tcode{A} is the set of elements \tcode{A[k0, j]} + for all \tcode{k0} such that \tcode{k0, j} is in \tcode{A.extents()}. +\end{itemize} + +\pnum +Some of the functions in \ref{linalg} distinguish between +the ``upper triangle,'' ``lower triangle,'' and ``diagonal'' of a matrix. +\begin{itemize} +\item +The \defn{diagonal} is the set of all elements of \tcode{A} accessed by + \tcode{A[i,i]} for 0 $\le$ \tcode{i} < min(\tcode{A.extent(0)}, \tcode{A.extent(1)}). +\item +The \defnadj{upper}{triangle} of a matrix \tcode{A} is the set of all elements of + \tcode{A} accessed by \tcode{A[i,j]} with \tcode{i} $\le$ \tcode{j}. It includes the diagonal. +\item +The \defnadj{lower}{triangle} of \tcode{A} is the set of all elements of \tcode{A} + accessed by \tcode{A[i,j]} with \tcode{i} $\ge$ \tcode{j}. It includes the diagonal. +\end{itemize} + +\pnum +For any function \tcode{F} that takes +a parameter named \tcode{t}, +\tcode{t} applies to accesses done through the parameter preceding \tcode{t} in the parameter list of \tcode{F}. +Let \tcode{m} be such an access-modified function parameter. +\tcode{F} will only access the triangle of \tcode{m} specified by \tcode{t}. +For accesses \tcode{m[i, j]} outside the triangle specified by \tcode{t}, +\tcode{F} will use the value +\begin{itemize} +\item +\tcode{\exposid{conj-if-needed}(m[j, i])} if the name of \tcode{F} starts with \tcode{hermitian}, +\item +\tcode{m[j, i]} if the name of \tcode{F} starts with \tcode{symmetric}, or +\item +the additive identity if the name of \tcode{F} starts with \tcode{triangular}. +\end{itemize} +\begin{example} +Small vector product accessing only specified triangle. +It would not be a precondition violation for the non-accessed +matrix element to be non-zero. +\begin{codeblock} +template +void triangular_matrix_vector_2x2_product( + mdspan> m, + Triangle t, + mdspan> x, + mdspan> y) { + + static_assert(is_same_v || + is_same_v); + + if constexpr (is_same_v) { + y[0] = m[0,0] * x[0]; // \tcode{+ 0 * x[1]} + y[1] = m[1,0] * x[0] + m[1,1] * x[1]; + } else { // upper_triangle_t + y[0] = m[0,0] * x[0] + m[0,1] * x[1]; + y[1] = /* 0 * x[0] + */ m[1,1] * x[1]; + } +} +\end{codeblock} +\end{example} + +\pnum +For any function \tcode{F} that takes a parameter named \tcode{d}, +\tcode{d} applies to accesses done through +the previous-of-the-previous parameter of \tcode{d} +in the parameter list of \tcode{F}. +Let \tcode{m} be such an access-modified function parameter. +If \tcode{d} specifies that an implicit unit diagonal is to be assumed, then +\begin{itemize} +\item +\tcode{F} will not access the diagonal of \tcode{m}; and +\item +the algorithm will interpret \tcode{m} as if it has a unit diagonal, that is, +a diagonal each of whose elements behaves as a two-sided multiplicative identity +(even if \tcode{m}'s value type does not have +a two-sided multiplicative identity). +\end{itemize} +Otherwise, +if \tcode{d} specifies that an explicit diagonal is to be assumed, +then \tcode{F} will access the diagonal of \tcode{m}. + +\pnum +Within all the functions in \ref{linalg}, +any calls to \tcode{abs}, \tcode{conj}, \tcode{imag}, and \tcode{real} +are unqualified. + +\pnum +Two \tcode{mdspan} objects \tcode{x} and \tcode{y} \term{alias} each other, +if they have the same extents \tcode{e}, and +for every pack of integers \tcode{i} +which is a multidimensional index in \tcode{e}, +\tcode{x[i...]} and \tcode{y[i...]} refer to the same element. +\begin{note} +This means that +\tcode{x} and \tcode{y} view the same elements in the same order. +\end{note} + +\pnum +Two \tcode{mdspan} objects \tcode{x} and \tcode{y} \term{overlap} each other, +if for some pack of integers \tcode{i} +that is a multidimensional index in \tcode{x.extents()}, +there exists a pack of integers \tcode{j} +that is a multidimensional index in \tcode{y.extents()}, +such that \tcode{x[i...]} and \tcode{y[j...]} refer to the same element. +\begin{note} +Aliasing is a special case of overlapping. +If \tcode{x} and \tcode{y} do not overlap, +then they also do not alias each other. +\end{note} + +\rSec2[linalg.reqs]{Requirements} + +\rSec3[linalg.reqs.val]{Linear algebra value types} + +\pnum +Throughout \ref{linalg}, +the following types are +\defnadjx{linear algebra}{value types}{value type}: +\begin{itemize} +\item +the \tcode{value_type} type alias of +any input or output \tcode{mdspan} parameter(s) of +any function in \ref{linalg}; and +\item +the \tcode{Scalar} template parameter (if any) of +any function or class in \ref{linalg}. +\end{itemize} + +\pnum +Linear algebra value types shall model \libconcept{semiregular}. + +\pnum +A value-initialized object of linear algebra value type +shall act as the additive identity. + +\rSec3[linalg.reqs.alg]{Algorithm and class requirements} + +\pnum +\ref{linalg.reqs.alg} lists common requirements for +all algorithms and classes in \ref{linalg}. + +\pnum +All of the following statements presume +that the algorithm's asymptotic complexity requirements, if any, are satisfied. +\begin{itemize} +\item +The function may make arbitrarily many objects of any linear algebra value type, +value-initializing or direct-initializing them +with any existing object of that type. +\item +The \term{triangular solve algorithms} in +\ref{linalg.algs.blas2.trsv}, +\ref{linalg.algs.blas3.trmm}, +\ref{linalg.algs.blas3.trsm}, and +\ref{linalg.algs.blas3.inplacetrsm} +either have +a \tcode{BinaryDi\-videOp} template parameter (see \ref{linalg.algs.reqs}) and +a binary function object parameter \tcode{divide} of that type, +or they have effects equivalent to invoking such an algorithm. +Triangular solve algorithms interpret \tcode{divide(a, b)} as +\tcode{a} times the multiplicative inverse of \tcode{b}. +Each triangular solve algorithm uses a sequence of evaluations of +\tcode{*}, \tcode{*=}, \tcode{divide}, +unary \tcode{+}, binary \tcode{+}, \tcode{+=}, +unary \tcode{-}, binary \tcode{-}, \tcode{-=}, +and \tcode{=} operators +that would produce the result +specified by the algorithm's \Fundescx{Effects} and \Fundescx{Remarks} +when operating on elements of a field with noncommutative multiplication. +It is a precondition of the algorithm that +any addend, +any subtrahend, +any partial sum of addends in any order +(treating any difference as a sum with the second term negated), +any factor, +any partial product of factors respecting their order, +any numerator (first argument of \tcode{divide}), +any denominator (second argument of \tcode{divide}), +and any assignment +is a well-formed expression. +\item +Each function in +\ref{linalg.algs.blas1}, \ref{linalg.algs.blas2}, and \ref{linalg.algs.blas3} +that is not a triangular solve algorithm +will use a sequence of evaluations of +\tcode{*}, \tcode{*=}, \tcode{+}, \tcode{+=}, and \tcode{=} operators +that would produce the result +specified by the algorithm's \Fundescx{Effects} and \Fundescx{Remarks} +when operating on elements of a semiring with noncommutative multiplication. +It is a precondition of the algorithm that +any addend, +any partial sum of addends in any order, +any factor, +any partial product of factors respecting their order, +and any assignment +is a well-formed expression. +\item +If the function has an output \tcode{mdspan}, +then all addends, +subtrahends (for the triangular solve algorithms), +or results of the \tcode{divide} parameter on intermediate terms +(if the function takes a \tcode{divide} parameter) +are assignable and convertible to +the output \tcode{mdspan}'s \tcode{value_type}. +\item +The function may reorder addends and partial sums arbitrarily. +\begin{note} +Factors in each product are not reordered; +multiplication is not necessarily commutative. +\end{note} +\end{itemize} +\begin{note} +The above requirements do not prohibit +implementation approaches and optimization techniques +which are not user-observable. +In particular, if for all input and output arguments +the \tcode{value_type} is a floating-point type, +implementers are free to leverage approximations, +use arithmetic operations not explicitly listed above, and +compute floating point sums in any way that improves their accuracy. +\end{note} + +\pnum +\begin{note} +For all functions in \ref{linalg}, +suppose that all input and output \tcode{mdspan} have as \tcode{value_type} +a floating-point type, and +any \tcode{Scalar} template argument has a floating-point type. +Then, functions can do all of the following: +\begin{itemize} +\item +compute floating-point sums in any way +that improves their accuracy for arbitrary input; +\item +perform additional arithmetic operations +(other than those specified by the function's wording and \ref{linalg.reqs.alg}) +in order to improve performance or accuracy; and +\item +use approximations +(that might not be exact even if computing with real numbers), +instead of computations that would be exact +if it were possible to compute without rounding error; +\end{itemize} +as long as +\begin{itemize} +\item +the function satisfies the complexity requirements; and +\item +the function is logarithmically stable, +as defined in Demmel 2007\supercite{linalg-stable}. +Strassen's algorithm for matrix-matrix multiply +is an example of a logarithmically stable algorithm. +\end{itemize} +\end{note} + +\rSec2[linalg.tags]{Tag classes} + +\rSec3[linalg.tags.order]{Storage order tags} + +\pnum +The storage order tags describe +the order of elements in an \tcode{mdspan} with +\tcode{layout_blas_packed}\iref{linalg.layout.packed} layout. +\begin{itemdecl} +struct @\libglobal{column_major_t}@ { + explicit column_major_t() = default; +}; +inline constexpr column_major_t @\libglobal{column_major}@{}; + +struct @\libglobal{row_major_t}@ { + explicit row_major_t() = default; +}; +inline constexpr row_major_t @\libglobal{row_major}@{}; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{column_major_t} indicates a column-major order, +and \tcode{row_major_t} indicates a row-major order. +\end{itemdescr} + +\rSec3[linalg.tags.triangle]{Triangle tags} + +\begin{itemdecl} +struct @\libglobal{upper_triangle_t}@ { + explicit upper_triangle_t() = default; +}; +inline constexpr upper_triangle_t @\libglobal{upper_triangle}@{}; + +struct @\libglobal{lower_triangle_t}@ { + explicit lower_triangle_t() = default; +}; +inline constexpr lower_triangle_t @\libglobal{lower_triangle}@{}; +\end{itemdecl} + +\begin{itemdescr} +\pnum +These tag classes specify whether +algorithms and other users of a matrix (represented as an \tcode{mdspan}) +access the +upper triangle (\tcode{upper_triangle_t}) or +lower triangle (\tcode{lower_triangle_t}) +of the matrix (see also \ref{linalg.general}). +This is also subject to the restrictions of \tcode{implicit_unit_diagonal_t} +if that tag is also used as a function argument; see below. +\end{itemdescr} + +\rSec3[linalg.tags.diagonal]{Diagonal tags} + +\begin{itemdecl} +struct @\libglobal{implicit_unit_diagonal_t}@ { + explicit implicit_unit_diagonal_t() = default; +}; +inline constexpr implicit_unit_diagonal_t @\libglobal{implicit_unit_diagonal}@{}; + +struct @\libglobal{explicit_diagonal_t}@ { + explicit explicit_diagonal_t() = default; +}; +inline constexpr explicit_diagonal_t @\libglobal{explicit_diagonal}@{}; +\end{itemdecl} + +\begin{itemdescr} +\pnum +These tag classes specify whether algorithms +access the matrix's diagonal entries, and if not, +then how algorithms interpret +the matrix's implicitly represented diagonal values. + +\pnum +The \tcode{implicit_unit_diagonal_t} tag indicates that +an implicit unit diagonal is to be assumed\iref{linalg.general}. + +\pnum +The \tcode{explicit_diagonal_t} tag indicates that +an explicit diagonal is used\iref{linalg.general}. +\end{itemdescr} + +\rSec2[linalg.layout.packed]{Layouts for packed matrix types} + +\rSec3[linalg.layout.packed.overview]{Overview} + +\pnum +\tcode{layout_blas_packed} is an \tcode{mdspan} layout mapping policy +that represents a square matrix that stores only the entries in one +triangle, in a packed contiguous format. +Its \tcode{Triangle} template parameter determines +whether an \tcode{mdspan} with this layout +stores the upper or lower triangle of the matrix. +Its \tcode{StorageOrder} template parameter determines +whether the layout packs the matrix's elements +in column-major or row-major order. + +\pnum +A \tcode{StorageOrder} of \tcode{column_major_t} +indicates column-major ordering. +This packs matrix elements +starting with the leftmost (least column index) column, and +proceeding column by column, from the top entry (least row index). + +\pnum +A \tcode{StorageOrder} of \tcode{row_major_t} +indicates row-major ordering. +This packs matrix elements +starting with the topmost (least row index) row, and +proceeding row by row, from the leftmost (least column index) entry. + +\pnum +\begin{note} +\tcode{layout_blas_packed} describes the data layout used by +the BLAS' +Symmetric Packed (SP), Hermitian Packed (HP), and Triangular Packed (TP) +matrix types. +\end{note} +\begin{codeblock} +namespace std::linalg { + template + class @\libglobal{layout_blas_packed}@ { + public: + using triangle_type = Triangle; + using storage_order_type = StorageOrder; + + template + struct 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_blas_packed; + + // \ref{linalg.layout.packed.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& other) noexcept; + + constexpr mapping& operator=(const mapping&) noexcept = default; + + // \ref{linalg.layout.packed.obs}, observers + constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } + + constexpr index_type required_span_size() const noexcept; + + template + constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept; + + static constexpr bool is_always_unique() noexcept { + return (extents_type::static_extent(0) != dynamic_extent && + extents_type::static_extent(0) < 2) || + (extents_type::static_extent(1) != dynamic_extent && + extents_type::static_extent(1) < 2); + } + static constexpr bool is_always_exhaustive() noexcept { return true; } + static constexpr bool is_always_strided() noexcept + { return is_always_unique(); } + + constexpr bool is_unique() const noexcept { + return @\exposid{extents_}@.extent(0) < 2; + } + constexpr bool is_exhaustive() const noexcept { return true; } + constexpr bool is_strided() const noexcept { + return @\exposid{extents_}@.extent(0) < 2; + } + + constexpr index_type stride(rank_type) const noexcept; + + template + friend constexpr bool operator==(const mapping&, const mapping&) noexcept; + + private: + extents_type @\exposid{extents_}@{}; // \expos + }; + }; +} +\end{codeblock} + +\begin{itemdescr} +\pnum +\mandates +\begin{itemize} +\item +\tcode{Triangle} is either \tcode{upper_triangle_t} or \tcode{lower_triangle_t}, +\item +\tcode{StorageOrder} is either \tcode{column_major_t} or \tcode{row_major_t}, +\item +\tcode{Extents} is a specialization of \tcode{std::extents}, +\item +\tcode{Extents::rank()} equals 2, +\item +one of +\begin{codeblock} +extents_type::static_extent(0) == dynamic_extent@\textrm{,}@ +extents_type::static_extent(1) == dynamic_extent@\textrm{, or}@ +extents_type::static_extent(0) == extents_type::static_extent(1) +\end{codeblock} +is \tcode{true}, and +\item +if \tcode{Extents::rank_dynamic() == 0} is \tcode{true}, +let $N_s$ be equal to \tcode{Extents::static_extent(0)}; then, +$N_s \times (N_s + 1)$ is representable as a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\tcode{layout_blas_packed::mapping} is a trivially copyable type +that models \libconcept{regular} for each \tcode{T}, \tcode{SO}, and \tcode{E}. +\end{itemdescr} + +\rSec3[linalg.layout.packed.cons]{Constructors} + +\indexlibraryctor{layout_blas_packed::mapping}% +\begin{itemdecl} +constexpr mapping(const extents_type& e) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +Let $N$ be equal to \tcode{e.extent(0)}. +Then, $N \times (N+1)$ is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. +\item +\tcode{e.extent(0)} equals \tcode{e.extent(1)}. +\end{itemize} + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{e}. +\end{itemdescr} + +\indexlibraryctor{layout_blas_packed::mapping}% +\begin{itemdecl} +template + explicit(!is_convertible_v) + constexpr mapping(const mapping& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\expects +Let $N$ be \tcode{other.extents().extent(0)}. +Then, $N \times (N+1)$ 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} + +\rSec3[linalg.layout.packed.obs]{Observers} + +\indexlibrarymember{layout_blas_packed::mapping}{required_span_size}% +\begin{itemdecl} +constexpr index_type required_span_size() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{extents_}.extent(0) * (\exposid{extents_}.extent(0) + 1)/2}. +\begin{note} +For example, a 5 x 5 packed matrix +only stores 15 matrix elements. +\end{note} +\end{itemdescr} + +\indexlibrarymember{layout_blas_packed::mapping}{operator()}% +\begin{itemdecl} +template + constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v} is \tcode{true}, +\item +\tcode{is_convertible_v} is \tcode{true}, +\item +\tcode{is_nothrow_constructible_v} is \tcode{true}, and +\item +\tcode{is_nothrow_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +Let \tcode{i} be \tcode{extents_type::\exposid{index-cast}(ind0)}, and +let \tcode{j} be \tcode{extents_type::\exposid{index-cast}(ind1)}. + +\pnum +\expects +\tcode{i, j} +is a multidimensional index in \exposid{extents_}\iref{mdspan.overview}. + +\pnum +\returns +Let \tcode{N} be \tcode{\exposid{extents_}.extent(0)}. +Then +\begin{itemize} +\item +\tcode{(*this)(j, i)} if \tcode{i > j} is \tcode{true}; otherwise +\item +\tcode{i + j * (j + 1)/2} if +\begin{codeblock} +is_same_v && is_same_v +\end{codeblock} +is \tcode{true} or +\begin{codeblock} +is_same_v && is_same_v +\end{codeblock} +is \tcode{true}; otherwise +\item +\tcode{j + N * i - i * (i + 1)/2}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{layout_blas_packed::mapping}{stride}% +\begin{itemdecl} +constexpr index_type stride(rank_type r) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +\tcode{is_strided()} is \tcode{true}, and +\item +\tcode{r < extents_type::rank()} is \tcode{true}. +\end{itemize} + +\pnum +\returns +\tcode{1}. +\end{itemdescr} + +\indexlibrarymember{layout_blas_packed::mapping}{operator==}% +\begin{itemdecl} +template + friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.extents() == y.extents();} +\end{itemdescr} + +\rSec2[linalg.helpers]{Exposition-only helpers} + +\rSec3[linalg.helpers.abs]{\exposid{abs-if-needed}} + +\pnum +The name \exposid{abs-if-needed} denotes an exposition-only function object. +The expression \tcode{\exposid{abs-if-needed}(E)} for a subexpression \tcode{E} +whose type is \tcode{T} is expression-equivalent to: +\begin{itemize} +\item +\tcode{E} if \tcode{T} is an unsigned integer; +\item +otherwise, \tcode{std::abs(E)} if \tcode{T} is an arithmetic type, +\item +otherwise, \tcode{abs(E)}, +if that expression is valid, +with overload resolution performed in a context that includes the declaration +\begin{codeblock} +template U abs(U) = delete; +\end{codeblock} +If the function selected by overload resolution +does not return the absolute value of its input, +the program is ill-formed, no diagnostic required. +\end{itemize} + +\rSec3[linalg.helpers.conj]{\exposid{conj-if-needed}} + +\pnum +The name \exposid{conj-if-needed} denotes an exposition-only function object. +The expression \tcode{\exposid{conj-if-needed}(E)} for a subexpression \tcode{E} +whose type is \tcode{T} is expression-equivalent to: +\begin{itemize} +\item +\tcode{conj(E)}, +if \tcode{T} is not an arithmetic type and +the expression \tcode{conj(E)} is valid, +with overload resolution performed in a context that includes the declaration +\begin{codeblock} +template U conj(const U&) = delete; +\end{codeblock} +If the function selected by overload resolution +does not return the complex conjugate of its input, +the program is ill-formed, no diagnostic required; +\item +otherwise, \tcode{E}. +\end{itemize} + +\rSec3[linalg.helpers.real]{\exposid{real-if-needed}} + +\pnum +The name \exposid{real-if-needed} denotes an exposition-only function object. +The expression \tcode{\exposid{real-if-needed}(E)} for a subexpression \tcode{E} +whose type is \tcode{T} is expression-equivalent to: +\begin{itemize} +\item +\tcode{real(E)}, +if \tcode{T} is not an arithmetic type and +the expression \tcode{real(E)} is valid, +with overload resolution performed in a context that includes the declaration +\begin{codeblock} +template U real(const U&) = delete; +\end{codeblock} +If the function selected by overload resolution +does not return the real part of its input, +the program is ill-formed, no diagnostic required; +\item +otherwise, \tcode{E}. +\end{itemize} + +\rSec3[linalg.helpers.imag]{\exposid{imag-if-needed}} + +\pnum +The name \exposid{imag-if-needed} denotes an exposition-only function object. +The expression \tcode{\exposid{imag-if-needed}(E)} for a subexpression \tcode{E} +whose type is \tcode{T} is expression-equivalent to: +\begin{itemize} +\item +\tcode{imag(E)}, +if \tcode{T} is not an arithmetic type and the expression \tcode{imag(E)} +is valid, with overload resolution performed in a context +that includes the declaration +\begin{codeblock} +template U imag(const U&) = delete; +\end{codeblock} +If the function selected by overload resolution +does not return the imaginary part of its input, +the program is ill-formed, no diagnostic required; +\item +otherwise, \tcode{((void)E, T\{\})}. +\end{itemize} + +\rSec3[linalg.helpers.concepts]{Argument concepts} + +\pnum +The exposition-only concepts defined in this section +constrain the algorithms in \ref{linalg}. +\begin{codeblock} +template + constexpr bool @\exposid{is-mdspan}@ = false; + +template + constexpr bool @\exposid{is-mdspan}@> = true; + +template + concept @\defexposconcept{in-vector}@ = + @\exposid{is-mdspan}@ && T::rank() == 1; + +template + concept @\defexposconcept{out-vector}@ = + @\exposid{is-mdspan}@ && T::rank() == 1 && + is_assignable_v && T::is_always_unique(); + +template + concept @\defexposconcept{inout-vector}@ = + @\exposid{is-mdspan}@ && T::rank() == 1 && + is_assignable_v && T::is_always_unique(); + +template + concept @\defexposconcept{in-matrix}@ = + @\exposid{is-mdspan}@ && T::rank() == 2; + +template + concept @\defexposconcept{out-matrix}@ = + @\exposid{is-mdspan}@ && T::rank() == 2 && + is_assignable_v && T::is_always_unique(); + +template + concept @\defexposconcept{inout-matrix}@ = + @\exposid{is-mdspan}@ && T::rank() == 2 && + is_assignable_v && T::is_always_unique(); + +template + constexpr bool @\exposid{is-layout-blas-packed}@ = false; // \expos + +template + constexpr bool @\exposid{is-layout-blas-packed}@> = true; + +template + concept @\defexposconcept{possibly-packed-inout-matrix}@ = + @\exposid{is-mdspan}@ && T::rank() == 2 && + is_assignable_v && + (T::is_always_unique() || @\exposid{is-layout-blas-packed}@); + +template + concept @\defexposconcept{in-object}@ = + @\exposid{is-mdspan}@ && (T::rank() == 1 || T::rank() == 2); + +template + concept @\defexposconcept{out-object}@ = + @\exposid{is-mdspan}@ && (T::rank() == 1 || T::rank() == 2) && + is_assignable_v && T::is_always_unique(); + +template + concept @\defexposconcept{inout-object}@ = + @\exposid{is-mdspan}@ && (T::rank() == 1 || T::rank() == 2) && + is_assignable_v && T::is_always_unique(); +\end{codeblock} + +\pnum +If a function in \ref{linalg} accesses the elements +of a parameter constrained by +\exposconcept{in-vector}, +\exposconcept{in-matrix}, or +\exposconcept{in-object}, +those accesses will not modify the elements. + +\pnum +Unless explicitly permitted, any +\exposconcept{inout-vector}, +\exposconcept{inout-matrix}, +\exposconcept{inout-object}, +\exposconcept{out-vector}, +\exposconcept{out-matrix}, +\exposconcept{out-object}, or +\exposconcept{possibly-packed-inout-matrix} +parameter of a function in \ref{linalg} +shall not overlap any other \tcode{mdspan} parameter of the function. + +\rSec3[linalg.helpers.mandates]{Mandates} + +\pnum +\begin{note} +These exposition-only helper functions use +the less constraining input concepts even for the output arguments, +because the additional constraint for assignability of elements +is not necessary, and +they are sometimes used in a context +where the third argument is an input type too. +\end{note} + +\begin{codeblock} +template + requires(@\exposid{is-mdspan}@ && @\exposid{is-mdspan}@) + constexpr + bool @\exposid{compatible-static-extents}@(size_t r1, size_t r2) { // \expos + return MDS1::static_extent(r1) == dynamic_extent || + MDS2::static_extent(r2) == dynamic_extent || + MDS1::static_extent(r1) == MDS2::static_extent(r2); + } + +template<@\exposconcept{in-vector}@ In1, @\exposconcept{in-vector}@ In2, @\exposconcept{in-vector}@ Out> + constexpr bool @\exposid{possibly-addable}@() { // \expos + return @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(0, 0); + } + +template<@\exposconcept{in-matrix}@ In1, @\exposconcept{in-matrix}@ In2, @\exposconcept{in-matrix}@ Out> + constexpr bool @\exposid{possibly-addable}@() { // \expos + return @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(1, 1) && + @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(1, 1) && + @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(1, 1); + } + +template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-vector}@ OutVec> + constexpr bool @\exposid{possibly-multipliable}@() { // \expos + return @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(1, 0); + } + +template<@\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ OutVec> + constexpr bool @\exposid{possibly-multipliable}@() { // \expos + return @\exposid{compatible-static-extents}@(0, 1) && + @\exposid{compatible-static-extents}@(0, 0); + } + +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ OutMat> + constexpr bool @\exposid{possibly-multipliable}@() { // \expos + return @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(1, 1) && + @\exposid{compatible-static-extents}@(1, 0); + } +\end{codeblock} + +\rSec3[linalg.helpers.precond]{Preconditions} + +\pnum +\begin{note} +These exposition-only helper functions use +the less constraining input concepts even for the output arguments, +because the additional constraint for assignability of elements +is not necessary, and +they are sometimes used in a context +where the third argument is an input type too. +\end{note} + +\begin{codeblock} +constexpr bool @\exposid{addable}@( // \expos + const @\exposconcept{in-vector}@ auto& in1, const @\exposconcept{in-vector}@ auto& in2, const @\exposconcept{in-vector}@ auto& out) { + return out.extent(0) == in1.extent(0) && out.extent(0) == in2.extent(0); +} + +constexpr bool @\exposid{addable}@( // \expos + const @\exposconcept{in-matrix}@ auto& in1, const @\exposconcept{in-matrix}@ auto& in2, const @\exposconcept{in-matrix}@ auto& out) { + return out.extent(0) == in1.extent(0) && out.extent(1) == in1.extent(1) && + out.extent(0) == in2.extent(0) && out.extent(1) == in2.extent(1); +} + +constexpr bool @\exposid{multipliable}@( // \expos + const @\exposconcept{in-matrix}@ auto& in_mat, const @\exposconcept{in-vector}@ auto& in_vec, const @\exposconcept{in-vector}@ auto& out_vec) { + return out_vec.extent(0) == in_mat.extent(0) && in_mat.extent(1) == in_vec.extent(0); +} + +constexpr bool @\exposid{multipliable}@( // \expos + const @\exposconcept{in-vector}@ auto& in_vec, const @\exposconcept{in-matrix}@ auto& in_mat, const @\exposconcept{in-vector}@ auto& out_vec) { + return out_vec.extent(0) == in_mat.extent(1) && in_mat.extent(0) == in_vec.extent(0); +} + +constexpr bool @\exposid{multipliable}@( // \expos + const @\exposconcept{in-matrix}@ auto& in_mat1, const @\exposconcept{in-matrix}@ auto& in_mat2, const @\exposconcept{in-matrix}@ auto& out_mat) { + return out_mat.extent(0) == in_mat1.extent(0) && out_mat.extent(1) == in_mat2.extent(1) && + in_mat1.extent(1) == in_mat2.extent(0); +} +\end{codeblock} + +\rSec2[linalg.scaled]{Scaled in-place transformation} + +\rSec3[linalg.scaled.intro]{Introduction} + +\pnum +The \tcode{scaled} function +takes a value \tcode{alpha} and an \tcode{mdspan} \tcode{x}, and +returns a new read-only \tcode{mdspan} +that represents +the elementwise product of \tcode{alpha} with each element of \tcode{x}. +\begin{example} +\begin{codeblock} +using Vec = mdspan>; + +// z = alpha * x + y +void z_equals_alpha_times_x_plus_y(double alpha, Vec x, Vec y, Vec z) { + add(scaled(alpha, x), y, z); +} + +// z = alpha * x + beta * y +void z_equals_alpha_times_x_plus_beta_times_y(double alpha, Vec x, double beta, Vec y, Vec z) { + add(scaled(alpha, x), scaled(beta, y), z); +} +\end{codeblock} +\end{example} + +\rSec3[linalg.scaled.scaledaccessor]{Class template \tcode{scaled_accessor}} + +\pnum +The class template \tcode{scaled_accessor} is an \tcode{mdspan} accessor policy +which upon access produces scaled elements. +It is part of the implementation of \tcode{scaled}\iref{linalg.scaled.scaled}. +\begin{codeblock} +namespace std::linalg { + template + class @\libglobal{scaled_accessor}@ { + public: + using element_type = + add_const_t() * declval())>; + using reference = remove_const_t; + using data_handle_type = NestedAccessor::data_handle_type; + using offset_policy = scaled_accessor; + + constexpr scaled_accessor() = default; + template + explicit(!is_convertible_v) + constexpr scaled_accessor(const scaled_accessor& other); + constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a); + + constexpr reference access(data_handle_type p, size_t i) const; + constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const; + + constexpr const ScalingFactor& scaling_factor() const noexcept { return @\exposid{scaling-factor}@; } + constexpr const NestedAccessor& nested_accessor() const noexcept { return @\exposid{nested-accessor}@; } + + private: + ScalingFactor @\exposid{scaling-factor}@{}; // \expos + NestedAccessor @\exposid{nested-accessor}@{}; // \expos + }; +} +\end{codeblock} + +\pnum +\mandates +\begin{itemize} +\item +\tcode{element_type} is valid and denotes a type, +\item +\tcode{is_copy_constructible_v} is \tcode{true}, +\item +\tcode{is_reference_v} is \tcode{false}, +\item +\tcode{ScalingFactor} models \libconcept{semiregular}, and +\item +\tcode{NestedAccessor} meets the accessor policy requirements\iref{mdspan.accessor.reqmts}. +\end{itemize} + +\indexlibraryctor{scaled_accessor}% +\begin{itemdecl} +template + explicit(!is_convertible_v) + constexpr scaled_accessor(const scaled_accessor& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{scaling-factor} +with \tcode{other.scaling_factor()}, and +\item +direct-non-list-initializes \exposid{nested-accessor} +with \tcode{other.nested_accessor()}. +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{scaled_accessor}% +\begin{itemdecl} +constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{scaling-factor} with \tcode{s}, and +\item +direct-non-list-initializes \exposid{nested-accessor} with \tcode{a}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{scaled_accessor}{access}% +\begin{itemdecl} +constexpr reference access(data_handle_type p, size_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +scaling_factor() * NestedAccessor::element_type(@\exposid{nested-accessor}@.access(p, i)) +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{scaled_accessor}{offset}% +\begin{itemdecl} +constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{nested-accessor}.offset(p, i)} +\end{itemdescr} + +\rSec3[linalg.scaled.scaled]{Function template \tcode{scaled}} + +\pnum +The \tcode{scaled} function template takes +a scaling factor \tcode{alpha} and +an \tcode{mdspan} \tcode{x}, and +returns a new read-only \tcode{mdspan} with the same domain as \tcode{x}, +that represents the elementwise product of \tcode{alpha} +with each element of \tcode{x}. + +\indexlibraryglobal{scaled}% +\begin{itemdecl} + template + constexpr auto scaled(ScalingFactor alpha, mdspan x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{SA} be \tcode{scaled_accessor}. + +\pnum +\returns +\begin{codeblock} +mdspan(x.data_handle(), x.mapping(), + SA(alpha, x.accessor())) +\end{codeblock} +\end{itemdescr} + +\pnum +\begin{example} +\begin{codeblock} +void test_scaled(mdspan> x) +{ + auto x_scaled = scaled(5.0, x); + for (int i = 0; i < x.extent(0); ++i) { + assert(x_scaled[i] == 5.0 * x[i]); + } +} +\end{codeblock} +\end{example} + +\rSec2[linalg.conj]{Conjugated in-place transformation} + +\rSec3[linalg.conj.intro]{Introduction} + +\pnum +The \tcode{conjugated} function takes an \tcode{mdspan} \tcode{x}, +and returns a new read-only \tcode{mdspan} \tcode{y} +with the same domain as \tcode{x}, +whose elements are the complex conjugates +of the corresponding elements of \tcode{x}. + +\rSec3[linalg.conj.conjugatedaccessor]{Class template \tcode{conjugated_accessor}} + +\pnum +The class template \tcode{conjugated_accessor} +is an \tcode{mdspan} accessor policy +which upon access produces conjugate elements. +It is part of the implementation of +\tcode{conjugated}\iref{linalg.conj.conjugated}. + +\begin{codeblock} +namespace std::linalg { + template + class @\libglobal{conjugated_accessor}@ { + public: + using element_type = + add_const_t()))>; + using reference = remove_const_t; + using data_handle_type = typename NestedAccessor::data_handle_type; + using offset_policy = conjugated_accessor; + + constexpr conjugated_accessor() = default; + template + explicit(!is_convertible_v>) + constexpr conjugated_accessor(const conjugated_accessor& other); + + constexpr reference access(data_handle_type p, size_t i) const; + + constexpr typename offset_policy::data_handle_type + offset(data_handle_type p, size_t i) const; + + constexpr const Accessor& nested_accessor() const noexcept { return @\exposid{nested-accessor_}@; } + + private: + NestedAccessor @\exposid{nested-accessor_}@{}; // \expos + }; +} +\end{codeblock} + +\pnum +\mandates +\begin{itemize} +\item +\tcode{element_type} is valid and denotes a type, +\item +\tcode{is_copy_constructible_v} is \tcode{true}, +\item +\tcode{is_reference_v} is \tcode{false}, and +\item +\tcode{NestedAccessor} meets the accessor policy requirements\iref{mdspan.accessor.reqmts}. +\end{itemize} + +\indexlibraryctor{conjugated_accessor}% +\begin{itemdecl} +constexpr conjugated_accessor(const NestedAccessor& acc); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Direct-non-list-initializes +\exposid{nested-accessor_} with \tcode{acc}. +\end{itemdescr} + +\indexlibraryctor{conjugated_accessor}% +\begin{itemdecl} +template + explicit(!is_convertible_v>) + constexpr conjugated_accessor(const conjugated_accessor& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} +is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes \exposid{nested-accessor_} +with \tcode{other.nested_accessor()}. +\end{itemdescr} + +\indexlibrarymember{conjugated_accessor}{access}% +\begin{itemdecl} +constexpr reference access(data_handle_type p, size_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{conj-if-needed}(NestedAccessor::element_type(\exposid{nested-accessor_}.access(p, i)))} +\end{itemdescr} + +\indexlibrarymember{conjugated_accessor}{offset}% +\begin{itemdecl} +constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{nested-accessor_}.offset(p, i)} +\end{itemdescr} + +\rSec3[linalg.conj.conjugated]{Function template \tcode{conjugated}} + +\begin{itemdecl} + template + constexpr auto @\libglobal{conjugated}@(mdspan a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{A} be +\begin{itemize} +\item +\tcode{remove_cvref_t} +if \tcode{Accessor} is a specialization of \tcode{conjugated_accessor}; +\item +otherwise, +\tcode{Accessor} if \tcode{remove_cvref_t} is an arithmetic type; +\item +otherwise, +\tcode{conjugated_accessor} +if the expression \tcode{conj(E)} is valid for any subexpression \tcode{E} +whose type is \tcode{remove_cvref_t} +with overload resolution performed in a context that includes the declaration +\tcode{template U conj(const U\&) = delete;}; +\item +otherwise, +\tcode{Accessor}. +\end{itemize} + +\pnum +\returns +Let \tcode{MD} be \tcode{mdspan}. +\begin{itemize} +\item +\tcode{MD(a.data_handle(), a.mapping(), a.accessor().nested_accessor())} +if \tcode{Accessor} is a\newline specialization of \tcode{conjugated_accessor}; +\item +otherwise, +\tcode{a}, if \tcode{is_same_v} is \tcode{true}; +\item +otherwise, +\tcode{MD(a.data_handle(), a.mapping(), conjugated_accessor(a.accessor()))}. +\end{itemize} +\end{itemdescr} + +\pnum +\begin{example} +\begin{codeblock} +void test_conjugated_complex(mdspan, extents> a) { + auto a_conj = conjugated(a); + for (int i = 0; i < a.extent(0); ++i) { + assert(a_conj[i] == conj(a[i]); + } + auto a_conj_conj = conjugated(a_conj); + for (int i = 0; i < a.extent(0); ++i) { + assert(a_conj_conj[i] == a[i]); + } +} + +void test_conjugated_real(mdspan> a) { + auto a_conj = conjugated(a); + for (int i = 0; i < a.extent(0); ++i) { + assert(a_conj[i] == a[i]); + } + auto a_conj_conj = conjugated(a_conj); + for (int i = 0; i < a.extent(0); ++i) { + assert(a_conj_conj[i] == a[i]); + } +} +\end{codeblock} +\end{example} + +\rSec2[linalg.transp]{Transpose in-place transformation} + +\rSec3[linalg.transp.intro]{Introduction} + +\pnum +\tcode{layout_transpose} is an \tcode{mdspan} layout mapping policy +that swaps the two indices, extents, and strides +of any unique \tcode{mdspan} layout mapping policy. + +\pnum +The \tcode{transposed} function takes an \tcode{mdspan} +representing a matrix, and returns a new \tcode{mdspan} +representing the transpose of the input matrix. + +\rSec3[linalg.transp.helpers]{Exposition-only helpers for \tcode{layout_transpose} and \tcode{transposed}} + +\pnum +The exposition-only \exposid{transpose-extents} function +takes an \tcode{extents} object representing the extents of a matrix, +and returns a new \tcode{extents} object +representing the extents of the transpose of the matrix. + +\pnum +The exposition-only alias template +\tcode{\exposid{transpose-extents-t}} +gives the type of \tcode{\exposid{transpose-ex\-tents}(e)} +for a given \tcode{extents} object \tcode{e} of type \tcode{InputExtents}. +\begin{itemdecl} +template + constexpr extents + @\exposid{transpose-extents}@(const extents& in); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{extents(in.extent(1), in.extent(0))} +\end{itemdescr} + +\begin{codeblock} +template + using @\exposid{transpose-extents-t}@ = + decltype(@\exposid{transpose-extents}@(declval())); // \expos +\end{codeblock} + +\rSec3[linalg.transp.layout.transpose]{Class template \tcode{layout_transpose}} + +\pnum +\tcode{layout_transpose} is an \tcode{mdspan} layout mapping policy +that swaps the two indices, extents, and strides +of any \tcode{mdspan} layout mapping policy. + +\begin{codeblock} +namespace std::linalg { + template + class @\libglobal{layout_transpose}@ { + public: + using nested_layout_type = Layout; + + template + struct mapping { + private: + using @\exposid{nested-mapping-type}@ = + typename Layout::template mapping<@\exposid{transpose-extents-t}@>; // \expos + + 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_transpose; + + constexpr explicit mapping(const @\exposid{nested-mapping-type}@&); + + constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } + + constexpr index_type required_span_size() const + { return @\exposid{nested-mapping_}@.required_span_size(); + + template + constexpr index_type operator()(Index0 ind0, Index1 ind1) const + { return @\exposid{nested-mapping_}@(ind1, ind0); } + + constexpr const @\exposid{nested-mapping-type}@& nested_mapping() const noexcept + { return @\exposid{nested-mapping_}@; } + + static constexpr bool is_always_unique() noexcept + { return @\exposid{nested-mapping-type}@::is_always_unique(); } + static constexpr bool is_always_exhaustive() noexcept + { return @\exposid{nested-mapping-type}@::is_always_exhaustive(); } + static constexpr bool is_always_strided() noexcept + { return @\exposid{nested-mapping-type}@::is_always_strided(); } + + constexpr bool is_unique() const { return @\exposid{nested-mapping_}@.is_unique(); } + constexpr bool is_exhaustive() const { return @\exposid{nested-mapping_}@.is_exhaustive(); } + constexpr bool is_strided() const { return @\exposid{nested-mapping_}@.is_strided(); } + + constexpr index_type stride(size_t r) const; + + template + friend constexpr bool operator==(const mapping& x, const mapping& y); + }; + + private: + @\exposid{nested-mapping-type}@ @\exposid{nested-mapping_}@; // \expos + extents_type @\exposid{extents_}@; // \expos + }; +} +\end{codeblock} + +\pnum +\tcode{Layout} shall meet +the layout mapping policy requirements\iref{mdspan.layout.policy.reqmts}. + +\pnum +\mandates +\begin{itemize} +\item +\tcode{Extents} is a specialization of \tcode{std::extents}, and +\item +\tcode{Extents::rank()} equals 2. +\end{itemize} + +\indexlibraryctor{layout_transpose::mapping}% +\begin{itemdecl} +constexpr explicit mapping(const @\exposid{nested-mapping-type}@& map); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +Initializes \exposid{nested-mapping_} with \tcode{map}, and +\item +initializes \exposid{extents_} +with \tcode{\exposid{transpose-extents}(map.extents())}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{layout_transpose::mapping}{stride}% +\begin{itemdecl} +constexpr index_type stride(size_t r) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +\tcode{is_strided()} is \tcode{true}, and +\item +\tcode{r < 2} is \tcode{true}. +\end{itemize} + +\pnum +\returns +\tcode{\exposid{nested-mapping_}.stride(r == 0 ? 1 : 0)} +\end{itemdescr} + +\indexlibrarymember{layout_transpose::mapping}{operator==}% +\begin{itemdecl} +template + friend constexpr bool operator==(const mapping& x, const mapping& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The expression +\tcode{x.\exposid{nested-mapping_} == y.\exposid{nested-mapping_}} +is well-formed and its result is convertible to \tcode{bool}. + +\pnum +\returns +\tcode{x.\exposid{nested-mapping_} == y.\exposid{nested-mapping_}}. +\end{itemdescr} + +\rSec3[linalg.transp.transposed]{Function template \tcode{transposed}} + +\pnum +The \tcode{transposed} function +takes a rank-2 \tcode{mdspan} representing a matrix, and +returns a new \tcode{mdspan} representing the input matrix's transpose. +The input matrix's data are not modified, and +the returned \tcode{mdspan} accesses the input matrix's data in place. +\indexlibraryglobal{transposed}% +\begin{itemdecl} + template + constexpr auto transposed(mdspan a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{Extents::rank() == 2} is \tcode{true}. + +\pnum +Let \tcode{ReturnExtents} be +\tcode{\exposid{transpose-extents-t}}. +Let \tcode{R} be +\tcode{mdspan}, +where \tcode{ReturnLayout} is: +\begin{itemize} +\item +\tcode{layout_right} if \tcode{Layout} is \tcode{layout_left}; +\item +otherwise, \tcode{layout_left} if \tcode{Layout} is \tcode{layout_right}; +\item +otherwise, \tcode{layout_right_padded} if \tcode{Layout} is\newline +\tcode{layout_left_padded} +for some \tcode{size_t} value \tcode{PaddingValue}; +\item +otherwise, \tcode{layout_left_padded} if \tcode{Layout} is\newline +\tcode{layout_right_padded} +for some \tcode{size_t} value \tcode{PaddingValue}; +\item +otherwise, \tcode{layout_stride} if \tcode{Layout} is \tcode{layout_stride}; +\item +otherwise, +\tcode{layout_blas_packed}, +if \tcode{Layout} is\newline +\tcode{layout_blas_packed} +for some \tcode{Triangle} and \tcode{StorageOrder}, where +\begin{itemize} +\item +\tcode{OppositeTriangle} is +\begin{codeblock} +conditional_t, + lower_triangle_t, upper_triangle_t> +\end{codeblock} +and +\item +\tcode{OppositeStorageOrder} is +\begin{codeblock} +conditional_t, row_major_t, column_major_t> +\end{codeblock} +\end{itemize} +\item +otherwise, \tcode{NestedLayout} +if \tcode{Layout} is \tcode{layout_transpose} +for some \tcode{NestedLay\-out}; +\item +otherwise, \tcode{layout_transpose}. +\end{itemize} + +\pnum +\returns +With \tcode{ReturnMapping} being +the type \tcode{typename ReturnLayout::template mapping}: +\begin{itemize} +\item +if \tcode{Layout} is \tcode{layout_left}, \tcode{layout_right}, or +a specialization of \tcode{layout_blas_packed}, +\begin{codeblock} +R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents())), + a.accessor()) +\end{codeblock} +\item +otherwise, +\begin{codeblock} +R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents()), + a.mapping().stride(1)), a.accessor()) +\end{codeblock} +if \tcode{Layout} is \tcode{layout_left_padded} +for some \tcode{size_t} value \tcode{PaddingValue}; +\item +otherwise, +\begin{codeblock} +R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents()), + a.mapping().stride(0)), a.accessor()) +\end{codeblock} +if \tcode{Layout} is \tcode{layout_right_padded} +for some \tcode{size_t} value \tcode{PaddingValue}; +\item +otherwise, if \tcode{Layout} is \tcode{layout_stride}, +\begin{codeblock} +R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents()), + array{a.mapping().stride(1), a.mapping().stride(0)}), a.accessor()) +\end{codeblock} +\item +otherwise, if \tcode{Layout} is a specialization of \tcode{layout_transpose}, +\begin{codeblock} +R(a.data_handle(), a.mapping().nested_mapping(), a.accessor()) +\end{codeblock} +\item +otherwise, +\begin{codeblock} +R(a.data_handle(), ReturnMapping(a.mapping()), a.accessor()) +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\pnum +\begin{example} +\begin{codeblock} +void test_transposed(mdspan> a) { + const auto num_rows = a.extent(0); + const auto num_cols = a.extent(1); + + auto a_t = transposed(a); + assert(num_rows == a_t.extent(1)); + assert(num_cols == a_t.extent(0)); + assert(a.stride(0) == a_t.stride(1)); + assert(a.stride(1) == a_t.stride(0)); + + for (size_t row = 0; row < num_rows; ++row) { + for (size_t col = 0; col < num_rows; ++col) { + assert(a[row, col] == a_t[col, row]); + } + } + + auto a_t_t = transposed(a_t); + assert(num_rows == a_t_t.extent(0)); + assert(num_cols == a_t_t.extent(1)); + assert(a.stride(0) == a_t_t.stride(0)); + assert(a.stride(1) == a_t_t.stride(1)); + + for (size_t row = 0; row < num_rows; ++row) { + for (size_t col = 0; col < num_rows; ++col) { + assert(a[row, col] == a_t_t[row, col]); + } + } +} +\end{codeblock} +\end{example} + +\rSec2[linalg.conjtransposed]{Conjugate transpose in-place transform} + +\pnum +The \tcode{conjugate_transposed} function +returns a conjugate transpose view of an object. +This combines the effects of \tcode{transposed} and \tcode{conjugated}. +\indexlibraryglobal{conjugate_transposed}% +\begin{itemdecl} + template + constexpr auto conjugate_transposed(mdspan a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return conjugated(transposed(a));} +\end{itemdescr} + +\pnum +\begin{example} +\begin{codeblock} +void test_conjugate_transposed(mdspan, extents> a) { + const auto num_rows = a.extent(0); + const auto num_cols = a.extent(1); + + auto a_ct = conjugate_transposed(a); + assert(num_rows == a_ct.extent(1)); + assert(num_cols == a_ct.extent(0)); + assert(a.stride(0) == a_ct.stride(1)); + assert(a.stride(1) == a_ct.stride(0)); + + for (size_t row = 0; row < num_rows; ++row) { + for (size_t col = 0; col < num_rows; ++col) { + assert(a[row, col] == conj(a_ct[col, row])); + } + } + + auto a_ct_ct = conjugate_transposed(a_ct); + assert(num_rows == a_ct_ct.extent(0)); + assert(num_cols == a_ct_ct.extent(1)); + assert(a.stride(0) == a_ct_ct.stride(0)); + assert(a.stride(1) == a_ct_ct.stride(1)); + + for (size_t row = 0; row < num_rows; ++row) { + for (size_t col = 0; col < num_rows; ++col) { + assert(a[row, col] == a_ct_ct[row, col]); + assert(conj(a_ct[col, row]) == a_ct_ct[row, col]); + } + } +} +\end{codeblock} +\end{example} + +\rSec2[linalg.algs.reqs]{Algorithm requirements based on template parameter name} + +\pnum +Throughout +\ref{linalg.algs.blas1}, \ref{linalg.algs.blas2}, and \ref{linalg.algs.blas3}, +where the template parameters are not constrained, +the names of template parameters are used to express the following constraints. +\begin{itemize} +\item +\tcode{is_execution_policy::value} +is \tcode{true}\iref{execpol.type}. +\item +\tcode{Real} is any type such that \tcode{complex} is +specified\iref{complex.numbers.general}. +\item +\tcode{Triangle} is either \tcode{upper_triangle_t} or \tcode{lower_triangle_t}. +\item +\tcode{DiagonalStorage} is +either \tcode{implicit_unit_diagonal_t} or \tcode{explicit_diagonal_t}. +\end{itemize} +\begin{note} +Function templates that have a template parameter named \tcode{ExecutionPolicy} +are parallel algorithms\iref{algorithms.parallel.defns}. +\end{note} + +\rSec2[linalg.algs.blas1]{BLAS 1 algorithms} + +\rSec3[linalg.algs.blas1.complexity]{Complexity} + +\pnum +\complexity +All algorithms in \ref{linalg.algs.blas1} with \tcode{mdspan} parameters +perform a count of \tcode{mdspan} array accesses +and arithmetic operations that is linear in +the maximum product of extents of any \tcode{mdspan} parameter. + +\rSec3[linalg.algs.blas1.givens]{Givens rotations} + +\rSec4[linalg.algs.blas1.givens.lartg]{Compute Givens rotation} + +\indexlibraryglobal{setup_givens_rotation}% +\begin{itemdecl} +template + setup_givens_rotation_result setup_givens_rotation(Real a, Real b) noexcept; + +template + setup_givens_rotation_result> + setup_givens_rotation(complex a, complex b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions compute the Givens plane rotation +represented by the two values $c$ and $s$ +such that the 2 x 2 system of equations +\begin{equation*} +\left[ \begin{matrix} +c & s \\ +-\overline{s} & c \\ +\end{matrix} \right] +\cdot +\left[ \begin{matrix} +a \\ +b \\ +\end{matrix} \right] += +\left[ \begin{matrix} +r \\ +0 \\ +\end{matrix} \right] +\end{equation*} + +holds, where $c$ is always a real scalar, and $c^2 + |s|^2 = 1$. +That is, $c$ and $s$ represent a 2 x 2 matrix, +that when multiplied by the right by the input vector +whose components are $a$ and $b$, +produces a result vector +whose first component $r$ is the Euclidean norm of the input vector, and +whose second component is zero. +\begin{note} +These functions correspond to the LAPACK function \tcode{xLARTG}\supercite{lapack}. +\end{note} + +\pnum +\returns +\tcode{{c, s, r}}, +where \tcode{c} and \tcode{s} form the Givens plane rotation +corresponding to the input \tcode{a} and \tcode{b}, +and \tcode{r} is the Euclidean norm of the two-component vector +formed by \tcode{a} and \tcode{b}. +\end{itemdescr} + +\rSec4[linalg.algs.blas1.givens.rot]{Apply a computed Givens rotation to vectors} + +\indexlibraryglobal{apply_givens_rotation}% +\begin{itemdecl} +template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real> + void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s); +template + void apply_givens_rotation(ExecutionPolicy&& exec, + InOutVec1 x, InOutVec2 y, Real c, Real s); +template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real> + void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex s); +template + void apply_givens_rotation(ExecutionPolicy&& exec, + InOutVec1 x, InOutVec2 y, Real c, complex s); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xROT}\supercite{blas1}. +\end{note} + +\pnum +\mandates +\tcode{\exposid{compatible-static-extents}(0, 0)} is \tcode{true}. + +\pnum +\expects +\tcode{x.extent(0)} equals \tcode{y.extent(0)}. + +\pnum +\effects +Applies the plane rotation +specified by \tcode{c} and \tcode{s} to +the input vectors \tcode{x} and \tcode{y}, +as if the rotation were a 2 x 2 matrix and +the input vectors were successive rows of a matrix with two rows. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.swap]{Swap matrix or vector elements} + +\indexlibraryglobal{swap_elements}% +\begin{itemdecl} +template<@\exposconcept{inout-object}@ InOutObj1, @\exposconcept{inout-object}@ InOutObj2> + void swap_elements(InOutObj1 x, InOutObj2 y); +template + void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xSWAP}\supercite{blas1}. +\end{note} + +\pnum +\constraints +\tcode{x.rank()} equals \tcode{y.rank()}. + +\pnum +\mandates +For all \tcode{r} in the range $[0, \tcode{x.rank()})$, +\begin{codeblock} +@\exposid{compatible-static-extents}@(r, r) +\end{codeblock} +is \tcode{true}. + +\pnum +\expects +\tcode{x.extents()} equals \tcode{y.extents()}. + +\pnum +\effects +Swaps all corresponding elements of \tcode{x} and \tcode{y}. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.scal]{Multiply the elements of an object in place by a scalar} + +\indexlibraryglobal{scale}% +\begin{itemdecl} +template + void scale(Scalar alpha, InOutObj x); +template + void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xSCAL}\supercite{blas1}. +\end{note} + +\pnum +\effects +Overwrites $x$ with the result of +computing the elementwise multiplication $\alpha x$, +where the scalar $\alpha$ is \tcode{alpha}. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.copy]{Copy elements of one matrix or vector into another} + +\indexlibraryglobal{copy}% +\begin{itemdecl} +template<@\exposconcept{in-object}@ InObj, @\exposconcept{out-object}@ OutObj> + void copy(InObj x, OutObj y); +template + void copy(ExecutionPolicy&& exec, InObj x, OutObj y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xCOPY\supercite{blas1}}. +\end{note} + +\pnum +\constraints +\tcode{x.rank()} equals \tcode{y.rank()}. + +\pnum +\mandates +For all \tcode{r} in the range $[ 0, \tcode{x.rank()})$, +\begin{codeblock} +@\exposid{compatible-static-extents}@(r, r) +\end{codeblock} +is \tcode{true}. + +\pnum +\expects +\tcode{x.extents()} equals \tcode{y.extents()}. + +\pnum +\effects +Assigns each element of $x$ to the corresponding element of $y$. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.add]{Add vectors or matrices elementwise} + +\indexlibraryglobal{add}% +\begin{itemdecl} +template<@\exposconcept{in-object}@ InObj1, @\exposconcept{in-object}@ InObj2, @\exposconcept{out-object}@ OutObj> + void add(InObj1 x, InObj2 y, OutObj z); +template + void add(ExecutionPolicy&& exec, + InObj1 x, InObj2 y, OutObj z); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xAXPY}\supercite{blas1}. +\end{note} + +\pnum +\constraints +\tcode{x.rank()}, \tcode{y.rank()}, and \tcode{z.rank()} are all equal. + +\pnum +\mandates +\tcode{\exposid{possibly-addable}()} is \tcode{true}. + +\pnum +\expects +\tcode{\exposid{addable}(x,y,z)} is \tcode{true}. + +\pnum +\effects +Computes $z = x + y$. + +\pnum +\remarks +\tcode{z} may alias \tcode{x} or \tcode{y}. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.dot]{Dot product of two vectors} + +\pnum +\begin{note} +The functions in this section correspond to the BLAS +functions \tcode{xDOT}, \tcode{xDOTU}, and \tcode{xDOTC}\supercite{blas1}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas1.dot}. + +\pnum +\mandates +\tcode{\exposid{compatible-static-extents}(0, 0)} is \tcode{true}. + +\pnum +\expects +\tcode{v1.extent(0)} equals \tcode{v2.extent(0)}. + +\indexlibraryglobal{dot}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> + Scalar dot(InVec1 v1, InVec2 v2, Scalar init); +template + Scalar dot(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2, Scalar init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions compute a non-conjugated dot product +with an explicitly specified result type. + +\pnum +\returns +Let \tcode{N} be \tcode{v1.extent(0)}. +\begin{itemize} +\item +\tcode{init} if \tcode{N} is zero; +\item +otherwise, +\tcode{\placeholdernc{GENERALIZED_SUM}(plus<>(), init, v1[0]*v2[0], \ldots, v1[N-1]*v2[N-1])}. +\end{itemize} + +\pnum +\remarks +If \tcode{InVec1::value_type}, \tcode{InVec2::value_type}, and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InVec1::value_type} or \tcode{InVec2::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\indexlibraryglobal{dot}% +\begin{itemdecl} + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2> + auto dot(InVec1 v1, InVec2 v2); + template + auto dot(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions compute a non-conjugated dot product with a default result type. + +\pnum +\effects +Let \tcode{T} be +\tcode{decltype(declval() * declval())}. +Then, +\begin{itemize} +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return dot(v1, v2, T{}); +\end{codeblock} +and +\item +the three-parameter overload is equivalent to: +\begin{codeblock} +return dot(std::forward(exec), v1, v2, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{dotc}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> + Scalar dotc(InVec1 v1, InVec2 v2, Scalar init); +template + Scalar dotc(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2, Scalar init); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions compute a conjugated dot product +with an explicitly specified result type. + +\pnum +\effects +\begin{itemize} +\item +The three-parameter overload is equivalent to: +\begin{codeblock} +return dot(conjugated(v1), v2, init); +\end{codeblock} +and +\item +the four-parameter overload is equivalent to: +\begin{codeblock} +return dot(std::forward(exec), conjugated(v1), v2, init); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{dotc}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2> + auto dotc(InVec1 v1, InVec2 v2); +template + auto dotc(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions compute a conjugated dot product with a default result type. + +\pnum +\effects +Let \tcode{T} be \tcode{decltype(\exposid{conj-if-needed}(declval()) * decl\-val())}. +Then, +\begin{itemize} +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return dotc(v1, v2, T{}); +\end{codeblock} +and +\item +the three-parameter overload is equivalent to +\begin{codeblock} +return dotc(std::forward(exec), v1, v2, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.ssq]{Scaled sum of squares of a vector's elements} + +\indexlibraryglobal{vector_sum_of_squares}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec, class Scalar> + sum_of_squares_result vector_sum_of_squares(InVec v, sum_of_squares_result init); +template + sum_of_squares_result vector_sum_of_squares(ExecutionPolicy&& exec, + InVec v, sum_of_squares_result init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the LAPACK function \tcode{xLASSQ}\supercite{lapack}. +\end{note} + +\pnum +\mandates +\tcode{decltype(\exposid{abs-if-needed}(declval()))} is convertible to \tcode{Scalar}. + +\pnum +\effects +Returns a value \tcode{result} such that +\begin{itemize} +\item +\tcode{result.scaling_factor} is the maximum of \tcode{init.scaling_factor} and +\tcode{\exposid{abs-if-needed}(x[i])} +for all \tcode{i} in the domain of \tcode{v}; and +\item +let \tcode{s2init} be +\begin{codeblock} +init.scaling_factor * init.scaling_factor * init.scaled_sum_of_squares +\end{codeblock} +then \tcode{result.scaling_factor * result.scaling_factor * result.scaled_sum_of_squares} +equals the sum of \tcode{s2init} and +the squares of \tcode{\exposid{abs-if-needed}(x[i])} +for all \tcode{i} in the domain of \tcode{v}. +\end{itemize} + +\pnum +\remarks +If \tcode{InVec::value_type}, and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InVec::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.nrm2]{Euclidean norm of a vector} + +\indexlibraryglobal{vector_two_norm}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec, class Scalar> + Scalar vector_two_norm(InVec v, Scalar init); +template + Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xNRM2}\supercite{blas1}. +\end{note} + +\pnum +\mandates +Let \tcode{a} be +\tcode{\exposid{abs-if-needed}(declval())}. +Then, \tcode{decltype(\linebreak init + a * a} is convertible to \tcode{Scalar}. + +\pnum +\returns +The square root of the sum of the square of \tcode{init} and the squares of the absolute values of the elements of \tcode{v}. +\begin{note} +For \tcode{init} equal to zero, this is the Euclidean norm +(also called 2-norm) of the vector \tcode{v}. +\end{note} + +\pnum +\remarks +If \tcode{InVec::value_type}, and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InVec::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\begin{note} +An implementation of this function for floating-point types \tcode{T} +can use the \tcode{scaled_sum_of_squares} result from +\tcode{vector_sum_of_squares(x, \{.scaling_factor=1.0, .scaled_sum_of_squares=init\})}. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{vector_two_norm}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec> + auto vector_two_norm(InVec v); +template + auto vector_two_norm(ExecutionPolicy&& exec, InVec v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{a} be +\tcode{\exposid{abs-if-needed}(declval())}. +Let \tcode{T} be \tcode{decltype(a * a)}. +Then, +\begin{itemize} +\item +the one-parameter overload is equivalent to: +\begin{codeblock} +return vector_two_norm(v, T{}); +\end{codeblock} +and +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return vector_two_norm(std::forward(exec), v, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.asum]{Sum of absolute values of vector elements} + +\indexlibraryglobal{vector_abs_sum}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec, class Scalar> + Scalar vector_abs_sum(InVec v, Scalar init); +template + Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{SASUM}, \tcode{DASUM}, \tcode{SCASUM}, and \tcode{DZASUM}\supercite{blas1}. +\end{note} + +\pnum +\mandates +\begin{codeblock} +decltype(init + @\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(declval())) + + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(declval()))) +\end{codeblock} +is convertible to \tcode{Scalar}. + +\pnum +\returns +Let \tcode{N} be \tcode{v.extent(0)}. +\begin{itemize} +\item +\tcode{init} if \tcode{N} is zero; +\item +otherwise, if \tcode{InVec::value_type} is an arithmetic type, +\begin{codeblock} +@\placeholdernc{GENERALIZED_SUM}@(plus<>(), init, @\exposid{abs-if-needed}@(v[0]), @\ldots@, @\exposid{abs-if-needed}@(v[N-1])) +\end{codeblock} +\item +otherwise, +\begin{codeblock} +@\placeholdernc{GENERALIZED_SUM}@(plus<>(), init, + @\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(v[0])) + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(v[0])), + @\ldots@, + @\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(v[N-1])) + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(v[N-1]))) +\end{codeblock} +\end{itemize} + +\pnum +\remarks +If \tcode{InVec::value_type} and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InVec::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\indexlibraryglobal{vector_abs_sum}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec> + auto vector_abs_sum(InVec v); +template + auto vector_abs_sum(ExecutionPolicy&& exec, InVec v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{T} be \tcode{typename InVec::value_type}. +Then, +\begin{itemize} +\item +the one-parameter overload is equivalent to: +\begin{codeblock} +return vector_abs_sum(v, T{}); +\end{codeblock} +and +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return vector_abs_sum(std::forward(exec), v, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.iamax]{Index of maximum absolute value of vector elements} + +\indexlibraryglobal{vector_idx_abs_max}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec> + typename InVec::extents_type vector_idx_abs_max(InVec v); +template + typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{IxAMAX}\supercite{blas1}. +\end{note} + +\pnum +Let \tcode{T} be +\begin{codeblock} +decltype(@\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(declval())) + + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(declval()))) +\end{codeblock} + +\pnum +\mandates +\tcode{declval() < declval()} is a valid expression. + +\pnum +\returns +\begin{itemize} +\item +\tcode{numeric_limits::max()} + if \tcode{v} has zero elements; +\item +otherwise, the index of the first element of \tcode{v} +having largest absolute value, +if \tcode{InVec::value_type} is an arithmetic type; +\item +otherwise, the index of the first element $\tcode{v}_e$ of \tcode{v} +for which +\begin{codeblock} +@\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(@$\tcode{v}_e$@)) + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(@$\tcode{v}_e$@)) +\end{codeblock} +has the largest value. +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.matfrobnorm]{Frobenius norm of a matrix} + +\pnum +\begin{note} +These functions exist in the BLAS standard\supercite{blas-std} +but are not part of the reference implementation. +\end{note} + +\indexlibraryglobal{matrix_frob_norm}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_frob_norm(InMat A, Scalar init); +template + Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +\mandates +Let \tcode{a} be +\tcode{\exposid{abs-if-needed}(declval())}. +Then, \tcode{decltype(\linebreak init + a * a)} +is convertible to \tcode{Scalar}. + +\pnum +\returns +The square root of the sum of squares +of \tcode{init} and the absolute values of the elements of \tcode{A}. +\begin{note} +For \tcode{init} equal to zero, +this is the Frobenius norm of the matrix \tcode{A}. +\end{note} + +\pnum +\remarks +If \tcode{InMat::value_type} and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InMat::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\indexlibraryglobal{matrix_frob_norm}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat> + auto matrix_frob_norm(InMat A); +template + auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{a} be +\tcode{\exposid{abs-if-needed}(declval())}. +Let \tcode{T} be +\tcode{decltype(a * a)}. +Then, +\begin{itemize} +\item +the one-parameter overload is equivalent to: +\begin{codeblock} +return matrix_frob_norm(A, T{}); +\end{codeblock} +and +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return matrix_frob_norm(std::forward(exec), A, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.matonenorm]{One norm of a matrix} + +\pnum +\begin{note} +These functions exist in the BLAS standard\supercite{blas-std} +but are not part of the reference implementation. +\end{note} + +\indexlibraryglobal{matrix_one_norm}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_one_norm(InMat A, Scalar init); +template + Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{decltype(\exposid{abs-if-needed}(declval()))} +is convertible to \tcode{Scalar}. + +\pnum +\returns +\begin{itemize} +\item +\tcode{init} if \tcode{A.extent(1)} is zero; +\item +otherwise, the sum of \tcode{init} and the one norm of the matrix $A$. +\end{itemize} +\begin{note} +The one norm of the matrix \tcode{A} +is the maximum over all columns of \tcode{A}, +of the sum of the absolute values of the elements of the column. +\end{note} + +\pnum +\remarks +If \tcode{InMat::value_type} and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InMat::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\indexlibraryglobal{matrix_one_norm}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat> + auto matrix_one_norm(InMat A); +template + auto matrix_one_norm(ExecutionPolicy&& exec, InMat A); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{T} be +\tcode{decltype(\exposid{abs-if-needed}(declval())}. +Then, +\begin{itemize} +\item +the one-parameter overload is equivalent to: +\begin{codeblock} +return matrix_one_norm(A, T{}); +\end{codeblock} +and +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return matrix_one_norm(std::forward(exec), A, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.matinfnorm]{Infinity norm of a matrix} + +\pnum +\begin{note} +These functions exist in the BLAS standard\supercite{blas-std} +but are not part of the reference implementation. +\end{note} + +\indexlibraryglobal{matrix_inf_norm}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_inf_norm(InMat A, Scalar init); +template + Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{decltype(\exposid{abs-if-needed}(declval()))} +is convertible to \tcode{Scalar}. + +\pnum +\returns +\begin{itemize} +\item +\tcode{init} if \tcode{A.extent(0)} is zero; +\item +otherwise, +the sum of \tcode{init} and the infinity norm of the matrix \tcode{A}. +\end{itemize} +\begin{note} +The infinity norm of the matrix \tcode{A} +is the maximum over all rows of \tcode{A}, +of the sum of the absolute values +of the elements of the row. +\end{note} + +\pnum +\remarks +If \tcode{InMat::value_type} and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InMat::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\indexlibraryglobal{matrix_inf_norm}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat> + auto matrix_inf_norm(InMat A); +template + auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +\effects +Let \tcode{T} be +\tcode{decltype(\exposid{abs-if-needed}(declval())}. +Then, +\begin{itemize} +\item +the one-parameter overload is equivalent to: +\begin{codeblock} +return matrix_inf_norm(A, T{}); +\end{codeblock} +and +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return matrix_inf_norm(std::forward(exec), A, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec2[linalg.algs.blas2]{BLAS 2 algorithms} + +\rSec3[linalg.algs.blas2.gemv]{General matrix-vector product} + +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xGEMV}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.gemv}. + +\pnum +\mandates +\begin{itemize} +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}, and +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(A,x,y)} is \tcode{true}, and +\item +\tcode{\exposid{addable}(x,y,z)} is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. + +\indexlibraryglobal{matrix_vector_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void matrix_vector_product(InMat A, InVec x, OutVec y); +template + void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec x, OutVec y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an overwriting matrix-vector product. + +\pnum +\effects +Computes $y = A x$. +\end{itemdescr} + +\begin{example} +\begin{codeblock} +constexpr size_t num_rows = 5; +constexpr size_t num_cols = 6; + +// y = 3.0 * A * x +void scaled_matvec_1(mdspan> A, + mdspan> x, mdspan> y) { + matrix_vector_product(scaled(3.0, A), x, y); +} + +// z = 7.0 times the transpose of A, times y +void scaled_transposed_matvec(mdspan> A, + mdspan> y, mdspan> z) { + matrix_vector_product(scaled(7.0, transposed(A)), y, z); +} +\end{codeblock} +\end{example} + +\indexlibraryglobal{matrix_vector_product}% +\begin{itemdecl} + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z); + template + void matrix_vector_product(ExecutionPolicy&& exec, + InMat A, InVec1 x, InVec2 y, OutVec z); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an updating matrix-vector product. + +\pnum +\effects +Computes $z = y + A x$. + +\pnum +\remarks +\tcode{z} may alias \tcode{y}. +\end{itemdescr} + +\begin{example} +\begin{codeblock} +// y = 3.0 * A * x + 2.0 * y +void scaled_matvec_2(mdspan> A, + mdspan> x, mdspan> y) { + matrix_vector_product(scaled(3.0, A), x, scaled(2.0, y), y); +} +\end{codeblock} +\end{example} + +\rSec3[linalg.algs.blas2.symv]{Symmetric matrix-vector product} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYMV} and \tcode{xSPMV}\supercite{blas2}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.symv}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{\exposid{multipliable}(A,x,y)} is \tcode{true}, and +\item +\tcode{\exposid{addable}(x,y,z)} is \tcode{true} +for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. + +\indexlibraryglobal{symmetric_matrix_vector_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); +template + void symmetric_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec x, OutVec y); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions perform an overwriting symmetric matrix-vector product, +taking into account the \tcode{Triangle} parameter +that applies to the symmetric matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $y = A x$. +\end{itemdescr} + +\indexlibraryglobal{symmetric_matrix_vector_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); +template + void symmetric_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an updating symmetric matrix-vector product, +taking into account the \tcode{Triangle} parameter +that applies to the symmetric matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $z = y + A x$. + +\pnum +\remarks +\tcode{z} may alias \tcode{y}. +\end{itemdescr} + +\rSec3[linalg.algs.blas2.hemv]{Hermitian matrix-vector product} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xHEMV} and \tcode{xHPMV}\supercite{blas2}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.hemv}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument +has the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{\exposid{multipliable}(A, x, y)} is \tcode{true}, and +\item +\tcode{\exposid{addable}(x, y, z)} is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. + +\indexlibraryglobal{hermitian_matrix_vector_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); +template + void hermitian_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec x, OutVec y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an overwriting Hermitian matrix-vector product, +taking into account the \tcode{Triangle} parameter +that applies to the Hermitian matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $y = A x$. +\end{itemdescr} + +\indexlibraryglobal{hermitian_matrix_vector_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); +template + void hermitian_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an updating Hermitian matrix-vector product, +taking into account the \tcode{Triangle} parameter +that applies to the Hermitian matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $z = y + A x$. + +\pnum +\remarks +\tcode{z} may alias \tcode{y}. +\end{itemdescr} + +\rSec3[linalg.algs.blas2.trmv]{Triangular matrix-vector product} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xTRMV} and \tcode{xTPMV}\supercite{blas2}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.trmv}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true}; +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true} for those overloads that take an \tcode{x} parameter; and +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{A.extent(0)} equals \tcode{y.extent(0)}, +\item +\tcode{A.extent(0)} equals \tcode{x.extent(0)} for those overloads that take an \tcode{x} parameter, and +\item +\tcode{A.extent(0)} equals \tcode{z.extent(0)} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\indexlibraryglobal{triangular_matrix_vector_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec, + @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y); +template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions perform +an overwriting triangular matrix-vector product, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $y = A x$. + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_vector_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y); +template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutVec y); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions perform an in-place triangular matrix-vector product, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. +\begin{note} +Performing this operation in place hinders parallelization. +However, other \tcode{ExecutionPolicy} specific optimizations, +such as vectorization, are still possible. +\end{note} + +\pnum +\effects +Computes a vector $y'$ such that $y' = A y$, +and assigns each element of $y'$ to the corresponding element of $y$. + +\pnum +\complexity +\bigoh{\tcode{y.extent(0)} \times \tcode{A.extent(1)}}. +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_vector_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, + InVec1 x, InVec2 y, OutVec z); +template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InVec1 x, InVec2 y, OutVec z); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an updating triangular matrix-vector product, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $z = y + A x$. + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. + +\pnum +\remarks +\tcode{z} may alias \tcode{y}. +\end{itemdescr} + +\rSec3[linalg.algs.blas2.trsv]{Solve a triangular linear system} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xTRSV} and \tcode{xTPSV}\supercite{blas2}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.trsv}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true} for those overloads that take an \tcode{x} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{A.extent(0)} equals \tcode{b.extent(0)}, and +\item +\tcode{A.extent(0)} equals \tcode{x.extent(0)} +for those overloads that take an \tcode{x} parameter. +\end{itemize} + +\indexlibraryglobal{triangular_matrix_vector_solve}% +\begin{itemdecl} + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec, class BinaryDivideOp> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x, BinaryDivideOp divide); + template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions perform +a triangular solve, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes a vector $x'$ such that $b = A x'$, +and assigns each element of $x'$ to the corresponding element of $x$. +If no such $x'$ exists, +then the elements of \tcode{x} are valid but unspecified. + +\pnum +\complexity +\bigoh{\tcode{A.extent(1)} \times \tcode{b.extent(0)}}. +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_vector_solve}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_vector_solve(A, t, d, b, x, divides{}); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_vector_solve}% +\begin{itemdecl} +template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_vector_solve(std::forward(exec), + A, t, d, b, x, divides{}); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_vector_solve}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-vector}@ InOutVec, class BinaryDivideOp> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, + InOutVec b, BinaryDivideOp divide); +template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutVec b, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an in-place triangular solve, +taking into account the \tcode{Triangle} and \tcode{Diagonal\-Storage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. +\begin{note} +Performing triangular solve in place hinders parallelization. +However, other \tcode{ExecutionPolicy} specific optimizations, +such as vectorization, are still possible. +\end{note} + +\pnum +\effects +Computes a vector $x'$ such that $b = A x'$, +and assigns each element of $x'$ to the corresponding element of $b$. +If no such $x'$ exists, +then the elements of \tcode{b} are valid but unspecified. + +\pnum +\complexity +\bigoh{\tcode{A.extent(1)} \times \tcode{b.extent(0)}}. +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_vector_solve}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_vector_solve(A, t, d, b, divides{}); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_vector_solve}% +\begin{itemdecl} +template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutVec b); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_vector_solve(std::forward(exec), + A, t, d, b, divides{}); +\end{codeblock} +\end{itemdescr} + +\rSec3[linalg.algs.blas2.rank1]{Rank-1 (outer product) update of a matrix} + +\indexlibraryglobal{matrix_rank_1_update}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{inout-matrix}@ InOutMat> + void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A); +template + void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform a nonsymmetric nonconjugated rank-1 update. +\begin{note} +These functions correspond to the BLAS functions +\tcode{xGER} (for real element types) and +\tcode{xGERU} (for complex element types)\supercite{blas2}. +\end{note} + +\pnum +\mandates +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}. + +\pnum +\expects +\tcode{\exposid{multipliable}(A, y, x)} is \tcode{true}. + +\pnum +\effects +Computes a matrix $A'$ such that $A' = A + x y^T$, +and assigns each element of $A'$ to the corresponding element of $A$. + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{y.extent(0)}}. +\end{itemdescr} + +\indexlibraryglobal{matrix_rank_1_update}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{inout-matrix}@ InOutMat> + void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A); +template + void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform a nonsymmetric conjugated rank-1 update. +\begin{note} +These functions correspond to the BLAS functions +\tcode{xGER} (for real element types) and +\tcode{xGERC} (for complex element types)\supercite{blas2}. +\end{note} + +\pnum +\effects +\begin{itemize} +\item +For the overloads without an \tcode{ExecutionPolicy} argument, +equivalent to: +\begin{codeblock} +matrix_rank_1_update(x, conjugated(y), A); +\end{codeblock} +\item +otherwise, equivalent to: +\begin{codeblock} +matrix_rank_1_update(std::forward(exec), x, conjugated(y), A); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas2.symherrank1]{Symmetric or Hermitian Rank-1 (outer product) update of a matrix} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYR}, \tcode{xSPR}, \tcode{xHER}, and \tcode{xHPR}\supercite{blas2}. +They have overloads taking a scaling factor \tcode{alpha}, +because it would be impossible to express the update +$A = A - x x^T$ otherwise. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.symherrank1}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, and +\item +\tcode{A.extent(0)} equals \tcode{x.extent(0)}. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{x.extent(0)}}. + +\indexlibraryglobal{symmetric_matrix_rank_1_update}% +\begin{itemdecl} +template + void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); +template + void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a symmetric rank-1 update of the symmetric matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes a matrix $A'$ such that +$A' = A + \alpha x x^T$, where the scalar $\alpha$ is \tcode{alpha}, +and assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\indexlibraryglobal{symmetric_matrix_rank_1_update}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); +template + void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a symmetric rank-1 update of the symmetric matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes a matrix $A'$ such that $A' = A + x x^T$ +and assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\indexlibraryglobal{hermitian_matrix_rank_1_update}% +\begin{itemdecl} +template + void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); +template + void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a Hermitian rank-1 update of the Hermitian matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $A'$ such that +$A' = A + \alpha x x^H$, where the scalar $\alpha$ is \tcode{alpha}, +and assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\indexlibraryglobal{hermitian_matrix_rank_1_update}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); +template + void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a Hermitian rank-1 update of the Hermitian matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes a matrix $A'$ such that $A' = A + x x^H$ and +assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\rSec3[linalg.algs.blas2.rank2]{Symmetric and Hermitian rank-2 matrix updates} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYR2},\tcode{xSPR2}, \tcode{xHER2} and \tcode{xHPR2}\supercite{blas2}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.rank2}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; and +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, and +\item +\tcode{\exposid{multipliable}(A, x, y)} is \tcode{true}. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{y.extent(0)}}. + +\indexlibraryglobal{symmetric_matrix_rank_2_update}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); +template + void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a symmetric rank-2 update of the symmetric matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $A'$ such that $A' = A + x y^T + y x^T$ and +assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\indexlibraryglobal{hermitian_matrix_rank_2_update}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); +template + void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a Hermitian rank-2 update of the Hermitian matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $A'$ such that $A' = A + x y^H + y x^H$ and +assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\rSec2[linalg.algs.blas3]{BLAS 3 algorithms} + +\rSec3[linalg.algs.blas3.gemm]{General matrix-matrix product} + +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xGEMM}\supercite{blas3}. +\end{note} + +\pnum +The following elements apply +to all functions in \ref{linalg.algs.blas3.gemm} +in addition to function-specific elements. + +\pnum +\mandates +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}. + +\pnum +\expects +\tcode{\exposid{multipliable}(A, B, C)} is \tcode{true}. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. + +\indexlibraryglobal{matrix_product}% +\begin{itemdecl} + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void matrix_product(InMat1 A, InMat2 B, OutMat C); + template + void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes $C = A B$. +\end{itemdescr} + +\indexlibraryglobal{matrix_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C); +template + void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InMat3 E, OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{\exposid{possibly-addable}()} is \tcode{true}. + +\pnum +\expects +\tcode{\exposid{addable}(E, E, C)} is \tcode{true}. + +\pnum +\effects +Computes $C = E + A B$. + +\pnum +\remarks +\tcode{C} may alias \tcode{E}. +\end{itemdescr} + +\rSec3[linalg.algs.blas3.xxmm]{Symmetric, Hermitian, and triangular matrix-matrix product} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYMM}, \tcode{xHEMM}, and \tcode{xTRMM}\supercite{blas3}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas3.xxmm} +in addition to function-specific elements. + +\pnum +\mandates +\begin{itemize} +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}, and +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads that take an \tcode{E} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(A, B, C)} is \tcode{true}, and +\item +\tcode{\exposid{addable}(E, E, C)} +is \tcode{true} for those overloads that take an \tcode{E} parameter. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. + +\indexlibraryglobal{symmetric_matrix_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); +template + void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); +template + void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); +template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform a matrix-matrix multiply, +taking into account +the \tcode{Triangle} and \tcode{Diagonal\-Storage} (if applicable) parameters +that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{A}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat1} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. + +\pnum +\effects +Computes $C = A B$. +\end{itemdescr} + +\indexlibraryglobal{symmetric_matrix_product}% +\begin{itemdecl} + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); + template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); + template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage, + @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); + template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform a matrix-matrix multiply, +taking into account +the \tcode{Triangle} and \tcode{Diagonal\-Storage} (if applicable) parameters +that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{B}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat2} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{B.extent(0) == B.extent(1)} is \tcode{true}. + +\pnum +\effects +Computes $C = A B$. +\end{itemdescr} + +\indexlibraryglobal{symmetric_matrix_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); +template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); +template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, + OutMat C); +template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, + OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a potentially overwriting matrix-matrix multiply-add, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} (if applicable) parameters +that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{A}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat1} has \tcode{layout_blas_packed} layout, then the + layout's \tcode{Triangle} template argument has the same type as + the function's \tcode{Triangle} template argument; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. + +\pnum +\effects +Computes $C = E + A B$. + +\pnum +\remarks +\tcode{C} may alias \tcode{E}. +\end{itemdescr} + +\indexlibraryglobal{symmetric_matrix_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); +template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); +template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, + OutMat C); +template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, + OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a potentially overwriting matrix-matrix multiply-add, +taking into account +the \tcode{Triangle} and \tcode{Diagonal\-Storage} (if applicable) parameters +that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{B}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat2} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{B.extent(0) == B.extent(1)} is \tcode{true}. + +\pnum +\effects +Computes $C = E + A B$. + +\pnum +\remarks +\tcode{C} may alias \tcode{E}. +\end{itemdescr} + +\rSec3[linalg.algs.blas3.trmm]{In-place triangular matrix-matrix product} + +\pnum +These functions perform +an in-place matrix-matrix multiply, +taking into account +the \tcode{Triangle} and \tcode{Diagonal\-Storage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. +\begin{note} +These functions correspond to the BLAS function \tcode{xTRMM}\supercite{blas3}. +\end{note} + +\indexlibraryglobal{triangular_matrix_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); +template + void triangular_matrix_left_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(A, C, C)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes a matrix $C'$ such that $C' = A C$ and +assigns each element of $C'$ to the corresponding element of $C$. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_right_product}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); +template + void triangular_matrix_right_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(C, A, C)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes a matrix $C'$ such that $C' = C A$ and +assigns each element of $C'$ to the corresponding element of $C$. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. +\end{itemdescr} + +\rSec3[linalg.algs.blas3.rankk]{Rank-k update of a symmetric or Hermitian matrix} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYRK} and \tcode{xHERK}\supercite{blas3}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas3.rankk}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{C.extent(0)} equals \tcode{C.extent(1)}, and +\item +\tcode{A.extent(0)} equals \tcode{C.extent(0)}. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. + +\indexlibraryglobal{symmetric_matrix_rank_k_update}% +\begin{itemdecl} + template + void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); + template + void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, + Scalar alpha, InMat A, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + \alpha A A^T$, +where the scalar $\alpha$ is \tcode{alpha}, +and assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\indexlibraryglobal{symmetric_matrix_rank_k_update}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); +template + void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, + InMat A, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + A A^T$, and +assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\indexlibraryglobal{hermitian_matrix_rank_k_update}% +\begin{itemdecl} +template + void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); +template + void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, + Scalar alpha, InMat A, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + \alpha A A^H$, +where the scalar $\alpha$ is \tcode{alpha}, +and assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\indexlibraryglobal{hermitian_matrix_rank_k_update}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); +template + void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, + InMat A, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + A A^H$, and +assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\rSec3[linalg.algs.blas3.rank2k]{Rank-2k update of a symmetric or Hermitian matrix} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYR2K} and \tcode{xHER2K}\supercite{blas3}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas3.rank2k}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{addable}(A, B, C)} is \tcode{true}, and +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. + +\indexlibraryglobal{symmetric_matrix_rank_2k_update}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); +template + void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + A B^T + B A^T$, +and assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\indexlibraryglobal{hermitian_matrix_rank_2k_update}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); +template + void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + A B^H + B A^H$, +and assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\rSec3[linalg.algs.blas3.trsm]{Solve multiple triangular linear systems} + +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xTRSM}\supercite{blas3}. +\end{note} + +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp> + void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); +template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform multiple matrix solves, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat1} has \tcode{layout_blas_packed} layout, then the + layout's \tcode{Triangle} template argument has the same type as + the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(A, X, B)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes $X'$ such that $AX' = B$, +and assigns each element of $X'$ to the corresponding element of $X$. +If no such $X'$ exists, +then the elements of \tcode{X} are valid but unspecified. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{X.extent(1)} \times \tcode{X.extent(1)}}. +\end{itemdescr} + +\pnum +\begin{note} +Since the triangular matrix is on the left, +the desired \tcode{divide} implementation +in the case of noncommutative multiplication +is mathematically equivalent to $y^{-1} x$, +where $x$ is the first argument and $y$ is the second argument, +and $y^{-1}$ denotes the multiplicative inverse of $y$. +\end{note} + +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_left_solve(A, t, d, B, X, divides{}); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% +\begin{itemdecl} +template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_left_solve(std::forward(exec), + A, t, d, B, X, divides{}); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp> + void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); +template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions perform multiple matrix solves, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat1} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0,1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(X, A, B)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes $X'$ such that $X'A = B$, +and assigns each element of $X'$ to the corresponding element of $X$. +If no such $X'$ exists, +then the elements of \tcode{X} are valid but unspecified. + +\pnum +\complexity +$O($ \tcode{B.extent(0)} $\cdot$ \tcode{B.extent(1)} $\cdot$ \tcode{A.extent(1)} $)$ +\begin{note} +Since the triangular matrix is on the right, +the desired \tcode{divide} implementation +in the case of noncommutative multiplication +is mathematically equivalent to $x y^{-1}$, +where $x$ is the first argument and $y$ is the second argument, +and $y^{-1}$ denotes the multiplicative inverse of $y$. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_right_solve(A, t, d, B, X, divides{}); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% +\begin{itemdecl} +template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_right_solve(std::forward(exec), + A, t, d, B, X, divides{}); +\end{codeblock} +\end{itemdescr} + +\rSec3[linalg.algs.blas3.inplacetrsm]{Solve multiple triangular linear systems in-place} + +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xTRSM}\supercite{blas3}. +\end{note} + +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp> + void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); +template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform multiple in-place matrix solves, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. +\begin{note} +This algorithm makes it possible +to compute factorizations like Cholesky and LU in place. +Performing triangular solve in place hinders parallelization. +However, other \tcode{ExecutionPolicy} specific optimizations, +such as vectorization, are still possible. +\end{note} + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(A, B, B)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes $X'$ such that $AX' = B$, +and assigns each element of $X'$ to the corresponding element of $B$. +If so such $X'$ exists, +then the elements of \tcode{B} are valid but unspecified. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_left_solve(A, t, d, B, divides{}); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% +\begin{itemdecl} + template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_left_solve(std::forward(exec), + A, t, d, B, divides{}); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp> + void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); +template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform multiple in-place matrix solves, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. +\begin{note} +This algorithm makes it possible +to compute factorizations like Cholesky and LU in place. +Performing triangular solve in place hinders parallelization. +However, other \tcode{ExecutionPolicy} specific optimizations, +such as vectorization, are still possible. +\end{note} + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(B, A, B)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes $X'$ such that $X'A = B$, +and assigns each element of $X'$ to the corresponding element of $B$. +If so such $X'$ exists, +then the elements of \tcode{B} are valid but unspecified. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_right_solve(A, t, d, B, divides{}); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% +\begin{itemdecl} +template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_right_solve(std::forward(exec), + A, t, d, B, divides{}); +\end{codeblock} +\end{itemdescr} + +\rSec1[simd]{Data-parallel types} + +\rSec2[simd.general]{General} + +\pnum +Subclause \ref{simd} defines data-parallel types and operations on these types. +\begin{note} +The intent is to support acceleration through data-parallel execution resources +where available, such as SIMD registers and instructions or execution units +driven by a common instruction decoder. +SIMD stands for ``Single Instruction Stream -- Multiple Data Stream''; +it is defined in Flynn 1966\supercite{flynn-taxonomy}. +\end{note} + +\pnum +The set of \defnadjx{vectorizable}{types}{type} comprises +\begin{itemize} + \item + all standard integer types, character types, and the types \tcode{float} and + \tcode{double}\iref{basic.fundamental}; + \item + \tcode{std::float16_t}, \tcode{std::float32_t}, and \tcode{std::float64_t} + if defined\iref{basic.extended.fp}; and + \item + \tcode{complex} where \tcode{T} is a vectorizable floating-point type. +\end{itemize} + +\pnum +The term \defnadj{data-parallel}{type} refers to all enabled specializations of +the \tcode{basic_simd} and \tcode{basic_simd_mask} class templates. +A \defnadj{data-parallel}{object} is an object of data-parallel type. + +\pnum +Each specialization of \tcode{basic_simd} or \tcode{basic_simd_mask} is either +enabled or disabled, as described in \ref{simd.overview} and +\ref{simd.mask.overview}. + +\pnum +A data-parallel type consists of one or more elements of an underlying +vectorizable type, called the \defnadj{element}{type}. +The number of elements is a constant for each data-parallel type and called the +\defn{width} of that type. +The elements in a data-parallel type are indexed from 0 to $\textrm{width} - 1$. + +\pnum +An \defnadj{element-wise}{operation} applies a specified operation to the +elements of one or more data-parallel objects. +Each such application is unsequenced with respect to the others. +A \defnadj{unary element-wise}{operation} is an element-wise operation that +applies a unary operation to each element of a data-parallel object. +A \defnadj{binary element-wise}{operation} is an element-wise operation that +applies a binary operation to corresponding elements of two data-parallel +objects. + +\pnum +Given a \tcode{basic_simd_mask} object \tcode{mask}, the +\defnadj{selected}{indices} signify the integers $i$ in the range +\range{0}{mask.size()} for which \tcode{mask[$i$]} is \tcode{true}. +Given a data-parallel object \tcode{data}, the \defnadj{selected}{elements} +signify the elements \tcode{data[$i$]} for all selected indices $i$. + +\pnum +The conversion from an arithmetic type \tcode{U} to a vectorizable type +\tcode{T} is \defn{value-preserving} if all possible values of \tcode{U} can be +represented with type \tcode{T}. + +\rSec2[simd.expos]{Exposition-only types, variables, and concepts} + +\begin{codeblock} +using @\exposidnc{simd-size-type} = \seebelownc@; // \expos +template using @\exposidnc{integer-from} = \seebelownc@; // \expos + +template + constexpr @\exposidnc{simd-size-type} \exposidnc{simd-size-v} = \seebelownc@; // \expos +template constexpr size_t @\exposidnc{mask-element-size} = \seebelownc@; // \expos + +template + concept @\defexposconceptnc{constexpr-wrapper-like}@ = // \expos + @\libconcept{convertible_to}@ && + @\libconcept{equality_comparable_with}@ && + bool_constant::value && + bool_constant(T()) == T::value>::value; + +template using @\exposidnc{deduced-simd-t} = \seebelownc@; // \expos + +template using @\exposidnc{make-compatible-simd-t} = \seebelownc@; // \expos + +template + concept @\defexposconceptnc{simd-type}@ = // \expos + @\libconcept{same_as}@> && + is_default_constructible_v; + +template + concept @\defexposconceptnc{simd-floating-point}@ = // \expos + @\exposconcept{simd-type}@ && @\libconcept{floating_point}@; + +template + using @\exposidnc{simd-complex-value-type}@ = typename V::value_type::value_type; // \expos + +template + concept @\defexposconceptnc{simd-complex}@ = // \expos + @\exposconcept{simd-type}@ && @\libconcept{same_as}@>>; + +template + concept @\defexposconceptnc{math-floating-point}@ = // \expos + (@\exposconceptnc{simd-floating-point}<\exposidnc{deduced-simd-t}@> || ...); + +template + requires @\exposconceptnc{math-floating-point}@ + using @\exposidnc{math-common-simd-t} = \seebelownc@; // \expos + +template + concept @\exposconceptnc{reduction-binary-operation} = \seebelownc@; // \expos + +// \ref{simd.expos.abi}, \tcode{simd} ABI tags +template using @\exposidnc{native-abi} = \seebelownc@; // \expos +template using @\exposidnc{deduce-abi-t} = \seebelownc@; // \expos + +// \ref{simd.flags}, Load and store flags +struct @\exposidnc{convert-flag}@; // \expos +struct @\exposidnc{aligned-flag}@; // \expos +template struct @\exposidnc{overaligned-flag}@; // \expos +\end{codeblock} + +\rSec3[simd.expos.defn]{Exposition-only helpers} + +\begin{itemdecl} +using @\exposid{simd-size-type}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\exposid{simd-size-type} is an alias for a signed integer type. +\end{itemdescr} + +\begin{itemdecl} +template using @\exposid{integer-from}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{\exposid{integer-from}} is an alias for a signed integer type +\tcode{T} such that \tcode{sizeof(T)} equals \tcode{Bytes}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr @\exposid{simd-size-type} \exposid{simd-size-v}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{\exposid{simd-size-v}} denotes the width of \tcode{basic_simd} if the specialization \tcode{basic_simd} is enabled, or \tcode{0} +otherwise. +\end{itemdescr} + +\begin{itemdecl} +template constexpr size_t @\exposid{mask-element-size}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{\exposid{mask-element-size}>} has the value +\tcode{Bytes}. +\end{itemdescr} + +\begin{itemdecl} +template using @\exposid{deduced-simd-t}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{x} denote an lvalue of type \tcode{const T}. + +\pnum +\tcode{\exposid{deduced-simd-t}} is an alias for +\begin{itemize} + \item + \tcode{decltype(x + x)}, if the type of \tcode{x + x} is an enabled + specialization of \tcode{basic_simd}; otherwise + \item + \tcode{void}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template using @\exposid{make-compatible-simd-t}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{x} denote an lvalue of type \tcode{const T}. +\pnum +\tcode{\exposid{make-compatible-simd-t}} is an alias for +\begin{itemize} + \item + \tcode{\exposid{deduced-simd-t}}, if that type is not \tcode{void}, + otherwise + \item + \tcode{simd}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + requires @\exposconcept{math-floating-point}@ + using @\exposid{math-common-simd-t}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{T0} denote \tcode{Ts...[0]}. +Let \tcode{T1} denote \tcode{Ts...[1]}. +Let \tcode{TRest} denote a pack such that \tcode{T0, T1, TRest...} is equivalent +to \tcode{Ts...}. + +\pnum +Let \tcode{\exposid{math-common-simd-t}} be an alias for +\begin{itemize} + \item + \tcode{\exposid{deduced-simd-t}}, if \tcode{sizeof...(Ts)} equals $1$; + otherwise + \item + \tcode{common_type_t<\exposid{deduced-simd-t}, + \exposid{deduced-simd-t}>}, if \tcode{sizeof...(Ts)} equals $2$ and + \tcode{\exposconcept{math-floating-point} \&\& + \exposconcept{math-floating-point}} is \tcode{true}; otherwise + \item + \tcode{common_type_t<\exposid{deduced-simd-t}, T1>}, if + \tcode{sizeof...(Ts)} equals $2$ and + \tcode{\exposconceptx{math-floating-\brk{}point}{math-floating-point}<\brk{}T0>} + is \tcode{true}; otherwise + \item + \tcode{common_type_t>}, if + \tcode{sizeof...(Ts)} equals $2$; otherwise + \item + \tcode{common_type_t<\exposid{math-common-simd-t}, TRest...>}, if + \tcode{\exposid{math-common-simd-t}} is valid and denotes a type; + otherwise + \item + \tcode{common_type_t<\exposid{math-common-simd-t}, T0, T1>}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + concept @\defexposconcept{reduction-binary-operation}@ = + requires (const BinaryOperation binary_op, const simd v) { + { binary_op(v, v) } -> @\libconcept{same_as}@>; + }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Types \tcode{BinaryOperation} and \tcode{T} model +\tcode{\exposconcept{reduction-binary-operation}} only if: +\begin{itemize} +\item \tcode{BinaryOperation} is a binary element-wise operation and the +operation is commutative. + +\item An object of type \tcode{BinaryOperation} can be invoked with two +arguments of type \tcode{basic_simd}, with unspecified ABI tag +\tcode{Abi}, returning a \tcode{basic_simd}. +\end{itemize} +\end{itemdescr} + +\rSec3[simd.expos.abi]{\tcode{simd} ABI tags} + +\begin{itemdecl} +template using @\exposid{native-abi}@ = @\seebelow@; +template using @\exposid{deduce-abi-t}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +An \defn{ABI tag} is a type that indicates a choice of size and binary +representation for objects of data-parallel type. +\begin{note} +The intent is for the size and binary representation to depend on the target +architecture and compiler flags. +The ABI tag, together with a given element type, implies the width. +\end{note} + +\pnum +\begin{note} +The ABI tag is orthogonal to selecting the machine instruction set. +The selected machine instruction set limits the usable ABI tag types, though +(see \ref{simd.overview}). +The ABI tags enable users to safely pass objects of data-parallel type between +translation unit boundaries (e.g., function calls or I/O). +\end{note} + +\pnum +An implementation defines ABI tag types as necessary for the following aliases. + +\pnum +\tcode{\exposid{deduce-abi-t}} is defined if +\begin{itemize} +\item \tcode{T} is a vectorizable type, +\item \tcode{N} is greater than zero, and +\item \tcode{N} is not larger than an implementation-defined maximum. +\end{itemize} +The \impldef{maximum width for \tcode{simd} and \tcode{simd_mask}} maximum for +\tcode{N} is not smaller than 64 and can differ depending on \tcode{T}. + +\pnum +Where present, \tcode{\exposid{deduce-abi-t}} names an ABI tag type such +that +\begin{itemize} + \item + \tcode{\exposid{simd-size-v}>} equals + \tcode{N}, \item \tcode{basic_simd>} is + enabled\iref{simd.overview}, and + \item + \tcode{basic_simd_mask, N>>} is enabled. +\end{itemize} + +\pnum +\tcode{\exposid{native-abi}} is an \impldef{default ABI tag for +\tcode{basic_simd} and \tcode{basic_simd_mask}} alias for an ABI tag. +\tcode{basic_simd>} is an enabled specialization. +\begin{note} +The intent is to use the ABI tag producing the most efficient data-parallel +execution for the element type \tcode{T} on the currently targeted system. +For target architectures with ISA extensions, compiler flags can change the type +of the \tcode{\exposid{native-abi}} alias. +\end{note} +\begin{example} +Consider a target architecture supporting the ABI tags \tcode{__simd128} and +\tcode{__simd256}, where hardware support for \tcode{__simd256} exists only for +floating-point types. +The implementation therefore defines \tcode{\exposid{native-abi}} as an alias +for +\begin{itemize} +\item \tcode{__simd256} if \tcode{T} is a floating-point type, and +\item \tcode{__simd128} otherwise. +\end{itemize} +\end{example} +\end{itemdescr} + +\rSec2[simd.syn]{Header \tcode{} synopsis} +\indexheader{simd}% +\begin{codeblock} +namespace std::datapar { + // \ref{simd.traits}, \tcode{simd} type traits + template struct alignment; + template + constexpr size_t alignment_v = alignment::value; + + template struct rebind { using type = @\seebelow@; }; + template using rebind_t = typename rebind::type; + template<@\exposid{simd-size-type}@ N, class V> struct resize { using type = @\seebelow@; }; + template<@\exposid{simd-size-type}@ N, class V> using resize_t = typename resize::type; + + // \ref{simd.flags}, Load and store flags + template struct flags; + inline constexpr flags<> flag_default{}; + inline constexpr flags<@\exposid{convert-flag}@> flag_convert{}; + inline constexpr flags<@\exposid{aligned-flag}@> flag_aligned{}; + template requires (has_single_bit(N)) + constexpr flags<@\exposid{overaligned-flag}@> flag_overaligned{}; + + // \ref{simd.class}, Class template \tcode{basic_simd} + template> class basic_simd; + template>> + using simd = basic_simd>; + + // \ref{simd.mask.class}, Class template \tcode{basic_simd_mask} + template>> class basic_simd_mask; + template>> + using simd_mask = basic_simd_mask>; + + // \ref{simd.loadstore}, \tcode{basic_simd} load and store functions + template + requires ranges::@\libconcept{sized_range}@ + constexpr V unchecked_load(R&& r, flags f = {}); + template + requires ranges::@\libconcept{sized_range}@ + constexpr V unchecked_load(R&& r, const typename V::mask_type& k, + flags f = {}); + template + constexpr V unchecked_load(I first, iter_difference_t n, + flags f = {}); + template + constexpr V unchecked_load(I first, iter_difference_t n, + const typename V::mask_type& k, flags f = {}); + template S, class... Flags> + constexpr V unchecked_load(I first, S last, flags f = {}); + template S, class... Flags> + constexpr V unchecked_load(I first, S last, const typename V::mask_type& k, + flags f = {}); + + template + requires ranges::@\libconcept{sized_range}@ + constexpr V partial_load(R&& r, flags f = {}); + template + requires ranges::@\libconcept{sized_range}@ + constexpr V partial_load(R&& r, const typename V::mask_type& k, + flags f = {}); + template + constexpr V partial_load(I first, iter_difference_t n, flags f = {}); + template + constexpr V partial_load(I first, iter_difference_t n, + const typename V::mask_type& k, flags f = {}); + template S, class... Flags> + constexpr V partial_load(I first, S last, flags f = {}); + template S, class... Flags> + constexpr V partial_load(I first, S last, const typename V::mask_type& k, + flags f = {}); + + template + requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + constexpr void unchecked_store(const basic_simd& v, R&& r, + flags f = {}); + template + requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + constexpr void unchecked_store(const basic_simd& v, R&& r, + const typename basic_simd::mask_type& mask, flags f = {}); + template + requires @\libconcept{indirectly_writable}@ + constexpr void unchecked_store(const basic_simd& v, I first, + iter_difference_t n, flags f = {}); + template + requires @\libconcept{indirectly_writable}@ + constexpr void unchecked_store(const basic_simd& v, I first, + iter_difference_t n, const typename basic_simd::mask_type& mask, + flags f = {}); + template S, class... Flags> + requires @\libconcept{indirectly_writable}@ + constexpr void unchecked_store(const basic_simd& v, I first, S last, + flags f = {}); + template S, class... Flags> + requires @\libconcept{indirectly_writable}@ + constexpr void unchecked_store(const basic_simd& v, I first, S last, + const typename basic_simd::mask_type& mask, flags f = {}); + + template + requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + constexpr void partial_store(const basic_simd& v, R&& r, + flags f = {}); + template + requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + constexpr void partial_store(const basic_simd& v, R&& r, + const typename basic_simd::mask_type& mask, flags f = {}); + template + requires @\libconcept{indirectly_writable}@ + constexpr void partial_store( + const basic_simd& v, I first, iter_difference_t n, flags f = {}); + template + requires @\libconcept{indirectly_writable}@ + constexpr void partial_store( + const basic_simd& v, I first, iter_difference_t n, + const typename basic_simd::mask_type& mask, flags f = {}); + template S, class... Flags> + requires @\libconcept{indirectly_writable}@ + constexpr void partial_store(const basic_simd& v, I first, S last, + flags f = {}); + template S, class... Flags> + requires @\libconcept{indirectly_writable}@ + constexpr void partial_store(const basic_simd& v, I first, S last, + const typename basic_simd::mask_type& mask, flags f = {}); + + // \ref{simd.creation}, \tcode{basic_simd} and \tcode{basic_simd_mask} creation + template + constexpr auto chunk(const basic_simd& x) noexcept; + template + constexpr auto chunk(const basic_simd_mask<@\exposid{mask-element-size}@, Abi>& x) noexcept; + + template + constexpr auto chunk(const basic_simd& x) noexcept; + template + constexpr auto chunk(const basic_simd_mask& x) noexcept; + + template + constexpr basic_simd::size() + ...)>> + cat(const basic_simd&...) noexcept; + template + constexpr basic_simd_mask, + (basic_simd_mask::size() + ...)>> + cat(const basic_simd_mask&...) noexcept; + + // \ref{simd.mask.reductions}, \tcode{basic_simd_mask} reductions + template + constexpr bool all_of(const basic_simd_mask&) noexcept; + template + constexpr bool any_of(const basic_simd_mask&) noexcept; + template + constexpr bool none_of(const basic_simd_mask&) noexcept; + template + constexpr @\exposid{simd-size-type}@ reduce_count(const basic_simd_mask&) noexcept; + template + constexpr @\exposid{simd-size-type}@ reduce_min_index(const basic_simd_mask&); + template + constexpr @\exposid{simd-size-type}@ reduce_max_index(const basic_simd_mask&); + + constexpr bool all_of(@\libconcept{same_as}@ auto) noexcept; + constexpr bool any_of(@\libconcept{same_as}@ auto) noexcept; + constexpr bool none_of(@\libconcept{same_as}@ auto) noexcept; + constexpr @\exposid{simd-size-type}@ reduce_count(@\libconcept{same_as}@ auto) noexcept; + constexpr @\exposid{simd-size-type}@ reduce_min_index(@\libconcept{same_as}@ auto); + constexpr @\exposid{simd-size-type}@ reduce_max_index(@\libconcept{same_as}@ auto); + + // \ref{simd.reductions}, \tcode{basic_simd} reductions + template> + constexpr T reduce(const basic_simd&, BinaryOperation = {}); + template> + constexpr T reduce( + const basic_simd& x, const typename basic_simd::mask_type& mask, + BinaryOperation binary_op = {}, type_identity_t identity_element = @\seebelow@); + + template + constexpr T reduce_min(const basic_simd&) noexcept; + template + constexpr T reduce_min(const basic_simd&, + const typename basic_simd::mask_type&) noexcept; + template + constexpr T reduce_max(const basic_simd&) noexcept; + template + constexpr T reduce_max(const basic_simd&, + const typename basic_simd::mask_type&) noexcept; + + // \ref{simd.alg}, Algorithms + template + constexpr basic_simd + min(const basic_simd& a, const basic_simd& b) noexcept; + template + constexpr basic_simd + max(const basic_simd& a, const basic_simd& b) noexcept; + template + constexpr pair, basic_simd> + minmax(const basic_simd& a, const basic_simd& b) noexcept; + template + constexpr basic_simd + clamp(const basic_simd& v, const basic_simd& lo, + const basic_simd& hi); + + template + constexpr auto select(bool c, const T& a, const U& b) + -> remove_cvref_t; + template + constexpr auto select(const basic_simd_mask& c, const T& a, const U& b) + noexcept -> decltype(@\exposid{simd-select-impl}@(c, a, b)); + + // \ref{simd.math}, Mathematical functions + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ acos(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ asin(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ atan(const V& x); + template + constexpr @\exposid{math-common-simd-t}@ atan2(const V0& y, const V1& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cos(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sin(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tan(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ acosh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ asinh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ atanh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cosh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sinh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tanh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ exp(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ exp2(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ expm1(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ + frexp(const V& value, rebind_t>* exp); + template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_t> ilogb(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ ldexp(const V& x, const + rebind_t>& exp); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log10(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log1p(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log2(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ logb(const V& x); + template + constexpr basic_simd modf(const type_identity_t>& value, + basic_simd* iptr); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ scalbn(const V& x, const + rebind_t>& n); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ scalbln( + const V& x, const rebind_t>& n); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cbrt(const V& x); + template<@\libconcept{signed_integral}@ T, class Abi> + constexpr basic_simd abs(const basic_simd& j); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ abs(const V& j); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ fabs(const V& x); + template + constexpr @\exposid{math-common-simd-t}@ hypot(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ hypot(const V0& x, const V1& y, const V2& z); + template + constexpr @\exposid{math-common-simd-t}@ pow(const V0& x, const V1& y); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sqrt(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ erf(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ erfc(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ lgamma(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tgamma(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ ceil(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ floor(const V& x); + template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ nearbyint(const V& x); + template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ rint(const V& x); + template<@\exposconcept{math-floating-point}@ V> + rebind_t> lrint(const V& x); + template<@\exposconcept{math-floating-point}@ V> + rebind_t llrint(const @\exposid{deduced-simd-t}@& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ round(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_t> lround(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_t> llround(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ trunc(const V& x); + template + constexpr @\exposid{math-common-simd-t}@ fmod(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ remainder(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ + remquo(const V0& x, const V1& y, rebind_t>* quo); + template + constexpr @\exposid{math-common-simd-t}@ copysign(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ nextafter(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ fdim(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ fmax(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ fmin(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ fma(const V0& x, const V1& y, const V2& z); + template + constexpr @\exposid{math-common-simd-t}@ + lerp(const V0& a, const V1& b, const V2& t) noexcept; + template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_t> fpclassify(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isfinite(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isinf(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isnan(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isnormal(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type signbit(const V& x); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + isgreater(const V0& x, const V1& y); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + isgreaterequal(const V0& x, const V1& y); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + isless(const V0& x, const V1& y); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + islessequal(const V0& x, const V1& y); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + islessgreater(const V0& x, const V1& y); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + isunordered(const V0& x, const V1& y); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ assoc_laguerre(const rebind_t>& n, const + rebind_t>& m, + const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ assoc_legendre(const rebind_t>& l, const + rebind_t>& m, + const V& x); + template + @\exposid{math-common-simd-t}@ beta(const V0& x, const V1& y); + template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ comp_ellint_1(const V& k); + template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ comp_ellint_2(const V& k); + template + @\exposid{math-common-simd-t}@ comp_ellint_3(const V0& k, const V1& nu); + template + @\exposid{math-common-simd-t}@ cyl_bessel_i(const V0& nu, const V1& x); + template + @\exposid{math-common-simd-t}@ cyl_bessel_j(const V0& nu, const V1& x); + template + @\exposid{math-common-simd-t}@ cyl_bessel_k(const V0& nu, const V1& x); + template + @\exposid{math-common-simd-t}@ cyl_neumann(const V0& nu, const V1& x); + template + @\exposid{math-common-simd-t}@ ellint_1(const V0& k, const V1& phi); + template + @\exposid{math-common-simd-t}@ ellint_2(const V0& k, const V1& phi); + template + @\exposid{math-common-simd-t}@ ellint_3(const V0& k, const V1& nu, const V2& phi); + template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ expint(const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ hermite(const rebind_t>& n, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ laguerre(const rebind_t>& n, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ legendre(const rebind_t>& l, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ riemann_zeta(const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ sph_bessel( + const rebind_t>& n, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ sph_legendre(const rebind_t>& l, + const rebind_t>& m, const V& theta); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ + sph_neumann(const rebind_t>& n, const V& x); + + // \ref{simd.bit}, Bit manipulation + template<@\exposconcept{simd-type}@ V> constexpr V byteswap(const V& v) noexcept; + template<@\exposconcept{simd-type}@ V> constexpr V bit_ceil(const V& v) noexcept; + template<@\exposconcept{simd-type}@ V> constexpr V bit_floor(const V& v) noexcept; + + template<@\exposconcept{simd-type}@ V> + constexpr typename V::mask_type has_single_bit(const V& v) noexcept; + + template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1> + constexpr V0 rotl(const V0& v, const V1& s) noexcept; + template<@\exposconcept{simd-type}@ V> + constexpr V rotl(const V& v, int s) noexcept; + + template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1> + constexpr V0 rotr(const V0& v, const V1& s) noexcept; + template<@\exposconcept{simd-type}@ V> + constexpr V rotr(const V& v, int s) noexcept; + + template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> bit_width(const V& v) noexcept; + template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> + countl_zero(const V& v) noexcept; + template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> countl_one(const V& v) noexcept; + template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> + countr_zero(const V& v) noexcept; + template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> countr_one(const V& v) noexcept; + template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> popcount(const V& v) noexcept; + + // \ref{simd.complex.math}, simd complex math + template<@\exposconcept{simd-complex}@ V> + constexpr rebind_t<@\exposid{simd-complex-value-type}@, V> real(const V&) noexcept; + + template<@\exposconcept{simd-complex}@ V> + constexpr rebind_t<@\exposid{simd-complex-value-type}@, V> imag(const V&) noexcept; + + template<@\exposconcept{simd-complex}@ V> + constexpr rebind_t<@\exposid{simd-complex-value-type}@, V> abs(const V&); + + template<@\exposconcept{simd-complex}@ V> + constexpr rebind_t<@\exposid{simd-complex-value-type}@, V> arg(const V&); + + template<@\exposconcept{simd-complex}@ V> + constexpr rebind_t<@\exposid{simd-complex-value-type}@, V> norm(const V&); + + template<@\exposconcept{simd-complex}@ V> constexpr V conj(const V&); + template<@\exposconcept{simd-complex}@ V> constexpr V proj(const V&); + template<@\exposconcept{simd-complex}@ V> constexpr V exp(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V log(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V log10(const V& v); + + template<@\exposconcept{simd-complex}@ V> constexpr V sqrt(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V sin(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V asin(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V cos(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V acos(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V tan(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V atan(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V sinh(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V asinh(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V cosh(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V acosh(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V tanh(const V& v); + template<@\exposconcept{simd-complex}@ V> constexpr V atanh(const V& v); + + template<@\exposconcept{simd-floating-point}@ V> + rebind_t, V> polar(const V& x, const V& y = {}); + + template<@\exposconcept{simd-complex}@ V> constexpr V pow(const V& x, const V& y); +} + +namespace std { + // See \ref{simd.alg}, Algorithms + using datapar::min; + using datapar::max; + using datapar::minmax; + using datapar::clamp; + + // See \ref{simd.math}, Mathematical functions + using datapar::acos; + using datapar::asin; + using datapar::atan; + using datapar::atan2; + using datapar::cos; + using datapar::sin; + using datapar::tan; + using datapar::acosh; + using datapar::asinh; + using datapar::atanh; + using datapar::cosh; + using datapar::sinh; + using datapar::tanh; + using datapar::exp; + using datapar::exp2; + using datapar::expm1; + using datapar::frexp; + using datapar::ilogb; + using datapar::ldexp; + using datapar::log; + using datapar::log10; + using datapar::log1p; + using datapar::log2; + using datapar::logb; + using datapar::modf; + using datapar::scalbn; + using datapar::scalbln; + using datapar::cbrt; + using datapar::abs; + using datapar::abs; + using datapar::fabs; + using datapar::hypot; + using datapar::pow; + using datapar::sqrt; + using datapar::erf; + using datapar::erfc; + using datapar::lgamma; + using datapar::tgamma; + using datapar::ceil; + using datapar::floor; + using datapar::nearbyint; + using datapar::rint; + using datapar::lrint; + using datapar::llrint; + using datapar::round; + using datapar::lround; + using datapar::llround; + using datapar::trunc; + using datapar::fmod; + using datapar::remainder; + using datapar::remquo; + using datapar::copysign; + using datapar::nextafter; + using datapar::fdim; + using datapar::fmax; + using datapar::fmin; + using datapar::fma; + using datapar::lerp; + using datapar::fpclassify; + using datapar::isfinite; + using datapar::isinf; + using datapar::isnan; + using datapar::isnormal; + using datapar::signbit; + using datapar::isgreater; + using datapar::isgreaterequal; + using datapar::isless; + using datapar::islessequal; + using datapar::islessgreater; + using datapar::isunordered; + using datapar::assoc_laguerre; + using datapar::assoc_legendre; + using datapar::beta; + using datapar::comp_ellint_1; + using datapar::comp_ellint_2; + using datapar::comp_ellint_3; + using datapar::cyl_bessel_i; + using datapar::cyl_bessel_j; + using datapar::cyl_bessel_k; + using datapar::cyl_neumann; + using datapar::ellint_1; + using datapar::ellint_2; + using datapar::ellint_3; + using datapar::expint; + using datapar::hermite; + using datapar::laguerre; + using datapar::legendre; + using datapar::riemann_zeta; + using datapar::sph_bessel; + using datapar::sph_legendre; + using datapar::sph_neumann; + + // See \ref{simd.bit}, Bit manipulation + using datapar::byteswap; + using datapar::bit_ceil; + using datapar::bit_floor; + using datapar::has_single_bit; + using datapar::rotl; + using datapar::rotr; + using datapar::bit_width; + using datapar::countl_zero; + using datapar::countl_one; + using datapar::countr_zero; + using datapar::countr_one; + using datapar::popcount; + + // See \ref{simd.complex.math}, simd complex math + using datapar::real; + using datapar::imag; + using datapar::arg; + using datapar::norm; + using datapar::conj; + using datapar::proj; + using datapar::polar; +} +\end{codeblock} + +\rSec2[simd.traits]{\tcode{simd} type traits} + +\begin{itemdecl} +template struct alignment { @\seebelow@ }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{alignment} has a member \tcode{value} if and only if +\begin{itemize} + \item + \tcode{T} is a specialization of \tcode{basic_simd_mask} and \tcode{U} is + \tcode{bool}, or + \item + \tcode{T} is a specialization of \tcode{basic_simd} and \tcode{U} is a + vectorizable type. +\end{itemize} + +\pnum +If \tcode{value} is present, the type \tcode{alignment} is a +\tcode{BinaryTypeTrait} with a base characteristic of +\tcode{integral_constant} for some unspecified +\tcode{N}\iref{simd.ctor,simd.loadstore}. +\begin{note} +\tcode{value} identifies the alignment restrictions on pointers used for +(converting) loads and stores for the given type \tcode{T} on arrays of type +\tcode{U}. +\end{note} + +\pnum +The behavior of a program that adds specializations for \tcode{alignment} +is undefined. +\end{itemdescr} + +\begin{itemdecl} +template struct rebind { using type = @\seebelow@; }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The member \tcode{type} is present if and only if +\begin{itemize} +\item \tcode{V} is a data-parallel type, +\item \tcode{T} is a vectorizable type, and +\item \tcode{\exposid{deduce-abi-t}} has a member type + \tcode{type}. +\end{itemize} + +\pnum +If \tcode V is a specialization of \tcode{basic_simd}, let \tcode{Abi1} denote +an ABI tag such that \tcode{basic_simd::\brk{}size()} equals +\tcode{V::size()}. +If \tcode V is a specialization of \tcode{basic_simd_mask}, let \tcode{Abi1} +denote an ABI tag such that \tcode{basic_simd_mask::\brk{}size()} equals \tcode{V::size()}. + +\pnum +Where present, the member typedef \tcode{type} names \tcode{basic_simd} +if \tcode V is a specialization of \tcode{basic_simd} or +\tcode{basic_simd_mask} if \tcode V is a specialization of +\tcode{basic_simd_mask}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposid{simd-size-type}@ N, class V> struct resize { using type = @\seebelow@; }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{T} denote +\begin{itemize} + \item + \tcode{typename V::value_type} if \tcode{V} is a specialization of + \tcode{basic_simd}, + \item + otherwise \tcode{\exposid{integer-from}<\exposid{mask-element-size}>} if + \tcode{V} is a specialization of \tcode{basic_simd_mask}. +\end{itemize} + +\pnum +The member \tcode{type} is present if and only if +\begin{itemize} +\item \tcode{V} is a data-parallel type, and +\item \tcode{\exposid{deduce-abi-t}} has a member type \tcode{type}. +\end{itemize} + +\pnum +If \tcode V is a specialization of \tcode{basic_simd}, let \tcode{Abi1} denote an +ABI tag such that \tcode{basic_simd::\brk{}size()} equals +\tcode{V::size()}. +If \tcode V is a specialization of \tcode{basic_simd_mask}, let \tcode{Abi1} +denote an ABI tag such that \tcode{basic_simd_mask::\brk{}size()} equals \tcode{V::size()}. + +\pnum +Where present, the member typedef \tcode{type} names \tcode{basic_simd} +if \tcode V is a specialization of \tcode{basic_simd} or +\tcode{basic_simd_mask} if \tcode V is a specialization of +\tcode{basic_simd_mask}. +\end{itemdescr} + +\rSec2[simd.flags]{Load and store flags} + +\rSec3[simd.flags.overview]{Class template \tcode{flags} overview} + +\begin{codeblock} +namespace std::datapar { + template struct flags { + // \ref{simd.flags.oper}, \tcode{flags} operators + template + friend consteval auto operator|(flags, flags); + }; +} +\end{codeblock} + +\pnum +\begin{note} +The class template \tcode{flags} acts like an integer bit-flag for types. +\end{note} + +\pnum +\constraints +Every type in the parameter pack \tcode{Flags} is one of \tcode{\exposid{convert-flag}}, +\tcode{\exposid{aligned-flag}}, or \tcode{\exposid{over\-aligned-\brk{}flag}}. + +\rSec3[simd.flags.oper]{\tcode{flags} operators} + +\begin{itemdecl} +template + friend consteval auto operator|(flags a, flags b); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns + A default-initialized object of type \tcode{flags} for some + \tcode{Flags2} where every type in \tcode{Flags2} is present either in template parameter pack + \tcode{Flags} or in template parameter pack \tcode{Other}, and every type in template parameter + packs \tcode{Flags} and \tcode{Other} is present in \tcode{Flags2}. + If the packs \tcode{Flags} and \tcode{Other} contain two + different specializations \tcode{\exposid{overaligned-flag}} and + \tcode{\exposid{overaligned-flag}}, \tcode{Flags2} is not required to contain the + specialization \tcode{\exposid{overaligned-flag}}. +\end{itemdescr} + +\rSec2[simd.class]{Class template \tcode{basic_simd}} + +\rSec3[simd.overview]{Class template \tcode{basic_simd} overview} + +\begin{codeblock} +namespace std::datapar { + template class basic_simd { + public: + using value_type = T; + using mask_type = basic_simd_mask; + using abi_type = Abi; + + static constexpr integral_constant<@\exposid{simd-size-type}@, @\exposid{simd-size-v}@> size {}; + + constexpr basic_simd() noexcept = default; + + // \ref{simd.ctor}, \tcode{basic_simd} constructors + template constexpr explicit(@\seebelow@) basic_simd(U&& value) noexcept; + template + constexpr explicit(@\seebelow@) basic_simd(const basic_simd&) noexcept; + template constexpr explicit basic_simd(G&& gen) noexcept; + template + constexpr basic_simd(R&& range, flags = {}); + template + constexpr basic_simd(R&& range, const mask_type& mask, flags = {}); + template<@\exposconcept{simd-floating-point}@ V> + constexpr explicit(@\seebelow@) basic_simd(const V& reals, const V& imags = {}) noexcept; + + // \ref{simd.subscr}, \tcode{basic_simd} subscript operators + constexpr value_type operator[](@\exposid{simd-size-type}@) const; + + // \ref{simd.unary}, \tcode{basic_simd} unary operators + constexpr basic_simd& operator++() noexcept; + constexpr basic_simd operator++(int) noexcept; + constexpr basic_simd& operator--() noexcept; + constexpr basic_simd operator--(int) noexcept; + constexpr mask_type operator!() const noexcept; + constexpr basic_simd operator~() const noexcept; + constexpr basic_simd operator+() const noexcept; + constexpr basic_simd operator-() const noexcept; + + // \ref{simd.binary}, \tcode{basic_simd} binary operators + friend constexpr basic_simd operator+(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator-(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator*(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator/(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator%(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator&(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator|(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator^(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator<<(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator>>(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator<<(const basic_simd&, @\exposid{simd-size-type}@) noexcept; + friend constexpr basic_simd operator>>(const basic_simd&, @\exposid{simd-size-type}@) noexcept; + + // \ref{simd.cassign}, \tcode{basic_simd} compound assignment + friend constexpr basic_simd& operator+=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator-=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator*=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator/=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator%=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator&=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator|=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator^=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator<<=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator>>=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator<<=(basic_simd&, @\exposid{simd-size-type}@) noexcept; + friend constexpr basic_simd& operator>>=(basic_simd&, @\exposid{simd-size-type}@) noexcept; + + // \ref{simd.comparison}, \tcode{basic_simd} compare operators + friend constexpr mask_type operator==(const basic_simd&, const basic_simd&) noexcept; + friend constexpr mask_type operator!=(const basic_simd&, const basic_simd&) noexcept; + friend constexpr mask_type operator>=(const basic_simd&, const basic_simd&) noexcept; + friend constexpr mask_type operator<=(const basic_simd&, const basic_simd&) noexcept; + friend constexpr mask_type operator>(const basic_simd&, const basic_simd&) noexcept; + friend constexpr mask_type operator<(const basic_simd&, const basic_simd&) noexcept; + + // \ref{simd.complex.access}, \tcode{basic_simd} complex-value accessors + constexpr auto real() const noexcept; + constexpr auto imag() const noexcept; + template<@\exposconcept{simd-floating-point}@ V> + constexpr void real(const V& v) noexcept; + template<@\exposconcept{simd-floating-point}@ V> + constexpr void imag(const V& v) noexcept; + + // \ref{simd.cond}, \tcode{basic_simd} exposition only conditional operators + friend constexpr basic_simd @\exposid{simd-select-impl}@( // \expos + const mask_type&, const basic_simd&, const basic_simd&) noexcept; + }; + + template + basic_simd(R&& r, Ts...) -> @\seebelow@; +} +\end{codeblock} + +\pnum +Every specialization of \tcode{basic_simd} is a complete type. +The specialization of \tcode{basic_simd} is +\begin{itemize} + \item + enabled, if \tcode{T} is a vectorizable type, and there exists value + \tcode{N} in the range \crange{1}{64}, such that \tcode{Abi} is + \tcode{\exposid{deduce-abi-t}}, + \item + otherwise, disabled, if \tcode{T} is not a vectorizable type, + \item + otherwise, it is \impldef{set of enabled \tcode{basic_simd} + specializations} if such a specialization is enabled. +\end{itemize} + +If \tcode{basic_simd} is disabled, then the specialization has a +deleted default constructor, deleted destructor, deleted copy constructor, and +deleted copy assignment. +In addition only the \tcode{value_type}, \tcode{abi_type}, and +\tcode{mask_type} members are present. + +If \tcode{basic_simd} is enabled, then \tcode{basic_simd} is +trivially copyable, default-initialization of an object of such a type +default-initializes all elements, and value-initialization value-initializes +all elements\iref{dcl.init.general}. + +\pnum +\recommended +Implementations should support implicit conversions between specializations of +\tcode{basic_simd} and appropriate \impldef{conversions of \tcode{basic_simd} +from/to implementation-specific vector types} types. +\begin{note} +Appropriate types are non-standard vector types which are available in the +implementation. +\end{note} + +\rSec3[simd.ctor]{\tcode{basic_simd} constructors} + +\begin{itemdecl} +template constexpr explicit(@\seebelow@) basic_simd(U&& value) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{From} denote the type \tcode{remove_cvref_t}. + +\pnum +\constraints +\tcode{value_type} satisfies \tcode{\libconcept{constructible_from}}. + +\pnum +\effects +Initializes each element to the value of the argument after conversion to +\tcode{value_type}. + +\pnum +\remarks +The expression inside \tcode{explicit} evaluates to \tcode{false} if and only if +\tcode{U} satisfies \tcode{\libconcept{convertible_to}}, and either +\begin{itemize} + \item + \tcode{From} is not an arithmetic type and does not satisfy + \exposconcept{constexpr-wrapper-like}, + \item + \tcode{From} is an arithmetic type and the conversion from \tcode{From} to + \tcode{value_type} is value-preserving\iref{simd.general}, or + \item + \tcode{From} satisfies \exposconcept{constexpr-wrapper-like}, + \tcode{remove_const_t} is an arithmetic type, and + \tcode{From::value} is representable by \tcode{value_type}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr explicit(@\seebelow@) basic_simd(const basic_simd& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{\exposid{simd-size-v} == size()} is \tcode{true}. + +\pnum +\effects +Initializes the $i^\text{th}$ element with \tcode{static_cast(x[$i$])} for +all $i$ in the range of \range{0}{size()}. + +\pnum +\remarks +The expression inside \tcode{explicit} evaluates to \tcode{true} if either +\begin{itemize} + \item + the conversion from \tcode{U} to \tcode{value_type} is not value-preserving, + or + \item + both \tcode{U} and \tcode{value_type} are integral types and the integer + conversion rank\iref{conv.rank} of \tcode{U} is greater than the integer + conversion rank of \tcode{value_type}, or + \item + both \tcode{U} and \tcode{value_type} are floating-point types and the + floating-point conversion rank\iref{conv.rank} of \tcode{U} is greater than + the floating-point conversion rank of \tcode{value_type}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template constexpr explicit basic_simd(G&& gen); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{From}$_i$ denote the type +\tcode{decltype(gen(integral_constant<\exposid{simd-size-type}, $i$>()))}. + +\pnum +\constraints +\tcode{From}$_i$ satisfies \tcode{\libconcept{convertible_to}} for all $i$ in +the range of \range{0}{size()}. +In addition, for all $i$ in the range of \range{0}{size()}, if \tcode{From}$_i$ +is an arithmetic type, conversion from \tcode{From}$_i$ to \tcode{value_type} +is value-preserving. + +\pnum +\effects +Initializes the $i^\text{th}$ element with +\tcode{static_cast(gen(integral_constant<\exposid{simd-\brk{}size-\brk{}type}, +i>()))} for all $i$ in the range of \range{0}{size()}. + +\pnum +\remarks +\tcode{gen} is invoked exactly once for each $i$, in increasing order of $i$. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr basic_simd(R&& r, flags = {}); +template + constexpr basic_simd(R&& r, const mask_type& mask, flags = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{mask} be \tcode{mask_type(true)} for the overload with no +\tcode{mask} parameter. + +\pnum +\constraints +\begin{itemize} +\item \tcode{R} models \tcode{ranges::\libconcept{contiguous_range}} and + \tcode{ranges::\libconcept{sized_range}}, +\item \tcode{ranges::size(r)} is a constant expression, and +\item \tcode{ranges::size(r)} is equal to \tcode{size()}. +\end{itemize} + +\pnum +\mandates +\begin{itemize} + \item + \tcode{ranges::range_value_t} is a vectorizable type, and + \item + if the template parameter pack \tcode{Flags} does not contain + \tcode{\exposid{convert-flag}}, then the conversion from + \tcode{ranges::range_value_t} to \tcode{value_type} is value-preserving. +\end{itemize} + +\pnum +\expects +\begin{itemize} + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{aligned-flag}}, \tcode{ranges::data(r)} points to + storage aligned by \tcode{alignment_v>}. + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{overaligned-flag}}, \tcode{ranges::data(r)} points to + storage aligned by \tcode{N}. +\end{itemize} + +\pnum +\effects +Initializes the $i^\text{th}$ element with \tcode{mask[$i$] ? +static_cast(\brk{}ranges::\brk{}data(r)[$i$]) : T()} for all $i$ in the +range of \range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +template + basic_simd(R&& r, Ts...) -> @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{R} models \tcode{ranges::\libconcept{contiguous_range}} and + \tcode{ranges::\libconcept{sized_range}}, and +\item \tcode{ranges::size(r)} is a constant expression. +\end{itemize} + +\pnum +\remarks +The deduced type is equivalent to \tcode{simd, +ranges::size(r)>}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-floating-point}@ V> + constexpr explicit(@\seebelow@) + basic_simd(const V& reals, const V& imags = {}) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} + \item + \tcode{\exposconcept{simd-complex}} is modeled, and + \item + \tcode{V::size() == size()} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Initializes the $i^\text{th}$ element with \tcode{value_type(reals[$i$], +imags[$i$])} for all $i$ in the range \range{0}{size()}. + +\pnum +\remarks +The expression inside \tcode{explicit} evaluates to \tcode{false} if and only +if the floating-point conversion rank of \tcode{T::value_type} is greater than +or equal to the floating-point conversion rank of \tcode{V::value_type}. +\end{itemdescr} + +\rSec3[simd.subscr]{\tcode{basic_simd} subscript operator} + +\begin{itemdecl} +constexpr value_type operator[](@\exposid{simd-size-type}@ i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{i >= 0 \&\& i < size()} is \tcode{true}. + +\pnum +\returns +The value of the $i^\text{th}$ element. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\rSec3[simd.unary]{\tcode{basic_simd} unary operators} + +\pnum +Effects in [simd.unary] are applied as unary element-wise operations. + +\begin{itemdecl} +constexpr basic_simd& operator++() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (value_type a) \{ ++a; \}} is \tcode{true}. + +\pnum +\effects +Increments every element by one. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd operator++(int) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (value_type a) \{ a++; \}} is \tcode{true}. + +\pnum +\effects +Increments every element by one. + +\pnum +\returns +A copy of \tcode{*this} before incrementing. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd& operator--() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (value_type a) \{ --a; \}} is \tcode{true}. + +\pnum +\effects +Decrements every element by one. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd operator--(int) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (value_type a) \{ a--; \}} is \tcode{true}. + +\pnum +\effects +Decrements every element by one. + +\pnum +\returns +A copy of \tcode{*this} before decrementing. +\end{itemdescr} + +\begin{itemdecl} +constexpr mask_type operator!() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (const value_type a) \{ !a; \}} is \tcode{true}. + +\pnum +\returns +A \tcode{basic_simd_mask} object with the $i^\text{th}$ element set to +\tcode{!operator[]($i$)} for all $i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd operator~() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (const value_type a) \{ \~{}a; \}} is \tcode{true}. + +\pnum +\returns +A \tcode{basic_simd} object with the $i^\text{th}$ element set to +\tcode{\~{}operator[]($i$)} for all $i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd operator+() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (const value_type a) \{ +a; \}} is \tcode{true}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd operator-() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (const value_type a) \{ -a; \}} is \tcode{true}. + +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to +\tcode{-operator[]($i$)} for all $i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\rSec2[simd.nonmembers]{\tcode{basic_simd} non-member operations} + +\rSec3[simd.binary]{\tcode{basic_simd} binary operators} + +\begin{itemdecl} +friend constexpr basic_simd operator+(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator-(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator*(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator/(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator%(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator&(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator|(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator^(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator<<(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator>>(const basic_simd& lhs, const basic_simd& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\constraints +\tcode{requires (value_type a, value_type b) \{ a \placeholder{op} b; \}} is +\tcode{true}. + +\pnum +\returns +A \tcode{basic_simd} object initialized with the results of applying +\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise +operation. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr basic_simd operator<<(const basic_simd& v, @\exposid{simd-size-type}@ n) noexcept; +friend constexpr basic_simd operator>>(const basic_simd& v, @\exposid{simd-size-type}@ n) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\constraints +\tcode{requires (value_type a, \exposid{simd-size-type} b) \{ a +\placeholder{op} b; \}} is \tcode{true}. + +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to +the result of applying \placeholder{op} to \tcode{v[$i$]} and \tcode{n} for all +$i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\rSec3[simd.cassign]{\tcode{basic_simd} compound assignment} + +\begin{itemdecl} +friend constexpr basic_simd& operator+=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator-=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator*=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator/=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator%=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator&=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator|=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator^=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator<<=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator>>=(basic_simd& lhs, const basic_simd& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\constraints +\tcode{requires (value_type a, value_type b) \{ a \placeholder{op} b; \}} is +\tcode{true}. + +\pnum +\effects +These operators apply the indicated operator to \tcode{lhs} and \tcode{rhs} as +an element-wise operation. + +\pnum +\returns +\tcode{lhs}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr basic_simd& operator<<=(basic_simd& lhs, @\exposid{simd-size-type}@ n) noexcept; +friend constexpr basic_simd& operator>>=(basic_simd& lhs, @\exposid{simd-size-type}@ n) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\constraints +\tcode{requires (value_type a, \exposid{simd-size-type} b) \{ a +\placeholder{op} b; \}} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return operator \placeholder{op} (lhs, basic_simd(n));} +\end{itemdescr} + +\rSec3[simd.comparison]{\tcode{basic_simd} compare operators} + +\begin{itemdecl} +friend constexpr mask_type operator==(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr mask_type operator!=(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr mask_type operator>=(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr mask_type operator<=(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr mask_type operator>(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr mask_type operator<(const basic_simd& lhs, const basic_simd& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\constraints +\tcode{requires (value_type a, value_type b) \{ a \placeholder{op} b; \}} is +\tcode{true}. + +\pnum +\returns +A \tcode{basic_simd_mask} object initialized with the results of applying +\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise +operation. +\end{itemdescr} + +\rSec3[simd.complex.access]{\tcode{simd} complex accessors} + +\begin{itemdecl} +constexpr auto real() const noexcept; +constexpr auto imag() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{\exposconcept{simd-complex}} is modeled. + +\pnum +\returns +An object of type \tcode{rebind_t} +where the $i^\text{th}$ element is initialized to the result of +\tcode{\placeholder{cmplx-func}(operator[]($i$))} for all $i$ in the range +\range{0}{size()}, where \placeholder{cmplx-func} is the corresponding function +from \libheader{complex}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-floating-point}@ V> + constexpr void real(const V& v) noexcept; +template<@\exposconcept{simd-floating-point}@ V> + constexpr void imag(const V& v) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} + \item + \tcode{\exposconcept{simd-complex}} is modeled, + \item + \tcode{\libconcept{same_as}} + is modeled, and + \item + \tcode{V::size() == size()} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Replaces each element of the \tcode{basic_simd} object such that the +$i^\text{th}$ element is replaced with \tcode{value_type(v[$i$], +operator[]($i$).imag())} or \tcode{value_type(operator[]($i$).real(), v[$i$])} +for \tcode{real} and \tcode{imag} respectively, for all $i$ in the range \range{0}{size()}. +\end{itemdescr} + +\rSec3[simd.cond]{\tcode{basic_simd} exposition only conditional operators} + +\begin{itemdecl} +friend constexpr basic_simd +@\exposid{simd-select-impl}@(const mask_type& mask, const basic_simd& a, const basic_simd& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element equals +\tcode{mask[$i$] ? a[$i$] : b[$i$]} for all $i$ in the range of +\range{0}{size()}. +\end{itemdescr} + +\rSec3[simd.reductions]{\tcode{basic_simd} reductions} + +\begin{itemdecl} +template> + constexpr T reduce(const basic_simd& x, BinaryOperation binary_op = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{BinaryOperation} models +\tcode{\exposconcept{reduction-binary-operation}}. + +\pnum +\expects +\tcode{binary_op} does not modify \tcode{x}. + +\pnum +\returns +\tcode{\placeholdernc{GENERALIZED_SUM}(binary_op, simd(x[0]), $\ldots$, +simd(x[x.size() - 1])\brk{})[0]}\iref{numerics.defns}. + +\pnum +\throws +Any exception thrown from \tcode{binary_op}. +\end{itemdescr} + +\begin{itemdecl} +template> + constexpr T reduce( + const basic_simd& x, const typename basic_simd::mask_type& mask, + BinaryOperation binary_op = {}, type_identity_t identity_element = @\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item + \tcode{BinaryOperation} models + \tcode{\exposconcept{reduction-binary-operation}}. +\item + An argument for \tcode{identity_element} is provided for the invocation, + unless \tcode{BinaryOperation} is one of \tcode{plus<>}, + \tcode{multiplies<>}, \tcode{bit_and<>}, \tcode{bit_or<>}, or + \tcode{bit_xor<>}. +\end{itemize} + +\pnum +\expects +\begin{itemize} + \item + \tcode{binary_op} does not modify \tcode{x}. + \item + For all finite values \tcode{y} representable by \tcode{T}, the results of + \tcode{y == binary_op(simd(iden\-ti\-ty\-_\-element), simd(y))[0]} and \tcode{y == binary_op(simd(y), simd(iden\-ti\-ty\-_\-element))[0]} are \tcode{true}. +\end{itemize} + +\pnum +\returns +If \tcode{none_of(mask)} is \tcode{true}, returns \tcode{identity_element}. +Otherwise, returns \tcode{\placeholdernc{GENERALIZED_SUM}(binary_op, simd(x[$k_0$]), $\ldots$, simd(x[$k_n$]))[0]} where $k_0, \ldots, k_n$ are +the selected indices of \tcode{mask}. + +\pnum +\throws +Any exception thrown from \tcode{binary_op}. + +\pnum +\remarks +The default argument for \tcode{identity_element} is equal to +\begin{itemize} +\item \tcode{T()} if \tcode{BinaryOperation} is \tcode{plus<>}, +\item \tcode{T(1)} if \tcode{BinaryOperation} is \tcode{multiplies<>}, +\item \tcode{T(\~{}T())} if \tcode{BinaryOperation} is \tcode{bit_and<>}, +\item \tcode{T()} if \tcode{BinaryOperation} is \tcode{bit_or<>}, or +\item \tcode{T()} if \tcode{BinaryOperation} is \tcode{bit_xor<>}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template constexpr T reduce_min(const basic_simd& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +The value of an element \tcode{x[$j$]} for which \tcode{x[$i$] < x[$j$]} is +\tcode{false} for all $i$ in the range of \range{0}{basic_simd::size()}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr T reduce_min( + const basic_simd&, const typename basic_simd::mask_type&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +If \tcode{none_of(mask)} is \tcode{true}, returns +\tcode{numeric_limits::max()}. +Otherwise, returns the value of a selected element \tcode{x[$j$]} for which +\tcode{x[$i$] < x[$j$]} is \tcode{false} for all selected indices $i$ of +\tcode{mask}. +\end{itemdescr} + +\begin{itemdecl} +template constexpr T reduce_max(const basic_simd& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +The value of an element \tcode{x[$j$]} for which \tcode{x[$j$] < x[$i$]} is +\tcode{false} for all $i$ in the range of \range{0}{basic_simd::size()}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr T reduce_max( + const basic_simd&, const typename basic_simd::mask_type&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +If \tcode{none_of(mask)} is \tcode{true}, returns +\tcode{numeric_limits::lowest()}. +Otherwise, returns the value of a selected element \tcode{x[$j$]} for which +\tcode{x[$j$] < x[$i$]} is \tcode{false} for all selected indices $i$ of +\tcode{mask}. +\end{itemdescr} + +\rSec3[simd.loadstore]{\tcode{basic_simd} load and store functions} + +\begin{itemdecl} +template + requires ranges::@\libconcept{sized_range}@ + constexpr V unchecked_load(R&& r, flags f = {}); +template + requires ranges::@\libconcept{sized_range}@ + constexpr V unchecked_load(R&& r, const typename V::mask_type& mask, flags f = {}); +template + constexpr V unchecked_load(I first, iter_difference_t n, flags f = {}); +template + constexpr V unchecked_load(I first, iter_difference_t n, const typename V::mask_type& mask, + flags f = {}); +template S, class... Flags> + constexpr V unchecked_load(I first, S last, flags f = {}); +template S, class... Flags> + constexpr V unchecked_load(I first, S last, const typename V::mask_type& mask, + flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let +\begin{itemize} + \item + \tcode{mask} be \tcode{V::mask_type(true)} for the overloads with no + \tcode{mask} parameter; + \item + \tcode{R} be \tcode{span>} for the overloads with no + template parameter \tcode{R}; + \item + \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n} + parameter and \tcode{R(first, last)} for the overloads with a \tcode{last} + parameter. +\end{itemize} + +\pnum +\mandates +If \tcode{ranges::size(r)} is a constant expression then +\tcode{ranges::size(r)} $\ge$ \tcode{V::size()}. + +\pnum +\expects +\begin{itemize} +\item \range{first}{first + n} is a valid range for the overloads with an + \tcode{n} parameter. +\item \range{first}{last} is a valid range for the overloads with a + \tcode{last} parameter. +\item \tcode{ranges::size(r)} $\ge$ \tcode{V::size()} +\end{itemize} + +\pnum +\effects +Equivalent to: \tcode{return partial_load(r, mask, f);} + +\pnum +\remarks +The default argument for template parameter \tcode{V} is +\tcode{basic_simd>}. +\end{itemdescr} + +\begin{itemdecl} +template + requires ranges::@\libconcept{sized_range}@ + constexpr V partial_load(R&& r, flags f = {}); +template + requires ranges::@\libconcept{sized_range}@ + constexpr V partial_load(R&& r, const typename V::mask_type& mask, flags f = {}); +template + constexpr V partial_load(I first, iter_difference_t n, flags f = {}); +template + constexpr V partial_load(I first, iter_difference_t n, const typename V::mask_type& mask, + flags f = {}); +template S, class... Flags> + constexpr V partial_load(I first, S last, flags f = {}); +template S, class... Flags> + constexpr V partial_load(I first, S last, const typename V::mask_type& mask, + flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let +\begin{itemize} + \item + \tcode{mask} be \tcode{V::mask_type(true)} for the overloads with no + \tcode{mask} parameter; + \item + \tcode{R} be \tcode{span>} for the overloads with no + template parameter \tcode{R}; + \item + \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n} + parameter and \tcode{R(first, last)} for the overloads with a \tcode{last} + parameter. +\end{itemize} + +\pnum +\mandates +\begin{itemize} + \item + \tcode{ranges::range_value_t} is a vectorizable type, + \item + \tcode{same_as, V>} is \tcode{true}, + \item + \tcode{V} is an enabled specialization of \tcode{basic_simd}, and + \item + if the template parameter pack \tcode{Flags} does not contain + \tcode{\exposid{convert-flag}}, then the conversion from + \tcode{ranges::range_value_t} to \tcode{V::value_type} is + value-preserving. +\end{itemize} + +\pnum +\expects +\begin{itemize} + \item + \range{first}{first + n} is a valid range for the overloads with an + \tcode{n} parameter. + \item + \range{first}{last} is a valid range for the overloads with a \tcode{last} + parameter. + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{aligned-flag}}, \tcode{ranges::data(r)} points to storage + aligned by \tcode{alignment_v>}. + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{overaligned-flag}}, \tcode{ranges::data(r)} points to + storage aligned by \tcode{N}. +\end{itemize} + +\pnum +\effects +Initializes the $i^\text{th}$ element with\\ +\tcode{mask[$i$] \&\& $i$ < ranges::size(r) ? +static_cast(\brk{}ranges::data(r)[$i$]) : T()} for all $i$ in the range of +\range{0}{V::size()}. + +\pnum +\remarks +The default argument for template parameter \tcode{V} is +\tcode{basic_simd>}. +\end{itemdescr} + +\begin{itemdecl} +template + requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + constexpr void unchecked_store(const basic_simd& v, R&& r, flags f = {}); +template + requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + constexpr void unchecked_store(const basic_simd& v, R&& r, + const typename basic_simd::mask_type& mask, flags f = {}); +template + requires @\libconcept{indirectly_writable}@ + constexpr void unchecked_store(const basic_simd& v, I first, iter_difference_t n, + flags f = {}); +template + requires @\libconcept{indirectly_writable}@ + constexpr void unchecked_store(const basic_simd& v, I first, iter_difference_t n, + const typename basic_simd::mask_type& mask, flags f = {}); +template S, class... Flags> + requires @\libconcept{indirectly_writable}@ + constexpr void unchecked_store(const basic_simd& v, I first, S last, + flags f = {}); +template S, class... Flags> + requires @\libconcept{indirectly_writable}@ + constexpr void unchecked_store(const basic_simd& v, I first, S last, + const typename basic_simd::mask_type& mask, flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let +\begin{itemize} + \item + \tcode{mask} be \tcode{basic_simd::mask_type(true)} for the + overloads with no \tcode{mask} parameter; + \item + \tcode{R} be \tcode{span>} for the overloads with no + template parameter \tcode{R}; + \item + \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n} + parameter and \tcode{R(first, last)} for the overloads with a \tcode{last} + parameter. +\end{itemize} + +\pnum +\mandates +If \tcode{ranges::size(r)} is a constant expression then +\tcode{ranges::size(r)} $\ge$ \tcode{\exposid{simd-size-v}}. + +\pnum +\expects +\begin{itemize} + \item + \range{first}{first + n} is a valid range for the overloads with an + \tcode{n} parameter. + \item + \range{first}{last} is a valid range for the overloads with a \tcode{last} + parameter. + \item + \tcode{ranges::size(r)} $\ge$ \tcode{\exposid{simd-size-v}} +\end{itemize} + +\pnum +\effects +Equivalent to: \tcode{partial_store(v, r, mask, f)}. +\end{itemdescr} + +\begin{itemdecl} +template + requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + constexpr void partial_store(const basic_simd& v, R&& r, flags f = {}); +template + requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + constexpr void partial_store(const basic_simd& v, R&& r, + const typename basic_simd::mask_type& mask, flags f = {}); +template + requires @\libconcept{indirectly_writable}@ + constexpr void partial_store(const basic_simd& v, I first, iter_difference_t n, + flags f = {}); +template + requires @\libconcept{indirectly_writable}@ + constexpr void partial_store(const basic_simd& v, I first, iter_difference_t n, + const typename basic_simd::mask_type& mask, flags f = {}); +template S, class... Flags> + requires @\libconcept{indirectly_writable}@ + constexpr void partial_store(const basic_simd& v, I first, S last, + flags f = {}); +template S, class... Flags> + requires @\libconcept{indirectly_writable}@ + constexpr void partial_store(const basic_simd& v, I first, S last, + const typename basic_simd::mask_type& mask, flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let +\begin{itemize} + \item + \tcode{mask} be \tcode{basic_simd::mask_type(true)} for the + overloads with no \tcode{mask} parameter; + \item + \tcode{R} be \tcode{span>} for the overloads with no + template parameter \tcode{R}; + \item + \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n} + parameter and \tcode{R(first, last)} for the overloads with a \tcode{last} + parameter. +\end{itemize} + +\pnum +\mandates +\begin{itemize} + \item + \tcode{ranges::range_value_t} is a vectorizable type, and + \item + if the template parameter pack \tcode{Flags} does not contain + \tcode{\exposid{convert-flag}}, then the conversion from \tcode{T} to + \tcode{ranges::range_value_t} is value-preserving. +\end{itemize} + +\pnum +\expects +\begin{itemize} + \item + \range{first}{first + n} is a valid range for the overloads with an + \tcode{n} parameter. + \item + \range{first}{last} is a valid range for the overloads with a \tcode{last} + parameter. + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{aligned-flag}}, \tcode{ranges::data(r)} points to storage + aligned by \tcode{alignment_v, + ranges::range_value_t>}. + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{overaligned-flag}}, \tcode{ranges::data(r)} points to + storage aligned by \tcode{N}. +\end{itemize} + +\pnum +\effects +For all $i$ in the range of \range{0}{basic_simd::size()}, if +\tcode{mask[$i$] \&\& $i$ < ranges::\brk{}size(r)} is \tcode{true}, evaluates +\tcode{ranges::data(r)[$i$] = v[$i$]}. +\end{itemdescr} + +\rSec3[simd.creation]{\tcode{basic_simd} and \tcode{basic_simd_mask} creation} + +\begin{itemdecl} +template + constexpr auto chunk(const basic_simd& x) noexcept; +template + constexpr auto chunk(const basic_simd_mask<@\exposid{mask-element-size}@, Abi>& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} + \item + For the first overload \tcode{T} is an enabled specialization of + \tcode{basic_simd}. + If \tcode{basic_simd<\brk{}typename T::\brk{}value_type, Abi>::size() \% + T::size()} is not \tcode{0} then + \tcode{resize_t::size() + \% T::size(), T>} is valid and denotes a type. + + \item + For the second overload \tcode{T} is an enabled specialization of + \tcode{basic_simd\-_\-mask}. + If \tcode{basic_simd_mask<\exposid{mask-element-size}, Abi>::size() \% + T::size()} is not \tcode{0} then + \tcode{resize_t<\brk{}ba\-sic\-_\-simd_mask<\brk{}\exposid{mask-element-size}, + Abi>::size() \% T::size(), T>} is valid and denotes a type. +\end{itemize} + +\pnum +Let $N$ be \tcode{x.size() / T::size()}. + +\pnum +\returns +\begin{itemize} + \item + If \tcode{x.size() \% T::size() == 0} is \tcode{true}, an \tcode{array} with the $i^\text{th}$ \tcode{basic_simd} or \tcode{basic_simd_mask} + element of the $j^\text{th}$ \tcode{array} element initialized to the value + of the element in \tcode{x} with index \tcode{$i$ + $j$ * T::size()}. + + \item + Otherwise, a \tcode{tuple} of $N$ objects of type \tcode{T} and one object + of type \tcode{resize_t}. + The $i^\text{th}$ \tcode{basic_simd} or \tcode{basic_simd_mask} element of + the $j^\text{th}$ \tcode{tuple} element of type \tcode{T} is initialized to + the value of the element in \tcode{x} with index \tcode{$i$ + $j$ * + T::size()}. + The $i^\text{th}$ \tcode{basic_simd} or \tcode{basic_simd_mask} element of + the $N^\text{th}$ \tcode{tuple} element is initialized to the value of the + element in \tcode{x} with index \tcode{$i$ + $N$ * T::size()}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr auto chunk(const basic_simd& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return chunk>>(x);} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr auto chunk(const basic_simd_mask& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return chunk>>(x);} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr simd::size() + ...)> + cat(const basic_simd&... xs) noexcept; +template + constexpr basic_simd_mask, + (basic_simd_mask::size() + ...)>> + cat(const basic_simd_mask&... xs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} + \item + For the first overload \tcode{simd::size() + ...)>} + is enabled. + \item + For the second overload + \tcode{basic_simd_mask, + (ba\-sic_simd_mask::size() + ...)>>} is enabled. +\end{itemize} + +\pnum +\returns +A data-parallel object initialized with the concatenated values in the +\tcode{xs} pack of data-parallel objects: The $i^\text{th}$ +\tcode{basic_simd}/\tcode{basic_simd_mask} element of the $j^\text{th}$ +parameter in the \tcode{xs} pack is copied to the return value's element with +index $i$ + the sum of the width of the first $j$ parameters in the \tcode{xs} +pack. +\end{itemdescr} + +\rSec3[simd.alg]{Algorithms} + +\begin{itemdecl} +template + constexpr basic_simd min(const basic_simd& a, + const basic_simd& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +The result of the element-wise application of \tcode{min(a[$i$], b[$i$])} for +all $i$ in the range of \range{0}{basic_simd::size()}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr basic_simd max(const basic_simd& a, + const basic_simd& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +The result of the element-wise application of \tcode{max(a[$i$], b[$i$])} for +all $i$ in the range of \range{0}{basic_simd::size()}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr pair, basic_simd> + minmax(const basic_simd& a, const basic_simd& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return pair\{min(a, b), max(a, b)\};} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr basic_simd clamp( + const basic_simd& v, const basic_simd& lo, const basic_simd& hi); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\expects +No element in \tcode{lo} shall be greater than the corresponding element in +\tcode{hi}. + +\pnum +\returns +The result of element-wise application of \tcode{clamp(v[$i$], lo[$i$], +hi[$i$])} for all $i$ in the range of \range{0}{basic_simd::size()}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr auto select(bool c, const T& a, const U& b) + -> remove_cvref_t; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return c ? a : b;} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr auto select(const basic_simd_mask& c, const T& a, const U& b) + noexcept -> decltype(@\exposid{simd-select-impl}@(c, a, b)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{simd-select-impl}@(c, a, b); +\end{codeblock} +where \tcode{\exposid{simd-select-impl}} is found by argument-dependent +lookup\iref{basic.lookup.argdep} contrary to \ref{contents}. +\end{itemdescr} + +\rSec3[simd.math]{Mathematical functions} + +\begin{itemdecl} +template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_t> ilogb(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ ldexp(const V& x, const rebind_t>& exp); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ scalbn(const V& x, const rebind_t>& n); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ + scalbln(const V& x, const rebind_t>& n); +template<@\libconcept{signed_integral}@ T, class Abi> + constexpr basic_simd abs(const basic_simd& j); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ abs(const V& j); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ fabs(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ ceil(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ floor(const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ nearbyint(const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ rint(const V& x); +template<@\exposconcept{math-floating-point}@ V> + rebind_t> lrint(const V& x); +template<@\exposconcept{math-floating-point}@ V> + rebind_t> llrint(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ round(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_t> lround(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_t> llround(const V& x); +template + constexpr @\exposid{math-common-simd-t}@ fmod(const V0& x, const V1& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ trunc(const V& x); +template + constexpr @\exposid{math-common-simd-t}@ remainder(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ copysign(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ nextafter(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ fdim(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ fmax(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ fmin(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ fma(const V0& x, const V1& y, const V2& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_t> fpclassify(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isfinite(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isinf(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isnan(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isnormal(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type signbit(const V& x); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type isgreater(const V0& x, const V1& y); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + isgreaterequal(const V0& x, const V1& y); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type isless(const V0& x, const V1& y); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type islessequal(const V0& x, const V1& y); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type islessgreater(const V0& x, const V1& y); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type isunordered(const V0& x, const V1& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Ret} denote the return type of the specialization of a function +template with the name \placeholder{math-func}. +Let \placeholder{math-func-simd} denote: +\begin{codeblock} +template +Ret @\placeholder{math-func-simd}@(Args... args) { + return Ret([&](@\exposid{simd-size-type}@ i) { + @\placeholder{math-func}@(@\exposid{make-compatible-simd-t}@(args)[i]...); + }); +} +\end{codeblock} + +\pnum +\returns +A value \tcode{ret} of type \tcode{Ret}, that is element-wise equal to the +result of calling \placeholder{math-func-simd} with the arguments of the above +functions. +If in an invocation of a scalar overload of \placeholder{math-func} for index +\tcode{i} in \placeholder{math-func-simd} a domain, pole, or range error would +occur, the value of \tcode{ret[i]} is unspecified. + +\pnum +\remarks +It is unspecified whether \tcode{errno}\iref{errno} is accessed. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ acos(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ asin(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ atan(const V& x); +template + constexpr @\exposid{math-common-simd-t}@ atan2(const V0& y, const V1& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cos(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sin(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tan(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ acosh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ asinh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ atanh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cosh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sinh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tanh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ exp(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ exp2(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ expm1(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log10(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log1p(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log2(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ logb(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cbrt(const V& x); +template + constexpr @\exposid{math-common-simd-t}@ hypot(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ hypot(const V0& x, const V1& y, const V2& z); +template + constexpr @\exposid{math-common-simd-t}@ pow(const V0& x, const V1& y); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sqrt(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ erf(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ erfc(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ lgamma(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tgamma(const V& x); +template + constexpr @\exposid{math-common-simd-t}@ lerp(const V0& a, const V1& b, const V2& t) noexcept; +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ assoc_laguerre(const rebind_t>& n, const + rebind_t>& m, + const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ assoc_legendre(const rebind_t>& l, const + rebind_t>& m, + const V& x); +template + @\exposid{math-common-simd-t}@ beta(const V0& x, const V1& y); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ comp_ellint_1(const V& k); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ comp_ellint_2(const V& k); +template + @\exposid{math-common-simd-t}@ comp_ellint_3(const V0& k, const V1& nu); +template + @\exposid{math-common-simd-t}@ cyl_bessel_i(const V0& nu, const V1& x); +template + @\exposid{math-common-simd-t}@ cyl_bessel_j(const V0& nu, const V1& x); +template + @\exposid{math-common-simd-t}@ cyl_bessel_k(const V0& nu, const V1& x); +template + @\exposid{math-common-simd-t}@ cyl_neumann(const V0& nu, const V1& x); +template + @\exposid{math-common-simd-t}@ ellint_1(const V0& k, const V1& phi); +template + @\exposid{math-common-simd-t}@ ellint_2(const V0& k, const V1& phi); +template + @\exposid{math-common-simd-t}@ ellint_3(const V0& k, const V1& nu, const V2& phi); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ expint(const V& x); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ hermite(const rebind_t>& n, const V& x); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ laguerre(const rebind_t>& n, const V& x); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ legendre(const rebind_t>& l, const V& x); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ riemann_zeta(const V& x); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ sph_bessel(const rebind_t>& n, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ sph_legendre(const rebind_t>& l, + const rebind_t>& m, + const V& theta); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ sph_neumann(const rebind_t>& n, const V& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Ret} denote the return type of the specialization of a function +template with the name \placeholder{math-func}. +Let \placeholder{math-func-simd} denote: +\begin{codeblock} +template +Ret @\placeholder{math-func-simd}@(Args... args) { + return Ret([&](@\exposid{simd-size-type}@ i) { + @\placeholder{math-func}@(@\exposid{make-compatible-simd-t}@(args)[i]...); + }); +} +\end{codeblock} + +\pnum +\returns +A value \tcode{ret} of type \tcode{Ret}, that is element-wise approximately +equal to the result of calling \placeholder{math-func-simd} with the arguments +of the above functions. +If in an invocation of a scalar overload of \placeholder{math-func} for index +\tcode{i} in \placeholder{math-func-simd} a domain, pole, or range error would +occur, the value of \tcode{ret[i]} is unspecified. + +\pnum +\remarks +It is unspecified whether \tcode{errno}\iref{errno} is accessed. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ frexp(const V& value, rebind_t>* exp); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Ret} be \tcode{\exposid{deduced-simd-t}}. +Let \placeholder{frexp-simd} denote: +\begin{codeblock} +template +pair> @\placeholder{frexp-simd}@(const V& x) { + int r1[Ret::size()]; + Ret r0([&](@\exposid{simd-size-type}@ i) { + frexp(@\exposid{make-compatible-simd-t}@(x)[i], &r1[i]); + }); + return {r0, rebind_t(r1)}; +} +\end{codeblock} +Let \tcode{ret} be a value of type \tcode{pair>} +that is the same value as the result of calling +\placeholder{frexp-simd}\tcode{(x)}. + +\pnum +\effects +Sets \tcode{*exp} to \tcode{ret.second}. + +\pnum +\returns +\tcode{ret.first}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr @\exposid{math-common-simd-t}@ remquo(const V0& x, const V1& y, + rebind_t>* quo); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Ret} be \tcode{\exposid{math-common-simd-t}}. +Let \placeholder{remquo-simd} denote: +\begin{codeblock} +template +pair> @\placeholder{remquo-simd}@(const V0& x, const V1& y) { + int r1[Ret::size()]; + Ret r0([&](@\exposid{simd-size-type}@ i) { + remquo(@\exposid{make-compatible-simd-t}@(x)[i], + @\exposid{make-compatible-simd-t}@(y)[i], &r1[i]); + }); + return {r0, rebind_t(r1)}; +} +\end{codeblock} +Let \tcode{ret} be a value of type \tcode{pair>} +that is the same value as the result of calling +\placeholder{remquo-simd}\tcode{(x, y)}. +If in an invocation of a scalar overload of \tcode{remquo} for index \tcode{i} +in \placeholder{remquo-simd} a domain, pole, or range error would occur, the +value of \tcode{ret[i]} is unspecified. + +\pnum +\effects +Sets \tcode{*quo} to \tcode{ret.second}. + +\pnum +\returns +\tcode{ret.first}. + +\pnum +\remarks +It is unspecified whether \tcode{errno}\iref{errno} is accessed. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr basic_simd modf(const type_identity_t>& value, + basic_simd* iptr); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{V} be \tcode{basic_simd}. +Let \placeholder{modf-simd} denote: +\begin{codeblock} +pair @\placeholder{modf-simd}@(const V& x) { + T r1[Ret::size()]; + V r0([&](@\exposid{simd-size-type}@ i) { + modf(V(x)[i], &r1[i]); + }); + return {r0, V(r1)}; +} +\end{codeblock} +Let \tcode{ret} be a value of type \tcode{pair} that is the same value as +the result of calling \placeholder{modf-simd}\tcode{(value)}. + +\pnum +\effects +Sets \tcode{*iptr} to \tcode{ret.second}. + +\pnum +\returns +\tcode{ret.first}. +\end{itemdescr} + +\rSec3[simd.bit]{\tcode{basic_simd} bit library} + +\begin{itemdecl} +template<@\exposconcept{simd-type}@ V> constexpr V byteswap(const V& v) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The type \tcode{V::value_type} models \tcode{integral}. + +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to +the result of \tcode{std::byteswap(v[$i$])} for all $i$ in the range +\range{0}{V::size()}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-type}@ V> constexpr V bit_ceil(const V& v) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The type \tcode{V::value_type} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\expects +For every $i$ in the range \range{0}{V::size()}, the smallest power of 2 +greater than or equal to \tcode{v[$i$]} is representable as a value of type +\tcode{V::value_type}. + +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to +the result of \tcode{std::bit_ceil(v[$i$])} for all $i$ in the range +\range{0}{V::size()}. + +\pnum +\remarks +A function call expression that violates the precondition in the \expects +element is not a core constant expression\iref{expr.const}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-type}@ V> constexpr V bit_floor(const V& v) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The type \tcode{V::value_type} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to +the result of \tcode{std::bit_floor(v[$i$])} for all $i$ in the range +\range{0}{V::size()}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-type}@ V> + constexpr typename V::mask_type has_single_bit(const V& v) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The type \tcode{V::value_type} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +A \tcode{basic_simd_mask} object where the $i^\text{th}$ element is initialized +to the result of \tcode{std::has_single_bit(v[$i$])} for all $i$ in the range +\range{0}{V::size()}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1> + constexpr V0 rotl(const V0& v0, const V1& v1) noexcept; +template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1> + constexpr V0 rotr(const V0& v0, const V1& v1) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} + \item + The type \tcode{V0::value_type} is an unsigned integer type\iref{basic.fundamental}, + \item + the type \tcode{V1::value_type} models \tcode{integral}, + \item + \tcode{V0::size() == V1::size()} is \tcode{true}, and + \item + \tcode{sizeof(typename V0::value_type) == sizeof(typename V1::value_type)} is \tcode{true}. +\end{itemize} + +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to +the result of \tcode{\placeholder{bit-func}(v0[$i$], +static_cast(v1[$i$]))} for all $i$ in the range \range{0}{V0::size()}, +where \placeholder{bit-func} is the corresponding scalar function from \libheader{bit}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-type}@ V> constexpr V rotl(const V& v, int s) noexcept; +template<@\exposconcept{simd-type}@ V> constexpr V rotr(const V& v, int s) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The type \tcode{V::value_type} is an unsigned integer type\iref{basic.fundamental} + +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to +the result of \tcode{\placeholder{bit-func}(v[$i$], s)} for all $i$ in the +range \range{0}{V::size()}, where \placeholder{bit-func} is the corresponding +scalar function from \libheader{bit}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> bit_width(const V& v) noexcept; +template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> countl_zero(const V& v) noexcept; +template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> countl_one(const V& v) noexcept; +template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> countr_zero(const V& v) noexcept; +template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> countr_one(const V& v) noexcept; +template<@\exposconcept{simd-type}@ V> + constexpr rebind_t, V> popcount(const V& v) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The type \tcode{V::value_type} is an unsigned integer type\iref{basic.fundamental} + +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to +the result of \tcode{\placeholder{bit-func}(v[$i$])} for all $i$ in the range +\range{0}{V::size()}, where \placeholder{bit-func} is the corresponding scalar +function from \libheader{bit}. +\end{itemdescr} + +\rSec3[simd.complex.math]{\tcode{simd} complex math} + +\begin{itemdecl} +template<@\exposconcept{simd-complex}@ V> + constexpr rebind_t<@\exposid{simd-complex-value-type}@, V> real(const V&) noexcept; +template<@\exposconcept{simd-complex}@ V> + constexpr rebind_t<@\exposid{simd-complex-value-type}@, V> imag(const V&) noexcept; + +template<@\exposconcept{simd-complex}@ V> + constexpr rebind_t<@\exposid{simd-complex-value-type}@, V> abs(const V&); +template<@\exposconcept{simd-complex}@ V> + constexpr rebind_t<@\exposid{simd-complex-value-type}@, V> arg(const V&); +template<@\exposconcept{simd-complex}@ V> + constexpr rebind_t<@\exposid{simd-complex-value-type}@, V> norm(const V&); +template<@\exposconcept{simd-complex}@ V> constexpr V conj(const V&); +template<@\exposconcept{simd-complex}@ V> constexpr V proj(const V&); + +template<@\exposconcept{simd-complex}@ V> constexpr V exp(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V log(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V log10(const V& v); + +template<@\exposconcept{simd-complex}@ V> constexpr V sqrt(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V sin(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V asin(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V cos(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V acos(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V tan(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V atan(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V sinh(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V asinh(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V cosh(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V acosh(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V tanh(const V& v); +template<@\exposconcept{simd-complex}@ V> constexpr V atanh(const V& v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{basic_simd} object \tcode{ret} where the $i^\text{th}$ element is +initialized to the result of \tcode{\placeholder{cmplx-func}(v[$i$])} for all +$i$ in the range \range{0}{V::size()}, where \placeholder{cmplx-func} is the +corresponding function from \libheader{complex}. If in an invocation of +\placeholder{cmplx-func} for index $i$ a domain, pole, or range error would +occur, the value of \tcode{ret[$i$]} is unspecified. + +\pnum +\remarks +It is unspecified whether \tcode{errno}\iref{errno} is accessed. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-floating-point}@ V> + rebind_t, V> polar(const V& x, const V& y = {}); + +template<@\exposconcept{simd-complex}@ V> constexpr V pow(const V& x, const V& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{basic_simd} object \tcode{ret} where the $i^\text{th}$ element is +initialized to the result of \tcode{\placeholder{cmplx-func}(x[$i$], y[$i$])} +for all $i$ in the range \range{0}{V::size()}, where \placeholder{cmplx-func} +is the corresponding function from \libheader{complex}. If in an invocation of +\placeholder{cmplx-func} for index $i$ a domain, pole, or range error would +occur, the value of \tcode{ret[$i$]} is unspecified. + +\pnum +\remarks +It is unspecified whether \tcode{errno}\iref{errno} is accessed. +\end{itemdescr} + +\rSec2[simd.mask.class]{Class template \tcode{basic_simd_mask}} + +\rSec3[simd.mask.overview]{Class template \tcode{basic_simd_mask} overview} + +\begin{codeblock} +namespace std::datapar { + template class basic_simd_mask { + public: + using value_type = bool; + using abi_type = Abi; + + static constexpr integral_constant<@\exposid{simd-size-type}@, @\exposid{simd-size-v}@<@\exposid{integer-from}@, Abi>> + size {}; + + constexpr basic_simd_mask() noexcept = default; + + // \ref{simd.mask.ctor}, \tcode{basic_simd_mask} constructors + constexpr explicit basic_simd_mask(value_type) noexcept; + template + constexpr explicit basic_simd_mask(const basic_simd_mask&) noexcept; + template constexpr explicit basic_simd_mask(G&& gen) noexcept; + + // \ref{simd.mask.subscr}, \tcode{basic_simd_mask} subscript operators + constexpr value_type operator[](@\exposid{simd-size-type}@) const; + + // \ref{simd.mask.unary}, \tcode{basic_simd_mask} unary operators + constexpr basic_simd_mask operator!() const noexcept; + constexpr basic_simd<@\exposid{integer-from}@, Abi> operator+() const noexcept; + constexpr basic_simd<@\exposid{integer-from}@, Abi> operator-() const noexcept; + constexpr basic_simd<@\exposid{integer-from}@, Abi> operator~() const noexcept; + + // \ref{simd.mask.conv}, \tcode{basic_simd_mask} conversion operators + template + constexpr explicit(sizeof(U) != Bytes) operator basic_simd() const noexcept; + + // \ref{simd.mask.binary}, \tcode{basic_simd_mask} binary operators + friend constexpr basic_simd_mask + operator&&(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator||(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator&(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator|(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator^(const basic_simd_mask&, const basic_simd_mask&) noexcept; + + // \ref{simd.mask.cassign}, \tcode{basic_simd_mask} compound assignment + friend constexpr basic_simd_mask& + operator&=(basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask& + operator|=(basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask& + operator^=(basic_simd_mask&, const basic_simd_mask&) noexcept; + + // \ref{simd.mask.comparison}, \tcode{basic_simd_mask} comparisons + friend constexpr basic_simd_mask + operator==(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator!=(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator>=(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator<=(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator>(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator<(const basic_simd_mask&, const basic_simd_mask&) noexcept; + + // \ref{simd.mask.cond}, \tcode{basic_simd_mask} exposition only conditional operators + friend constexpr basic_simd_mask @\exposid{simd-select-impl}@( // \expos + const basic_simd_mask&, const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask @\exposid{simd-select-impl}@( // \expos + const basic_simd_mask&, @\libconcept{same_as}@ auto, @\libconcept{same_as}@ auto) noexcept; + template + friend constexpr simd<@\seebelow@, size()> + @\exposid{simd-select-impl}@(const basic_simd_mask&, const T0&, const T1&) noexcept; // \expos + }; +} +\end{codeblock} + +\pnum +Every specialization of \tcode{basic_simd_mask} is a complete type. +The specialization of \tcode{basic_simd_mask} is: +\begin{itemize} + \item + disabled, if there is no vectorizable type \tcode{T} such that \tcode{Bytes} + is equal to \tcode{sizeof(T)}, + \item + otherwise, enabled, if there exists a vectorizable type \tcode{T} and a + value \tcode{N} in the range \crange{1}{64} such that \tcode{Bytes} is equal + to \tcode{sizeof(T)} and \tcode{Abi} is \tcode{\exposid{deduce-abi-t}}, + \item + otherwise, it is \impldef{set of enabled \tcode{basic_simd_mask} + specializations} if such a specialization is enabled. +\end{itemize} + +If \tcode{basic_simd_mask} is disabled, the specialization has a +deleted default constructor, deleted destructor, deleted copy constructor, and +deleted copy assignment. +In addition only the \tcode{value_type} and \tcode{abi_type} members are +present. + +If \tcode{basic_simd_mask} is enabled, +\tcode{basic_simd_mask} is trivially copyable. + +\pnum +\recommended Implementations should support implicit conversions between +specializations of \tcode{basic_simd_mask} and appropriate \impldef{conversions +of \tcode{basic_simd_mask} from/to implementation-specific vector types} types. +\begin{note} +Appropriate types are non-standard vector types which are available in the +implementation. +\end{note} + +\rSec3[simd.mask.ctor]{\tcode{basic_simd_mask} constructors} + +\begin{itemdecl} +constexpr explicit basic_simd_mask(value_type x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes each element with \tcode{x}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr explicit basic_simd_mask(const basic_simd_mask& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{basic_simd_mask::size() == size()} is +\tcode{true}. + +\pnum +\effects +Initializes the $i^\text{th}$ element with \tcode{x[$i$]} for all $i$ in the +range of \range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +template constexpr explicit basic_simd_mask(G&& gen); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The expression \tcode{gen(integral_constant<\exposid{simd-size-type}, i>())} is +well-formed and its type is \tcode{bool} for all $i$ in the range of +\range{0}{size()}. + +\pnum +\effects +Initializes the $i^\text{th}$ element with +\tcode{gen(integral_constant<\exposid{simd-size-type}, i>())} for all $i$ in +the range of \range{0}{size()}. + +\pnum +\remarks +\tcode{gen} is invoked exactly once for each $i$, in increasing order of $i$. +\end{itemdescr} + +\rSec3[simd.mask.subscr]{\tcode{basic_simd_mask} subscript operator} + +\begin{itemdecl} +constexpr value_type operator[](@\exposid{simd-size-type}@ i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{i >= 0 \&\& i < size()} is \tcode{true}. + +\pnum +\returns +The value of the $i^\text{th}$ element. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\rSec3[simd.mask.unary]{\tcode{basic_simd_mask} unary operators} + +\begin{itemdecl} +constexpr basic_simd_mask operator!() const noexcept; +constexpr basic_simd<@\exposid{integer-from}@, Abi> operator+() const noexcept; +constexpr basic_simd<@\exposid{integer-from}@, Abi> operator-() const noexcept; +constexpr basic_simd<@\exposid{integer-from}@, Abi> operator~() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\returns +A data-parallel object where the $i^\text{th}$ element is initialized to the +results of applying \placeholder{op} to \tcode{operator[]($i$)} for all $i$ in +the range of \range{0}{size()}. +\end{itemdescr} + +\rSec3[simd.mask.conv]{\tcode{basic_simd_mask} conversion operators} + +\begin{itemdecl} +template + constexpr explicit(sizeof(U) != Bytes) operator basic_simd() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{\exposid{simd-size-v} == \exposid{simd-size-v}}. + +\pnum +\returns +A data-parallel object where the $i^\text{th}$ element is initialized to +\tcode{static_cast(operator[]($i$))}. +\end{itemdescr} + +\rSec2[simd.mask.nonmembers]{Non-member operations} + +\rSec3[simd.mask.binary]{\tcode{basic_simd_mask} binary operators} + +\begin{itemdecl} +friend constexpr basic_simd_mask + operator&&(const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask + operator||(const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask + operator& (const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask + operator| (const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask + operator^ (const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\returns +A \tcode{basic_simd_mask} object initialized with the results of applying +\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise +operation. +\end{itemdescr} + +\rSec3[simd.mask.cassign]{\tcode{basic_simd_mask} compound assignment} + +\begin{itemdecl} +friend constexpr basic_simd_mask& + operator&=(basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask& + operator|=(basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask& + operator^=(basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\effects +These operators apply \placeholder{op} to \tcode{lhs} and \tcode{rhs} as a +binary element-wise operation. + +\pnum +\returns +\tcode{lhs}. +\end{itemdescr} + +\rSec3[simd.mask.comparison]{\tcode{basic_simd_mask} comparisons} + +\begin{itemdecl} +friend constexpr basic_simd_mask + operator==(const basic_simd_mask&, const basic_simd_mask&) noexcept; +friend constexpr basic_simd_mask + operator!=(const basic_simd_mask&, const basic_simd_mask&) noexcept; +friend constexpr basic_simd_mask + operator>=(const basic_simd_mask&, const basic_simd_mask&) noexcept; +friend constexpr basic_simd_mask + operator<=(const basic_simd_mask&, const basic_simd_mask&) noexcept; +friend constexpr basic_simd_mask + operator>(const basic_simd_mask&, const basic_simd_mask&) noexcept; +friend constexpr basic_simd_mask + operator<(const basic_simd_mask&, const basic_simd_mask&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\returns +A \tcode{basic_simd_mask} object initialized with the results of applying +\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise +operation. +\end{itemdescr} + +\rSec3[simd.mask.cond]{\tcode{basic_simd_mask} exposition only conditional operators} + +\begin{itemdecl} +friend constexpr basic_simd_mask @\exposid{simd-select-impl}@( + const basic_simd_mask& mask, const basic_simd_mask& a, const basic_simd_mask& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{basic_simd_mask} object where the $i^\text{th}$ element equals +\tcode{mask[$i$] ? a[$i$] : b[$i$]} for all $i$ in the range of +\range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr basic_simd_mask +@\exposid{simd-select-impl}@(const basic_simd_mask& mask, @\libconcept{same_as}@ auto a, @\libconcept{same_as}@ auto b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{basic_simd_mask} object where the $i^\text{th}$ element equals +\tcode{mask[$i$] ? a : b} for all $i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +template + friend constexpr simd<@\seebelow@, size()> + @\exposid{simd-select-impl}@(const basic_simd_mask& mask, const T0& a, const T1& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} + \item + \tcode{same_as} is \tcode{true}, + \item + \tcode{T0} is a vectorizable type, and + \item + \tcode{sizeof(T0) == Bytes}. +\end{itemize} + +\pnum +\returns +A \tcode{simd} object where the $i^\text{th}$ element equals +\tcode{mask[$i$] ? a : b} for all $i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\rSec3[simd.mask.reductions]{\tcode{basic_simd_mask} reductions} + +\begin{itemdecl} +template + constexpr bool all_of(const basic_simd_mask& k) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if all boolean elements in \tcode{k} are \tcode{true}, otherwise +\tcode{false}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr bool any_of(const basic_simd_mask& k) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if at least one boolean element in \tcode{k} is \tcode{true}, +otherwise \tcode{false}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr bool none_of(const basic_simd_mask& k) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!any_of(k)}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr @\exposid{simd-size-type}@ reduce_count(const basic_simd_mask& k) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The number of boolean elements in \tcode{k} that are \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr @\exposid{simd-size-type}@ reduce_min_index(const basic_simd_mask& k); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{any_of(k)} is \tcode{true}. + +\pnum +\returns +The lowest element index $i$ where \tcode{k[$i$]} is \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr @\exposid{simd-size-type}@ reduce_max_index(const basic_simd_mask& k); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{any_of(k)} is \tcode{true}. + +\pnum +\returns +The greatest element index $i$ where \tcode{k[$i$]} is \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +constexpr bool all_of(@\libconcept{same_as}@ auto x) noexcept; +constexpr bool any_of(@\libconcept{same_as}@ auto x) noexcept; +constexpr @\exposid{simd-size-type}@ reduce_count(@\libconcept{same_as}@ auto x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x}. +\end{itemdescr} + +\begin{itemdecl} +constexpr bool none_of(@\libconcept{same_as}@ auto x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!x}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{simd-size-type}@ reduce_min_index(@\libconcept{same_as}@ auto x); +constexpr @\exposid{simd-size-type}@ reduce_max_index(@\libconcept{same_as}@ auto x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x} is \tcode{true}. + +\pnum +\returns +\tcode{0}. +\end{itemdescr} + +\rSec1[numerics.c]{C compatibility} + +\rSec2[stdckdint.h.syn]{Header \tcode{} synopsis} + +\indexheader{stdckdint.h}% +\begin{codeblock} +#define @\libmacro{__STDC_VERSION_STDCKDINT_H__}@ 202311L + +template + bool ckd_add(type1* result, type2 a, type3 b); +template + bool ckd_sub(type1* result, type2 a, type3 b); +template + bool ckd_mul(type1* result, type2 a, type3 b); +\end{codeblock} + +\pnum +\xref{\IsoCUndated{}:2024, 7.20} %% TODO: change to \xrefc{7.20} + +\rSec2[numerics.c.ckdint]{Checked integer operations} + +\indexlibraryglobal{ckd_add}% +\indexlibraryglobal{ckd_sub}% +\indexlibraryglobal{ckd_mul}% +\begin{itemdecl} +template + bool ckd_add(type1* result, type2 a, type3 b); +template + bool ckd_sub(type1* result, type2 a, type3 b); +template + bool ckd_mul(type1* result, type2 a, type3 b); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +Each of the types \tcode{type1}, \tcode{type2}, and \tcode{type3} is a +cv-unqualified signed or unsigned integer type. + +\pnum +\remarks +Each function template has the same semantics as +the corresponding type-generic macro with the same name +specified in \IsoCUndated{}:2024, 7.20. +\end{itemdescr} diff --git a/source/overloading.tex b/source/overloading.tex index a43a964b5c..5343a015a7 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -154,15 +154,17 @@ \indextext{function!overload resolution and}% The set of candidate functions can contain both member and non-member functions to be resolved against the same argument list. -So that argument and parameter lists are comparable within this -heterogeneous set, a member function that does not have an explicit object parameter is considered to have an -extra first parameter, called the -\defn{implicit object parameter}, -which represents the object for which the member function has been -called. -For the purposes of overload resolution, both static and -non-static member functions have an object parameter, -but constructors do not. +If a member function is +\begin{itemize} +\item +an implicit object member function that is not a constructor, or +\item +a static member function and +the argument list includes an implied object argument, +\end{itemize} +it is considered to have an extra first parameter, +called the \defnadj{implicit}{object parameter}, +which represents the object for which the member function has been called. \pnum Similarly, when appropriate, the context can construct an @@ -183,7 +185,7 @@ \end{itemize} where \tcode{X} -is the class of which the function is a member and +is the class of which the function is a direct member and \cv{} is the cv-qualification on the member function declaration. @@ -367,7 +369,11 @@ \pnum If the \grammarterm{postfix-expression} is the address of an overload set, overload resolution is applied using that set as described above. -If the function selected by overload resolution is a non-static member function, +\begin{note} +No implied object argument is added in this case. +\end{note} +If the function selected by overload resolution is +an implicit object member function, the program is ill-formed. \begin{note} The resolution of the address of an @@ -443,25 +449,43 @@ The function declarations found by name lookup\iref{basic.lookup} constitute the set of candidate functions. Because of the rules for name lookup, the set of candidate functions -consists (1) entirely of non-member functions or (2) entirely of +consists either entirely of non-member functions or entirely of member functions of some class \tcode{T}. -In case (1), +In the former case or +if the \grammarterm{primary-expression} is the address of an overload set, the argument list is the same as the \grammarterm{expression-list} in the call. -In case (2), the argument list is the +Otherwise, the argument list is the \grammarterm{expression-list} in the call augmented by the addition of an implied object argument as in a qualified function call. If the current class is, or is derived from, \tcode{T}, and the keyword \keyword{this}\iref{expr.prim.this} refers to it, -then the implied object argument is \tcode{(*this)}. +\begin{itemize} +\item +if the unqualified function call +appears in a precondition assertion of a constructor +or a postcondition assertion of a destructor +and overload resolution selects a non-static member function, +the call is ill-formed; +\item +otherwise, +the implied object argument is +\tcode{(*\keyword{this})}. +\end{itemize} Otherwise, +\begin{itemize} +\item +if overload resolution selects a non-static member function, +the call is ill-formed; +\item +otherwise, a contrived object of type \tcode{T} -becomes the implied object argument; +becomes the implied object argument. \begin{footnote} An implied object argument is contrived to correspond to the implicit object @@ -475,16 +499,29 @@ reject a function. \end{footnote} -if overload resolution selects a non-static member function, -the call is ill-formed. +\end{itemize} + \begin{example} \begin{codeblock} struct C { - void a(); + bool a(); void b() { a(); // OK, \tcode{(*this).a()} } + void c(this const C&); // \#1 + void c() &; // \#2 + static void c(int = 0); // \#3 + + void d() { + c(); // error: ambiguous between \#2 and \#3 + (C::c)(); // error: as above + (&(C::c))(); // error: cannot resolve address of overloaded \tcode{this->C::c}\iref{over.over} + (&C::c)(C{}); // selects \#1 + (&C::c)(*this); // error: selects \#2, and is ill-formed\iref{over.match.call.general} + (&C::c)(); // selects \#3 + } + void f(this const C&); void g() const { f(); // OK, \tcode{(*this).f()} @@ -504,6 +541,15 @@ void m(this const C& c) { c.k(); // OK } + + C() + pre(a()) // error: implied \keyword{this} in constructor precondition + pre(this->a()) // OK + post(a()); // OK + ~C() + pre(a()) // OK + post(a()) // error: implied \keyword{this} in destructor postcondition + post(this->a()); // OK }; \end{codeblock} \end{example} @@ -579,12 +625,6 @@ When comparing the call against a surrogate call function, the implied object argument is compared against the first parameter of the surrogate call function. -The -conversion function from which the surrogate call function was -derived will be used in the conversion sequence for that -parameter since it converts the implied object argument to the -appropriate function pointer or reference required by that first -parameter. \end{note} \begin{example} \begin{codeblock} @@ -662,7 +702,7 @@ \hdstyle{Subclause} & \hdstyle{Expression} & \hdstyle{As member function} & \hdstyle{As non-member function} \\ \capsep \ref{over.unary} & \tcode{@a} & \tcode{(a).\keyword{operator}@ (\,)} & \tcode{\keyword{operator}@(a)} \\ \ref{over.binary} & \tcode{a@b} & \tcode{(a).\keyword{operator}@ (b)} & \tcode{\keyword{operator}@(a, b)} \\ -\ref{over.ass} & \tcode{a=b} & \tcode{(a).\keyword{operator}= (b)} & \\ +\ref{over.assign} & \tcode{a=b} & \tcode{(a).\keyword{operator}= (b)} & \\ \ref{over.sub} & \tcode{a[b]} & \tcode{(a).\keyword{operator}[](b)} & \\ \ref{over.ref} & \tcode{a->} & \tcode{(a).\keyword{operator}->(\,)} & \\ \ref{over.inc} & \tcode{a@} & \tcode{(a).\keyword{operator}@ (0)} & \tcode{\keyword{operator}@(a, 0)} \\ @@ -729,6 +769,7 @@ operands can be converted according to \ref{over.best.ics}, and \item do not have the same parameter-type-list as any non-member candidate +or rewritten non-member candidate that is not a function template specialization. \end{itemize} @@ -818,15 +859,8 @@ \end{example} \pnum -For the built-in assignment operators, conversions of the left -operand are restricted as follows: -\begin{itemize} -\item -no temporaries are introduced to hold the left operand, and -\item -no user-defined conversions are applied to the left operand to achieve -a type match with the left-most parameter of a built-in candidate. -\end{itemize} +For the first parameter of the built-in assignment operators, +only standard conversion sequences\iref{over.ics.scs} are considered. \pnum For all other operators, no such restrictions apply. @@ -993,17 +1027,18 @@ or default-initialized\iref{dcl.init}, overload resolution selects the constructor. For direct-initialization or default-initialization -that is not in the context of copy-initialization, the -candidate functions are +(including default-initialization in the context of copy-list-initialization), +the candidate functions are all the constructors of the class of the object being initialized. -For copy-initialization (including default initialization -in the context of copy-initialization), the candidate functions are all -the converting constructors\iref{class.conv.ctor} of that +Otherwise, the candidate functions are all +the non-explicit constructors\iref{class.conv.ctor} of that class. The argument list is the \grammarterm{expression-list} or \grammarterm{assignment-expression} of the \grammarterm{initializer}. +For default-initialization in the context of copy-list-initialization, +if an explicit constructor is chosen, the initialization is ill-formed. \rSec3[over.match.copy]{Copy-initialization of class by user-defined conversion}% \indextext{overloading!resolution!initialization} @@ -1028,7 +1063,7 @@ \begin{itemize} \item -The converting constructors\iref{class.conv.ctor} of +The non-explicit constructors\iref{class.conv.ctor} of \tcode{T} are candidate functions. \item @@ -1109,11 +1144,11 @@ \begin{itemize} \item ``lvalue reference to \cvqual{cv2} \tcode{T2}'' -(when initializing an lvalue reference or an rvalue reference to function) and +(when converting to an lvalue) and \item ``\cvqual{cv2} \tcode{T2}'' -and ``rvalue reference to \cvqual{cv2} \tcode{T2}'' (when initializing an -rvalue reference or an lvalue reference to function) +and ``rvalue reference to \cvqual{cv2} \tcode{T2}'' +(when converting to an rvalue or an lvalue of function type) \end{itemize} for any \tcode{T2}. The permissible types for non-explicit conversion functions are @@ -1164,7 +1199,7 @@ chosen, the initialization is ill-formed. \begin{note} This differs from other situations\iref{over.match.ctor,over.match.copy}, -where only converting constructors are considered for copy-initialization. +where only non-explicit constructors are considered for copy-initialization. This restriction only applies if this initialization is part of the final result of overload resolution. @@ -1190,7 +1225,18 @@ by the template parameters (including default template arguments) of the constructor, if any. \item -The types of the function parameters are those of the constructor. +The associated constraints\iref{temp.constr.decl} are the conjunction of +the associated constraints of \tcode{C} and +the associated constraints of the constructor, if any. +\begin{note} +A \grammarterm{constraint-expression} in +the \grammarterm{template-head} of \tcode{C} +is checked for satisfaction before any constraints from +the \grammarterm{template-head} or trailing \grammarterm{requires-clause} +of the constructor. +\end{note} +\item +The \grammarterm{parameter-declaration-clause} is that of the constructor. \item The return type is the class template specialization designated by \tcode{C} @@ -1216,8 +1262,8 @@ \begin{itemize} \item -The template parameters, if any, -and function parameters +The \grammarterm{template-head}, if any, +and \grammarterm{parameter-declaration-clause} are those of the \grammarterm{deduction-guide}. \item The return type @@ -1246,8 +1292,12 @@ \begin{itemize} \item brace elision is not considered for any aggregate element -that has a dependent non-array type or -an array type with a value-dependent bound, and +that has +\begin{itemize} +\item a dependent non-array type, +\item an array type with a value-dependent bound, or +\item an array type with a dependent array element type and $x_i$ is a string literal; and +\end{itemize} \item each non-trailing aggregate element that is a pack expansion is assumed to correspond to no elements of the initializer list, and @@ -1263,9 +1313,14 @@ \begin{itemize} \item if $e_i$ is of array type and -$x_i$ is a \grammarterm{braced-init-list} or \grammarterm{string-literal}, +$x_i$ is a \grammarterm{braced-init-list}, $\tcode{T}_i$ is an rvalue reference to the declared type of $e_i$, and \item +if $e_i$ is of array type and +$x_i$ is a \grammarterm{string-literal}, +$\tcode{T}_i$ is an lvalue reference to +the const-qualified declared type of $e_i$, and +\item otherwise, $\tcode{T}_i$ is the declared type of $e_i$, \end{itemize} except that additional parameter packs of the form $\tcode{P}_j \tcode{...}$ @@ -1335,6 +1390,23 @@ } G g(true, 'a', 1); // OK, deduces \tcode{G} + +template +struct H { + T array[N]; +}; +template +struct I { + volatile T array[N]; +}; +template +struct J { + unsigned char array[N]; +}; + +H h = { "abc" }; // OK, deduces \tcode{H} (not \tcode{T = const char}) +I i = { "def" }; // OK, deduces \tcode{I} +J j = { "ghi" }; // error: cannot bind reference to array of \tcode{unsigned char} to array of \tcode{char} in deduction \end{codeblock} \end{example} @@ -1357,6 +1429,8 @@ according to the process in \ref{temp.deduct.type} with the exception that deduction does not fail if not all template arguments are deduced. +If deduction fails for another reason, +proceed with an empty set of deduced template arguments. Let \tcode{g} denote the result of substituting these deductions into \tcode{f}. If substitution succeeds, @@ -1686,10 +1760,10 @@ (see~\ref{dcl.init}, \ref{over.match.conv}, and~\ref{over.match.ref}) and the standard conversion sequence -from the return type of $\tcode{F}_1$ to the destination type +from the result of $\tcode{F}_1$ to the destination type (i.e., the type of the entity being initialized) is a better conversion sequence than the standard conversion sequence -from the return type of $\tcode{F}_2$ to the destination type +from the result of $\tcode{F}_2$ to the destination type \begin{example} \begin{codeblock} struct A { @@ -1707,8 +1781,8 @@ \item the context is an initialization by conversion function for direct reference binding\iref{over.match.ref} of a reference to function type, the -return type of \tcode{F1} is the same kind of reference (lvalue or rvalue) -as the reference being initialized, and the return type of \tcode{F2} is not +return type of $\tcode{F}_1$ is the same kind of reference (lvalue or rvalue) +as the reference being initialized, and the return type of $\tcode{F}_2$ is not \begin{example} \begin{codeblock} template struct A { @@ -1724,38 +1798,52 @@ or, if not that, \item -\tcode{F1} +$\tcode{F}_1$ is not a function template specialization and -\tcode{F2} +$\tcode{F}_2$ is a function template specialization, or, if not that, \item -\tcode{F1} +$\tcode{F}_1$ and -\tcode{F2} +$\tcode{F}_2$ are function template specializations, and the function template for -\tcode{F1} +$\tcode{F}_1$ is more specialized than the template for -\tcode{F2} +$\tcode{F}_2$ according to the partial ordering rules described in~\ref{temp.func.order}, or, if not that, \item -\tcode{F1} and \tcode{F2} are non-template functions with the same -parameter-type-lists, and \tcode{F1} is more constrained than \tcode{F2} -according to the partial ordering of constraints described in -\ref{temp.constr.order}, or if not that, +$\tcode{F}_1$ and $\tcode{F}_2$ are non-template functions and +$\tcode{F}_1$ is more partial-ordering-constrained than +$\tcode{F}_2$\iref{temp.constr.order} +\begin{example} +\begin{codeblock} +template +struct S { + constexpr void f(); // \#1 + constexpr void f(this S&) requires true; // \#2 +}; + +void test() { + S<> s; + s.f(); // calls \#2 +} +\end{codeblock} +\end{example} +or, if not that, \item -\tcode{F1} is a constructor for a class \tcode{D}, -\tcode{F2} is a constructor for a base class \tcode{B} of \tcode{D}, and +$\tcode{F}_1$ is a constructor for a class \tcode{D}, +$\tcode{F}_2$ is a constructor for a base class \tcode{B} of \tcode{D}, and for all arguments -the corresponding parameters of \tcode{F1} and \tcode{F2} have the same type +the corresponding parameters of $\tcode{F}_1$ and $\tcode{F}_2$ have the same type \begin{example} \begin{codeblock} struct A { @@ -1775,8 +1863,8 @@ or, if not that, \item -\tcode{F2} is a rewritten candidate\iref{over.match.oper} and -\tcode{F1} is not +$\tcode{F}_2$ is a rewritten candidate\iref{over.match.oper} and +$\tcode{F}_1$ is not \begin{example} \begin{codeblock} struct S { @@ -1789,10 +1877,10 @@ or, if not that, \item -\tcode{F1} and \tcode{F2} are rewritten candidates, and -\tcode{F2} is a synthesized candidate +$\tcode{F}_1$ and $\tcode{F}_2$ are rewritten candidates, and +$\tcode{F}_2$ is a synthesized candidate with reversed order of parameters -and \tcode{F1} is not +and $\tcode{F}_1$ is not \begin{example} \begin{codeblock} struct S { @@ -1802,32 +1890,32 @@ bool b = 1 < S(); // calls \#2 \end{codeblock} \end{example} -or, if not that +or, if not that, \item -\tcode{F1} and \tcode{F2} are generated +$\tcode{F}_1$ and $\tcode{F}_2$ are generated from class template argument deduction\iref{over.match.class.deduct} for a class \tcode{D}, and -\tcode{F2} is generated +$\tcode{F}_2$ is generated from inheriting constructors from a base class of \tcode{D} -while \tcode{F1} is not, and +while $\tcode{F}_1$ is not, and for each explicit function argument, -the corresponding parameters of \tcode{F1} and \tcode{F2} +the corresponding parameters of $\tcode{F}_1$ and $\tcode{F}_2$ are either both ellipses or have the same type, or, if not that, \item -\tcode{F1} is generated from a +$\tcode{F}_1$ is generated from a \grammarterm{deduction-guide}\iref{over.match.class.deduct} -and \tcode{F2} is not, or, if not that, +and $\tcode{F}_2$ is not, or, if not that, \item -\tcode{F1} is the copy deduction candidate\iref{over.match.class.deduct} -and \tcode{F2} is not, or, if not that, +$\tcode{F}_1$ is the copy deduction candidate\iref{over.match.class.deduct} +and $\tcode{F}_2$ is not, or, if not that, \item -\tcode{F1} is generated from a non-template constructor -and \tcode{F2} is generated from a constructor template. +$\tcode{F}_1$ is generated from a non-template constructor +and $\tcode{F}_2$ is generated from a constructor template. \begin{example} \begin{codeblock} template struct A { @@ -1965,7 +2053,7 @@ are converted to match the corresponding properties of the parameter. \begin{note} -Other properties, such as the lifetime, storage class, +Other properties, such as the lifetime, storage duration, linkage, alignment, accessibility of the argument, whether the argument is a bit-field, and whether a function is deleted\iref{dcl.fct.def.delete}, are ignored. So, although an implicit @@ -2051,6 +2139,8 @@ to \tcode{A}. \end{example} + +\pnum When the parameter has a class type and the argument expression has the same type, the implicit conversion sequence is an identity conversion. When the parameter has a class type and the argument expression has a @@ -2058,11 +2148,13 @@ derived-to-base \indextext{conversion!derived-to-base}% conversion from the derived class to the base class. +A derived-to-base conversion has Conversion rank\iref{over.ics.scs}. \begin{note} There is no such standard conversion; this derived-to-base conversion exists only in the description of implicit conversion sequences. \end{note} -A derived-to-base conversion has Conversion rank\iref{over.ics.scs}. + +\pnum When the parameter is the implicit object parameter of a static member function, the implicit conversion sequence is a standard conversion sequence that is neither better nor worse than any other standard conversion sequence. @@ -2072,8 +2164,8 @@ or when converting to the left operand of an assignment operation only standard conversion sequences are allowed. \begin{note} -When converting to the explicit object parameter, if any, -user-defined conversion sequences are allowed. +When a conversion to the explicit object parameter occurs, +it can include user-defined conversion sequences. \end{note} \pnum @@ -2219,7 +2311,7 @@ \pnum If the user-defined conversion is specified by a specialization of a conversion function template, -the second standard conversion sequence shall have exact match rank. +the second standard conversion sequence shall have Exact Match rank. \pnum A conversion of an expression of class type @@ -2241,11 +2333,32 @@ \rSec4[over.ics.ref]{Reference binding} \pnum -When a parameter of reference type binds directly\iref{dcl.init.ref} to an -argument expression, the implicit conversion sequence is the identity conversion, -unless the argument expression has a type that is a derived class of the parameter -type, in which case the implicit conversion sequence is a derived-to-base +When a parameter of type ``reference to \cv~\tcode{T}'' +binds directly\iref{dcl.init.ref} to an argument expression: +\begin{itemize} +\item +If the argument expression has a type that +is a derived class of the parameter type, +the implicit conversion sequence is a derived-to-base conversion\iref{over.best.ics}. + +\item +Otherwise, +if the type of the argument is possibly cv-qualified \tcode{T}, or +if \tcode{T} is an array type of unknown bound with element type \tcode{U} and +the argument has an array type of known bound whose +element type is possibly cv-qualified \tcode{U}, +the implicit conversion sequence is the identity conversion. + +\item +Otherwise, +if \tcode{T} is a function type, +the implicit conversion sequence is a function pointer conversion. + +\item +Otherwise, the implicit conversion sequence is a qualification conversion. +\end{itemize} + \begin{example} \begin{codeblock} struct A {}; @@ -2253,14 +2366,18 @@ int f(A&); int f(B&); int i = f(b); // calls \tcode{f(B\&)}, an exact match, rather than \tcode{f(A\&)}, a conversion + +void g() noexcept; +int h(void (&)() noexcept); // \#1 +int h(void (&)()); // \#2 +int j = h(g); // calls \#1, an exact match, rather than \#2, a function pointer conversion \end{codeblock} \end{example} If the parameter binds directly to the result of applying a conversion function to the argument expression, the implicit conversion sequence is a user-defined conversion sequence\iref{over.ics.user} -whose second standard conversion sequence is either an identity conversion or, -if the conversion function returns an entity of a type that is a derived class -of the parameter type, a derived-to-base conversion. +whose second standard conversion sequence is +determined by the above rules. \pnum When a parameter of reference type is not bound directly to an argument @@ -2278,7 +2395,7 @@ binding an lvalue reference other than a reference to a non-volatile \keyword{const} type to an rvalue -or binding an rvalue reference to an lvalue other than a function lvalue. +or binding an rvalue reference to an lvalue of object type. \begin{note} This means, for example, that a candidate function cannot be a viable function if it has a non-\keyword{const} lvalue reference parameter (other than @@ -2316,7 +2433,8 @@ expression and special rules apply for converting it to a parameter type. \pnum -If the initializer list is a \grammarterm{designated-initializer-list}, +If the initializer list is a \grammarterm{designated-initializer-list} +and the parameter is not a reference, a conversion is only possible if the parameter has an aggregate type that can be initialized from the initializer list @@ -2383,9 +2501,9 @@ f( {1.0} ); // error: narrowing struct A { - A(std::initializer_list); // \#1 - A(std::initializer_list>); // \#2 - A(std::initializer_list); // \#3 + A(std::initializer_list); // \#1 + A(std::initializer_list>); // \#2 + A(std::initializer_list); // \#3 }; A a{ 1.0,2.0 }; // OK, uses \#1 @@ -2675,8 +2793,8 @@ \item \tcode{S1} and \tcode{S2} include reference bindings\iref{dcl.init.ref} and -\tcode{S1} binds an lvalue reference to a function lvalue and \tcode{S2} binds -an rvalue reference to a function lvalue +\tcode{S1} binds an lvalue reference to an lvalue of function type and +\tcode{S2} binds an rvalue reference to an lvalue of function type \begin{example} \begin{codeblock} int f(void(&)()); // \#1 @@ -2690,28 +2808,33 @@ \item \tcode{S1} and \tcode{S2} differ only in their qualification conversion\iref{conv.qual} and -yield similar types \tcode{T1} and \tcode{T2}, respectively, -where \tcode{T1} can be converted to \tcode{T2} by a qualification conversion. +yield similar types \tcode{T1} and \tcode{T2}, respectively +(where a standard conversion sequence that is a reference binding +is considered to yield the cv-unqualified referenced type), +where \tcode{T1} and \tcode{T2} are not the same type, and +\tcode{const T2} is reference-compatible with \tcode{T1}\iref{dcl.init.ref} \begin{example} \begin{codeblock} int f(const volatile int *); int f(const int *); int i; int j = f(&i); // calls \tcode{f(const int*)} +int g(const int*); +int g(const volatile int* const&); +int* p; +int k = g(p); // calls \tcode{g(const int*)} \end{codeblock} \end{example} or, if not that, + \item \tcode{S1} and \tcode{S2} -include reference bindings\iref{dcl.init.ref}, and the types to which the references -refer are the same type except for top-level cv-qualifiers, and the type to -which the reference initialized by -\tcode{S2} -refers is more cv-qualified than the type to which the reference initialized by -\tcode{S1} -refers. +bind ``reference to \tcode{T1}'' and ``reference to \tcode{T2}'', +respectively\iref{dcl.init.ref}, +where \tcode{T1} and \tcode{T2} are not the same type, and +\tcode{T2} is reference-compatible with \tcode{T1} \begin{example} \begin{codeblock} int f(const int &); @@ -2731,6 +2854,39 @@ a.f(); // calls \tcode{X::f() const} b.f(); // calls \tcode{X::f()} } + +int h(int (&)[]); +int h(int (&)[1]); +void g2() { + int a[1]; + h(a); // calls \tcode{h(int (\&)[1])} +} +\end{codeblock} +\end{example} +or, if not that, + +\item +\tcode{S1} and \tcode{S2} +bind the same reference type ``reference to \tcode{T}'' and +have source types \tcode{V1} and \tcode{V2}, respectively, +where the standard conversion sequence from \tcode{V1*} to \tcode{T*} +is better than the standard conversion sequence from \tcode{V2*} to \tcode{T*}. +\begin{example} +\begin{codeblock} +struct Z {}; + +struct A { + operator Z&(); + operator const Z&(); // \#1 +}; + +struct B { + operator Z(); + operator const Z&&(); // \#2 +}; + +const Z& r1 = A(); // OK, uses \#1 +const Z&& r2 = B(); // OK, uses \#2 \end{codeblock} \end{example} \end{itemize} @@ -2963,7 +3119,7 @@ \item an object or reference being initialized\iref{dcl.init,dcl.init.ref,dcl.init.list}, \item -the left side of an assignment\iref{expr.ass}, +the left side of an assignment\iref{expr.assign}, \item a parameter of a function\iref{expr.call}, \item @@ -2973,9 +3129,11 @@ \item an explicit type conversion\iref{expr.type.conv,expr.static.cast,expr.cast}, or \item -a non-type -\grammarterm{template-parameter}\iref{temp.arg.nontype}. +a constant template parameter\iref{temp.arg.nontype}. \end{itemize} +If the target type contains a placeholder type, +placeholder type deduction is performed\iref{dcl.type.auto.deduct}, and +the remainder of this subclause uses the target type so deduced. The \grammarterm{id-expression} can be preceded by the \tcode{\&} operator. \begin{note} Any redundant set of parentheses surrounding the function name is @@ -3006,7 +3164,7 @@ explicit object member functions match targets of function pointer type or reference to function type. -Non-static member functions match targets of +Implicit object member functions match targets of pointer-to-member-function type. \begin{note} %% FIXME: Should this only apply after the eliminations in the next paragraph? @@ -3028,10 +3186,8 @@ \tcode{F0} is eliminated if the set contains a second non-template function that -is more constrained than -\tcode{F0} -according to -the partial ordering rules of \ref{temp.constr.order}. +is more partial-ordering-constrained than +\tcode{F0}\iref{temp.constr.order}. Any given function template specialization \tcode{F1} @@ -3067,8 +3223,9 @@ with type \tcode{int(...)} has been declared, and not because of any ambiguity. -For another example, +\end{example} +\begin{example} \begin{codeblock} struct X { int f(int); @@ -3085,6 +3242,21 @@ \end{codeblock} \end{example} +\begin{example} +\begin{codeblock} +template struct X { + void f(short) requires B; + void f(long); + template void g(short) requires B; + template void g(long); +}; +void test() { + &X::f; // error: ambiguous; constraints are not considered + &X::g; // error: ambiguous; constraints are not considered +} +\end{codeblock} +\end{example} + \pnum \begin{note} If \tcode{f} and \tcode{g} are both overload sets, @@ -3135,13 +3307,13 @@ \begin{bnf} %% Ed. note: character protrusion would misalign various operators. -\microtypesetup{protrusion=false}\obeyspaces +\microtypesetup{protrusion=false} \nontermdef{operator} \textnormal{one of}\br - \terminal{new delete new[] delete[] co_await (\rlap{\,)} [\rlap{\,]} -> ->*}\br - \terminal{\~ ! + - * / \% \caret{} \&}\br - \terminal{| = += -= *= /= \%= \caret{}= \&=}\br - \terminal{|= == != < > <= >= <=> \&\&}\br - \terminal{|| << >> <<= >>= ++ -- ,}\br + \terminal{new \ \ \ \ \ delete \ \ new[] \ \ \ delete[] co_await (\rlap{\,)} \ \ \ \ \ \ \ [\rlap{\,]} \ \ \ \ \ \ \ -> \ \ \ \ \ \ ->*}\br + \terminal{\~ \ \ \ \ \ \ \ ! \ \ \ \ \ \ \ + \ \ \ \ \ \ \ - \ \ \ \ \ \ \ * \ \ \ \ \ \ \ / \ \ \ \ \ \ \ \% \ \ \ \ \ \ \ \caret{} \ \ \ \ \ \ \ \&}\br + \terminal{| \ \ \ \ \ \ \ = \ \ \ \ \ \ \ += \ \ \ \ \ \ -= \ \ \ \ \ \ *= \ \ \ \ \ \ /= \ \ \ \ \ \ \%= \ \ \ \ \ \ \caret{}= \ \ \ \ \ \ \&=}\br + \terminal{|= \ \ \ \ \ \ == \ \ \ \ \ \ != \ \ \ \ \ \ < \ \ \ \ \ \ \ > \ \ \ \ \ \ \ <= \ \ \ \ \ \ >= \ \ \ \ \ \ <=> \ \ \ \ \ \&\&}\br + \terminal{|| \ \ \ \ \ \ << \ \ \ \ \ \ >> \ \ \ \ \ \ <<= \ \ \ \ \ >>= \ \ \ \ \ ++ \ \ \ \ \ \ -- \ \ \ \ \ \ ,}\br \end{bnf} \begin{note} The operators @@ -3159,8 +3331,8 @@ \pnum Both the unary and binary forms of -\begin{ncsimplebnf}\obeyspaces -\terminal{+ - * \&} +\begin{ncsimplebnf} +\terminal{+ \ \ \ \ \ - \ \ \ \ \ * \ \ \ \ \ \&} \end{ncsimplebnf} can be overloaded. @@ -3168,8 +3340,8 @@ \begin{note} \indextext{restriction!operator overloading}% The following operators cannot be overloaded: -\begin{ncsimplebnf}\obeyspaces -\terminal{. .* :: ?:} +\begin{ncsimplebnf} +\terminal{. \ \ \ \ \ .* \ \ \ \ :: \ \ \ \ ?:} \end{ncsimplebnf} nor can the preprocessing symbols \tcode{\#}\iref{cpp.stringize} @@ -3211,15 +3383,10 @@ \pnum \indextext{restriction!overloading}% An operator function -shall either -\begin{itemize} -\item -be a member function or -\item -be a non-member function that -has at least one non-object parameter whose type is a class, a reference to a class, an +shall have at least one +function parameter or implicit object parameter whose type is +a class, a reference to a class, an enumeration, or a reference to an enumeration. -\end{itemize} It is not possible to change the precedence, grouping, or number of operands of operators. The meaning of @@ -3240,14 +3407,14 @@ \pnum \indextext{operator}% \begin{note} -The identities among certain predefined operators applied to basic types +The identities among certain predefined operators applied to fundamental types (for example, \tcode{++a} $\equiv$ \tcode{a+=1}) need not hold for operator functions. Some predefined operators, such as \tcode{+=}, -require an operand to be an lvalue when applied to basic types; +require an operand to be an lvalue when applied to fundamental types; this is not required by operator functions. \end{note} @@ -3261,7 +3428,7 @@ described in the rest of \ref{over.oper}. \pnum -Operators not mentioned explicitly in subclauses~\ref{over.ass} through~\ref{over.inc} +Operators not mentioned explicitly in subclauses~\ref{over.assign} through~\ref{over.inc} act as ordinary unary and binary operators obeying the rules of~\ref{over.unary} or~\ref{over.binary}.% \indextext{overloading!resolution!best viable function|)}% @@ -3342,7 +3509,7 @@ a relational operator function, or a three-way comparison operator function. -\rSec3[over.ass]{Simple assignment} +\rSec3[over.assign]{Simple assignment} \indextext{assignment operator!overloaded}% \indextext{overloading!assignment operator} @@ -3414,11 +3581,12 @@ where the \grammarterm{postfix-expression} is of class type, the operator function is selected by overload resolution\iref{over.call.object}. -If a surrogate call function for a conversion function -named \keyword{operator} \grammarterm{conversion-type-id} is selected, +If a surrogate call function is selected, +let $e$ be the result of invoking the corresponding conversion operator function on the \grammarterm{postfix-expression}; + the expression is interpreted as \begin{ncsimplebnf} -postfix-expression \terminal{.} \keyword{operator} conversion-type-id \terminal{(}\terminal{)} \terminal{(} \opt{expression-list} \terminal{)} +$e$ \terminal{(} \opt{expression-list} \terminal{)} \end{ncsimplebnf} Otherwise, the expression is interpreted as \begin{ncsimplebnf} @@ -3431,8 +3599,8 @@ \pnum A \defnadj{subscripting}{operator function} -is a function named \tcode{\keyword{operator}[]} -that is a non-static member function with an arbitrary number of parameters. +is a member function named \tcode{\keyword{operator}[]} +with an arbitrary number of parameters. It may have default arguments. For an expression of the form \begin{ncsimplebnf} @@ -3894,18 +4062,20 @@ \begin{bnf} \nontermdef{literal-operator-id}\br - \keyword{operator} string-literal identifier\br + \keyword{operator} unevaluated-string identifier\br \keyword{operator} user-defined-string-literal \end{bnf} \pnum -The \grammarterm{string-literal} or \grammarterm{user-defined-string-literal} -in a \grammarterm{literal-operator-id} shall have no -\grammarterm{encoding-prefix} and shall contain no characters other than the -implicit terminating \tcode{'\textbackslash 0'}. +The \grammarterm{user-defined-string-literal} +in a \grammarterm{literal-operator-id} +shall have no \grammarterm{encoding-prefix}. +The \grammarterm{unevaluated-string} or +\grammarterm{user-defined-string-literal} shall be empty. The \grammarterm{ud-suffix} of the \grammarterm{user-defined-string-literal} or the \grammarterm{identifier} in a \grammarterm{literal-operator-id} is called a \defnx{literal suffix identifier}{literal!suffix identifier}. +The first form of \grammarterm{literal-operator-id} is deprecated\iref{depr.lit}. Some literal suffix identifiers are reserved for future standardization; see~\ref{usrlit.suffix}. A declaration whose \grammarterm{literal-operator-id} uses such a literal suffix identifier is ill-formed, no diagnostic required. @@ -3950,12 +4120,13 @@ A \defnx{numeric literal operator template}{literal!operator!template numeric} is a literal operator template whose \grammarterm{template-parameter-list} has a single \grammarterm{template-parameter} -that is a non-type template parameter pack\iref{temp.variadic} +that is a constant template parameter pack\iref{temp.variadic} with element type \tcode{char}. A \defnx{string literal operator template}{literal!operator!template string} is a literal operator template whose \grammarterm{template-parameter-list} comprises -a single non-type \grammarterm{template-parameter} of class type. +a single \grammarterm{parameter-declaration} that declares a +constant template parameter of class type. The declaration of a literal operator template shall have an empty \grammarterm{parameter-declaration-clause} and shall declare either a numeric literal operator template @@ -3980,19 +4151,19 @@ \pnum \begin{example} \begin{codeblock} -void operator "" _km(long double); // OK -string operator "" _i18n(const char*, std::size_t); // OK -template double operator "" _\u03C0(); // OK, UCN for lowercase pi +void operator ""_km(long double); // OK +string operator "" _i18n(const char*, std::size_t); // OK, deprecated +template double operator ""_\u03C0(); // OK, UCN for lowercase pi float operator ""_e(const char*); // OK float operator ""E(const char*); // ill-formed, no diagnostic required: // reserved literal suffix\iref{usrlit.suffix,lex.ext} double operator""_Bq(long double); // OK, does not use the reserved \grammarterm{identifier} \tcode{_Bq}\iref{lex.name} double operator"" _Bq(long double); // ill-formed, no diagnostic required: // uses the reserved \grammarterm{identifier} \tcode{_Bq}\iref{lex.name} -float operator " " B(const char*); // error: non-empty \grammarterm{string-literal} -string operator "" 5X(const char*, std::size_t); // error: invalid literal suffix identifier -double operator "" _miles(double); // error: invalid \grammarterm{parameter-declaration-clause} -template int operator "" _j(const char*); // error: invalid \grammarterm{parameter-declaration-clause} -extern "C" void operator "" _m(long double); // error: C language linkage +float operator " "B(const char*); // error: non-empty \grammarterm{string-literal} +string operator ""5X(const char*, std::size_t); // error: invalid literal suffix identifier +double operator ""_miles(double); // error: invalid \grammarterm{parameter-declaration-clause} +template int operator ""_j(const char*); // error: invalid \grammarterm{parameter-declaration-clause} +extern "C" void operator ""_m(long double); // error: C language linkage \end{codeblock} \end{example} diff --git a/source/preface.tex b/source/preface.tex new file mode 100644 index 0000000000..6e0b3fa036 --- /dev/null +++ b/source/preface.tex @@ -0,0 +1,19 @@ +%!TEX root = std.tex + +\chapter{Foreword} + +[This page is intentionally left blank.] + +\chapter{Introduction} + +Clauses and subclauses in this document are annotated +with a so-called stable name, +presented in square brackets next to the (sub)clause heading +(such as ``[lex.token]'' for \ref{lex.token}, ``Tokens''). +Stable names aid in the discussion and evolution of this document +by serving as stable references to subclauses across editions +that are unaffected by changes of subclause numbering. + +Aspects of the language syntax of \Cpp{} are distinguished typographically +by the use of \fakegrammarterm{italic, sans-serif} type +or \tcode{constant width} type to avoid ambiguities; see \ref{syntax}. diff --git a/source/preprocessor.tex b/source/preprocessor.tex index af42cac023..ee7959abeb 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -45,17 +45,18 @@ \terminal{\#} conditionally-supported-directive \end{bnf} -\begin{bnf}\obeyspaces +\begin{bnf} \nontermdef{control-line}\br \terminal{\# include} pp-tokens new-line\br pp-import\br + \terminal{\# embed \ } pp-tokens new-line\br \terminal{\# define } identifier replacement-list new-line\br \terminal{\# define } identifier lparen \opt{identifier-list} \terminal{)} replacement-list new-line\br \terminal{\# define } identifier lparen \terminal{... )} replacement-list new-line\br \terminal{\# define } identifier lparen identifier-list \terminal{, ... )} replacement-list new-line\br - \terminal{\# undef } identifier new-line\br - \terminal{\# line } pp-tokens new-line\br - \terminal{\# error } \opt{pp-tokens} new-line\br + \terminal{\# undef \ } identifier new-line\br + \terminal{\# line \ \ } pp-tokens new-line\br + \terminal{\# error \ } \opt{pp-tokens} new-line\br \terminal{\# warning} \opt{pp-tokens} new-line\br \terminal{\# pragma } \opt{pp-tokens} new-line\br \terminal{\# }new-line @@ -66,34 +67,33 @@ if-group \opt{elif-groups} \opt{else-group} endif-line \end{bnf} -\begin{bnf}\obeyspaces +\begin{bnf} \nontermdef{if-group}\br - \terminal{\# if } constant-expression new-line \opt{group}\br - \terminal{\# ifdef } identifier new-line \opt{group}\br + \terminal{\# if \ \ \ \ } constant-expression new-line \opt{group}\br + \terminal{\# ifdef \ } identifier new-line \opt{group}\br \terminal{\# ifndef } identifier new-line \opt{group} \end{bnf} \begin{bnf} \nontermdef{elif-groups}\br - elif-group\br - elif-groups elif-group + elif-group \opt{elif-groups} \end{bnf} -\begin{bnf}\obeyspaces +\begin{bnf} \nontermdef{elif-group}\br - \terminal{\# elif } constant-expression new-line \opt{group}\br - \terminal{\# elifdef } constant-expression new-line \opt{group}\br - \terminal{\# elifndef} constant-expression new-line \opt{group} + \terminal{\# elif \ \ \ } constant-expression new-line \opt{group}\br + \terminal{\# elifdef } identifier new-line \opt{group}\br + \terminal{\# elifndef} identifier new-line \opt{group} \end{bnf} -\begin{bnf}\obeyspaces +\begin{bnf} \nontermdef{else-group}\br - \terminal{\# else } new-line \opt{group} + \terminal{\# else \ \ } new-line \opt{group} \end{bnf} -\begin{bnf}\obeyspaces +\begin{bnf} \nontermdef{endif-line}\br - \terminal{\# endif } new-line + \terminal{\# endif \ } new-line \end{bnf} \begin{bnf} @@ -124,8 +124,48 @@ \begin{bnf} \nontermdef{pp-tokens}\br - preprocessing-token\br - pp-tokens preprocessing-token + preprocessing-token \opt{pp-tokens} +\end{bnf} + +\begin{bnf} +\nontermdef{embed-parameter-seq}\br + embed-parameter \opt{embed-parameter-seq} +\end{bnf} + +\begin{bnf} +\nontermdef{embed-parameter}\br + embed-standard-parameter\br + embed-prefixed-parameter +\end{bnf} + +\begin{bnf} +\nontermdef{embed-standard-parameter}\br + \terminal{limit} \terminal{(} pp-balanced-token-seq \terminal{)}\br + \terminal{prefix} \terminal{(} \opt{pp-balanced-token-seq} \terminal{)}\br + \terminal{suffix} \terminal{(} \opt{pp-balanced-token-seq} \terminal{)}\br + \terminal{if_empty} \terminal{(} \opt{pp-balanced-token-seq} \terminal{)} +\end{bnf} + +\begin{bnf} +\nontermdef{embed-prefixed-parameter}\br + identifier :: identifier\br + identifier :: identifier \terminal{(} \opt{pp-balanced-token-seq} \terminal{)} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-balanced-token-seq}\br + pp-balanced-token \opt{pp-balanced-token-seq} +\end{bnf} + +\begin{bnf} +\nontermdef{pp-balanced-token}\br + \terminal{(} \opt{pp-balanced-token-seq} \terminal{)}\br + \terminal{[} \opt{pp-balanced-token-seq} \terminal{]}\br + \terminal{\{} \opt{pp-balanced-token-seq} \terminal{\}}\br + \textnormal{any} pp-token \textnormal{except:}\br + \bnfindent\textnormal{parenthesis (\unicode{0028}{left parenthesis} and \unicode{0029}{right parenthesis}),}\br + \bnfindent\textnormal{bracket (\unicode{005b}{left square bracket} and \unicode{005d}{right square bracket}), or}\br + \bnfindent\textnormal{brace (\unicode{007b}{left curly bracket} and \unicode{007d}{right curly bracket}).} \end{bnf} \begin{bnf} @@ -137,7 +177,7 @@ A \defn{preprocessing directive} consists of a sequence of preprocessing tokens that satisfies the following constraints: At the start of translation phase 4, -the first token in the sequence, +the first preprocessing token in the sequence, referred to as a \defnadj{directive-introducing}{token}, begins with the first character in the source file (optionally after whitespace containing no new-line characters) or @@ -150,7 +190,7 @@ \item an \keyword{import} preprocessing token -immediately followed on the same logical line by a +immediately followed on the same logical source line by a \grammarterm{header-name}, \tcode{<}, \grammarterm{identifier}, @@ -160,7 +200,7 @@ \item a \keyword{module} preprocessing token -immediately followed on the same logical line by an +immediately followed on the same logical source line by an \grammarterm{identifier}, \tcode{:}, or \tcode{;} @@ -168,11 +208,11 @@ \item an \keyword{export} preprocessing token -immediately followed on the same logical line by +immediately followed on the same logical source line by one of the two preceding forms. \end{itemize} -The last token in the sequence is the first token within the sequence that +The last preprocessing token in the sequence is the first preprocessing token within the sequence that is immediately followed by whitespace containing a new-line character. \begin{footnote} Thus, @@ -216,6 +256,16 @@ \pnum A sequence of preprocessing tokens is only a \grammarterm{text-line} if it does not begin with a directive-introducing token. +\begin{example} +\begin{codeblock} +using module = int; +module i; // not a \grammarterm{text-line} and not a \grammarterm{control-line} +int foo() { + return i; +} +\end{codeblock} +The example is not a valid \grammarterm{preprocessing-file}. +\end{example} A sequence of preprocessing tokens is only a \grammarterm{conditionally-supported-directive} if it does not begin with any of the directive names appearing after a \tcode{\#} in the syntax. @@ -224,6 +274,10 @@ \impldef{additional supported forms of preprocessing directive} semantics. +\pnum +Any \grammarterm{embed-prefixed-parameter} is conditionally-supported, +with \impldef{supported forms of \#embed prefix parameters} semantics. + \pnum At the start of phase 4 of translation, the \grammarterm{group} of a \grammarterm{pp-global-module-fragment} shall @@ -290,8 +344,7 @@ \begin{bnf} \nontermdef{h-pp-tokens}\br - h-preprocessing-token\br - h-pp-tokens h-preprocessing-token + h-preprocessing-token \opt{h-pp-tokens} \end{bnf} \begin{bnf} @@ -307,6 +360,12 @@ \terminal{\xname{has_include}} \terminal{(} header-name-tokens \terminal{)} \end{bnf} +\indextext{\idxxname{has_embed}}% +\begin{bnf} +\nontermdef{has-embed-expression}\br + \terminal{\xname{has_embed}} \terminal{(} pp-balanced-token-seq \terminal{)} +\end{bnf} + \indextext{\idxxname{has_cpp_attribute}}% \begin{bnf} \nontermdef{has-attribute-expression}\br @@ -325,9 +384,12 @@ all identifiers either are or are not macro names --- there simply are no keywords, enumeration constants, etc. \end{footnote} -and it may contain zero or more \grammarterm{defined-macro-expression}{s} and/or -\grammarterm{has-include-expression}{s} and/or -\grammarterm{has-attribute-expression}{s} as unary operator expressions. +and it may contain zero or more +\grammarterm{defined-macro-expression}{s}, +\grammarterm{has-include-expression}{s}, +\grammarterm{has-attribute-expression}{s}, +and/or \grammarterm{has-embed-expression}{s} +as unary operator expressions. \pnum A \grammarterm{defined-macro-expression} evaluates to \tcode{1} @@ -361,6 +423,31 @@ to \tcode{1} if the search for the source file succeeds, and to \tcode{0} if the search fails. +\pnum +The parenthesized \grammarterm{pp-balanced-token-seq} in each contained +\grammarterm{has-embed-expression} is processed as if that +\grammarterm{pp-balanced-token-seq} were the \grammarterm{pp-tokens} in the +third form of a \tcode{\#embed} directive\iref{cpp.embed}. +If such a directive would not satisfy the syntactic requirements of a +\tcode{\#embed} directive, the program is ill-formed. +The \grammarterm{has-embed-expression} evaluates to: +\begin{itemize} +\item +\mname{STDC_EMBED_FOUND} if the search for the resource succeeds, +all the given \grammarterm{embed-parameter}s in the \grammarterm{embed-parameter-seq} +are supported, and the resource is not empty. +\item +Otherwise, \mname{STDC_EMBED_EMPTY} if the search for the resource succeeds, +all the given \grammarterm{embed-parameter}s in the \grammarterm{embed-parameter-seq} +are supported, and the resource is empty. +\item +Otherwise, \mname{STDC_EMBED_NOT_FOUND}. +\end{itemize} +\begin{note} +An unrecognized \grammarterm{embed-parameter} in an \grammarterm{has-embed-expression} +is not ill-formed and is instead treated as not supported. +\end{note} + \pnum Each \grammarterm{has-attribute-expression} is replaced by a non-zero \grammarterm{pp-number} @@ -375,8 +462,10 @@ \pnum For an attribute specified in this document, -the value of the \grammarterm{has-attribute-expression} -is given by \tref{cpp.cond.ha}. +it is \impldef{value of \grammarterm{has-attribute-expression} +for standard attributes} +whether the value of the \grammarterm{has-attribute-expression} +is \tcode{0} or is given by \tref{cpp.cond.ha}. For other attributes recognized by the implementation, the value is \impldef{value of \grammarterm{has-attribute-expression} @@ -390,7 +479,7 @@ {ll} \topline \lhdr{Attribute} & \rhdr{Value} \\ \rowsep -\tcode{carries_dependency} & \tcode{200809L} \\ +\tcode{assume} & \tcode{202207L} \\ \tcode{deprecated} & \tcode{201309L} \\ \tcode{fallthrough} & \tcode{201603L} \\ \tcode{likely} & \tcode{201803L} \\ @@ -406,9 +495,9 @@ \tcode{\#ifdef}, \tcode{\#ifndef}, \tcode{\#elifdef}, and \tcode{\#elifndef} directives, and the \tcode{defined} conditional inclusion operator, -shall treat \xname{has_include} and \xname{has_cpp_attribute} +shall treat \xname{has_include}, \xname{has_embed}, and \xname{has_cpp_attribute} as if they were the names of defined macros. -The identifiers \xname{has_include} and \xname{has_cpp_attribute} +The identifiers \xname{has_include}, \xname{has_embed}, and \xname{has_cpp_attribute} shall not appear in any context not mentioned in this subclause. \pnum @@ -419,11 +508,11 @@ \pnum Preprocessing directives of the forms -\begin{ncsimplebnf}\obeyspaces +\begin{ncsimplebnf} \indextext{\idxcode{\#if}}% -\terminal{\# if } constant-expression new-line \opt{group}\br +\terminal{\# if \ \ \ \ } constant-expression new-line \opt{group}\br \indextext{\idxcode{\#elif}}% -\terminal{\# elif } constant-expression new-line \opt{group} +\terminal{\# elif \ \ } constant-expression new-line \opt{group} \end{ncsimplebnf} check whether the controlling constant expression evaluates to nonzero. @@ -436,7 +525,7 @@ \tcode{defined} unary operator), just as in normal text. -If the token +If the preprocessing token \tcode{defined} is generated as a result of this replacement process or use of the @@ -449,7 +538,8 @@ After all replacements due to macro expansion and evaluations of \grammarterm{defined-macro-expression}s, -\grammarterm{has-include-expression}s, and +\grammarterm{has-include-expression}s, +\grammarterm{has-embed-expression}s, and \grammarterm{has-attribute-expression}s have been performed, all remaining identifiers and keywords, @@ -474,7 +564,7 @@ in~\ref{support.limits}. For the purposes of this token conversion and evaluation all signed and unsigned integer types act as if they have the same representation as, respectively, -\tcode{intmax_t} or \tcode{uintmax_t}\iref{cstdint}. +\tcode{intmax_t} or \tcode{uintmax_t}\iref{cstdint.syn}. \begin{note} Thus on an implementation where \tcode{std::numeric_limits::max()} is \tcode{0x7FFF} @@ -495,10 +585,10 @@ \pnum Preprocessing directives of the forms -\begin{ncsimplebnf}\obeyspaces -\terminal{\# ifdef } identifier new-line \opt{group}\br +\begin{ncsimplebnf} +\terminal{\# ifdef \ \ } identifier new-line \opt{group}\br \indextext{\idxcode{\#ifdef}}% -\terminal{\# ifndef } identifier new-line \opt{group}\br +\terminal{\# ifndef \ } identifier new-line \opt{group}\br \indextext{\idxcode{\#ifndef}}% \terminal{\# elifdef } identifier new-line \opt{group}\br \indextext{\idxcode{\#elifdef}}% @@ -658,13 +748,13 @@ If the directive resulting after all replacements does not match one of the two previous forms, the behavior is undefined. -\begin{footnote} -Note that adjacent \grammarterm{string-literal}s are not concatenated into +\begin{note} +Adjacent \grammarterm{string-literal}s are not concatenated into a single \grammarterm{string-literal} (see the translation phases in~\ref{lex.phases}); thus, an expansion that results in two \grammarterm{string-literal}s is an invalid directive. -\end{footnote} +\end{note} The method by which a sequence of preprocessing tokens between a \tcode{<} and a @@ -742,6 +832,356 @@ \end{codeblock} \end{example} +\rSec1[cpp.embed]{Resource inclusion} +\indextext{preprocessing directive!embed a resource} +\indextext{\idxcode{\#embed}}% + +\rSec2[cpp.embed.gen]{General} + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# embed <} h-char-sequence \terminal{>} \opt{pp-tokens} new-line +\end{ncsimplebnf} +searches a sequence of +\impldef{sequence of places searched for an embedded resource} +places for a resource identified uniquely by the specified sequence between +the \tcode{<} and \tcode{>} delimiters. +How the places are specified or the resource identified is +\impldef{search locations for embedded resources specified with \tcode{<>}}. + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# embed "} q-char-sequence \terminal{"} \opt{pp-tokens} new-line +\end{ncsimplebnf} +searches for a resource identified by the specified sequence between the +\tcode{"} delimiters. +The named resource is searched for in an +\impldef{manner of search for named resource} +manner. +If this search is not supported, or if the search fails, the directive is +reprocessed as if it read +\begin{ncsimplebnf} +\terminal{\# embed <} h-char-sequence \terminal{>} \opt{pp-tokens} new-line +\end{ncsimplebnf} +with the identical contained sequence (including \tcode{>} characters, if any) +from the original directive. + +\pnum +\recommended A mechanism similar to, but distinct from, the +\impldef{sequence of places searched for a header} +search paths used for \tcode{\#include} \iref{cpp.include} +is encouraged. + +\pnum +Either form of the \tcode{\#embed} directive processes the +\grammarterm{pp-tokens}, if present, just as in normal text. +The \grammarterm{pp-tokens} shall then have the form +\grammarterm{embed-parameter-seq}. + +\pnum +A resource is a source of data accessible from the translation environment. +A resource has an \defn{implementation-resource-width}, which is the +\impldef{size in bits of a resource} +size in bits of the resource. +If the implementation-resource-width is not an integral multiple of +\libmacro{CHAR_BIT}, the program is ill-formed. +Let \defn{implementation-resource-count} be +implementation-resource-width divided by \libmacro{CHAR_BIT}. +Every resource also has a \defn{resource-count}, which is + +\begin{itemize} +\item + the value as computed from the optionally-provided \tcode{limit} + \grammarterm{embed-parameter}\iref{cpp.embed.param.limit}, if present; +\item + otherwise, the implementation-resource-count. +\end{itemize} + +A resource is empty if the resource-count is zero. + +\pnum +\begin{example} +\begin{codeblock} +// ill-formed if the implementation-resource-width is 6 bits +#embed "6_bits.bin" +\end{codeblock} +\end{example} + +\pnum +The \tcode{\#embed} directive is replaced by a comma-delimited list of integer +literals of type \tcode{int}, unless otherwise modified by embed +parameters\iref{cpp.embed.param}. + +\pnum +The integer literals in the comma-delimited list correspond to +resource-count consecutive calls to \tcode{std::fgetc} \iref{cstdio.syn} +from the resource, as a binary file. +If any call to \tcode{std::fgetc} returns \tcode{EOF}, the program is +ill-formed. + +\pnum +\recommended The value of each integer literal should closely represent +the bit stream of the resource unmodified. +This can require an implementation to consider potential differences between +translation and execution environments, as well as any other applicable +sources of mismatch. + +\begin{example} +\begin{codeblock} +#include +#include +#include +#include +#include + +int main() { + // If the file is the same as the resource in the translation environment, no assert in this program should fail. + constexpr unsigned char d[] = { +#embed + }; + const std::vector vec_d = { +#embed + }; + + constexpr std::size_t expected_size = sizeof(d); + + // same file in execution environment as was embedded + std::ifstream f_source("data.dat", std::ios::binary | std::ios::in); + unsigned char runtime_d[expected_size]; + char* ifstream_ptr = reinterpret_cast(runtime_d); + assert(!f_source.read(ifstream_ptr, expected_size)); + std::size_t ifstream_size = f_source.gcount(); + assert (ifstream_size == expected_size); + int is_same = std::memcmp(&d[0], ifstream_ptr, ifstream_size); + assert(is_same == 0); + int is_same_vec = std::memcmp(vec_d.data(), ifstream_ptr, ifstream_size); + assert(is_same_vec == 0); +} +\end{codeblock} +\end{example} + +\begin{example} +\begin{codeblock} +int i = { +#embed "i.dat" +}; // well-formed if \tcode{i.dat} produces a single value +int i2 = +#embed "i.dat" +; // also well-formed if \tcode{i.dat} produces a single value +struct s { + double a, b, c; + struct { double e, f, g; } x; + double h, i, j; +}; +s x = { +// well-formed if the directive produces nine or fewer values +#embed "s.dat" +}; +\end{codeblock} +\end{example} + +\pnum +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# embed} pp-tokens new-line +\end{ncsimplebnf} +(that does not match one of the two previous forms) is permitted. +The preprocessing tokens after \tcode{embed} in the directive are processed +just as in normal text (i.e., each identifier currently defined as a macro +name is replaced by its replacement list of preprocessing tokens). +The directive resulting after all replacements of the third form shall match +one of the two previous forms. +\begin{note} +Adjacent \grammarterm{string-literal}{s} are not concatenated into a single +\grammarterm{string-literal} (see the translation phases in \iref{lex.phases}); +thus, an expansion that results in two \grammarterm{string-literal}{s} is an +invalid directive. +\end{note} + +Any further processing as in normal text described for the two previous +forms is not performed. +\begin{note} +That is, processing as in normal text happens once and only once for the entire +directive. +\end{note} + +\begin{example} +If the directive matches the third form, the whole directive is replaced. +If the directive matches the first two forms, everything after the name is +replaced. + +\begin{codeblock} +#define prefix(ARG) suffix(ARG) +#define THE_ADDITION "teehee" +#define THE_RESOURCE ":3c" +#embed ":3c" prefix(THE_ADDITION) +#embed THE_RESOURCE prefix(THE_ADDITION) +\end{codeblock} + +is equivalent to: + +\begin{codeblock} +#embed ":3c" suffix("teehee") +#embed ":3c" suffix("teehee") +\end{codeblock} +\end{example} + +\pnum +The method by which a sequence of preprocessing tokens between a \tcode{<} and +a \tcode{>} preprocessing token pair or a pair of \tcode{"} characters is +combined into a single resource name preprocessing token is +\impldef{search locations for \tcode{""""} resource}. + +\rSec2[cpp.embed.param]{Embed parameters} +\rSec3[cpp.embed.param.limit]{limit parameter} +\pnum +An \grammarterm{embed-parameter} of the form +\tcode{limit (} \grammarterm{pp-balanced-token-seq} \tcode{)} +specifies the +maximum possible number of elements in the comma-delimited list. +It shall appear at most once in the \grammarterm{embed-parameter-seq}. +The token \tcode{defined} shall not appear in the +\grammarterm{constant-expression}. + +\pnum +The \grammarterm{pp-balanced-token-seq} is evaluated as a +\grammarterm{constant-expression} using the rules as described in conditional +inclusion\iref{cpp.cond}, but without being processed as in normal text an +additional time. + +\begin{example} +\begin{codeblock} +#undef DATA_LIMIT +#if __has_embed( limit(DATA_LIMIT)) +#endif +\end{codeblock} + +is equivalent to: + +\begin{codeblock} +#if __has_embed( limit(0)) +#endif +\end{codeblock} +\end{example} + +\begin{example} +\begin{codeblock} +#embed limit(__has_include("a.h")) + +#if __has_embed( limit(__has_include("a.h"))) +// ill-formed: \tcode{__has_include}\iref{cpp.cond} cannot appear here +#endif +\end{codeblock} +\end{example} + +\pnum +The \grammarterm{constant-expression} shall be an integral constant expression +whose value is greater than or equal to zero. +The resource-count\iref{cpp.embed.gen} becomes +implementation-resource-count, if the value of the +\grammarterm{constant-expression} is greater than +implementation-resource-count; otherwise, the value of the +\grammarterm{constant-expression}. +\begin{example} +\begin{codeblock} +constexpr unsigned char sound_signature[] = { + // a hypothetical resource capable of expanding to four or more elements +#embed limit(2+2) +}; + +static_assert(sizeof(sound_signature) == 4); // OK +\end{codeblock} +\end{example} + +\rSec3[cpp.embed.param.prefix]{prefix parameter} +\pnum +An \grammarterm{embed-parameter} of the form +\begin{ncsimplebnf} +\terminal{prefix (} \opt{pp-balanced-token-seq} \terminal{)} +\end{ncsimplebnf} +shall appear at most once in the \grammarterm{embed-parameter-seq}. + +\pnum +If the resource is empty, this \grammarterm{embed-parameter} is ignored. +Otherwise, the \grammarterm{pp-balanced-token-seq} is placed immediately +before the comma-delimited list of integral literals. + +\rSec3[cpp.embed.param.suffix]{suffix parameter} +\pnum +An \grammarterm{embed-parameter} of the form +\begin{ncsimplebnf} +\terminal{suffix (} \opt{pp-balanced-token-seq} \terminal{)} +\end{ncsimplebnf} +shall appear at most once in the \grammarterm{embed-parameter-seq}. + +\pnum +If the resource is empty, this \grammarterm{embed-parameter} is ignored. +Otherwise, the \grammarterm{pp-balanced-token-seq} is placed immediately after +the comma-delimited list of the integral constant expressions. + +\begin{example} +\begin{codeblock} +constexpr unsigned char whl[] = { +#embed "ches.glsl" \ + prefix(0xEF, 0xBB, 0xBF, ) /* a sequence of bytes */ \ + suffix(,) + 0 +}; +// always null-terminated, contains the sequence if not empty +constexpr bool is_empty = sizeof(whl) == 1 && whl[0] == '\0'; +constexpr bool is_not_empty = sizeof(whl) >= 4 + && whl[sizeof(whl) - 1] == '\0' + && whl[0] == '\xEF' && whl[1] == '\xBB' && whl[2] == '\xBF'; +static_assert(is_empty || is_not_empty); +\end{codeblock} +\end{example} + +\rSec3[cpp.embed.param.if.empty]{\tcode{if_empty} parameter} +\pnum +An embed-parameter of the form +\begin{ncsimplebnf} +\terminal{if_empty (} \opt{pp-balanced-token-seq} \terminal{)} +\end{ncsimplebnf} +shall appear at most once in the \grammarterm{embed-parameter-seq}. + +\pnum +If the resource is not empty, this \grammarterm{embed-parameter} is ignored. +Otherwise, the \tcode{\#embed} directive is replaced by the +\grammarterm{pp-balanced-token-seq}. + +\begin{example} +\tcode{limit(0)} affects when a resource is considered empty. +Therefore, the following program: + +\begin{codeblock} +#embed \ + if_empty(42203) limit(0) +\end{codeblock} +expands to +\begin{codeblock} +42203 +\end{codeblock} +\end{example} + +\begin{example} +This resource is considered empty due to the \tcode{limit(0)} \grammarterm{embed-parameter}, +always, including in \tcode{__has_embed} clauses. + +\begin{codeblock} +int infinity_zero () { +#if __has_embed( limit(0) prefix(some tokens)) == __STDC_EMBED_EMPTY__ + // if \tcode{} exists, this conditional inclusion branch is taken and the function returns \tcode{0}. + return 0; +#else + // otherwise, the resource does not exist +#error "The resource does not exist" +#endif +} +\end{codeblock} +\end{example} + \rSec1[cpp.module]{Module directive} \indextext{preprocessing directive!module}% @@ -753,9 +1193,35 @@ \pnum A \grammarterm{pp-module} shall not appear in a context where \tcode{module} -or (if it is the first token of the \grammarterm{pp-module}) \tcode{export} +or (if it is the first preprocessing token of the \grammarterm{pp-module}) \tcode{export} is an identifier defined as an object-like macro. +\pnum +The \grammarterm{pp-tokens}, if any, of a \grammarterm{pp-module} +shall be of the form: +\begin{ncsimplebnf} +pp-module-name \opt{pp-module-partition} \opt{pp-tokens} +\end{ncsimplebnf} +where the \grammarterm{pp-tokens} (if any) shall not begin with +a \tcode{(} preprocessing token and +the grammar non-terminals are defined as: +\begin{ncbnf} +\nontermdef{pp-module-name}\br + \opt{pp-module-name-qualifier} identifier +\end{ncbnf} +\begin{ncbnf} +\nontermdef{pp-module-partition}\br + \terminal{:} \opt{pp-module-name-qualifier} identifier +\end{ncbnf} +\begin{ncbnf} +\nontermdef{pp-module-name-qualifier}\br + identifier \terminal{.}\br + pp-module-name-qualifier identifier \terminal{.} +\end{ncbnf} +No \grammarterm{identifier} in +the \grammarterm{pp-module-name} or \grammarterm{pp-module-partition} +shall currently be defined as an object-like macro. + \pnum Any preprocessing tokens after the \tcode{module} preprocessing token in the \tcode{module} directive are processed just as in normal text. @@ -788,7 +1254,7 @@ \pnum A \grammarterm{pp-import} shall not appear in a context where \tcode{import} -or (if it is the first token of the \grammarterm{pp-import}) \tcode{export} +or (if it is the first preprocessing token of the \grammarterm{pp-import}) \tcode{export} is an identifier defined as an object-like macro. \pnum @@ -883,8 +1349,8 @@ \end{itemize} \pnum -\indextext{active macro directive|see{macro, active}}% -A macro directive is \defnx{active}{macro!active} at a source location +\indextext{active macro definition|see{macro, active}}% +A macro definition is \defnx{active}{macro!active} at a source location if it has a point of definition in that translation unit preceding the location, and does not have a point of undefinition in that translation unit preceding the location. @@ -928,6 +1394,18 @@ int a = Y; // OK, active macro definitions \#2 and \#4 are valid redefinitions int c = Z; // error: active macro definitions \#3 and \#5 are not valid redefinitions of \tcode{Z} \end{codeblocktu} + +\begin{codeblocktu}{Module unit \tcode{f}} +export module f; +export import "a.h"; + +int a = Y; // OK +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \tcode{\#1}} +import f; +int x = Y; // error: \tcode{Y} is neither a defined macro nor a declared name +\end{codeblocktu} \end{example} \indextext{macro!import|)} @@ -1161,7 +1639,7 @@ For each parameter in the replacement list that is neither preceded by a \tcode{\#} or \tcode{\#\#} preprocessing token nor followed by a \tcode{\#\#} preprocessing token, the preprocessing tokens -naming the parameter are replaced by a token sequence determined as follows: +naming the parameter are replaced by a preprocessing token sequence determined as follows: \begin{itemize} \item If the parameter is of the form \grammarterm{va-opt-replacement}, @@ -1174,7 +1652,7 @@ macros contained therein have been expanded. The argument's preprocessing tokens are completely macro replaced before being substituted as if they formed the rest of the preprocessing - file with no other preprocessing tokens being available. + translation unit with no other preprocessing tokens being available. \end{itemize} \begin{example} \begin{codeblock} @@ -1361,15 +1839,13 @@ of two placemarkers results in a single placemarker preprocessing token, and concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token. -If the result begins with a sequence matching the syntax of \grammarterm{universal-character-name}, -the behavior is undefined. \begin{note} -This determination does not consider the replacement of -\grammarterm{universal-character-name}s in translation phase 3\iref{lex.phases}. +Concatenation can form +a \grammarterm{universal-character-name}\iref{lex.charset}. \end{note} If the result is not a valid preprocessing token, the behavior is undefined. -The resulting token is available for further macro replacement. +The resulting preprocessing token is available for further macro replacement. The order of evaluation of \tcode{\#\#} operators is unspecified. @@ -1412,7 +1888,7 @@ "hello, world" \end{codeblock} -Space around the \tcode{\#} and \tcode{\#\#} tokens in the macro definition +Space around the \tcode{\#} and \tcode{\#\#} preprocessing tokens in the macro definition is optional. \end{example} @@ -1438,8 +1914,8 @@ "x ## y" \end{codeblock} -In other words, expanding \tcode{hash_hash} produces a new token, -consisting of two adjacent sharp signs, but this new token is not the +In other words, expanding \tcode{hash_hash} produces a new preprocessing token, +consisting of two adjacent sharp signs, but this new preprocessing token is not the \tcode{\#\#} operator. \end{example} @@ -1561,10 +2037,12 @@ \pnum The \defn{line number} -of the current source line is one greater than +of the current source line is +the line number of the current physical source line, +i.e., it is one greater than the number of new-line characters read or introduced in translation phase 1\iref{lex.phases} -while processing the source file to the current token. +while processing the source file to the current preprocessing token. \pnum A preprocessing directive of the form @@ -1611,14 +2089,20 @@ \indextext{\idxcode{\#error}|see{preprocessing directive, error}} \pnum -A preprocessing directive of either of the following forms +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# error} \opt{pp-tokens} new-line +\end{ncsimplebnf} +renders the program ill-formed. +A preprocessing directive of the form \begin{ncsimplebnf} -\terminal{\# error} \opt{pp-tokens} new-line\br \terminal{\# warning} \opt{pp-tokens} new-line \end{ncsimplebnf} -causes the implementation to produce -a diagnostic message that should include the specified sequence of preprocessing tokens; -the \tcode{\# error} directive renders the program ill-formed. +requires the implementation to produce at least one diagnostic message +for the preprocessing translation unit\iref{intro.compliance.general}. +\recommended +Any diagnostic message caused by either of these directives +should include the specified sequence of preprocessing tokens. \rSec1[cpp.pragma]{Pragma directive}% \indextext{preprocessing directive!pragma}% @@ -1659,7 +2143,7 @@ \xname{cplusplus}\\ The integer literal \tcode{\cppver}. \begin{note} -Future revisions of \Cpp{} will +Future revisions of this document will replace the value of this macro with a greater value. \end{note} @@ -1667,7 +2151,7 @@ The macros defined in \tref{cpp.predefined.ft} shall be defined to the corresponding integer literal. \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} @@ -1706,6 +2190,16 @@ The presumed line number can be changed by the \tcode{\#line} directive. \end{footnote} +\item +\indextext{stdc__embed_not_found__@\mname{STDC_EMBED_NOT_FOUND}}% +\indextext{stdc__embed_found__@\mname{STDC_EMBED_FOUND}}% +\indextext{stdc__embed_empty__@\mname{STDC_EMBED_EMPTY}}% +\mname{STDC_EMBED_NOT_FOUND}, \mname{STDC_EMBED_FOUND}, and \mname{STDC_EMBED_EMPTY}\\ +The integer literals \tcode{0}, \tcode{1}, and \tcode{2}, respectively. +\begin{note} +These represent values replaced from \grammarterm{has-embed-expression}{s}\iref{cpp.cond}. +\end{note} + \item \indextext{__stdc_hosted__@\mname{STDC_HOSTED}}% \indextext{implementation!hosted}% @@ -1733,7 +2227,7 @@ \mname{STDCPP_FLOAT16_T}\\ Defined as the integer literal \tcode{1} if and only if the implementation supports -the ISO/IEC/IEEE 60559 floating-point interchange format binary16 +the \IsoFloatUndated{} floating-point interchange format binary16 as an extended floating-point type\iref{basic.extended.fp}. \item @@ -1741,7 +2235,7 @@ \mname{STDCPP_FLOAT32_T}\\ Defined as the integer literal \tcode{1} if and only if the implementation supports -the ISO/IEC/IEEE 60559 floating-point interchange format binary32 +the \IsoFloatUndated{} floating-point interchange format binary32 as an extended floating-point type. \item @@ -1749,7 +2243,7 @@ \mname{STDCPP_FLOAT64_T}\\ Defined as the integer literal \tcode{1} if and only if the implementation supports -the ISO/IEC/IEEE 60559 floating-point interchange format binary64 +the \IsoFloatUndated{} floating-point interchange format binary64 as an extended floating-point type. \item @@ -1757,7 +2251,7 @@ \mname{STDCPP_FLOAT128_T}\\ Defined as the integer literal \tcode{1} if and only if the implementation supports -the ISO/IEC/IEEE 60559 floating-point interchange format binary128 +the \IsoFloatUndated{} floating-point interchange format binary128 as an extended floating-point type. \item @@ -1765,7 +2259,8 @@ \mname{STDCPP_BFLOAT16_T}\\ Defined as the integer literal \tcode{1} if and only if the implementation supports an extended floating-point type -with the properties described in \ref{basic.extended.fp}. +with the properties of the \grammarterm{typedef-name} \tcode{std::bfloat16_t} +as described in \ref{basic.extended.fp}. \item \indextext{__time__@\mname{TIME}}% @@ -1780,6 +2275,8 @@ an \impldef{text of \mname{TIME} when time of translation is not available} valid time shall be supplied. \end{description} +\indextext{macro!feature-test}% +\indextext{feature-test macro|see{macro, feature-test}}% \begin{LongTable}{Feature-test macros}{cpp.predefined.ft}{ll} \\ \topline \lhdr{Macro name} & \rhdr{Value} \\ \capsep @@ -1794,20 +2291,24 @@ \defnxname{cpp_alias_templates} & \tcode{200704L} \\ \rowsep \defnxname{cpp_aligned_new} & \tcode{201606L} \\ \rowsep \defnxname{cpp_attributes} & \tcode{200809L} \\ \rowsep +\defnxname{cpp_auto_cast} & \tcode{202110L} \\ \rowsep \defnxname{cpp_binary_literals} & \tcode{201304L} \\ \rowsep \defnxname{cpp_capture_star_this} & \tcode{201603L} \\ \rowsep \defnxname{cpp_char8_t} & \tcode{202207L} \\ \rowsep \defnxname{cpp_concepts} & \tcode{202002L} \\ \rowsep \defnxname{cpp_conditional_explicit} & \tcode{201806L} \\ \rowsep -\defnxname{cpp_constexpr} & \tcode{202207L} \\ \rowsep +\defnxname{cpp_constexpr} & \tcode{202406L} \\ \rowsep \defnxname{cpp_constexpr_dynamic_alloc} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_constexpr_exceptions} & \tcode{202411L} \\ \rowsep \defnxname{cpp_constexpr_in_decltype} & \tcode{201711L} \\ \rowsep -\defnxname{cpp_consteval} & \tcode{201811L} \\ \rowsep +\defnxname{cpp_consteval} & \tcode{202211L} \\ \rowsep \defnxname{cpp_constinit} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_contracts} & \tcode{202502L} \\ \rowsep \defnxname{cpp_decltype} & \tcode{200707L} \\ \rowsep \defnxname{cpp_decltype_auto} & \tcode{201304L} \\ \rowsep \defnxname{cpp_deduction_guides} & \tcode{201907L} \\ \rowsep \defnxname{cpp_delegating_constructors} & \tcode{200604L} \\ \rowsep +\defnxname{cpp_deleted_function} & \tcode{202403L} \\ \rowsep \defnxname{cpp_designated_initializers} & \tcode{201707L} \\ \rowsep \defnxname{cpp_enumerator_attributes} & \tcode{201411L} \\ \rowsep \defnxname{cpp_explicit_this_parameter} & \tcode{202110L} \\ \rowsep @@ -1827,30 +2328,37 @@ \defnxname{cpp_inline_variables} & \tcode{201606L} \\ \rowsep \defnxname{cpp_lambdas} & \tcode{200907L} \\ \rowsep \defnxname{cpp_modules} & \tcode{201907L} \\ \rowsep -\defnxname{cpp_multidimensional_subscript} & \tcode{202110L} \\ \rowsep +\defnxname{cpp_multidimensional_subscript} & \tcode{202211L} \\ \rowsep \defnxname{cpp_named_character_escapes} & \tcode{202207L} \\ \rowsep \defnxname{cpp_namespace_attributes} & \tcode{201411L} \\ \rowsep \defnxname{cpp_noexcept_function_type} & \tcode{201510L} \\ \rowsep \defnxname{cpp_nontype_template_args} & \tcode{201911L} \\ \rowsep \defnxname{cpp_nontype_template_parameter_auto} & \tcode{201606L} \\ \rowsep \defnxname{cpp_nsdmi} & \tcode{200809L} \\ \rowsep -\defnxname{cpp_range_based_for} & \tcode{201603L} \\ \rowsep +\defnxname{cpp_pack_indexing} & \tcode{202311L} \\ \rowsep +\defnxname{cpp_placeholder_variables} & \tcode{202306L} \\ \rowsep +\defnxname{cpp_pp_embed} & \tcode{202502L} \\ \rowsep +\defnxname{cpp_range_based_for} & \tcode{202211L} \\ \rowsep \defnxname{cpp_raw_strings} & \tcode{200710L} \\ \rowsep \defnxname{cpp_ref_qualifiers} & \tcode{200710L} \\ \rowsep \defnxname{cpp_return_type_deduction} & \tcode{201304L} \\ \rowsep \defnxname{cpp_rvalue_references} & \tcode{200610L} \\ \rowsep \defnxname{cpp_size_t_suffix} & \tcode{202011L} \\ \rowsep \defnxname{cpp_sized_deallocation} & \tcode{201309L} \\ \rowsep -\defnxname{cpp_static_assert} & \tcode{201411L} \\ \rowsep +\defnxname{cpp_static_assert} & \tcode{202306L} \\ \rowsep \defnxname{cpp_static_call_operator} & \tcode{202207L} \\ \rowsep -\defnxname{cpp_structured_bindings} & \tcode{201606L} \\ \rowsep +\defnxname{cpp_structured_bindings} & \tcode{202411L} \\ \rowsep +\defnxname{cpp_template_parameters} & \tcode{202502L} \\ \rowsep \defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep \defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep +\defnxname{cpp_trivial_relocatability} & \tcode{202502L} \\ \rowsep +\defnxname{cpp_trivial_union} & \tcode{202502L} \\ \rowsep \defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep \defnxname{cpp_unicode_literals} & \tcode{200710L} \\ \rowsep \defnxname{cpp_user_defined_literals} & \tcode{200809L} \\ \rowsep \defnxname{cpp_using_enum} & \tcode{201907L} \\ \rowsep \defnxname{cpp_variable_templates} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_variadic_friend} & \tcode{202403L} \\ \rowsep \defnxname{cpp_variadic_templates} & \tcode{200704L} \\ \rowsep \defnxname{cpp_variadic_using} & \tcode{201611L} \\ \end{LongTable} @@ -1881,13 +2389,11 @@ \item \indextext{__stdc_iso_10646__@\mname{STDC_ISO_10646}}% \mname{STDC_ISO_10646}\\ -An integer literal of the form \tcode{yyyymmL} (for example, -\tcode{199712L}). -If this symbol is defined, then every character in the Unicode required set, when -stored in an object of type \keyword{wchar_t}, has the same value as the code point -of that character. The \defn{Unicode required set} consists of all -the characters that are defined by ISO/IEC 10646, along with -all amendments and technical corrigenda as of the specified year and month. +An integer literal of the form \tcode{yyyymmL} +(for example, \tcode{199712L}). +Whether \mname{STDC_ISO_10646} is predefined and +if so, what its value is, +are \impldef{presence and value of \mname{STDC_ISO_10646}}. \item \indextext{__stdcpp_threads__@\mname{STDCPP_THREADS}}% diff --git a/source/ranges.tex b/source/ranges.tex index 82e0257ed3..c16eba7f10 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -27,6 +27,7 @@ \indexheader{ranges}% \indexlibraryglobal{all_t}% \begin{codeblock} +// mostly freestanding #include // see \ref{compare.syn} #include // see \ref{initializer.list.syn} #include // see \ref{iterator.synopsis} @@ -34,109 +35,117 @@ namespace std::ranges { inline namespace @\unspec@ { // \ref{range.access}, range access - inline constexpr @\unspec@ begin = @\unspec@; // freestanding - inline constexpr @\unspec@ end = @\unspec@; // freestanding - inline constexpr @\unspec@ cbegin = @\unspec@; // freestanding - inline constexpr @\unspec@ cend = @\unspec@; // freestanding - inline constexpr @\unspec@ rbegin = @\unspec@; // freestanding - inline constexpr @\unspec@ rend = @\unspec@; // freestanding - inline constexpr @\unspec@ crbegin = @\unspec@; // freestanding - inline constexpr @\unspec@ crend = @\unspec@; // freestanding - - inline constexpr @\unspec@ size = @\unspec@; // freestanding - inline constexpr @\unspec@ ssize = @\unspec@; // freestanding - inline constexpr @\unspec@ empty = @\unspec@; // freestanding - inline constexpr @\unspec@ data = @\unspec@; // freestanding - inline constexpr @\unspec@ cdata = @\unspec@; // freestanding + inline constexpr @\unspec@ begin = @\unspec@; + inline constexpr @\unspec@ end = @\unspec@; + inline constexpr @\unspec@ cbegin = @\unspec@; + inline constexpr @\unspec@ cend = @\unspec@; + inline constexpr @\unspec@ rbegin = @\unspec@; + inline constexpr @\unspec@ rend = @\unspec@; + inline constexpr @\unspec@ crbegin = @\unspec@; + inline constexpr @\unspec@ crend = @\unspec@; + + inline constexpr @\unspec@ size = @\unspec@; + inline constexpr @\unspec@ reserve_hint = @\unspec@; + inline constexpr @\unspec@ ssize = @\unspec@; + inline constexpr @\unspec@ empty = @\unspec@; + inline constexpr @\unspec@ data = @\unspec@; + inline constexpr @\unspec@ cdata = @\unspec@; } // \ref{range.range}, ranges template - concept range = @\seebelow@; // freestanding + concept range = @\seebelow@; template - inline constexpr bool enable_borrowed_range = false; // freestanding + constexpr bool enable_borrowed_range = false; template - concept borrowed_range = @\seebelow@; // freestanding + concept borrowed_range = @\seebelow@; template - using iterator_t = decltype(ranges::begin(declval())); // freestanding + using iterator_t = decltype(ranges::begin(declval())); template<@\libconcept{range}@ R> - using sentinel_t = decltype(ranges::end(declval())); // freestanding + using sentinel_t = decltype(ranges::end(declval())); template<@\libconcept{range}@ R> - using const_iterator_t = const_iterator>; // freestanding + using const_iterator_t = decltype(ranges::cbegin(declval())); template<@\libconcept{range}@ R> - using range_difference_t = iter_difference_t>; // freestanding + using const_sentinel_t = decltype(ranges::cend(declval())); + template<@\libconcept{range}@ R> + using range_difference_t = iter_difference_t>; template<@\libconcept{sized_range}@ R> - using range_size_t = decltype(ranges::size(declval())); // freestanding + using range_size_t = decltype(ranges::size(declval())); + template<@\libconcept{range}@ R> + using range_value_t = iter_value_t>; template<@\libconcept{range}@ R> - using range_value_t = iter_value_t>; // freestanding + using range_reference_t = iter_reference_t>; template<@\libconcept{range}@ R> - using range_reference_t = iter_reference_t>; // freestanding + using range_const_reference_t = iter_const_reference_t>; template<@\libconcept{range}@ R> - using range_const_reference_t = iter_const_reference_t>; // freestanding + using range_rvalue_reference_t = iter_rvalue_reference_t>; template<@\libconcept{range}@ R> - using range_rvalue_reference_t = iter_rvalue_reference_t>; // freestanding + using range_common_reference_t = iter_common_reference_t>; // \ref{range.sized}, sized ranges template - inline constexpr bool disable_sized_range = false; // freestanding + constexpr bool disable_sized_range = false; + + template + concept approximately_sized_range = @\seebelow@; template - concept sized_range = @\seebelow@; // freestanding + concept sized_range = @\seebelow@; // \ref{range.view}, views template - inline constexpr bool enable_view = @\seebelow@; // freestanding + constexpr bool enable_view = @\seebelow@; - struct view_base {}; // freestanding + struct view_base {}; template - concept view = @\seebelow@; // freestanding + concept view = @\seebelow@; // \ref{range.refinements}, other range refinements template - concept output_range = @\seebelow@; // freestanding + concept output_range = @\seebelow@; template - concept input_range = @\seebelow@; // freestanding + concept input_range = @\seebelow@; template - concept forward_range = @\seebelow@; // freestanding + concept forward_range = @\seebelow@; template - concept bidirectional_range = @\seebelow@; // freestanding + concept bidirectional_range = @\seebelow@; template - concept random_access_range = @\seebelow@; // freestanding + concept random_access_range = @\seebelow@; template - concept contiguous_range = @\seebelow@; // freestanding + concept contiguous_range = @\seebelow@; template - concept common_range = @\seebelow@; // freestanding + concept common_range = @\seebelow@; template - concept viewable_range = @\seebelow@; // freestanding + concept viewable_range = @\seebelow@; template - concept constant_range = @\seebelow@; // freestanding + concept constant_range = @\seebelow@; // \ref{view.interface}, class template \tcode{view_interface} template requires is_class_v && @\libconcept{same_as}@> - class view_interface; // freestanding + class view_interface; // \ref{range.subrange}, sub-ranges - enum class subrange_kind : bool { unsized, sized }; // freestanding + enum class @\libglobal{subrange_kind}@ : bool { @\libmember{unsized}{subrange_kind}@, @\libmember{sized}{subrange_kind}@ }; template<@\libconcept{input_or_output_iterator}@ I, @\libconcept{sentinel_for}@ S = I, subrange_kind K = @\seebelow@> requires (K == subrange_kind::sized || !@\libconcept{sized_sentinel_for}@) - class subrange; // freestanding + class subrange; template - inline constexpr bool enable_borrowed_range> = true; // freestanding + constexpr bool @\libspec{enable_borrowed_range}{subrange}@> = true; template requires ((N == 0 && @\libconcept{copyable}@) || N == 1) @@ -153,47 +162,47 @@ namespace std::ranges { // \ref{range.dangling}, dangling iterator handling - struct dangling; // freestanding + struct dangling; - // \ref{ranges.elementsof}, class template \tcode{elements_of} + // \ref{range.elementsof}, class template \tcode{elements_of} template<@\libconcept{range}@ R, class Allocator = allocator> - struct elements_of; + struct elements_of; // hosted template<@\libconcept{range}@ R> - using borrowed_iterator_t = @\seebelow@; // freestanding + using borrowed_iterator_t = @\seebelow@; template<@\libconcept{range}@ R> - using borrowed_subrange_t = @\seebelow@; // freestanding + using borrowed_subrange_t = @\seebelow@; // \ref{range.utility.conv}, range conversions template requires (!@\libconcept{view}@) - constexpr C to(R&& r, Args&&... args); // freestanding + constexpr C to(R&& r, Args&&... args); template class C, @\libconcept{input_range}@ R, class... Args> - constexpr auto to(R&& r, Args&&... args); // freestanding + constexpr auto to(R&& r, Args&&... args); template requires (!@\libconcept{view}@) - constexpr auto to(Args&&... args); // freestanding + constexpr auto to(Args&&... args); template class C, class... Args> - constexpr auto to(Args&&... args); // freestanding + constexpr auto to(Args&&... args); // \ref{range.empty}, empty view template requires is_object_v - class empty_view; // freestanding + class empty_view; template - inline constexpr bool enable_borrowed_range> = true; // freestanding + constexpr bool @\libspec{enable_borrowed_range}{empty_view}@> = true; namespace views { template - inline constexpr empty_view @\libmember{empty}{views}@{}; // freestanding + constexpr empty_view @\libmember{empty}{views}@{}; } // \ref{range.single}, single view template<@\libconcept{move_constructible}@ T> requires is_object_v - class single_view; // freestanding + class single_view; - namespace views { inline constexpr @\unspecnc@ single = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ single = @\unspecnc@; } template using @\exposidnc{maybe-const}@ = conditional_t; // \expos @@ -201,146 +210,142 @@ // \ref{range.iota}, iota view template<@\libconcept{weakly_incrementable}@ W, @\libconcept{semiregular}@ Bound = unreachable_sentinel_t> requires @\exposconcept{weakly-equality-comparable-with}@ && @\libconcept{copyable}@ - class iota_view; // freestanding + class iota_view; template - inline constexpr bool enable_borrowed_range> = true; // freestanding + constexpr bool @\libspec{enable_borrowed_range}{iota_view}@> = true; - namespace views { inline constexpr @\unspecnc@ iota = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ iota = @\unspecnc@; } // \ref{range.repeat}, repeat view - template<@\libconcept{move_constructible}@ W, @\libconcept{semiregular}@ Bound = unreachable_sentinel_t> - requires (is_object_v && @\libconcept{same_as}@> - && (@\exposid{is-integer-like}@ || @\libconcept{same_as}@)) + template<@\libconcept{move_constructible}@ T, @\libconcept{semiregular}@ Bound = unreachable_sentinel_t> + requires @\seebelow@ class repeat_view; - namespace views { inline constexpr @\unspec@ repeat = @\unspec@; } + namespace views { inline constexpr @\unspecnc@ repeat = @\unspecnc@; } // \ref{range.istream}, istream view template<@\libconcept{movable}@ Val, class CharT, class Traits = char_traits> requires @\seebelow@ - class basic_istream_view; + class basic_istream_view; // hosted template - using istream_view = basic_istream_view; + using istream_view = basic_istream_view; // hosted template - using wistream_view = basic_istream_view; + using wistream_view = basic_istream_view; // hosted - namespace views { template inline constexpr @\unspecnc@ istream = @\unspecnc@; } + namespace views { + template constexpr @\unspecnc@ istream = @\unspecnc@; // hosted + } // \ref{range.adaptor.object}, range adaptor objects template requires is_class_v && @\libconcept{same_as}@> - class range_adaptor_closure { }; // freestanding + class range_adaptor_closure { }; // \ref{range.all}, all view namespace views { - inline constexpr @\unspecnc@ all = @\unspecnc@; // freestanding + inline constexpr @\unspecnc@ all = @\unspecnc@; template<@\libconcept{viewable_range}@ R> - using all_t = decltype(all(declval())); // freestanding + using all_t = decltype(all(declval())); } // \ref{range.ref.view}, ref view template<@\libconcept{range}@ R> requires is_object_v - class ref_view; // freestanding + class ref_view; template - inline constexpr bool enable_borrowed_range> = true; // freestanding + constexpr bool @\libspec{enable_borrowed_range}{ref_view}@> = true; // \ref{range.owning.view}, owning view template<@\libconcept{range}@ R> requires @\seebelow@ - class owning_view; // freestanding + class owning_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{owning_view}@> = enable_borrowed_range; // \ref{range.as.rvalue}, as rvalue view template<@\libconcept{view}@ V> requires @\libconcept{input_range}@ - class as_rvalue_view; // freestanding + class as_rvalue_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{as_rvalue_view}@> = enable_borrowed_range; - namespace views { inline constexpr @\unspecnc@ as_rvalue = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ as_rvalue = @\unspecnc@; } // \ref{range.filter}, filter view template<@\libconcept{input_range}@ V, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{view}@ && is_object_v - class filter_view; // freestanding + class filter_view; - namespace views { inline constexpr @\unspecnc@ filter = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ filter = @\unspecnc@; } // \ref{range.transform}, transform view template<@\libconcept{input_range}@ V, @\libconcept{move_constructible}@ F> requires @\libconcept{view}@ && is_object_v && @\libconcept{regular_invocable}@> && @\exposconcept{can-reference}@>> - class transform_view; // freestanding + class transform_view; - namespace views { inline constexpr @\unspecnc@ transform = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ transform = @\unspecnc@; } // \ref{range.take}, take view - template<@\libconcept{view}@> class take_view; // freestanding + template<@\libconcept{view}@> class take_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{take_view}@> = enable_borrowed_range; - namespace views { inline constexpr @\unspecnc@ take = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ take = @\unspecnc@; } // \ref{range.take.while}, take while view template<@\libconcept{view}@ V, class Pred> requires @\libconcept{input_range}@ && is_object_v && @\libconcept{indirect_unary_predicate}@> - class take_while_view; // freestanding + class take_while_view; - namespace views { inline constexpr @\unspecnc@ take_while = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ take_while = @\unspecnc@; } // \ref{range.drop}, drop view template<@\libconcept{view}@ V> - class drop_view; // freestanding + class drop_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{drop_view}@> = enable_borrowed_range; - namespace views { inline constexpr @\unspecnc@ drop = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ drop = @\unspecnc@; } // \ref{range.drop.while}, drop while view template<@\libconcept{view}@ V, class Pred> requires @\libconcept{input_range}@ && is_object_v && @\libconcept{indirect_unary_predicate}@> - class drop_while_view; // freestanding + class drop_while_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{drop_while_view}@> = enable_borrowed_range; - namespace views { inline constexpr @\unspecnc@ drop_while = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ drop_while = @\unspecnc@; } // \ref{range.join}, join view template<@\libconcept{input_range}@ V> requires @\libconcept{view}@ && @\libconcept{input_range}@> - class join_view; // freestanding + class join_view; - namespace views { inline constexpr @\unspecnc@ join = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ join = @\unspecnc@; } // \ref{range.join.with}, join with view - template - concept @\exposconcept{compatible-joinable-ranges}@ = @\seebelow@; // \expos - template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> - requires @\libconcept{view}@ && @\libconcept{input_range}@> - && @\libconcept{view}@ - && @\exposconcept{compatible-joinable-ranges}@, Pattern> - class join_with_view; // freestanding + requires @\seebelow@ + class join_with_view; - namespace views { inline constexpr @\unspecnc@ join_with = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ join_with = @\unspecnc@; } // \ref{range.lazy.split}, lazy split view template @@ -350,48 +355,55 @@ requires @\libconcept{view}@ && @\libconcept{view}@ && @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> && (@\libconcept{forward_range}@ || @\exposconcept{tiny-range}@) - class lazy_split_view; // freestanding + class lazy_split_view; // \ref{range.split}, split view - template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern> - requires @\libconcept{view}@ && @\libconcept{view}@ && - @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> - class split_view; // freestanding + template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern> + requires @\libconcept{view}@ && @\libconcept{view}@ && + @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> + class split_view; namespace views { - inline constexpr @\unspecnc@ lazy_split = @\unspecnc@; // freestanding - inline constexpr @\unspecnc@ split = @\unspecnc@; // freestanding + inline constexpr @\unspecnc@ lazy_split = @\unspecnc@; + inline constexpr @\unspecnc@ split = @\unspecnc@; } + // \ref{range.concat}, concat view + template<@\libconcept{input_range}@... Views> + requires @\seebelow@ + class concat_view; + + namespace views { inline constexpr @\unspecnc@ concat = @\unspecnc@; } + // \ref{range.counted}, counted view - namespace views { inline constexpr @\unspecnc@ counted = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ counted = @\unspecnc@; } // \ref{range.common}, common view template<@\libconcept{view}@ V> requires (!@\libconcept{common_range}@ && @\libconcept{copyable}@>) - class common_view; // freestanding + class common_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{common_view}@> = enable_borrowed_range; - namespace views { inline constexpr @\unspecnc@ common = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ common = @\unspecnc@; } // \ref{range.reverse}, reverse view template<@\libconcept{view}@ V> requires @\libconcept{bidirectional_range}@ - class reverse_view; // freestanding + class reverse_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{reverse_view}@> = enable_borrowed_range; - namespace views { inline constexpr @\unspecnc@ reverse = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ reverse = @\unspecnc@; } // \ref{range.as.const}, as const view template<@\libconcept{input_range}@ R> - constexpr auto& @\exposid{possibly-const-range}@(R& r) { // \expos - if constexpr (@\libconcept{constant_range}@ && !@\libconcept{constant_range}@) { + constexpr auto& @\exposid{possibly-const-range}@(R& r) noexcept { // \expos + if constexpr (@\libconcept{input_range}@) { return const_cast(r); } else { return r; @@ -400,113 +412,124 @@ template<@\libconcept{view}@ V> requires @\libconcept{input_range}@ - class as_const_view; // freestanding + class as_const_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{as_const_view}@> = enable_borrowed_range; - namespace views { inline constexpr @\unspecnc@ as_const = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ as_const = @\unspecnc@; } // \ref{range.elements}, elements view template<@\libconcept{input_range}@ V, size_t N> requires @\seebelow@ - class elements_view; // freestanding + class elements_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{elements_view}@> = enable_borrowed_range; template - using @\libglobal{keys_view}@ = elements_view; // freestanding + using @\libglobal{keys_view}@ = elements_view; template - using @\libglobal{values_view}@ = elements_view; // freestanding + using @\libglobal{values_view}@ = elements_view; namespace views { template - inline constexpr @\unspecnc@ elements = @\unspecnc@; // freestanding - inline constexpr auto @\libmember{keys}{views}@ = elements<0>; // freestanding - inline constexpr auto @\libmember{values}{views}@ = elements<1>; // freestanding + constexpr @\unspecnc@ elements = @\unspecnc@; + inline constexpr auto @\libmember{keys}{views}@ = elements<0>; + inline constexpr auto @\libmember{values}{views}@ = elements<1>; } + // \ref{range.enumerate}, enumerate view + template<@\libconcept{view}@ V> + requires @\seebelow@ + class enumerate_view; + + template + constexpr bool @\libspec{enable_borrowed_range}{enumerate_view}@> = + enable_borrowed_range; + + namespace views { inline constexpr @\unspecnc@ enumerate = @\unspecnc@; } + // \ref{range.zip}, zip view template<@\libconcept{input_range}@... Views> requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) - class zip_view; // freestanding + class zip_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{zip_view}@> = (enable_borrowed_range && ...); - namespace views { inline constexpr @\unspecnc@ zip = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ zip = @\unspecnc@; } // \ref{range.zip.transform}, zip transform view 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; // freestanding + class zip_transform_view; - namespace views { inline constexpr @\unspecnc@ zip_transform = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ zip_transform = @\unspecnc@; } // \ref{range.adjacent}, adjacent view template<@\libconcept{forward_range}@ V, size_t N> requires @\libconcept{view}@ && (N > 0) - class adjacent_view; // freestanding + class adjacent_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{adjacent_view}@> = enable_borrowed_range; namespace views { template - inline constexpr @\unspecnc@ adjacent = @\unspecnc@; // freestanding - inline constexpr auto @\libmember{pairwise}{views}@ = adjacent<2>; // freestanding + constexpr @\unspecnc@ adjacent = @\unspecnc@; + inline constexpr auto @\libmember{pairwise}{views}@ = adjacent<2>; } // \ref{range.adjacent.transform}, adjacent transform view template<@\libconcept{forward_range}@ V, @\libconcept{move_constructible}@ F, size_t N> requires @\seebelow@ - class adjacent_transform_view; // freestanding + class adjacent_transform_view; namespace views { template - inline constexpr @\unspecnc@ adjacent_transform = @\unspecnc@; // freestanding - inline constexpr auto @\libmember{pairwise_transform}{views}@ = adjacent_transform<2>; // freestanding + constexpr @\unspecnc@ adjacent_transform = @\unspecnc@; + inline constexpr auto @\libmember{pairwise_transform}{views}@ = adjacent_transform<2>; } // \ref{range.chunk}, chunk view template<@\libconcept{view}@ V> requires @\libconcept{input_range}@ - class chunk_view; // freestanding + class chunk_view; template<@\libconcept{view}@ V> requires @\libconcept{forward_range}@ - class chunk_view; // freestanding + class chunk_view; template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool @\libspec{enable_borrowed_range}{chunk_view}@> = @\libconcept{forward_range}@ && enable_borrowed_range; - namespace views { inline constexpr @\unspecnc@ chunk = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ chunk = @\unspecnc@; } // \ref{range.slide}, slide view template<@\libconcept{forward_range}@ V> requires @\libconcept{view}@ - class slide_view; // freestanding + class slide_view; template - inline constexpr bool enable_borrowed_range> = - enable_borrowed_range; // freestanding + constexpr bool @\libspec{enable_borrowed_range}{slide_view}@> = + enable_borrowed_range; - namespace views { inline constexpr @\unspecnc@ slide = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ slide = @\unspecnc@; } // \ref{range.chunk.by}, chunk by view template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@, iterator_t> Pred> requires @\libconcept{view}@ && is_object_v - class chunk_by_view; // freestanding + class chunk_by_view; - namespace views { inline constexpr @\unspecnc@ chunk_by = @\unspecnc@; } // freestanding + namespace views { inline constexpr @\unspecnc@ chunk_by = @\unspecnc@; } // \ref{range.stride}, stride view template<@\libconcept{input_range}@ V> @@ -514,7 +537,8 @@ class stride_view; template - inline constexpr bool enable_borrowed_range> = enable_borrowed_range; + constexpr bool @\libspec{enable_borrowed_range}{stride_view}@> = + enable_borrowed_range; namespace views { inline constexpr @\unspecnc@ stride = @\unspecnc@; } @@ -524,36 +548,54 @@ class cartesian_product_view; namespace views { inline constexpr @\unspecnc@ cartesian_product = @\unspecnc@; } + + // \ref{range.cache.latest}, cache latest view + template<@\libconcept{input_range}@ V> + requires @\libconcept{view}@ + class cache_latest_view; + + namespace views { inline constexpr @\unspec@ cache_latest = @\unspec@; } + + // \ref{range.to.input}, to input view + template<@\libconcept{input_range}@ V> + requires @\libconcept{view}@ + class to_input_view; + + template + constexpr bool enable_borrowed_range> = + enable_borrowed_range; + + namespace views { inline constexpr @\unspec@ to_input = @\unspec@; } } namespace std { - namespace views = ranges::views; // freestanding + namespace views = ranges::views; - template struct tuple_size; // freestanding - template struct tuple_element; // freestanding + template struct tuple_size; + template struct tuple_element; template - struct tuple_size> // freestanding + struct tuple_size> : integral_constant {}; template - struct tuple_element<0, ranges::subrange> { // freestanding - using type = I; // freestanding + struct tuple_element<0, ranges::subrange> { + using type = I; }; template - struct tuple_element<1, ranges::subrange> { // freestanding - using type = S; // freestanding + struct tuple_element<1, ranges::subrange> { + using type = S; }; template - struct tuple_element<0, const ranges::subrange> { // freestanding - using type = I; // freestanding + struct tuple_element<0, const ranges::subrange> { + using type = I; }; template - struct tuple_element<1, const ranges::subrange> { // freestanding - using type = S; // freestanding + struct tuple_element<1, const ranges::subrange> { + using type = S; }; - struct from_range_t { explicit from_range_t() = default; }; // freestanding - inline constexpr from_range_t from_range{}; // freestanding + struct from_range_t { explicit from_range_t() = default; }; + inline constexpr from_range_t from_range{}; } \end{codeblock} @@ -585,7 +627,7 @@ \pnum In addition to being available via inclusion of the \libheader{ranges} header, the customization point objects in \ref{range.access} are -available when \libheaderrefx{iterator}{iterator.synopsis} is included. +available when the header \libheaderrefx{iterator}{iterator.synopsis} is included. \pnum Within \ref{range.access}, @@ -637,15 +679,10 @@ \tcode{auto(begin(t))} is a valid expression whose type models \libconcept{input_or_output_iterator} - with overload resolution performed in a context in which - unqualified lookup for \tcode{begin} finds only the declarations -\begin{codeblock} -void begin(auto&) = delete; -void begin(const auto&) = delete; -\end{codeblock} + where the meaning of \tcode{begin} is established as-if by performing + argument-dependent lookup only\iref{basic.lookup.argdep}, then \tcode{ranges::begin(E)} is expression-equivalent to - \tcode{auto(begin(t))} - with overload resolution performed in the above context. + that expression. \item Otherwise, \tcode{ranges::begin(E)} is ill-formed. @@ -708,15 +745,10 @@ \tcode{auto(end(t))} is a valid expression whose type models \tcode{\libconcept{sentinel_for}>} - with overload resolution performed in a context in which - unqualified lookup for \tcode{end} finds only the declarations -\begin{codeblock} -void end(auto&) = delete; -void end(const auto&) = delete; -\end{codeblock} + where the meaning of \tcode{end} is established as-if by performing + argument-dependent lookup only\iref{basic.lookup.argdep}, then \tcode{ranges::end(E)} is expression-equivalent to - \tcode{auto(end(t))} - with overload resolution performed in the above context. + that expression. \item Otherwise, \tcode{ranges::end(E)} is ill-formed. @@ -830,15 +862,10 @@ \tcode{auto(rbegin(t))} is a valid expression whose type models \libconcept{input_or_output_iterator} - with overload resolution performed in a context in which - unqualified lookup for \tcode{rbegin} finds only the declarations -\begin{codeblock} -void rbegin(auto&) = delete; -void rbegin(const auto&) = delete; -\end{codeblock} + where the meaning of \tcode{rbegin} is established as-if by performing + argument-dependent lookup only\iref{basic.lookup.argdep}, then \tcode{ranges::rbegin(E)} is expression-equivalent to - \tcode{auto(rbegin(t))} - with overload resolution performed in the above context. + that expression. \item Otherwise, if both \tcode{ranges::begin(t)} and \tcode{ranges::end(t)} @@ -899,15 +926,10 @@ \tcode{auto(rend(t))} is a valid expression whose type models \tcode{\libconcept{sentinel_for}} - with overload resolution performed in a context in which - unqualified lookup for \tcode{rend} finds only the declarations -\begin{codeblock} -void rend(auto&) = delete; -void rend(const auto&) = delete; -\end{codeblock} + where the meaning of \tcode{rend} is established as-if by performing + argument-dependent lookup only\iref{basic.lookup.argdep}, then \tcode{ranges::rend(E)} is expression-equivalent to - \tcode{auto(rend(t))} - with overload resolution performed in the above context. + that expression. \item Otherwise, if both \tcode{ranges::begin(t)} and \tcode{ranges::end(t)} @@ -1029,15 +1051,10 @@ \tcode{disable_sized_range>} is \tcode{false} and \tcode{auto(size(t))} is a valid expression of integer-like type - with overload resolution performed in a context in which - unqualified lookup for \tcode{size} finds only the declarations -\begin{codeblock} -void size(auto&) = delete; -void size(const auto&) = delete; -\end{codeblock} + where the meaning of \tcode{size} is established as-if by performing + argument-dependent lookup only\iref{basic.lookup.argdep}, then \tcode{ranges::size(E)} is expression-equivalent to - \tcode{auto(size(t))} - with overload resolution performed in the above context. + that expression. \item Otherwise, if @@ -1085,6 +1102,50 @@ \tcode{ranges::ssize(E)} is expression-equivalent to \tcode{static_cast(ranges::size(t))}. +\rSec2[range.prim.size.hint]{\tcode{ranges::reserve_hint}} +\indexlibraryglobal{reserve_hint}% + +\pnum +The name \tcode{ranges::reserve_hint} denotes +a customization point object\iref{customization.point.object}. + +\pnum +Given a subexpression \tcode{E} with type \tcode{T}, +let \tcode{t} be an lvalue that denotes the reified object for \tcode{E}. +Then: +\begin{itemize} +\item +If \tcode{ranges::size(E)} is a valid expression, +\tcode{ranges::reserve_hint(E)} is expression-equivalent to +\tcode{ranges::size(E)}. +\item +Otherwise, +if \tcode{auto(t.reserve_hint())} is a valid expression of +integer-like type\iref{iterator.concept.winc}, +\tcode{ranges::re\-serve_hint(E)} is expression-equivalent to +\tcode{auto(t.reserve_hint())}. +\item +Otherwise, +if \tcode{T} is a class or enumeration type and +\tcode{auto(reserve_hint(t))} is a valid expression of +integer-like type where +the meaning of \tcode{reserve_hint} is established as-if by +performing argument-dependent lookup only\iref{basic.lookup.argdep}, then +\tcode{ranges::reserve_hint(E)} is expression-equivalent to that expression. +\item +Otherwise, +\tcode{ranges::reserve_hint(E)} is ill-formed. +\end{itemize} +\begin{note} +Diagnosable ill-formed cases above result in substitution failure when +\tcode{ranges::reserve_hint(E)} appears in the immediate context of +a template instantiation. +\end{note} +\begin{note} +Whenever \tcode{ranges::reserve_hint(E)} is a valid expression, +its type is integer-like. +\end{note} + \rSec2[range.prim.empty]{\tcode{ranges::empty}} \indexlibraryglobal{empty}% @@ -1194,7 +1255,7 @@ \begin{codeblock} template -constexpr auto @\exposid{as-const-pointer}@(const T* p) { return p; } // \expos +constexpr auto @\exposid{as-const-pointer}@(const T* p) noexcept { return p; } // \expos \end{codeblock} \pnum @@ -1275,14 +1336,6 @@ \end{itemdecl} \begin{itemdescr} -\pnum -The required expressions -\tcode{ranges::begin(t)} -and -\tcode{ranges::end(t)} -of the \libconcept{range} concept -do not require implicit expression variations\iref{concepts.equality}. - \pnum Given an expression \tcode{t} such that \tcode{decltype((t))} is \tcode{T\&}, \tcode{T} models \libconcept{range} only if @@ -1303,7 +1356,7 @@ \pnum \begin{note} Equality preservation of both \tcode{ranges::begin} and -\tcode{ranges::end} enables passing a \libconcept{range} whose iterator +\tcode{ranges::end} enables passing a range whose iterator type models \libconcept{forward_iterator} to multiple algorithms and making multiple passes over the range by repeated calls to \tcode{ranges::begin} and \tcode{ranges::end}. @@ -1341,7 +1394,7 @@ \indexlibraryglobal{enable_borrowed_range}% \begin{itemdecl} template - inline constexpr bool enable_borrowed_range = false; + constexpr bool enable_borrowed_range = false; \end{itemdecl} \begin{itemdescr} @@ -1370,17 +1423,58 @@ \end{example} \end{itemdescr} +\rSec2[range.approximately.sized]{Approximately sized ranges} + +\pnum +The \libconcept{approximately_sized_range} concept refines \libconcept{range} +with the requirement that +an approximation of the number of elements in the range +can be determined in amortized constant time using \tcode{ranges::reserve_hint}. + +\begin{itemdecl} +template + concept @\deflibconcept{approximately_sized_range}@ = + @\libconcept{range}@ && requires(T& t) { ranges::reserve_hint(t); }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Given an lvalue \tcode{t} of type \tcode{remove_reference_t}, +\tcode{T} models \libconcept{approximately_sized_range} only if +\begin{itemize} +\item +\tcode{ranges::reserve_hint(t)} is amortized \bigoh{1}, +does not modify \tcode{t}, and +has a value that +is not negative and is representable in \tcode{range_difference_t}, and +\item +if \tcode{iterator_t} models \libconcept{forward_iterator}, +\tcode{ranges::reserve_hint(t)} is well-defined +regardless of the evaluation of \tcode{ranges::begin(t)}. +\begin{note} +\tcode{ranges::reserve_hint(t)} is otherwise not required to be well-defined +after evaluating \tcode{ranges::\linebreak begin(t)}. +For example, +it is possible for \tcode{ranges::reserve_hint(t)} to be well-defined for +an \libconceptx{approximate\-ly_sized_range}{approximately_sized_range} whose +iterator type does not model \libconcept{forward_iterator} +only if evaluated before the first call to \tcode{ranges::begin(t)}. +\end{note} +\end{itemize} +\end{itemdescr} + \rSec2[range.sized]{Sized ranges} \pnum -The \libconcept{sized_range} concept refines \libconcept{range} with +The \libconcept{sized_range} concept +refines \libconcept{approximately_sized_range} with the requirement that the number of elements in the range can be determined in amortized constant time using \tcode{ranges::size}. \begin{itemdecl} template concept @\deflibconcept{sized_range}@ = - @\libconcept{range}@ && requires(T& t) { ranges::size(t); }; + @\libconcept{approximately_sized_range}@ && requires(T& t) { ranges::size(t); }; \end{itemdecl} \begin{itemdescr} @@ -1408,7 +1502,7 @@ \indexlibraryglobal{disable_sized_range}% \begin{itemdecl} template - inline constexpr bool disable_sized_range = false; + constexpr bool disable_sized_range = false; \end{itemdecl} \begin{itemdescr} @@ -1423,7 +1517,7 @@ \pnum \begin{note} -\tcode{disable_sized_range} allows use of range types with the library +\tcode{disable_sized_range} allows use of \libconcept{range} types with the library that satisfy but do not in fact model \libconcept{sized_range}. \end{note} \end{itemdescr} @@ -1444,7 +1538,7 @@ \begin{itemdescr} \pnum -\tcode{T} models \libconcept{view} only if: +\tcode{T} models \libconcept{view} only if \begin{itemize} \item \tcode{T} has \bigoh{1} move construction; and @@ -1476,7 +1570,7 @@ \pnum \begin{example} -Examples of \libconcept{view}s are: +Examples of views are: \begin{itemize} \item A \libconcept{range} type that wraps a pair of iterators. @@ -1500,9 +1594,9 @@ \indexlibraryglobal{enable_view}% \begin{itemdecl} template - inline constexpr bool @\exposidnc{is-derived-from-view-interface}@ = @\seebelownc@; // \expos + constexpr bool @\exposidnc{is-derived-from-view-interface}@ = @\seebelownc@; // \expos template - inline constexpr bool enable_view = + constexpr bool enable_view = @\libconcept{derived_from}@ || @\exposid{is-derived-from-view-interface}@; \end{itemdecl} @@ -1520,8 +1614,8 @@ \remarks Pursuant to \ref{namespace.std}, users may specialize \tcode{enable_view} to \tcode{true} -for cv-unqualified program-defined types which model \libconcept{view}, -and \tcode{false} for types which do not. +for cv-unqualified program-defined types that model \libconcept{view}, +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}. @@ -1594,7 +1688,7 @@ \begin{itemdecl} template - inline constexpr bool @\exposidnc{is-initializer-list}@ = @\seebelow@; // \expos + constexpr bool @\exposidnc{is-initializer-list}@ = @\seebelow@; // \expos \end{itemdecl} \begin{itemdescr} @@ -1606,7 +1700,7 @@ \pnum The \libconcept{viewable_range} concept specifies the requirements of a -\libconcept{range} type that can be converted to a \libconcept{view} safely. +\libconcept{range} type that can be converted to a view safely. \begin{itemdecl} template @@ -1638,7 +1732,7 @@ \rSec2[range.utility.helpers]{Helper concepts} \pnum -Many of the types in subclause~\ref{range.utility} are specified in terms of +Many of the types in \ref{range.utility} are specified in terms of the following exposition-only concepts: \begin{codeblock} @@ -1650,11 +1744,16 @@ template concept @\defexposconceptnc{has-arrow}@ = // \expos - @\libconcept{input_iterator}@ && (is_pointer_v || requires(I i) { i.operator->(); }); + @\libconcept{input_iterator}@ && (is_pointer_v || requires(const I i) { i.operator->(); }); template concept @\defexposconceptnc{different-from}@ = // \expos !@\libconcept{same_as}@, remove_cvref_t>; + +template + concept @\defexposconceptnc{range-with-movable-references}@ = // \expos + @\libconcept{input_range}@ && @\libconcept{move_constructible}@> && + @\libconcept{move_constructible}@>; \end{codeblock} \rSec2[view.interface]{View interface} @@ -1663,7 +1762,7 @@ \pnum The class template \tcode{view_interface} is a helper for defining -\libconcept{view}-like types that offer a container-like interface. It is +view-like types that offer a container-like interface. It is parameterized with the type that is derived from it. \indexlibraryglobal{view_interface}% @@ -1694,17 +1793,17 @@ return ranges::begin(@\exposid{derived}@()) == ranges::end(@\exposid{derived}@()); } - constexpr auto cbegin() { - return ranges::cbegin(@\exposid{derived}@()); + constexpr auto cbegin() requires @\libconcept{input_range}@ { + return ranges::cbegin(@\exposid{derived}@()); } - constexpr auto cbegin() const requires @\libconcept{range}@ { - return ranges::cbegin(@\exposid{derived}@()); + constexpr auto cbegin() const requires @\libconcept{input_range}@ { + return ranges::cbegin(@\exposid{derived}@()); } - constexpr auto cend() { - return ranges::cend(@\exposid{derived}@()); + constexpr auto cend() requires @\libconcept{input_range}@ { + return ranges::cend(@\exposid{derived}@()); } - constexpr auto cend() const requires @\libconcept{range}@ { - return ranges::cend(@\exposid{derived}@()); + constexpr auto cend() const requires @\libconcept{input_range}@ { + return ranges::cend(@\exposid{derived}@()); } constexpr explicit operator bool() @@ -1726,11 +1825,11 @@ constexpr auto size() requires @\libconcept{forward_range}@ && @\libconcept{sized_sentinel_for}@, iterator_t> { - return ranges::end(@\exposid{derived}@()) - ranges::begin(@\exposid{derived}@()); + return @\exposid{to-unsigned-like}@(ranges::end(@\exposid{derived}@()) - ranges::begin(@\exposid{derived}@())); } constexpr auto size() const requires @\libconcept{forward_range}@ && @\libconcept{sized_sentinel_for}@, iterator_t> { - return ranges::end(@\exposid{derived}@()) - ranges::begin(@\exposid{derived}@()); + return @\exposid{to-unsigned-like}@(ranges::end(@\exposid{derived}@()) - ranges::begin(@\exposid{derived}@())); } constexpr decltype(auto) front() requires @\libconcept{forward_range}@; @@ -1835,7 +1934,7 @@ I @\exposid{begin_}@ = I(); // \expos S @\exposid{end_}@ = S(); // \expos @\exposidnc{make-unsigned-like-t}@> @\exposid{size_}@ = 0; // \expos; present only - // when \exposid{StoreSize} is \tcode{true} + // if \exposid{StoreSize} is \tcode{true} public: subrange() requires @\libconcept{default_initializable}@ = default; @@ -1863,17 +1962,17 @@ constexpr operator PairLike() const; constexpr I begin() const requires @\libconcept{copyable}@; - [[nodiscard]] constexpr I begin() requires (!@\libconcept{copyable}@); + constexpr I begin() requires (!@\libconcept{copyable}@); constexpr S end() const; constexpr bool empty() const; constexpr @\placeholdernc{make-unsigned-like-t}@> size() const requires (K == subrange_kind::sized); - [[nodiscard]] constexpr subrange next(iter_difference_t n = 1) const & + constexpr subrange next(iter_difference_t n = 1) const & requires @\libconcept{forward_iterator}@; - [[nodiscard]] constexpr subrange next(iter_difference_t n = 1) &&; - [[nodiscard]] constexpr subrange prev(iter_difference_t n = 1) const + constexpr subrange next(iter_difference_t n = 1) &&; + constexpr subrange prev(iter_difference_t n = 1) const requires @\libconcept{bidirectional_iterator}@; constexpr subrange& advance(iter_difference_t n); }; @@ -1992,7 +2091,7 @@ \indexlibrarymember{begin}{subrange}% \begin{itemdecl} -[[nodiscard]] constexpr I begin() requires (!@\libconcept{copyable}@); +constexpr I begin() requires (!@\libconcept{copyable}@); \end{itemdecl} \begin{itemdescr} @@ -2040,7 +2139,7 @@ \indexlibrarymember{next}{subrange}% \begin{itemdecl} -[[nodiscard]] constexpr subrange next(iter_difference_t n = 1) const & +constexpr subrange next(iter_difference_t n = 1) const & requires @\libconcept{forward_iterator}@; \end{itemdecl} @@ -2057,7 +2156,7 @@ \indexlibrarymember{next}{subrange}% \begin{itemdecl} -[[nodiscard]] constexpr subrange next(iter_difference_t n = 1) &&; +constexpr subrange next(iter_difference_t n = 1) &&; \end{itemdecl} \begin{itemdescr} @@ -2072,7 +2171,7 @@ \indexlibrarymember{prev}{subrange}% \begin{itemdecl} -[[nodiscard]] constexpr subrange prev(iter_difference_t n = 1) const +constexpr subrange prev(iter_difference_t n = 1) const requires @\libconcept{bidirectional_iterator}@; \end{itemdecl} @@ -2138,7 +2237,7 @@ \rSec2[range.dangling]{Dangling iterator handling} \pnum -The tag type \tcode{dangling} is used together with the template aliases +The type \tcode{dangling} is used together with the template aliases \tcode{borrowed_iterator_t} and \tcode{borrowed_subrange_t}. When an algorithm that typically returns an iterator into, or a subrange of, a range argument @@ -2146,7 +2245,7 @@ that does not model \libconcept{borrowed_range}\iref{range.range}, the return value possibly refers to a range whose lifetime has ended. In such cases, -the tag type \tcode{dangling} is returned instead of an iterator or subrange. +the type \tcode{dangling} is returned instead of an iterator or subrange. \indexlibraryglobal{dangling}% \begin{codeblock} namespace std::ranges { @@ -2191,7 +2290,7 @@ denote \tcode{dangling}. \end{itemize} -\rSec2[ranges.elementsof]{Class template \tcode{elements_of}} +\rSec2[range.elementsof]{Class template \tcode{elements_of}} Specializations of \tcode{elements_of} encapsulate a range and act as a tag in overload sets to disambiguate @@ -2261,25 +2360,33 @@ \end{codeblock} \pnum -Let \exposid{container-insertable} be defined as follows: +Let \exposid{container-appendable} be defined as follows: \begin{codeblock} template -constexpr bool @\exposid{container-insertable}@ = // \expos +constexpr bool @\exposid{container-appendable}@ = // \expos requires(Container& c, Ref&& ref) { - requires (requires { c.push_back(std::forward(ref)); } || + requires (requires { c.emplace_back(std::forward(ref)); } || + requires { c.push_back(std::forward(ref)); } || + requires { c.emplace(c.end(), std::forward(ref)); } || requires { c.insert(c.end(), std::forward(ref)); }); }; \end{codeblock} \pnum -Let \exposid{container-inserter} be defined as follows: +Let \exposid{container-append} be defined as follows: \begin{codeblock} -template -constexpr auto @\exposid{container-inserter}@(Container& c) { // \expos - if constexpr (requires { c.push_back(declval()); }) - return back_inserter(c); - else - return inserter(c, c.end()); +template +constexpr auto @\exposid{container-append}@(Container& c) { // \expos + return [&c](Ref&& ref) { + if constexpr (requires { c.emplace_back(declval()); }) + c.emplace_back(std::forward(ref)); + else if constexpr (requires { c.push_back(declval()); }) + c.push_back(std::forward(ref)); + else if constexpr (requires { c.emplace(c.end(), declval()); }) + c.emplace(c.end(), std::forward(ref)); + else + c.insert(c.end(), std::forward(ref)); + }; } \end{codeblock} @@ -2292,13 +2399,18 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{C} is a cv-unqualified class type. + \pnum \returns An object of type \tcode{C} constructed from the elements of \tcode{r} in the following manner: \begin{itemize} \item -If \tcode{\libconcept{convertible_to}, range_value_t>} +If \tcode{C} does not satisfy \libconcept{input_range} or +\tcode{\libconcept{convertible_to}, range_value_t>} is \tcode{true}: \begin{itemize} \item @@ -2319,7 +2431,10 @@ \item \tcode{\libconcept{common_range}} is \tcode{true}, \item -\tcode{\exposconcept{cpp17-input-iterator}>} is \tcode{true}, and +the \grammarterm{qualified-id} +\tcode{iterator_traits>::iterator_category} +is valid and denotes a type that models +\tcode{\libconcept{derived_from}}, and \item \tcode{\libconcept{constructible_from}, sentinel_t, Args...>} is \tcode{true}: @@ -2333,21 +2448,23 @@ \item \tcode{\libconcept{constructible_from}} is \tcode{true}, and \item -\tcode{\exposid{container-insertable}>} is \tcode{true}: +\tcode{\exposid{container-appendable}>} is \tcode{true}: \end{itemize} \begin{codeblock} C c(std::forward(args)...); -if constexpr (@\libconcept{sized_range}@ && @\exposid{reservable-container}@) - c.reserve(ranges::size(r)); -ranges::copy(r, @\exposid{container-inserter}@>(c)); +if constexpr (@\libconcept{approximately_sized_range}@ && @\exposid{reservable-container}@) + c.reserve(static_cast>(ranges::reserve_hint(r))); +ranges::for_each(r, @\exposid{container-append}@(c)); \end{codeblock} +\item +Otherwise, the program is ill-formed. \end{itemize} \item Otherwise, if \tcode{\libconcept{input_range}>} is \tcode{true}: \begin{codeblock} -to(r | views::transform([](auto&& elem) { +to(ref_view(r) | views::transform([](auto&& elem) { return to>(std::forward(elem)); }), std::forward(args)...); \end{codeblock} @@ -2419,6 +2536,11 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +For the first overload, +\tcode{C} is a cv-unqualified class type. + \pnum \returns A range adaptor closure object\iref{range.adaptor.object} \tcode{f} @@ -2444,7 +2566,7 @@ \pnum Subclause \ref{range.factories} defines \term{range factories}, -which are utilities to create a \libconcept{view}. +which are utilities to create a view. \pnum Range factories are declared in namespace \tcode{std::ranges::views}. @@ -2454,7 +2576,7 @@ \rSec3[range.empty.overview]{Overview} \pnum -\tcode{empty_view} produces a \libconcept{view} of no elements of +\tcode{empty_view} produces a view of no elements of a particular type. \pnum @@ -2489,7 +2611,7 @@ \rSec3[range.single.overview]{Overview} \pnum -\tcode{single_view} produces a \libconcept{view} that contains +\tcode{single_view} produces a view that contains exactly one element of a specified value. \pnum @@ -2531,6 +2653,7 @@ constexpr const T* begin() const noexcept; constexpr T* end() noexcept; constexpr const T* end() const noexcept; + static constexpr bool empty() noexcept; static constexpr size_t size() noexcept; constexpr T* data() noexcept; constexpr const T* data() const noexcept; @@ -2543,7 +2666,7 @@ \indexlibraryctor{single_view}% \begin{itemdecl} -constexpr explicit single_view(const T& t) requires @\libconcept{copy_constructible}@;; +constexpr explicit single_view(const T& t) requires @\libconcept{copy_constructible}@; \end{itemdecl} \begin{itemdescr} @@ -2601,6 +2724,17 @@ Equivalent to: \tcode{return data() + 1;} \end{itemdescr} +\indexlibrarymember{empty}{single_view}% +\begin{itemdecl} +static constexpr bool empty() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return false;} +\end{itemdescr} + \indexlibrarymember{size}{single_view}% \begin{itemdecl} static constexpr size_t size() noexcept; @@ -2639,7 +2773,8 @@ Given subexpressions \tcode{E} and \tcode{F}, the expressions \tcode{views::iota(E)} and \tcode{views::iota(E, F)} are expression-equivalent to -\tcode{iota_view(E)} and \tcode{iota_view(E, F)}, respectively. +\tcode{iota_view>(E)} and \tcode{iota_view(E, F)}, +respectively. \pnum \begin{example} @@ -2676,13 +2811,14 @@ public: iota_view() requires @\libconcept{default_initializable}@ = default; constexpr explicit iota_view(W value); - constexpr iota_view(type_identity_t value, type_identity_t bound); - constexpr iota_view(@\exposid{iterator}@ first, @\seebelow@ last); + constexpr explicit iota_view(type_identity_t value, type_identity_t bound); + constexpr explicit iota_view(@\exposid{iterator}@ first, @\seebelow@ last); constexpr @\exposid{iterator}@ begin() const; constexpr auto end() const; constexpr @\exposid{iterator}@ end() const requires @\libconcept{same_as}@; + constexpr bool empty() const; constexpr auto size() const requires @\seebelow@; }; @@ -2800,6 +2936,8 @@ \expects \tcode{Bound} denotes \tcode{unreachable_sentinel_t} or \tcode{Bound()} is reachable from \tcode{value}. +When \tcode{W} and \tcode{Bound} model \libconcept{totally_ordered_with}, +then \tcode{bool(value <= Bound())} is \tcode{true}. \pnum \effects @@ -2808,7 +2946,7 @@ \indexlibraryctor{iota_view}% \begin{itemdecl} -constexpr iota_view(type_identity_t value, type_identity_t bound); +constexpr explicit iota_view(type_identity_t value, type_identity_t bound); \end{itemdecl} \begin{itemdescr} @@ -2827,7 +2965,7 @@ \indexlibraryctor{iota_view}% \begin{itemdecl} -constexpr iota_view(@\exposid{iterator}@ first, @\seebelow@ last); +constexpr explicit iota_view(@\exposid{iterator}@ first, @\seebelow@ last); \end{itemdecl} \begin{itemdescr} @@ -2898,6 +3036,17 @@ Equivalent to: \tcode{return \exposid{iterator}\{\exposid{bound_}\};} \end{itemdescr} +\indexlibrarymember{empty}{iota_view}% +\begin{itemdecl} +constexpr bool empty() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{value_} == \exposid{bound_};} +\end{itemdescr} + \indexlibrarymember{size}{iota_view}% \begin{itemdecl} constexpr auto size() const requires @\seebelow@; @@ -2929,7 +3078,7 @@ \rSec3[range.iota.iterator]{Class \tcode{iota_view::\exposid{iterator}}} -\indexlibraryglobal{iota_view::iterator}% +\indexlibraryglobal{iota_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{weakly_incrementable}@ W, @\libconcept{semiregular}@ Bound> @@ -2937,6 +3086,7 @@ struct iota_view::@\exposid{iterator}@ { private: W @\exposid{value_}@ = W(); // \expos + public: using iterator_concept = @\seebelow@; using iterator_category = input_iterator_tag; // present only if \tcode{W} models \libconcept{incrementable} and @@ -3007,7 +3157,7 @@ Overloads for \tcode{iter_move} and \tcode{iter_swap} are omitted intentionally. \end{note} -\indexlibraryctor{iota_view::iterator} +\indexlibraryctor{iota_view::\exposid{iterator}} \begin{itemdecl} constexpr explicit @\exposid{iterator}@(W value); \end{itemdecl} @@ -3018,7 +3168,7 @@ Initializes \exposid{value_} with \tcode{value}. \end{itemdescr} -\indexlibrarymember{operator*}{iota_view::iterator} +\indexlibrarymember{operator*}{iota_view::\exposid{iterator}} \begin{itemdecl} constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v); \end{itemdecl} @@ -3035,7 +3185,7 @@ \end{note} \end{itemdescr} -\indexlibrarymember{operator++}{iota_view::iterator} +\indexlibrarymember{operator++}{iota_view::\exposid{iterator}} \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -3050,7 +3200,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{iota_view::iterator} +\indexlibrarymember{operator++}{iota_view::\exposid{iterator}} \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -3061,7 +3211,7 @@ Equivalent to \tcode{++*this}. \end{itemdescr} -\indexlibrarymember{operator++}{iota_view::iterator} +\indexlibrarymember{operator++}{iota_view::\exposid{iterator}} \begin{itemdecl} constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{incrementable}@; \end{itemdecl} @@ -3077,7 +3227,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{iota_view::iterator} +\indexlibrarymember{operator--}{iota_view::\exposid{iterator}} \begin{itemdecl} constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{decrementable}@; \end{itemdecl} @@ -3092,7 +3242,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{iota_view::iterator} +\indexlibrarymember{operator--}{iota_view::\exposid{iterator}} \begin{itemdecl} constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{decrementable}@; \end{itemdecl} @@ -3108,7 +3258,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+=}{iota_view::iterator} +\indexlibrarymember{operator+=}{iota_view::\exposid{iterator}} \begin{itemdecl} constexpr @\exposid{iterator}@& operator+=(difference_type n) requires @\exposconcept{advanceable}@; @@ -3131,7 +3281,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-=}{iota_view::iterator} +\indexlibrarymember{operator-=}{iota_view::\exposid{iterator}} \begin{itemdecl} constexpr @\exposid{iterator}@& operator-=(difference_type n) requires @\exposconcept{advanceable}@; @@ -3154,7 +3304,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator[]}{iota_view::iterator} +\indexlibrarymember{operator[]}{iota_view::\exposid{iterator}} \begin{itemdecl} constexpr W operator[](difference_type n) const requires @\exposconcept{advanceable}@; @@ -3166,7 +3316,7 @@ Equivalent to: \tcode{return W(\exposid{value_} + n);} \end{itemdescr} -\indexlibrarymember{operator==}{iota_view::iterator} +\indexlibrarymember{operator==}{iota_view::\exposid{iterator}} \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{equality_comparable}@; @@ -3178,7 +3328,7 @@ Equivalent to: \tcode{return x.\exposid{value_} == y.\exposid{value_};} \end{itemdescr} -\indexlibrarymember{operator<}{iota_view::iterator} +\indexlibrarymember{operator<}{iota_view::\exposid{iterator}} \begin{itemdecl} friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{totally_ordered}@; @@ -3190,7 +3340,7 @@ Equivalent to: \tcode{return x.\exposid{value_} < y.\exposid{value_};} \end{itemdescr} -\indexlibrarymember{operator>}{iota_view::iterator} +\indexlibrarymember{operator>}{iota_view::\exposid{iterator}} \begin{itemdecl} friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{totally_ordered}@; @@ -3202,7 +3352,7 @@ Equivalent to: \tcode{return y < x;} \end{itemdescr} -\indexlibrarymember{operator<=}{iota_view::iterator} +\indexlibrarymember{operator<=}{iota_view::\exposid{iterator}} \begin{itemdecl} friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{totally_ordered}@; @@ -3214,7 +3364,7 @@ Equivalent to: \tcode{return !(y < x);} \end{itemdescr} -\indexlibrarymember{operator>=}{iota_view::iterator} +\indexlibrarymember{operator>=}{iota_view::\exposid{iterator}} \begin{itemdecl} friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{totally_ordered}@; @@ -3226,7 +3376,7 @@ Equivalent to: \tcode{return !(x < y);} \end{itemdescr} -\indexlibrarymember{operator<=>}{iota_view::iterator} +\indexlibrarymember{operator<=>}{iota_view::\exposid{iterator}} \begin{itemdecl} friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{totally_ordered}@ && @\libconcept{three_way_comparable}@; @@ -3238,7 +3388,7 @@ Equivalent to: \tcode{return x.\exposid{value_} <=> y.\exposid{value_};} \end{itemdescr} -\indexlibrarymember{operator+}{iota_view::iterator} +\indexlibrarymember{operator+}{iota_view::\exposid{iterator}} \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator+(@\exposid{iterator}@ i, difference_type n) requires @\exposconcept{advanceable}@; @@ -3254,7 +3404,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+}{iota_view::iterator} +\indexlibrarymember{operator+}{iota_view::\exposid{iterator}} \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator+(difference_type n, @\exposid{iterator}@ i) requires @\exposconcept{advanceable}@; @@ -3266,7 +3416,7 @@ Equivalent to: \tcode{return i + n;} \end{itemdescr} -\indexlibrarymember{operator-}{iota_view::iterator} +\indexlibrarymember{operator-}{iota_view::\exposid{iterator}} \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator-(@\exposid{iterator}@ i, difference_type n) requires @\exposconcept{advanceable}@; @@ -3282,7 +3432,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-}{iota_view::iterator} +\indexlibrarymember{operator-}{iota_view::\exposid{iterator}} \begin{itemdecl} friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\exposconcept{advanceable}@; @@ -3309,7 +3459,7 @@ \rSec3[range.iota.sentinel]{Class \tcode{iota_view::\exposid{sentinel}}} -\indexlibraryglobal{iota_view::sentinel}% +\indexlibraryglobal{iota_view::\exposid{sentinel}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{weakly_incrementable}@ W, @\libconcept{semiregular}@ Bound> @@ -3317,6 +3467,7 @@ struct iota_view::@\exposid{sentinel}@ { private: Bound @\exposid{bound_}@ = Bound(); // \expos + public: @\exposid{sentinel}@() = default; constexpr explicit @\exposid{sentinel}@(Bound bound); @@ -3331,7 +3482,7 @@ } \end{codeblock} -\indexlibraryctor{iota_view::sentinel} +\indexlibraryctor{iota_view::\exposid{sentinel}} \begin{itemdecl} constexpr explicit @\exposid{sentinel}@(Bound bound); \end{itemdecl} @@ -3342,7 +3493,7 @@ Initializes \exposid{bound_} with \tcode{bound}. \end{itemdescr} -\indexlibrarymember{operator==}{iota_view::sentinel} +\indexlibrarymember{operator==}{iota_view::\exposid{sentinel}} \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} @@ -3390,7 +3541,7 @@ Given subexpressions \tcode{E} and \tcode{F}, the expressions \tcode{views::repeat(E)} and \tcode{views::repeat(E, F)} are expression-equivalent to -\tcode{repeat_view(E)} and \tcode{repeat_view(E, F)}, respectively. +\tcode{repeat_view>(E)} and \tcode{repeat_view(E, F)}, respectively. \pnum \begin{example} @@ -3405,28 +3556,33 @@ \begin{codeblock} namespace std::ranges { - template<@\libconcept{move_constructible}@ W, @\libconcept{semiregular}@ Bound = unreachable_sentinel_t> - requires (is_object_v && @\libconcept{same_as}@> && - (@\exposid{is-integer-like}@ || @\libconcept{same_as}@)) - class @\libglobal{repeat_view}@ : public view_interface> { + template + concept @\defexposconceptnc{integer-like-with-usable-difference-type}@ = // \expos + @\exposid{is-signed-integer-like}@ || (@\exposid{is-integer-like}@ && @\libconcept{weakly_incrementable}@); + + template<@\libconcept{move_constructible}@ T, @\libconcept{semiregular}@ Bound = unreachable_sentinel_t> + requires (is_object_v && @\libconcept{same_as}@> && + (@\exposconcept{integer-like-with-usable-difference-type}@ || + @\libconcept{same_as}@)) + class @\libglobal{repeat_view}@ : public view_interface> { private: // \ref{range.repeat.iterator}, class \tcode{repeat_view::\exposid{iterator}} struct @\exposidnc{iterator}@; // \expos - @\exposidnc{movable-box}@ @\exposid{value_}@ = W(); // \expos, see \ref{range.move.wrap} + @\exposidnc{movable-box}@ @\exposid{value_}@; // \expos, see \ref{range.move.wrap} Bound @\exposid{bound_}@ = Bound(); // \expos public: - repeat_view() requires @\libconcept{default_initializable}@ = default; + repeat_view() requires @\libconcept{default_initializable}@ = default; - constexpr explicit repeat_view(const W& value, Bound bound = Bound()) - requires @\libconcept{copy_constructible}@; - constexpr explicit repeat_view(W&& value, Bound bound = Bound()); - template - requires @\libconcept{constructible_from}@ && + constexpr explicit repeat_view(const T& value, Bound bound = Bound()) + requires @\libconcept{copy_constructible}@; + constexpr explicit repeat_view(T&& value, Bound bound = Bound()); + template + requires @\libconcept{constructible_from}@ && @\libconcept{constructible_from}@ constexpr explicit repeat_view(piecewise_construct_t, - tuple value_args, tuple bound_args = tuple<>{}); + tuple value_args, tuple bound_args = tuple<>{}); constexpr @\exposid{iterator}@ begin() const; constexpr @\exposid{iterator}@ end() const requires (!@\libconcept{same_as}@); @@ -3435,15 +3591,15 @@ constexpr auto size() const requires (!@\libconcept{same_as}@); }; - template - repeat_view(W, Bound) -> repeat_view; + template + repeat_view(T, Bound = Bound()) -> repeat_view; } \end{codeblock} \indexlibraryctor{repeat_view}% \begin{itemdecl} -constexpr explicit repeat_view(const W& value, Bound bound = Bound()) - requires @\libconcept{copy_constructible}@; +constexpr explicit repeat_view(const T& value, Bound bound = Bound()) + requires @\libconcept{copy_constructible}@; \end{itemdecl} \begin{itemdescr} @@ -3460,7 +3616,7 @@ \indexlibraryctor{repeat_view}% \begin{itemdecl} -constexpr explicit repeat_view(W&& value, Bound bound = Bound()); +constexpr explicit repeat_view(T&& value, Bound bound = Bound()); \end{itemdecl} \begin{itemdescr} @@ -3476,22 +3632,24 @@ \indexlibraryctor{repeat_view}% \begin{itemdecl} -template - requires @\libconcept{constructible_from}@ && +template + requires @\libconcept{constructible_from}@ && @\libconcept{constructible_from}@ constexpr explicit repeat_view(piecewise_construct_t, - tuple value_args, tuple bound_args = tuple<>{}); + tuple value_args, tuple bound_args = tuple<>{}); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{value_} with arguments of types \tcode{WArgs...} -obtained by forwarding the elements of \tcode{value_args} and -initializes \exposid{bound_} with arguments of types \tcode{BoundArgs...} -obtained by forwarding the elements of \tcode{bound_args}. -(Here, forwarding an element \tcode{x} of type \tcode{U} within a tuple object -means calling \tcode{std::forward(x)}.) +Initializes \exposid{value_} with +\tcode{make_from_tuple(std::move(value_args))} +and +initializes\linebreak{} \exposid{bound_} with +\tcode{make_from_tuple(std::move(bound_args))}. +The behavior is undefined if +\tcode{Bound} is not \tcode{unreachable_sentinel_t} and +\exposid{bound_} is negative. \end{itemdescr} \indexlibrarymember{begin}{repeat_view}% @@ -3540,31 +3698,31 @@ \rSec3[range.repeat.iterator]{Class \tcode{repeat_view::\exposid{iterator}}} +\indexlibraryglobal{repeat_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{move_constructible}@ W, @\libconcept{semiregular}@ Bound = unreachable_sentinel_t> - requires (is_object_v && @\libconcept{same_as}@> && - (@\exposid{is-integer-like}@ || @\libconcept{same_as}@)) - class repeat_view::@\exposid{iterator}@ { + template<@\libconcept{move_constructible}@ T, @\libconcept{semiregular}@ Bound> + requires (is_object_v && @\libconcept{same_as}@> && + (@\exposconcept{integer-like-with-usable-difference-type}@ || + @\libconcept{same_as}@)) + class repeat_view::@\exposid{iterator}@ { private: using @\exposidnc{index-type}@ = // \expos conditional_t<@\libconcept{same_as}@, ptrdiff_t, Bound>; - const W* @\exposidnc{value_}@ = nullptr; // \expos + const T* @\exposidnc{value_}@ = nullptr; // \expos @\exposidnc{index-type}@ @\exposidnc{current_}@ = @\exposidnc{index-type}@(); // \expos - constexpr explicit @\exposid{iterator}@(const W* value, @\exposid{index-type}@ b = @\exposidnc{index-type}@()); // \expos + constexpr explicit @\exposid{iterator}@(const T* value, @\exposid{index-type}@ b = @\exposidnc{index-type}@()); // \expos public: using iterator_concept = random_access_iterator_tag; using iterator_category = random_access_iterator_tag; - using value_type = W; - using difference_type = conditional_t<@\exposid{is-signed-integer-like}@<@\exposid{index-type}@>, - @\exposid{index-type}@, - @\placeholdernc{IOTA-DIFF-T}@(@\exposid{index-type}@)>; + using value_type = T; + using difference_type = @\seebelow@; @\exposid{iterator}@() = default; - constexpr const W& operator*() const noexcept; + constexpr const T& operator*() const noexcept; constexpr @\exposid{iterator}@& operator++(); constexpr @\exposid{iterator}@ operator++(int); @@ -3574,7 +3732,7 @@ constexpr @\exposid{iterator}@& operator+=(difference_type n); constexpr @\exposid{iterator}@& operator-=(difference_type n); - constexpr const W& operator[](difference_type n) const noexcept; + constexpr const T& operator[](difference_type n) const noexcept; friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); @@ -3588,9 +3746,15 @@ } \end{codeblock} -\indexlibraryctor{repeat_view::iterator}% +\pnum +If \tcode{\exposid{is-signed-integer-like}<\exposid{index-type}>} is \tcode{true}, +the member \grammarterm{typedef-name} \tcode{difference_type} +denotes \exposid{index-type}. +Otherwise, it denotes \tcode{\placeholdernc{IOTA-DIFF-T}(\exposid{index-type})}\iref{range.iota.view}. + +\indexlibraryctor{repeat_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit @\exposid{iterator}@(const W* value, @\exposid{index-type}@ b = @\exposid{index-type}@()); +constexpr explicit @\exposid{iterator}@(const T* value, @\exposid{index-type}@ b = @\exposid{index-type}@()); \end{itemdecl} \begin{itemdescr} @@ -3604,9 +3768,9 @@ \exposid{current_} with \tcode{b}. \end{itemdescr} -\indexlibrarymember{operator*}{repeat_view::iterator}% +\indexlibrarymember{operator*}{repeat_view::\exposid{iterator}}% \begin{itemdecl} -constexpr const W& operator*() const noexcept; +constexpr const T& operator*() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3615,7 +3779,7 @@ Equivalent to: \tcode{return *\exposid{value_};} \end{itemdescr} -\indexlibrarymember{operator++}{repeat_view::iterator}% +\indexlibrarymember{operator++}{repeat_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -3630,7 +3794,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{repeat_view::iterator}% +\indexlibrarymember{operator++}{repeat_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} @@ -3646,7 +3810,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{repeat_view::iterator}% +\indexlibrarymember{operator--}{repeat_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator--(); \end{itemdecl} @@ -3666,7 +3830,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{repeat_view::iterator}% +\indexlibrarymember{operator--}{repeat_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator--(int); \end{itemdecl} @@ -3682,7 +3846,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+=}{repeat_view::iterator}% +\indexlibrarymember{operator+=}{repeat_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator+=(difference_type n); \end{itemdecl} @@ -3702,7 +3866,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-=}{repeat_view::iterator}% +\indexlibrarymember{operator-=}{repeat_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator-=(difference_type n); \end{itemdecl} @@ -3722,9 +3886,9 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator[]}{repeat_view::iterator}% +\indexlibrarymember{operator[]}{repeat_view::\exposid{iterator}}% \begin{itemdecl} -constexpr const W& operator[](difference_type n) const noexcept; +constexpr const T& operator[](difference_type n) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3733,7 +3897,7 @@ Equivalent to: \tcode{return *(*this + n);} \end{itemdescr} -\indexlibrarymember{operator==}{repeat_view::iterator}% +\indexlibrarymember{operator==}{repeat_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \end{itemdecl} @@ -3741,10 +3905,10 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};}. +Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};} \end{itemdescr} -\indexlibrarymember{operator<=>}{repeat_view::iterator}% +\indexlibrarymember{operator<=>}{repeat_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \end{itemdecl} @@ -3752,10 +3916,10 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};}. +Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};} \end{itemdescr} -\indexlibrarymember{operator+}{repeat_view::iterator}% +\indexlibrarymember{operator+}{repeat_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator+(@\exposid{iterator}@ i, difference_type n); friend constexpr @\exposid{iterator}@ operator+(difference_type n, @\exposid{iterator}@ i); @@ -3771,7 +3935,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-}{repeat_view::iterator}% +\indexlibrarymember{operator-}{repeat_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator-(@\exposid{iterator}@ i, difference_type n); \end{itemdecl} @@ -3786,7 +3950,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-}{repeat_view::iterator}% +\indexlibrarymember{operator-}{repeat_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \end{itemdecl} @@ -3838,7 +4002,7 @@ template concept @\defexposconceptnc{stream-extractable}@ = // \expos requires(basic_istream& is, Val& t) { - is >> t; + is >> t; }; template<@\libconcept{movable}@ Val, class CharT, class Traits = char_traits> @@ -3888,7 +4052,7 @@ \rSec3[range.istream.iterator]{Class \tcode{basic_istream_view::\exposid{iterator}}} -\indexlibraryglobal{basic_istream_view::iterator}% +\indexlibraryglobal{basic_istream_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{movable}@ Val, class CharT, class Traits> @@ -3921,7 +4085,7 @@ } \end{codeblock} -\indexlibraryctor{basic_istream_view::iterator}% +\indexlibraryctor{basic_istream_view::\exposid{iterator}}% \begin{itemdecl} constexpr explicit @\exposid{iterator}@(basic_istream_view& parent) noexcept; \end{itemdecl} @@ -3932,7 +4096,7 @@ Initializes \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} -\indexlibrarymember{operator++}{basic_istream_view::iterator}% +\indexlibrarymember{operator++}{basic_istream_view::\exposid{iterator}}% \begin{itemdecl} @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -3947,7 +4111,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{basic_istream_view::iterator}% +\indexlibrarymember{operator++}{basic_istream_view::\exposid{iterator}}% \begin{itemdecl} void operator++(int); \end{itemdecl} @@ -3958,7 +4122,7 @@ Equivalent to \tcode{++*this}. \end{itemdescr} -\indexlibrarymember{operator*}{basic_istream_view::iterator}% +\indexlibrarymember{operator*}{basic_istream_view::\exposid{iterator}}% \begin{itemdecl} Val& operator*() const; \end{itemdecl} @@ -3969,7 +4133,7 @@ Equivalent to: \tcode{return \exposid{parent_}->\exposid{value_};} \end{itemdescr} -\indexlibrarymember{operator==}{basic_istream_view::iterator}% +\indexlibrarymember{operator==}{basic_istream_view::\exposid{iterator}}% \begin{itemdecl} friend bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); \end{itemdecl} @@ -3986,7 +4150,7 @@ \pnum Subclause \ref{range.adaptors} defines \term{range adaptors}, which are utilities that transform a -\libconcept{range} into a \libconcept{view} with custom behaviors. These +range into a view with custom behaviors. These adaptors can be chained to create pipelines of range transformations that evaluate lazily as the resulting view is iterated. @@ -4015,7 +4179,7 @@ \pnum A \term{range adaptor closure object} is a unary function object that accepts -a \libconcept{range} argument. For +a range argument. For a range adaptor closure object \tcode{C} and an expression \tcode{R} such that \tcode{decltype((R))} models \libconcept{range}, the following expressions are equivalent: @@ -4048,7 +4212,7 @@ Given an object \tcode{t} of type \tcode{T}, where \begin{itemize} \item -\tcode{t} is a unary function object that accepts a \libconcept{range} argument, +\tcode{t} is a unary function object that accepts a range argument, \item \tcode{T} models \tcode{\libconcept{derived_from}>}, \item @@ -4083,8 +4247,7 @@ \pnum A \term{range adaptor object} is a customization point object\iref{customization.point.object} -that accepts a \libconcept{viewable_range} as its first argument and returns a -\libconcept{view}. +that accepts a \libconcept{viewable_range} as its first argument and returns a view. \pnum If a range adaptor object accepts only one argument, @@ -4180,7 +4343,7 @@ \rSec2[range.nonprop.cache]{Non-propagating cache} \pnum -Some types in subclause \ref{range.adaptors} are specified in terms of +Some types in \ref{range.adaptors} are specified in terms of an exposition-only class template \exposid{non-propagating-\brk{}cache}. \tcode{\exposid{non-propagating-cache}} behaves exactly like \tcode{optional} with the following differences: @@ -4263,7 +4426,7 @@ to temporarily cache values as it is iterated over. \end{note} -\rSec2[range.adaptor.tuple]{Range adaptor helpers} +\rSec2[range.adaptor.helpers]{Range adaptor helpers} \begin{codeblock} namespace std::ranges { @@ -4277,9 +4440,24 @@ template constexpr void @\exposid{tuple-for-each}@(F&& f, Tuple&& t) { // \expos apply([&](Ts&&... elements) { - (invoke(f, std::forward(elements)), ...); + (static_cast(invoke(f, std::forward(elements))), ...); }, std::forward(t)); } + + template + constexpr T& @\exposid{as-lvalue}@(T&& t) { // \expos + return static_cast(t); + } + + 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}@> && ...); } \end{codeblock} @@ -4289,8 +4467,8 @@ \pnum \indexlibrarymember{all}{views}% -\tcode{views::all} returns a \libconcept{view} that includes all elements of -its \libconcept{range} argument. +\tcode{views::all} returns a view that includes all elements of +its range argument. \pnum The name \tcode{views::all} denotes a @@ -4309,7 +4487,7 @@ \rSec3[range.ref.view]{Class template \tcode{ref_view}} \pnum -\tcode{ref_view} is a \libconcept{view} of the elements of some other \libconcept{range}. +\tcode{ref_view} is a view of the elements of some other range. \indexlibraryglobal{ref_view}% \begin{codeblock} namespace std::ranges { @@ -4318,6 +4496,7 @@ class ref_view : public view_interface> { private: R* @\exposid{r_}@; // \expos + public: template<@\exposconcept{different-from}@ T> requires @\seebelow@ @@ -4335,6 +4514,9 @@ constexpr auto size() const requires @\libconcept{sized_range}@ { return ranges::size(*@\exposid{r_}@); } + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@ + { return ranges::reserve_hint(*@\exposid{r_}@); } + constexpr auto data() const requires @\libconcept{contiguous_range}@ { return ranges::data(*@\exposid{r_}@); } }; @@ -4374,7 +4556,9 @@ \pnum \tcode{owning_view} is a move-only view -of the elements of some other \libconcept{range}. +of the elements of some other range. + +\indexlibraryglobal{owning_view}% \begin{codeblock} namespace std::ranges { template<@\libconcept{range}@ R> @@ -4382,6 +4566,7 @@ class owning_view : public view_interface> { private: R @\exposid{r_}@ = R(); // \expos + public: owning_view() requires @\libconcept{default_initializable}@ = default; constexpr owning_view(R&& t); @@ -4412,6 +4597,11 @@ constexpr auto size() const requires @\libconcept{sized_range}@ { return ranges::size(@\exposid{r_}@); } + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@ + { return ranges::reserve_hint(@\exposid{r_}@); } + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@ + { return ranges::reserve_hint(@\exposid{r_}@); } + constexpr auto data() requires @\libconcept{contiguous_range}@ { return ranges::data(@\exposid{r_}@); } constexpr auto data() const requires @\libconcept{contiguous_range}@ @@ -4420,6 +4610,7 @@ } \end{codeblock} +\indexlibraryctor{owning_view}% \begin{itemdecl} constexpr owning_view(R&& t); \end{itemdecl} @@ -4435,10 +4626,10 @@ \rSec3[range.as.rvalue.overview]{Overview} \pnum -\tcode{as_rvalue_view} presents a \libconcept{view} of an underlying sequence +\tcode{as_rvalue_view} presents a view of an underlying sequence with the same behavior as the underlying sequence except that its elements are rvalues. -Some generic algorithms can be called with a \tcode{as_rvalue_view} +Some generic algorithms can be called with an \tcode{as_rvalue_view} to replace copying with moving. \pnum @@ -4449,7 +4640,9 @@ The expression \tcode{views::as_rvalue(E)} is expression-equivalent to: \begin{itemize} \item -\tcode{views::all(E)} if \tcode{\libconcept{same_as}, range_reference_t>} is \tcode{true}. +\tcode{views::all(E)} if +\tcode{T} models \libconcept{input_range} and +\tcode{\libconcept{same_as}, range_reference_t>} is \tcode{true}. \item Otherwise, \tcode{as_rvalue_view(E)}. \end{itemize} @@ -4481,9 +4674,9 @@ constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() requires (!@\exposconcept{simple-view}@) - { return move_iterator(ranges::begin(@\exposid{base_}@)); } + { return move_iterator(ranges::begin(@\exposid{base_}@)); } constexpr auto begin() const requires @\libconcept{range}@ - { return move_iterator(ranges::begin(@\exposid{base_}@)); } + { return move_iterator(ranges::begin(@\exposid{base_}@)); } constexpr auto end() requires (!@\exposconcept{simple-view}@) { if constexpr (@\libconcept{common_range}@) { @@ -4502,6 +4695,11 @@ 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 @@ -4525,7 +4723,7 @@ \rSec3[range.filter.overview]{Overview} \pnum -\tcode{filter_view} presents a \libconcept{view} of the elements +\tcode{filter_view} presents a view of the elements of an underlying sequence that satisfy a predicate. \pnum @@ -4568,7 +4766,7 @@ public: filter_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; - constexpr filter_view(V base, Pred pred); + constexpr explicit filter_view(V base, Pred pred); constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } @@ -4591,7 +4789,7 @@ \indexlibraryctor{filter_view}% \begin{itemdecl} -constexpr filter_view(V base, Pred pred); +constexpr explicit filter_view(V base, Pred pred); \end{itemdecl} \begin{itemdescr} @@ -4637,6 +4835,7 @@ \rSec3[range.filter.iterator]{Class \tcode{filter_view::\exposid{iterator}}} +\indexlibraryglobal{filter_view::\exposid{iterator}}% \indexlibrarymember{iterator}{filter_view}% \begin{codeblock} namespace std::ranges { @@ -4719,7 +4918,7 @@ \item Otherwise, \tcode{iterator_category} denotes \tcode{C}. \end{itemize} -\indexlibraryctor{filter_view::iterator}% +\indexlibraryctor{filter_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(filter_view& parent, iterator_t current); \end{itemdecl} @@ -4731,7 +4930,7 @@ \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} -\indexlibrarymember{base}{filter_view::iterator}% +\indexlibrarymember{base}{filter_view::\exposid{iterator}}% \begin{itemdecl} constexpr const iterator_t& base() const & noexcept; \end{itemdecl} @@ -4742,7 +4941,7 @@ Equivalent to: \tcode{return \exposid{current_};} \end{itemdescr} -\indexlibrarymember{base}{filter_view::iterator}% +\indexlibrarymember{base}{filter_view::\exposid{iterator}}% \begin{itemdecl} constexpr iterator_t base() &&; \end{itemdecl} @@ -4753,7 +4952,7 @@ Equivalent to: \tcode{return std::move(\exposid{current_});} \end{itemdescr} -\indexlibrarymember{operator*}{filter_view::iterator}% +\indexlibrarymember{operator*}{filter_view::\exposid{iterator}}% \begin{itemdecl} constexpr range_reference_t operator*() const; \end{itemdecl} @@ -4764,7 +4963,7 @@ Equivalent to: \tcode{return *\exposid{current_};} \end{itemdescr} -\indexlibrarymember{operator->}{filter_view::iterator}% +\indexlibrarymember{operator->}{filter_view::\exposid{iterator}}% \begin{itemdecl} constexpr iterator_t operator->() const requires @\exposconcept{has-arrow}@> && @\libconcept{copyable}@>; @@ -4776,7 +4975,7 @@ Equivalent to: \tcode{return \exposid{current_};} \end{itemdescr} -\indexlibrarymember{operator++}{filter_view::iterator}% +\indexlibrarymember{operator++}{filter_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -4792,7 +4991,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{filter_view::iterator}% +\indexlibrarymember{operator++}{filter_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -4803,7 +5002,7 @@ Equivalent to \tcode{++*this}. \end{itemdescr} -\indexlibrarymember{operator++}{filter_view::iterator}% +\indexlibrarymember{operator++}{filter_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@; \end{itemdecl} @@ -4819,7 +5018,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{filter_view::iterator}% +\indexlibrarymember{operator--}{filter_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; \end{itemdecl} @@ -4836,7 +5035,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{filter_view::iterator}% +\indexlibrarymember{operator--}{filter_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; \end{itemdecl} @@ -4852,7 +5051,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator==}{filter_view::iterator}% +\indexlibrarymember{operator==}{filter_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{equality_comparable}@>; @@ -4864,7 +5063,7 @@ Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};} \end{itemdescr} -\indexlibrarymember{iter_move}{filter_view::iterator}% +\indexlibrarymember{iter_move}{filter_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr range_rvalue_reference_t iter_move(const @\exposid{iterator}@& i) noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); @@ -4876,7 +5075,7 @@ Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});} \end{itemdescr} -\indexlibrarymember{iter_swap}{filter_view::iterator}% +\indexlibrarymember{iter_swap}{filter_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_}@))) @@ -4891,6 +5090,7 @@ \rSec3[range.filter.sentinel]{Class \tcode{filter_view::\exposid{sentinel}}} +\indexlibraryglobal{filter_view::\exposid{sentinel}}% \indexlibrarymember{sentinel}{filter_view}% \begin{codeblock} namespace std::ranges { @@ -4911,7 +5111,7 @@ } \end{codeblock} -\indexlibraryctor{filter_view::sentinel}% +\indexlibraryctor{filter_view::\exposid{sentinel}}% \begin{itemdecl} constexpr explicit @\exposid{sentinel}@(filter_view& parent); \end{itemdecl} @@ -4922,7 +5122,7 @@ Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}. \end{itemdescr} -\indexlibrarymember{base}{filter_view::sentinel}% +\indexlibrarymember{base}{filter_view::\exposid{sentinel}}% \begin{itemdecl} constexpr sentinel_t base() const; \end{itemdecl} @@ -4933,7 +5133,7 @@ Equivalent to: \tcode{return \exposid{end_};} \end{itemdescr} -\indexlibrarymember{operator==}{filter_view::sentinel}% +\indexlibrarymember{operator==}{filter_view::\exposid{sentinel}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} @@ -4950,7 +5150,7 @@ \pnum \tcode{transform_view} presents -a \libconcept{view} of an underlying sequence after +a view of an underlying sequence after applying a transformation function to each element. \pnum @@ -4995,7 +5195,7 @@ public: transform_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; - constexpr transform_view(V base, F fun); + constexpr explicit transform_view(V base, F fun); constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } @@ -5017,6 +5217,11 @@ 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 @@ -5026,7 +5231,7 @@ \indexlibraryctor{transform_view}% \begin{itemdecl} -constexpr transform_view(V base, F fun); +constexpr explicit transform_view(V base, F fun); \end{itemdecl} \begin{itemdescr} @@ -5128,7 +5333,7 @@ \rSec3[range.transform.iterator]{Class template \tcode{transform_view::\exposid{iterator}}} -\indexlibraryglobal{transform_view::iterator}% +\indexlibraryglobal{transform_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{input_range}@ V, @\libconcept{move_constructible}@ F> @@ -5231,7 +5436,7 @@ \tcode{iterator_traits>::iterator_category}. \begin{itemize} \item -If \tcode{is_lvalue_reference_v\&, range_reference_t<\linebreak\exposid{Base}>>>} +If \tcode{is_reference_v\&, range_reference_t<\exposid{Base}>>>} is \tcode{true}, then \begin{itemize} \item @@ -5247,7 +5452,7 @@ Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. \end{itemize} -\indexlibrarymember{iterator}{transform_view::iterator} +\indexlibrarymember{iterator}{transform_view::\exposid{iterator}} \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current); \end{itemdecl} @@ -5259,7 +5464,7 @@ \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} -\indexlibraryctor{transform_view::iterator}% +\indexlibraryctor{transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; @@ -5272,7 +5477,7 @@ \exposid{parent_} with \tcode{i.\exposid{parent_}}. \end{itemdescr} -\indexlibrarymember{base}{transform_view::iterator}% +\indexlibrarymember{base}{transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; \end{itemdecl} @@ -5283,7 +5488,7 @@ Equivalent to: \tcode{return \exposid{current_};} \end{itemdescr} -\indexlibrarymember{base}{transform_view::iterator}% +\indexlibrarymember{base}{transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr iterator_t<@\exposid{Base}@> base() &&; \end{itemdecl} @@ -5294,7 +5499,7 @@ Equivalent to: \tcode{return std::move(\exposid{current_});} \end{itemdescr} -\indexlibrarymember{operator++}{transform_view::iterator}% +\indexlibrarymember{operator++}{transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -5309,7 +5514,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{transform_view::iterator}% +\indexlibrarymember{operator++}{transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -5320,7 +5525,7 @@ Equivalent to \tcode{++\exposid{current_}}. \end{itemdescr} -\indexlibrarymember{operator++}{transform_view::iterator}% +\indexlibrarymember{operator++}{transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; \end{itemdecl} @@ -5336,7 +5541,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{transform_view::iterator}% +\indexlibrarymember{operator--}{transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} @@ -5351,7 +5556,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{transform_view::iterator}% +\indexlibrarymember{operator--}{transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} @@ -5367,7 +5572,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+=}{transform_view::iterator}% +\indexlibrarymember{operator+=}{transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator+=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -5383,7 +5588,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-=}{transform_view::iterator}% +\indexlibrarymember{operator-=}{transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator-=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -5399,7 +5604,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator==}{transform_view::iterator}% +\indexlibrarymember{operator==}{transform_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{equality_comparable}@>; @@ -5411,7 +5616,7 @@ Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};} \end{itemdescr} -\indexlibrarymember{operator<}{transform_view::iterator}% +\indexlibrarymember{operator<}{transform_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -5423,7 +5628,7 @@ Equivalent to: \tcode{return x.\exposid{current_} < y.\exposid{current_};} \end{itemdescr} -\indexlibrarymember{operator>}{transform_view::iterator}% +\indexlibrarymember{operator>}{transform_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -5435,7 +5640,7 @@ Equivalent to: \tcode{return y < x;} \end{itemdescr} -\indexlibrarymember{operator<=}{transform_view::iterator}% +\indexlibrarymember{operator<=}{transform_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -5447,7 +5652,7 @@ Equivalent to: \tcode{return !(y < x);} \end{itemdescr} -\indexlibrarymember{operator>=}{transform_view::iterator}% +\indexlibrarymember{operator>=}{transform_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -5459,7 +5664,7 @@ Equivalent to: \tcode{return !(x < y);} \end{itemdescr} -\indexlibrarymember{operator<=>}{transform_view::iterator}% +\indexlibrarymember{operator<=>}{transform_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}@>; @@ -5471,7 +5676,7 @@ Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};} \end{itemdescr} -\indexlibrarymember{operator+}{transform_view::iterator}% +\indexlibrarymember{operator+}{transform_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator+(@\exposid{iterator}@ i, difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -5485,7 +5690,7 @@ Equivalent to: \tcode{return \exposid{iterator}\{*i.\exposid{parent_}, i.\exposid{current_} + n\};} \end{itemdescr} -\indexlibrarymember{operator-}{transform_view::iterator}% +\indexlibrarymember{operator-}{transform_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator-(@\exposid{iterator}@ i, difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -5497,7 +5702,7 @@ Equivalent to: \tcode{return \exposid{iterator}\{*i.\exposid{parent_}, i.\exposid{current_} - n\};} \end{itemdescr} -\indexlibrarymember{operator-}{transform_view::iterator}% +\indexlibrarymember{operator-}{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{Base}@>>; @@ -5512,7 +5717,7 @@ \rSec3[range.transform.sentinel]{Class template \tcode{transform_view::\exposid{sentinel}}} -\indexlibraryglobal{transform_view::sentinel}% +\indexlibraryglobal{transform_view::\exposid{sentinel}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{input_range}@ V, @\libconcept{move_constructible}@ F> @@ -5525,6 +5730,7 @@ using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + public: @\exposid{sentinel}@() = default; constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); @@ -5550,7 +5756,7 @@ } \end{codeblock} -\indexlibraryctor{transform_view::sentinel}% +\indexlibraryctor{transform_view::\exposid{sentinel}}% \begin{itemdecl} constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); \end{itemdecl} @@ -5561,7 +5767,7 @@ Initializes \exposid{end_} with \tcode{end}. \end{itemdescr} -\indexlibraryctor{transform_view::sentinel}% +\indexlibraryctor{transform_view::\exposid{sentinel}}% \begin{itemdecl} constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -5573,7 +5779,7 @@ Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. \end{itemdescr} -\indexlibrarymember{base}{transform_view::sentinel} +\indexlibrarymember{base}{transform_view::\exposid{sentinel}} \begin{itemdecl} constexpr sentinel_t<@\exposid{Base}@> base() const; \end{itemdecl} @@ -5584,7 +5790,7 @@ Equivalent to: \tcode{return \exposid{end_};} \end{itemdescr} -\indexlibrarymember{operator==}{transform_view::sentinel} +\indexlibrarymember{operator==}{transform_view::\exposid{sentinel}} \begin{itemdecl} template requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> @@ -5597,7 +5803,7 @@ Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};} \end{itemdescr} -\indexlibrarymember{operator-}{transform_view::sentinel}% +\indexlibrarymember{operator-}{transform_view::\exposid{sentinel}}% \begin{itemdecl} template requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> @@ -5611,7 +5817,7 @@ Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};} \end{itemdescr} -\indexlibrarymember{operator-}{transform_view::sentinel}% +\indexlibrarymember{operator-}{transform_view::\exposid{sentinel}}% \begin{itemdecl} template requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> @@ -5630,9 +5836,9 @@ \rSec3[range.take.overview]{Overview} \pnum -\tcode{take_view} produces a \libconcept{view} of the first $N$ elements -from another \libconcept{view}, or all the elements if the adapted -\libconcept{view} contains fewer than $N$. +\tcode{take_view} produces a view of the first $N$ elements +from another view, or all the elements if the adapted +view contains fewer than $N$. \pnum \indexlibrarymember{take}{views}% @@ -5650,7 +5856,7 @@ \begin{itemize} \item If \tcode{T} is a specialization -of \tcode{ranges::empty_view}\iref{range.empty.view}, +of \tcode{empty_view}\iref{range.empty.view}, then \tcode{((void)F, \placeholdernc{decay-copy}(E))}, except that the evaluations of \tcode{E} and \tcode{F} are indeterminately sequenced. @@ -5661,7 +5867,7 @@ and is a specialization of \tcode{span}\iref{views.span}, \tcode{basic_string_view}\iref{string.view}, or -\tcode{ranges::subrange}\iref{range.subrange}, +\tcode{subrange}\iref{range.subrange}, then \tcode{U(ranges::begin(E), ranges::be\-gin(E) + std::min(ranges::distance(E), F))}, @@ -5673,22 +5879,22 @@ then \tcode{U} is \tcode{span}; \item otherwise, if \tcode{T} is a specialization of \tcode{basic_string_view}, then \tcode{U} is \tcode{T}; -\item otherwise, \tcode{T} is a specialization of \tcode{ranges::subrange}, and -\tcode{U} is \tcode{ranges::subrange>}; +\item otherwise, \tcode{T} is a specialization of \tcode{subrange}, and +\tcode{U} is \tcode{subrange>}; \end{itemize} \item otherwise, if \tcode{T} is -a specialization of \tcode{ranges::iota_view}\iref{range.iota.view} +a specialization of \tcode{iota_view}\iref{range.iota.view} that models \libconcept{random_access_range} and \libconcept{sized_range}, then -\tcode{ranges::iota_view(*ranges::begin(E), +\tcode{iota_view(*ranges::begin(E), *(ranges::begin(E) + std::\linebreak{}min(ranges::distance(E), F)))}, except that \tcode{E} is evaluated only once. \item Otherwise, if \tcode{T} is -a specialization of \tcode{ranges::repeat_view}\iref{range.repeat.view}: +a specialization of \tcode{repeat_view}\iref{range.repeat.view}: \begin{itemize} \item if \tcode{T} models \libconcept{sized_range}, @@ -5702,7 +5908,7 @@ \end{itemize} \item -Otherwise, \tcode{ranges::take_view(E, F)}. +Otherwise, \tcode{take_view(E, F)}. \end{itemize} \pnum @@ -5734,7 +5940,7 @@ public: take_view() requires @\libconcept{default_initializable}@ = default; - constexpr take_view(V base, range_difference_t count); + constexpr explicit take_view(V base, range_difference_t count); constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } @@ -5747,6 +5953,10 @@ auto sz = range_difference_t(size()); return counted_iterator(ranges::begin(@\exposid{base_}@), sz); } + } else if constexpr (@\libconcept{sized_sentinel_for}@, iterator_t>) { + auto it = ranges::begin(@\exposid{base_}@); + auto sz = std::min(@\exposid{count_}@, ranges::end(@\exposid{base_}@) - it); + return counted_iterator(std::move(it), sz); } else { return counted_iterator(ranges::begin(@\exposid{base_}@), @\exposid{count_}@); } @@ -5760,6 +5970,10 @@ auto sz = range_difference_t(size()); return counted_iterator(ranges::begin(@\exposid{base_}@), sz); } + } else if constexpr (@\libconcept{sized_sentinel_for}@, iterator_t>) { + auto it = ranges::begin(@\exposid{base_}@); + auto sz = std::min(@\exposid{count_}@, ranges::end(@\exposid{base_}@) - it); + return counted_iterator(std::move(it), sz); } else { return counted_iterator(ranges::begin(@\exposid{base_}@), @\exposid{count_}@); } @@ -5771,6 +5985,8 @@ return ranges::begin(@\exposid{base_}@) + range_difference_t(size()); else return default_sentinel; + } else if constexpr (@\libconcept{sized_sentinel_for}@, iterator_t>) { + return default_sentinel; } else { return @\exposid{sentinel}@{ranges::end(@\exposid{base_}@)}; } @@ -5782,6 +5998,8 @@ return ranges::begin(@\exposid{base_}@) + range_difference_t(size()); else return default_sentinel; + } else if constexpr (@\libconcept{sized_sentinel_for}@, iterator_t>) { + return default_sentinel; } else { return @\exposid{sentinel}@{ranges::end(@\exposid{base_}@)}; } @@ -5796,6 +6014,22 @@ auto n = ranges::size(@\exposid{base_}@); return ranges::min(n, static_cast(@\exposid{count_}@)); } + + constexpr auto reserve_hint() { + if constexpr (@\libconcept{approximately_sized_range}@) { + auto n = static_cast>(ranges::reserve_hint(@\exposid{base_}@)); + return @\exposid{to-unsigned-like}@(ranges::min(n, @\exposid{count_}@)); + } + return @\exposid{to-unsigned-like}@(@\exposid{count_}@); + } + + constexpr auto reserve_hint() const { + if constexpr (@\libconcept{approximately_sized_range}@) { + auto n = static_cast>(ranges::reserve_hint(@\exposid{base_}@)); + return @\exposid{to-unsigned-like}@(ranges::min(n, @\exposid{count_}@)); + } + return @\exposid{to-unsigned-like}@(@\exposid{count_}@); + } }; template @@ -5806,10 +6040,14 @@ \indexlibraryctor{take_view}% \begin{itemdecl} -constexpr take_view(V base, range_difference_t count); +constexpr explicit take_view(V base, range_difference_t count); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{count >= 0} is \tcode{true}. + \pnum \effects Initializes \exposid{base_} with \tcode{std::move(base)} and @@ -5818,7 +6056,7 @@ \rSec3[range.take.sentinel]{Class template \tcode{take_view::\exposid{sentinel}}} -\indexlibraryglobal{take_view::sentinel}% +\indexlibraryglobal{take_view::\exposid{sentinel}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{view}@ V> @@ -5829,6 +6067,7 @@ template using @\exposid{CI}@ = counted_iterator>>; // \expos sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + public: @\exposid{sentinel}@() = default; constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); @@ -5846,7 +6085,7 @@ } \end{codeblock} -\indexlibraryctor{take_view::sentinel}% +\indexlibraryctor{take_view::\exposid{sentinel}}% \begin{itemdecl} constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); \end{itemdecl} @@ -5857,7 +6096,7 @@ Initializes \exposid{end_} with \tcode{end}. \end{itemdescr} -\indexlibraryctor{take_view::sentinel}% +\indexlibraryctor{take_view::\exposid{sentinel}}% \begin{itemdecl} constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ s) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -5869,7 +6108,7 @@ Initializes \exposid{end_} with \tcode{std::move(s.\exposid{end_})}. \end{itemdescr} -\indexlibrarymember{base}{take_view::sentinel}% +\indexlibrarymember{base}{take_view::\exposid{sentinel}}% \begin{itemdecl} constexpr sentinel_t<@\exposid{Base}@> base() const; \end{itemdecl} @@ -5880,7 +6119,7 @@ Equivalent to: \tcode{return \exposid{end_};} \end{itemdescr} -\indexlibrarymember{operator==}{take_view::sentinel}% +\indexlibrarymember{operator==}{take_view::\exposid{sentinel}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{CI}@& y, const @\exposid{sentinel}@& x); @@ -5901,8 +6140,8 @@ \rSec3[range.take.while.overview]{Overview} \pnum -Given a unary predicate \tcode{pred} and a \libconcept{view} \tcode{r}, -\tcode{take_while_view} produces a \libconcept{view} +Given a unary predicate \tcode{pred} and a view \tcode{r}, +\tcode{take_while_view} produces a view of the range \range{ranges::be\-gin(r)}{ranges::find_if_not(r, pred)}. \indexlibraryglobal{take_while}% @@ -5949,7 +6188,7 @@ public: take_while_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; - constexpr take_while_view(V base, Pred pred); + constexpr explicit take_while_view(V base, Pred pred); constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } @@ -5980,7 +6219,7 @@ \indexlibraryctor{take_while_view}% \begin{itemdecl} -constexpr take_while_view(V base, Pred pred); +constexpr explicit take_while_view(V base, Pred pred); \end{itemdecl} \begin{itemdescr} @@ -6003,7 +6242,7 @@ \rSec3[range.take.while.sentinel]{Class template \tcode{take_while_view::\exposid{sentinel}}} -\indexlibraryglobal{take_while_view::sentinel}% +\indexlibraryglobal{take_while_view::\exposid{sentinel}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{view}@ V, class Pred> @@ -6034,7 +6273,7 @@ } \end{codeblock} -\indexlibraryctor{take_while_view::sentinel}% +\indexlibraryctor{take_while_view::\exposid{sentinel}}% \begin{itemdecl} constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end, const Pred* pred); \end{itemdecl} @@ -6045,7 +6284,7 @@ Initializes \exposid{end_} with \tcode{end} and \exposid{pred_} with \tcode{pred}. \end{itemdescr} -\indexlibraryctor{take_while_view::sentinel}% +\indexlibraryctor{take_while_view::\exposid{sentinel}}% \begin{itemdecl} constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ s) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -6058,7 +6297,7 @@ \exposid{pred_} with \tcode{s.\exposid{pred_}}. \end{itemdescr} -\indexlibrarymember{operator==}{take_while_view::sentinel}% +\indexlibrarymember{operator==}{take_while_view::\exposid{sentinel}}% \begin{itemdecl} friend constexpr bool operator==(const iterator_t<@\exposid{Base}@>& x, const @\exposid{sentinel}@& y); @@ -6080,9 +6319,9 @@ \rSec3[range.drop.overview]{Overview} \pnum -\tcode{drop_view} produces a \libconcept{view} -excluding the first $N$ elements from another \libconcept{view}, or -an empty range if the adapted \libconcept{view} contains fewer than $N$ elements. +\tcode{drop_view} produces a view +excluding the first $N$ elements from another view, or +an empty range if the adapted view contains fewer than $N$ elements. \pnum \indexlibrarymember{drop}{views}% @@ -6100,7 +6339,7 @@ \begin{itemize} \item If \tcode{T} is a specialization of -\tcode{ranges::empty_view}\iref{range.empty.view}, +\tcode{empty_view}\iref{range.empty.view}, then \tcode{((void)F, \placeholdernc{decay-copy}(E))}, except that the evaluations of \tcode{E} and \tcode{F} are indeterminately sequenced. @@ -6112,8 +6351,8 @@ \begin{itemize} \item a specialization of \tcode{span}\iref{views.span}, \item a specialization of \tcode{basic_string_view}\iref{string.view}, -\item a specialization of \tcode{ranges::iota_view}\iref{range.iota.view}, or -\item a specialization of \tcode{ranges::subrange}\iref{range.subrange} +\item a specialization of \tcode{iota_view}\iref{range.iota.view}, or +\item a specialization of \tcode{subrange}\iref{range.subrange} where \tcode{T::\exposid{StoreSize}} is \tcode{false}, \end{itemize} then \tcode{U(ranges::begin(E) + std::min(ranges::distance(E), F), ranges::end(E))}, @@ -6124,7 +6363,7 @@ \item Otherwise, if \tcode{T} is -a specialization of \tcode{ranges::subrange}\iref{range.subrange} +a specialization of \tcode{subrange} that models \libconcept{random_access_range} and \libconcept{sized_range}, then \tcode{T(ranges::begin(E) + std::min(ranges::distance(E), F), ranges::\linebreak{}end(E), @@ -6134,7 +6373,7 @@ \item Otherwise, if \tcode{T} is -a specialization of \tcode{ranges::repeat_view}\iref{range.repeat.view}: +a specialization of \tcode{repeat_view}\iref{range.repeat.view}: \begin{itemize} \item if \tcode{T} models \libconcept{sized_range}, @@ -6149,7 +6388,7 @@ \end{itemize} \item -Otherwise, \tcode{ranges::drop_view(E, F)}. +Otherwise, \tcode{drop_view(E, F)}. \end{itemize} \pnum @@ -6174,7 +6413,7 @@ class drop_view : public view_interface> { public: drop_view() requires @\libconcept{default_initializable}@ = default; - constexpr drop_view(V base, range_difference_t count); + constexpr explicit drop_view(V base, range_difference_t count); constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } @@ -6203,6 +6442,16 @@ return s < c ? 0 : s - c; } + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@ { + const auto s = static_cast>(ranges::reserve_hint(@\exposid{base_}@)); + return @\exposid{to-unsigned-like}@(s < @\exposid{count_}@ ? 0 : s - @\exposid{count_}@); + } + + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@ { + const auto s = static_cast>(ranges::reserve_hint(@\exposid{base_}@)); + return @\exposid{to-unsigned-like}@(s < @\exposid{count_}@ ? 0 : s - @\exposid{count_}@); + } + private: V @\exposid{base_}@ = V(); // \expos range_difference_t @\exposid{count_}@ = 0; // \expos @@ -6215,7 +6464,7 @@ \indexlibraryctor{drop_view}% \begin{itemdecl} -constexpr drop_view(V base, range_difference_t count); +constexpr explicit drop_view(V base, range_difference_t count); \end{itemdecl} \begin{itemdescr} @@ -6262,8 +6511,8 @@ \rSec3[range.drop.while.overview]{Overview} \pnum -Given a unary predicate \tcode{pred} and a \libconcept{view} \tcode{r}, -\tcode{drop_while_view} produces a \libconcept{view} +Given a unary predicate \tcode{pred} and a view \tcode{r}, +\tcode{drop_while_view} produces a view of the range \range{ranges::find_if_not(r, pred)}{ranges::end(r)}. \pnum @@ -6277,7 +6526,7 @@ \pnum \begin{example} \begin{codeblock} -constexpr auto source = " \t \t \t hello there"; +constexpr auto source = " \t \t \t hello there"sv; auto is_invisible = [](const auto x) { return x == ' ' || x == '\t'; }; auto skip_ws = views::drop_while(source, is_invisible); for (auto c : skip_ws) { @@ -6299,7 +6548,7 @@ class drop_while_view : public view_interface> { public: drop_while_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; - constexpr drop_while_view(V base, Pred pred); + constexpr explicit drop_while_view(V base, Pred pred); constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } @@ -6322,7 +6571,7 @@ \indexlibraryctor{drop_while_view}% \begin{itemdecl} -constexpr drop_while_view(V base, Pred pred); +constexpr explicit drop_while_view(V base, Pred pred); \end{itemdecl} \begin{itemdescr} @@ -6376,8 +6625,7 @@ \rSec3[range.join.overview]{Overview} \pnum -\tcode{join_view} flattens a \libconcept{view} of ranges into a -\libconcept{view}. +\tcode{join_view} flattens a view of ranges into a view. \pnum \indexlibrarymember{join}{views}% @@ -6420,8 +6668,10 @@ V @\exposid{base_}@ = V(); // \expos + @\exposidnc{non-propagating-cache}@> @\exposidnc{outer_}@; // \expos, present only + // when \tcode{!\libconcept{forward_range}} @\exposidnc{non-propagating-cache}@> @\exposid{inner_}@; // \expos, present only - // when \tcode{!is_reference_v<\exposid{InnerRng}>} + // if \tcode{is_reference_v<\exposid{InnerRng}>} is \tcode{false} public: join_view() requires @\libconcept{default_initializable}@ = default; @@ -6431,14 +6681,20 @@ constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() { - constexpr bool use_const = @\exposconcept{simple-view}@ && - is_reference_v<@\exposid{InnerRng}@>; - return @\exposid{iterator}@{*this, ranges::begin(@\exposid{base_}@)}; + if constexpr (@\libconcept{forward_range}@) { + constexpr bool use_const = @\exposconcept{simple-view}@ && + is_reference_v<@\exposid{InnerRng}@>; + return @\exposid{iterator}@{*this, ranges::begin(@\exposid{base_}@)}; + } else { + @\exposid{outer_}@ = ranges::begin(@\exposid{base_}@); + return @\exposid{iterator}@{*this}; + } } constexpr auto begin() const - requires @\libconcept{input_range}@ && - is_reference_v> + requires @\libconcept{forward_range}@ && + is_reference_v> && + @\libconcept{input_range}@> { return @\exposid{iterator}@{*this, ranges::begin(@\exposid{base_}@)}; } constexpr auto end() { @@ -6451,10 +6707,10 @@ } constexpr auto end() const - requires @\libconcept{input_range}@ && - is_reference_v> { - if constexpr (@\libconcept{forward_range}@ && - @\libconcept{forward_range}@> && + requires @\libconcept{forward_range}@ && + is_reference_v> && + @\libconcept{input_range}@> { + if constexpr (@\libconcept{forward_range}@> && @\libconcept{common_range}@ && @\libconcept{common_range}@>) return @\exposid{iterator}@{*this, ranges::end(@\exposid{base_}@)}; @@ -6481,7 +6737,7 @@ \rSec3[range.join.iterator]{Class template \tcode{join_view::\exposid{iterator}}} -\indexlibraryglobal{join_view::iterator}% +\indexlibraryglobal{join_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{input_range}@ V> @@ -6497,27 +6753,34 @@ static constexpr bool @\exposidnc{ref-is-glvalue}@ = // \expos is_reference_v>; - @\exposidnc{OuterIter}@ @\exposid{outer_}@ = @\exposidnc{OuterIter}@(); // \expos - @\exposidnc{InnerIter}@ @\exposid{inner_}@ = @\exposidnc{InnerIter}@(); // \expos + @\exposidnc{OuterIter}@ @\exposid{outer_}@ = @\exposidnc{OuterIter}@(); // \expos, present only + // if \exposid{Base} models \libconcept{forward_range} + optional<@\exposidnc{InnerIter}@> @\exposid{inner_}@; // \expos @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos constexpr void @\exposidnc{satisfy}@(); // \expos + constexpr @\exposidnc{OuterIter}@& @\exposidnc{outer}@(); // \expos + constexpr const @\exposidnc{OuterIter}@& @\exposidnc{outer}@() const; // \expos + + constexpr @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent, @\exposidnc{OuterIter}@ outer) + requires @\libconcept{forward_range}@<@\exposidnc{Base}@>; // \expos + constexpr explicit @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent) + requires (!@\libconcept{forward_range}@<@\exposidnc{Base}@>); // \expos + public: using iterator_concept = @\seebelow@; using iterator_category = @\seebelow@; // not always present using value_type = range_value_t>; using difference_type = @\seebelow@; - @\exposid{iterator}@() requires @\libconcept{default_initializable}@<@\exposid{OuterIter}@> && - @\itcorr[-2]\libconcept{default_initializable}@<@\exposid{InnerIter}@> = default; - constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{OuterIter}@ outer); + @\exposid{iterator}@() = default; constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && @\libconcept{convertible_to}@, @\exposid{OuterIter}@> && @\libconcept{convertible_to}@, @\exposid{InnerIter}@>; - constexpr decltype(auto) operator*() const { return *@\exposid{inner_}@; } + constexpr decltype(auto) operator*() const { return **@\exposid{inner_}@; } constexpr @\exposid{InnerIter}@ operator->() const requires @\exposconcept{has-arrow}@<@\exposid{InnerIter}@> && @\libconcept{copyable}@<@\exposid{InnerIter}@>; @@ -6539,16 +6802,16 @@ @\libconcept{common_range}@>; friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposid{ref-is-glvalue}@ && @\libconcept{equality_comparable}@> && + requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> && @\libconcept{equality_comparable}@>>; friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& i) - noexcept(noexcept(ranges::iter_move(i.@\exposid{inner_}@))) { - return ranges::iter_move(i.@\exposid{inner_}@); + noexcept(noexcept(ranges::iter_move(*i.@\exposid{inner_}@))) { + return ranges::iter_move(*i.@\exposid{inner_}@); } friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - noexcept(noexcept(ranges::iter_swap(x.@\exposid{inner_}@, y.@\exposid{inner_}@))) + noexcept(noexcept(ranges::iter_swap(*x.@\exposid{inner_}@, *y.@\exposid{inner_}@))) requires @\libconcept{indirectly_swappable}@<@\exposid{InnerIter}@>; }; } @@ -6575,7 +6838,7 @@ \exposid{Base} models \libconcept{forward_range}, and \tcode{range_reference_t<\exposid{Base}>} models \libconcept{forward_range}. In that case, -\tcode{iterator::iter\-ator_category} is defined as follows: +\tcode{\exposid{iterator}::iter\-ator_category} is defined as follows: \begin{itemize} \item Let \placeholder{OUTERC} denote \tcode{iterator_traits>::iterator_category}, and @@ -6595,7 +6858,7 @@ \end{itemize} \pnum -\tcode{iterator::difference_type} denotes the type: +\tcode{\exposid{iterator}::difference_type} denotes the type: \begin{codeblock} common_type_t< range_difference_t<@\exposid{Base}@>, @@ -6606,6 +6869,18 @@ \tcode{join_view} iterators use the \exposid{satisfy} function to skip over empty inner ranges. +\begin{itemdecl} +constexpr @\exposid{OuterIter}@& @\exposid{outer}@(); +constexpr const @\exposid{OuterIter}@& @\exposid{outer}@() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{outer_} if \exposid{Base} models \libconcept{forward_range}; +otherwise, \tcode{*\exposid{parent_}->\exposid{outer_}}. +\end{itemdescr} + \begin{itemdecl} constexpr void @\exposid{satisfy}@(); \end{itemdecl} @@ -6622,20 +6897,21 @@ return @\exposid{parent_}@->@\exposid{inner_}@.@\exposid{emplace-deref}@(x); }; -for (; @\exposid{outer_}@ != ranges::end(@\exposid{parent_}@->@\exposid{base_}@); ++@\exposid{outer_}@) { - auto&& inner = update_inner(@\exposid{outer_}@); +for (; @\exposid{outer}@() != ranges::end(@\exposid{parent_}@->@\exposid{base_}@); ++@\exposid{outer}@()) { + auto&& inner = update_inner(@\exposid{outer}@()); @\exposid{inner_}@ = ranges::begin(inner); - if (@\exposid{inner_}@ != ranges::end(inner)) + if (*@\exposid{inner_}@ != ranges::end(inner)) return; } if constexpr (@\exposid{ref-is-glvalue}@) - @\exposid{inner_}@ = @\exposid{InnerIter}@(); + @\exposid{inner_}@.reset(); \end{codeblock} \end{itemdescr} -\indexlibraryctor{join_view::iterator}% +\indexlibraryctor{join_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{OuterIter}@ outer); +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{OuterIter}@ outer) + requires @\libconcept{forward_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -6645,7 +6921,20 @@ \exposid{parent_} with \tcode{addressof(parent)}; then calls \tcode{\exposid{satisfy}()}. \end{itemdescr} -\indexlibraryctor{join_view::iterator}% +\indexlibraryctor{join_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr explicit @\exposid{iterator}@(@\exposid{Parent}@& parent) + requires (!@\libconcept{forward_range}@<@\exposid{Base}@>); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{addressof(parent)}; +then calls \tcode{\exposid{satisfy}()}. +\end{itemdescr} + +\indexlibraryctor{join_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && @@ -6659,9 +6948,15 @@ Initializes \exposid{outer_} with \tcode{std::move(i.\exposid{outer_})}, \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}, and \exposid{parent_} with \tcode{i.\exposid{parent_}}. + +\pnum +\begin{note} +\tcode{Const} can only be \tcode{true} +when \exposid{Base} models \libconcept{forward_range}. +\end{note} \end{itemdescr} -\indexlibrarymember{operator->}{join_view::iterator}% +\indexlibrarymember{operator->}{join_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{InnerIter}@ operator->() const requires @\exposconcept{has-arrow}@<@\exposid{InnerIter}@> && @\libconcept{copyable}@<@\exposid{InnerIter}@>; @@ -6670,10 +6965,10 @@ \begin{itemdescr} \pnum \effects -Equivalent to \tcode{return \exposid{inner_};} +Equivalent to: \tcode{return *\exposid{inner_};} \end{itemdescr} -\indexlibrarymember{operator++}{join_view::iterator}% +\indexlibrarymember{operator++}{join_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -6682,7 +6977,7 @@ \pnum Let \tcode{\placeholder{inner-range}} be: \begin{itemize} -\item If \exposid{ref-is-glvalue} is \tcode{true}, \tcode{*\exposid{outer_}}. +\item If \exposid{ref-is-glvalue} is \tcode{true}, \tcode{*\exposid{outer}()}. \item Otherwise, \tcode{*\exposid{parent_}->\exposid{inner_}}. \end{itemize} @@ -6690,16 +6985,15 @@ \effects Equivalent to: \begin{codeblock} -auto&& inner_rng = @\placeholder{inner-range}@; -if (++@\exposid{inner_}@ == ranges::end(inner_rng)) { - ++@\exposid{outer_}@; +if (++*@\exposid{inner_}@ == ranges::end(@\exposid{as-lvalue}@(@\placeholder{inner-range}@))) { + ++@\exposid{outer}@(); @\exposid{satisfy}@(); } return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{join_view::iterator}% +\indexlibrarymember{operator++}{join_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -6710,7 +7004,7 @@ Equivalent to: \tcode{++*this}. \end{itemdescr} -\indexlibrarymember{operator++}{join_view::iterator}% +\indexlibrarymember{operator++}{join_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator++(int) requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> && @@ -6728,7 +7022,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{join_view::iterator}% +\indexlibrarymember{operator--}{join_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator--() requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && @@ -6742,15 +7036,15 @@ Equivalent to: \begin{codeblock} if (@\exposid{outer_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) - @\exposid{inner_}@ = ranges::end(*--@\exposid{outer_}@); -while (@\exposid{inner_}@ == ranges::begin(*@\exposid{outer_}@)) - @\exposid{inner_}@ = ranges::end(*--@\exposid{outer_}@); ---@\exposid{inner_}@; + @\exposid{inner_}@ = ranges::end(@\exposid{as-lvalue}@(*--@\exposid{outer_}@)); +while (*@\exposid{inner_}@ == ranges::begin(@\exposid{as-lvalue}@(*@\exposid{outer_}@))) + *@\exposid{inner_}@ = ranges::end(@\exposid{as-lvalue}@(*--@\exposid{outer_}@)); +--*@\exposid{inner_}@; return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{join_view::iterator}% +\indexlibrarymember{operator--}{join_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator--(int) requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && @@ -6769,10 +7063,10 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator==}{join_view::iterator}% +\indexlibrarymember{operator==}{join_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposid{ref-is-glvalue}@ && @\libconcept{equality_comparable}@> && + requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> && @\libconcept{equality_comparable}@>>; \end{itemdecl} @@ -6783,22 +7077,22 @@ \tcode{return x.\exposid{outer_} == y.\exposid{outer_} \&\& x.\exposid{inner_} == y.\exposid{inner_};} \end{itemdescr} -\indexlibrarymember{iter_swap}{join_view::iterator}% +\indexlibrarymember{iter_swap}{join_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{inner_}@, y.@\exposid{inner_}@))) + noexcept(noexcept(ranges::iter_swap(*x.@\exposid{inner_}@, *y.@\exposid{inner_}@))) requires @\libconcept{indirectly_swappable}@<@\exposid{InnerIter}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return ranges::iter_swap(x.\exposid{inner_}, y.\exposid{inner_});} +Equivalent to: \tcode{return ranges::iter_swap(*x.\exposid{inner_}, *y.\exposid{inner_});} \end{itemdescr} \rSec3[range.join.sentinel]{Class template \tcode{join_view::\exposid{sentinel}}} -\indexlibraryglobal{join_view::sentinel}% +\indexlibraryglobal{join_view::\exposid{sentinel}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{input_range}@ V> @@ -6824,7 +7118,7 @@ } \end{codeblock} -\indexlibraryctor{join_view::sentinel}% +\indexlibraryctor{join_view::\exposid{sentinel}}% \begin{itemdecl} constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent); \end{itemdecl} @@ -6835,7 +7129,7 @@ Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}. \end{itemdescr} -\indexlibraryctor{join_view::sentinel}% +\indexlibraryctor{join_view::\exposid{sentinel}}% \begin{itemdecl} constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ s) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -6847,8 +7141,7 @@ Initializes \exposid{end_} with \tcode{std::move(s.\exposid{end_})}. \end{itemdescr} -\indexlibrarymember{operator==}{join_view::sentinel}%3431 - +\indexlibrarymember{operator==}{join_view::\exposid{sentinel}}%3431 \begin{itemdecl} template requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> @@ -6858,7 +7151,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{outer_} == y.\exposid{end_};} +Equivalent to: \tcode{return x.\exposid{outer}() == y.\exposid{end_};} \end{itemdescr} \rSec2[range.join.with]{Join with view} @@ -6866,11 +7159,11 @@ \rSec3[range.join.with.overview]{Overview} \pnum -\tcode{join_with_view} takes a \libconcept{view} and a delimiter, and -flattens the \libconcept{view}, +\tcode{join_with_view} takes a view and a delimiter, and +flattens the view, inserting every element of the delimiter -in between elements of the \libconcept{view}. -The delimiter can be a single element or a \libconcept{view} of elements. +in between elements of the view. +The delimiter can be a single element or a view of elements. \pnum \indexlibrarymember{join_with}{views}% @@ -6893,27 +7186,24 @@ \rSec3[range.join.with.view]{Class template \tcode{join_with_view}} +\indexlibraryglobal{join_with_view}% \begin{codeblock} namespace std::ranges { - template - concept @\defexposconcept{compatible-joinable-ranges}@ = // \expos - @\libconcept{common_with}@, range_value_t

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

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

>; - template concept @\defexposconcept{bidirectional-common}@ = @\libconcept{bidirectional_range}@ && @\libconcept{common_range}@; // \expos template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> requires @\libconcept{view}@ && @\libconcept{input_range}@> && @\libconcept{view}@ - && @\exposconcept{compatible-joinable-ranges}@, Pattern> + && @\exposconcept{concatable}@, Pattern> class join_with_view : public view_interface> { using @\exposid{InnerRng}@ = range_reference_t; // \expos V @\exposid{base_}@ = V(); // \expos + @\exposid{non-propagating-cache}@> @\exposid{outer_it_}@; // \expos, present only + // when \tcode{!\libconcept{forward_range}} @\exposid{non-propagating-cache}@> @\exposid{inner_}@; // \expos, present only - // when \tcode{!is_reference_v<\exposid{InnerRng}>} + // if \tcode{is_reference_v<\exposid{InnerRng}>} is \tcode{false} Pattern @\exposid{pattern_}@ = Pattern(); // \expos // \ref{range.join.with.iterator}, class template \tcode{join_with_view::\exposid{iterator}} @@ -6926,25 +7216,33 @@ join_with_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; - constexpr join_with_view(V base, Pattern pattern); + constexpr explicit join_with_view(V base, Pattern pattern); template<@\libconcept{input_range}@ R> requires @\libconcept{constructible_from}@> && @\libconcept{constructible_from}@>> - constexpr join_with_view(R&& r, range_value_t<@\exposid{InnerRng}@> e); + constexpr explicit join_with_view(R&& r, range_value_t<@\exposid{InnerRng}@> e); constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() { - constexpr bool use_const = - @\exposconcept{simple-view}@ && is_reference_v<@\exposid{InnerRng}@> && @\exposconcept{simple-view}@; - return @\exposid{iterator}@{*this, ranges::begin(@\exposid{base_}@)}; + if constexpr (@\libconcept{forward_range}@) { + constexpr bool use_const = + @\exposconcept{simple-view}@ && is_reference_v<@\exposid{InnerRng}@> && @\exposconcept{simple-view}@; + return @\exposid{iterator}@{*this, ranges::begin(@\exposid{base_}@)}; + } + else { + @\exposid{outer_it_}@ = ranges::begin(@\exposid{base_}@); + return @\exposid{iterator}@{*this}; + } } constexpr auto begin() const - requires @\libconcept{input_range}@ && + requires @\libconcept{forward_range}@ && @\libconcept{forward_range}@ && - is_reference_v> { + is_reference_v> && + @\libconcept{input_range}@> && + @\exposconcept{concatable}@, const Pattern> { return @\exposid{iterator}@{*this, ranges::begin(@\exposid{base_}@)}; } @@ -6957,10 +7255,12 @@ return @\exposid{sentinel}@<@\exposconcept{simple-view}@ && @\exposconcept{simple-view}@>{*this}; } constexpr auto end() const - requires @\libconcept{input_range}@ && @\libconcept{forward_range}@ && - is_reference_v> { + requires @\libconcept{forward_range}@ && @\libconcept{forward_range}@ && + is_reference_v> && + @\libconcept{input_range}@> && + @\exposconcept{concatable}@, const Pattern> { using InnerConstRng = range_reference_t; - if constexpr (@\libconcept{forward_range}@ && @\libconcept{forward_range}@ && + if constexpr (@\libconcept{forward_range}@ && @\libconcept{common_range}@ && @\libconcept{common_range}@) return @\exposid{iterator}@{*this, ranges::end(@\exposid{base_}@)}; else @@ -6977,8 +7277,9 @@ } \end{codeblock} +\indexlibraryctor{join_with_view}% \begin{itemdecl} -constexpr join_with_view(V base, Pattern pattern); +constexpr explicit join_with_view(V base, Pattern pattern); \end{itemdecl} \begin{itemdescr} @@ -6988,11 +7289,12 @@ \exposid{pattern_} with \tcode{std::move(pattern)}. \end{itemdescr} +\indexlibraryctor{join_with_view}% \begin{itemdecl} template<@\libconcept{input_range}@ R> requires @\libconcept{constructible_from}@> && @\libconcept{constructible_from}@>> -constexpr join_with_view(R&& r, range_value_t<@\exposid{InnerRng}@> e); +constexpr explicit join_with_view(R&& r, range_value_t<@\exposid{InnerRng}@> e); \end{itemdecl} \begin{itemdescr} @@ -7004,11 +7306,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 @@ -7023,12 +7326,18 @@ static constexpr bool @\exposid{ref-is-glvalue}@ = is_reference_v<@\exposid{InnerBase}@>; // \expos @\exposid{Parent}@* @\exposid{parent_}@ = nullptr; // \expos - @\exposid{OuterIter}@ @\exposid{outer_it_}@ = @\exposid{OuterIter}@(); // \expos + @\exposid{OuterIter}@ @\exposid{outer_it_}@ = @\exposid{OuterIter}@(); // \expos, present only + // if \exposid{Base} models \libconcept{forward_range} variant<@\exposid{PatternIter}@, @\exposid{InnerIter}@> @\exposid{inner_it_}@; // \expos - constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> outer); // \expos - constexpr auto&& @\exposid{update-inner}@(const @\exposid{OuterIter}@&); // \expos - constexpr auto&& @\exposid{get-inner}@(const @\exposid{OuterIter}@&); // \expos + constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{OuterIter}@ outer) + requires @\libconcept{forward_range}@<@\exposid{Base}@>; // \expos + constexpr explicit @\exposid{iterator}@(@\exposid{Parent}@& parent) + requires (!@\libconcept{forward_range}@<@\exposid{Base}@>); // \expos + constexpr @\exposid{OuterIter}@& @\exposid{outer}@(); // \expos + constexpr const @\exposid{OuterIter}@& @\exposid{outer}@() const; // \expos + constexpr auto& @\exposid{update-inner}@(); // \expos + constexpr auto& @\exposid{get-inner}@(); // \expos constexpr void @\exposid{satisfy}@(); // \expos public: @@ -7037,30 +7346,30 @@ using value_type = @\seebelow@; using difference_type = @\seebelow@; - @\exposid{iterator}@() requires @\libconcept{default_initializable}@<@\exposid{OuterIter}@> = default; + @\exposid{iterator}@() = default; constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, @\exposid{OuterIter}@> && - @\libconcept{convertible_to}@, @\exposid{InnerIter}@> && - @\libconcept{convertible_to}@, @\exposid{PatternIter}@>; + requires Const && @\libconcept{convertible_to}@, @\exposid{OuterIter}@> && + @\libconcept{convertible_to}@, @\exposid{InnerIter}@> && + @\libconcept{convertible_to}@, @\exposid{PatternIter}@>; constexpr decltype(auto) operator*() const; constexpr @\exposid{iterator}@& operator++(); constexpr void operator++(int); constexpr @\exposid{iterator}@ operator++(int) - requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_iterator}@<@\exposid{OuterIter}@> && - @\libconcept{forward_iterator}@<@\exposid{InnerIter}@>; + requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_iterator}@<@\exposid{OuterIter}@> && + @\libconcept{forward_iterator}@<@\exposid{InnerIter}@>; constexpr @\exposid{iterator}@& operator--() - requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && - @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; + requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && + @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; constexpr @\exposid{iterator}@ operator--(int) - requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && - @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; + requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && + @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposid{ref-is-glvalue}@ && @\libconcept{equality_comparable}@<@\exposid{OuterIter}@> && - @\libconcept{equality_comparable}@<@\exposid{InnerIter}@>; + requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> && + @\libconcept{equality_comparable}@<@\exposid{InnerIter}@>; friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& x) { using rvalue_reference = common_reference_t< @@ -7070,7 +7379,7 @@ } friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{indirectly_swappable}@<@\exposid{InnerIter}@, @\exposid{PatternIter}@> { + requires @\libconcept{indirectly_swappable}@<@\exposid{InnerIter}@, @\exposid{PatternIter}@> { visit(ranges::iter_swap, x.@\exposid{inner_it_}@, y.@\exposid{inner_it_}@); } }; @@ -7112,15 +7421,15 @@ \item If \begin{codeblock} -is_lvalue_reference_v, - iter_reference_t<@\exposid{PatternIter}@>>> +is_reference_v, + iter_reference_t<@\exposid{PatternIter}@>>> \end{codeblock} is \tcode{false}, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. \item Otherwise, if \placeholder{OUTERC}, \placeholder{INNERC}, and \placeholder{PATTERNC} -each model \tcode{\libconcept{derived_from}} +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}. @@ -7143,13 +7452,25 @@ \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} \begin{itemdecl} -constexpr auto&& @\exposid{update-inner}@(const @\exposid{OuterIter}@& x); +constexpr @\exposid{OuterIter}@& @\exposid{outer}@(); +constexpr const @\exposid{OuterIter}@& @\exposid{outer}@() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{outer_it_} if \exposid{Base} models \libconcept{forward_range}; +otherwise, \tcode{*\exposid{parent_}->\exposid{outer_it_}}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto& @\exposid{update-inner}@(); \end{itemdecl} \begin{itemdescr} @@ -7158,14 +7479,14 @@ Equivalent to: \begin{codeblock} if constexpr (@\exposid{ref-is-glvalue}@) - return *x; + return @\exposid{as-lvalue}@(*@\exposid{outer}@()); else - return @\exposid{parent_}@->@\exposid{inner_}@.@\exposid{emplace-deref}@(x); + return @\exposid{parent_}@->@\exposid{inner_}@.@\exposid{emplace-deref}@(@\exposid{outer}@()); \end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr auto&& @\exposid{get-inner}@(const @\exposid{OuterIter}@& x); +constexpr auto& @\exposid{get-inner}@(); \end{itemdecl} \begin{itemdescr} @@ -7174,7 +7495,7 @@ Equivalent to: \begin{codeblock} if constexpr (@\exposid{ref-is-glvalue}@) - return *x; + return @\exposid{as-lvalue}@(*@\exposid{outer}@()); else return *@\exposid{parent_}@->@\exposid{inner_}@; \end{codeblock} @@ -7193,18 +7514,16 @@ if (@\exposid{inner_it_}@.index() == 0) { if (std::get<0>(@\exposid{inner_it_}@) != ranges::end(@\exposid{parent_}@->@\exposid{pattern_}@)) break; - auto&& inner = @\exposid{update-inner}@(@\exposid{outer_it_}@); - @\exposid{inner_it_}@.emplace<1>(ranges::begin(inner)); + @\exposid{inner_it_}@.template emplace<1>(ranges::begin(@\exposid{update-inner}@())); } else { - auto&& inner = @\exposid{get-inner}@(@\exposid{outer_it_}@); - if (std::get<1>(@\exposid{inner_it_}@) != ranges::end(inner)) + if (std::get<1>(@\exposid{inner_it_}@) != ranges::end(@\exposid{get-inner}@())) break; - if (++@\exposid{outer_it_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { + 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} @@ -7216,19 +7535,22 @@ \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> outer); +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{OuterIter}@ outer) + requires @\libconcept{forward_range}@<@\exposid{Base}@>; +constexpr explicit @\exposid{iterator}@(@\exposid{Parent}@& parent) + requires (!@\libconcept{forward_range}@<@\exposid{Base}@>); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{addressof(parent)} and +Initializes \exposid{parent_} with \tcode{addressof(parent)}. +For the first overload, also initializes \exposid{outer_it_} with \tcode{std::move(outer)}. Then, equivalent to: \begin{codeblock} -if (@\exposid{outer_it_}@ != ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { - auto&& inner = @\exposid{update-inner}@(@\exposid{outer_it_}@); - @\exposid{inner_it_}@.emplace<1>(ranges::begin(inner)); +if (@\exposid{outer}@() != ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { + @\exposid{inner_it_}@.template emplace<1>(ranges::begin(@\exposid{update-inner}@())); @\exposidnc{satisfy}@(); } \end{codeblock} @@ -7250,12 +7572,19 @@ 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 +\begin{note} +\tcode{Const} can only be \tcode{true} +when \exposid{Base} models \libconcept{forward_range}. +\end{note} \end{itemdescr} +\indexlibrarymember{operator--}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr decltype(auto) operator*() const; \end{itemdecl} @@ -7271,6 +7600,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -7286,6 +7616,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -7296,6 +7627,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}@>; @@ -7312,6 +7644,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}@> && @@ -7325,7 +7658,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) { @@ -7333,7 +7666,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; } @@ -7341,7 +7674,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; } @@ -7352,6 +7685,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}@> && @@ -7371,7 +7705,7 @@ \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposid{ref-is-glvalue}@ && @\libconcept{equality_comparable}@<@\exposid{OuterIter}@> && + requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> && @\libconcept{equality_comparable}@<@\exposid{InnerIter}@>; \end{itemdecl} @@ -7386,11 +7720,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 @@ -7441,7 +7776,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{outer_it_} == y.\exposid{end_};} +Equivalent to: \tcode{return x.\exposid{outer}() == y.\exposid{end_};} \end{itemdescr} \rSec2[range.lazy.split]{Lazy split view} @@ -7449,9 +7784,9 @@ \rSec3[range.lazy.split.overview]{Overview} \pnum -\tcode{lazy_split_view} takes a \libconcept{view} and a delimiter, and splits -the \libconcept{view} into subranges on the delimiter. The delimiter can be -a single element or a \libconcept{view} of elements. +\tcode{lazy_split_view} takes a view and a delimiter, and splits +the view into subranges on the delimiter. The delimiter can be +a single element or a view of elements. \pnum \indexlibrarymember{lazy_split}{views}% @@ -7500,7 +7835,7 @@ Pattern @\exposid{pattern_}@ = Pattern(); // \expos @\exposidnc{non-propagating-cache}@> @\exposid{current_}@; // \expos, present only - // if \tcode{!\libconcept{forward_range}} + // if \tcode{\libconcept{forward_range}} is \tcode{false} // \ref{range.lazy.split.outer}, class template \tcode{lazy_split_view::\exposid{outer-iterator}} template struct @\exposidnc{outer-iterator}@; // \expos @@ -7511,12 +7846,12 @@ public: lazy_split_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; - constexpr lazy_split_view(V base, Pattern pattern); + constexpr explicit lazy_split_view(V base, Pattern pattern); template<@\libconcept{input_range}@ R> requires @\libconcept{constructible_from}@> && @\libconcept{constructible_from}@>> - constexpr lazy_split_view(R&& r, range_value_t e); + constexpr explicit lazy_split_view(R&& r, range_value_t e); constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } @@ -7559,7 +7894,7 @@ \indexlibraryctor{lazy_split_view}% \begin{itemdecl} -constexpr lazy_split_view(V base, Pattern pattern); +constexpr explicit lazy_split_view(V base, Pattern pattern); \end{itemdecl} \begin{itemdescr} @@ -7574,7 +7909,7 @@ template<@\libconcept{input_range}@ R> requires @\libconcept{constructible_from}@> && @\libconcept{constructible_from}@>> -constexpr lazy_split_view(R&& r, range_value_t e); +constexpr explicit lazy_split_view(R&& r, range_value_t e); \end{itemdecl} \begin{itemdescr} @@ -7684,8 +8019,9 @@ \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and -\exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}}, +\exposid{current_} with \tcode{std::move(i.\exposid{current_})}, and +\exposid{trailing_empty_} with \tcode{i.\exposid{trailing_empty_}}. \end{itemdescr} \indexlibrarymember{operator*}{lazy_split_view::\exposid{outer-iterator}}% @@ -7782,10 +8118,10 @@ : view_interface { 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; }; @@ -8011,9 +8347,9 @@ \rSec3[range.split.overview]{Overview} \pnum -\tcode{split_view} takes a \libconcept{view} and a delimiter, and -splits the \libconcept{view} into \tcode{subrange}s on the delimiter. -The delimiter can be a single element or a \libconcept{view} of elements. +\tcode{split_view} takes a view and a delimiter, and +splits the view into \tcode{subrange}s on the delimiter. +The delimiter can be a single element or a view of elements. \pnum The name \tcode{views::split} denotes @@ -8026,8 +8362,8 @@ \begin{example} \begin{codeblock} string str{"the quick brown fox"}; -for (string_view word : views::split(str, ' ')) { - cout << word << '*'; +for (auto word : views::split(str, ' ')) { + cout << string_view(word) << '*'; } // The above prints \tcode{the*quick*brown*fox*} \end{codeblock} @@ -8035,6 +8371,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> @@ -8054,12 +8391,12 @@ public: split_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; - constexpr split_view(V base, Pattern pattern); + constexpr explicit split_view(V base, Pattern pattern); template<@\libconcept{forward_range}@ R> requires @\libconcept{constructible_from}@> && @\libconcept{constructible_from}@>> - constexpr split_view(R&& r, range_value_t e); + constexpr explicit split_view(R&& r, range_value_t e); constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } @@ -8086,8 +8423,9 @@ } \end{codeblock} +\indexlibraryctor{split_view} \begin{itemdecl} -constexpr split_view(V base, Pattern pattern); +constexpr explicit split_view(V base, Pattern pattern); \end{itemdecl} \begin{itemdescr} @@ -8102,7 +8440,7 @@ template<@\libconcept{forward_range}@ R> requires @\libconcept{constructible_from}@> && @\libconcept{constructible_from}@>> -constexpr split_view(R&& r, range_value_t e); +constexpr explicit split_view(R&& r, range_value_t e); \end{itemdecl} \begin{itemdescr} @@ -8112,6 +8450,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} @@ -8149,6 +8488,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> @@ -8181,6 +8521,7 @@ } \end{codeblock} +\indexlibraryctor{split_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(split_view& parent, iterator_t current, subrange> next); \end{itemdecl} @@ -8193,6 +8534,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} @@ -8200,9 +8542,10 @@ \begin{itemdescr} \pnum \effects -Equivalent to \tcode{return \exposid{cur_};} +Equivalent to: \tcode{return \exposid{cur_};} \end{itemdescr} +\indexlibrarymember{operator*}{split_view::\exposid{iterator}}% \begin{itemdecl} constexpr value_type operator*() const; \end{itemdecl} @@ -8210,9 +8553,10 @@ \begin{itemdescr} \pnum \effects -Equivalent to \tcode{return \{\exposid{cur_}, \exposid{next_}.begin()\};} +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} @@ -8238,6 +8582,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{split_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} @@ -8253,6 +8598,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} @@ -8268,6 +8614,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> @@ -8286,6 +8633,7 @@ } \end{codeblock} +\indexlibraryctor{split_view::\exposid{sentinel}}% \begin{itemdecl} constexpr explicit @\exposid{sentinel}@(split_view& parent); \end{itemdecl} @@ -8296,6 +8644,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} @@ -8306,668 +8655,2883 @@ 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 \libconcept{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: - -\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 \libconcept{view} which has different types for -its iterator and sentinel and turns it into a \libconcept{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: +Given a pack of subexpressions \tcode{Es...}, +the expression \tcode{views::concat(Es...)} 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\}}. +\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} - -\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()); - // ... +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} -\rSec3[range.common.view]{Class template \tcode{common_view}} +\rSec3[range.concat.view]{Class template \tcode{concat_view}} -\indexlibraryglobal{common_view}% -\indexlibrarymember{base}{common_view}% -\indexlibrarymember{size}{common_view}% -\indexlibrarymember{begin}{common_view}% -\indexlibrarymember{end}{common_view}% +\indexlibraryglobal{concat_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; + 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...>; - constexpr explicit common_view(V r); + 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 - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && + @\exposconcept{concatable}@ + class concat_view : public view_interface> { - 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_}@)); - } + tuple @\exposidnc{views_}@; // \expos - 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_}@)); - } + // \ref{range.concat.iterator}, class template \tcode{concat_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos - constexpr auto end() { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@) + ranges::size(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); - } + public: + constexpr concat_view() = default; + constexpr explicit concat_view(Views... views); - constexpr auto end() const requires @\libconcept{range}@ { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@) + ranges::size(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); - } + constexpr @\exposid{iterator}@ begin() requires (!(@\exposconcept{simple-view}@ && ...)); + constexpr @\exposid{iterator}@ begin() const + requires (@\libconcept{range}@ && ...) && @\exposconcept{concatable}@; - 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}@ && ...)); + constexpr auto end() const + requires (@\libconcept{range}@ && ...) && @\exposconcept{concatable}@; + + constexpr auto size() requires (@\libconcept{sized_range}@ && ...); + constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); }; - template - common_view(R&&) -> common_view>; + template + concat_view(R&&...) -> concat_view...>; } \end{codeblock} -\indexlibraryctor{common_view}% \begin{itemdecl} -constexpr explicit common_view(V base); +template + concept @\defexposconcept{concat-indirectly-readable}@ = @\seebelow@; // \expos \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{base_} with \tcode{std::move(base)}. -\end{itemdescr} - -\rSec2[range.reverse]{Reverse view} +The exposition-only \exposconcept{concat-indirectly-readable} concept +is equivalent to: +\begin{codeblock} +template + concept @\defexposconcept{concat-indirectly-readable-impl}@ = // \expos + requires (const It it) { + { *it } -> @\libconcept{convertible_to}@; + { ranges::iter_move(it) } -> @\libconcept{convertible_to}@; + }; -\rSec3[range.reverse.overview]{Overview} +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} -\pnum -\tcode{reverse_view} takes a bidirectional \libconcept{view} and produces -another \libconcept{view} that iterates the same elements in reverse order. +\begin{itemdecl} +template + concept @\defexposconcept{concatable}@ = @\seebelow@; // \expos +\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: -\begin{codeblock} -subrange(E.end().base(), E.begin().base(), E.size()) -\end{codeblock} - \item - otherwise, equivalent to: +The exposition-only \exposconcept{concatable} concept is equivalent to: \begin{codeblock} -subrange(E.end().base(), E.begin().base()) +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{itemize} - However, in either case \tcode{E} is evaluated only once. -\item - Otherwise, equivalent to \tcode{reverse_view\{E\}}. -\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + concept @\defexposconcept{concat-is-random-access}@ = @\seebelow@; // \expos +\end{itemdecl} +\begin{itemdescr} \pnum -\begin{example} +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} -vector is {0,1,2,3,4}; -for (int i : is | views::reverse) - cout << i << ' '; // prints \tcode{4 3 2 1 0} +template + concept @\exposconcept{concat-is-random-access}@ = // \expos + @\exposconcept{all-random-access}@ && + (@\libconcept{common_range}@<@\exposid{maybe-const}@> && ...); \end{codeblock} -\end{example} +\end{itemdescr} -\rSec3[range.reverse.view]{Class template \tcode{reverse_view}} +\begin{itemdecl} +template + concept @\defexposconcept{concat-is-bidirectional}@ = @\seebelow@; // \expos +\end{itemdecl} -\indexlibraryglobal{reverse_view}% -\indexlibrarymember{base}{reverse_view}% -\indexlibrarymember{size}{reverse_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} -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_}@); - } - }; - - template - reverse_view(R&&) -> reverse_view>; -} +template + concept @\exposconcept{concat-is-bidirectional}@ = // \expos + @\exposconcept{all-bidirectional}@ && + (@\libconcept{common_range}@<@\exposid{maybe-const}@> && ...); \end{codeblock} +\end{itemdescr} -\indexlibraryctor{reverse_view}% +\indexlibraryctor{concat_view}% \begin{itemdecl} -constexpr explicit reverse_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} -\indexlibrarymember{begin}{reverse_view}% +\indexlibrarymember{begin}{concat_view}% \begin{itemdecl} -constexpr reverse_iterator> begin(); +constexpr @\exposid{iterator}@ begin() requires (!(@\exposconcept{simple-view}@ && ...)); +constexpr @\exposid{iterator}@ begin() const + requires (@\libconcept{range}@ && ...) && @\exposconcept{concatable}@; \end{itemdecl} \begin{itemdescr} \pnum -\returns +\effects +Let \exposid{is-const} be +\tcode{true} for the const-qualified overload, and +\tcode{false} otherwise. +Equivalent to: \begin{codeblock} -make_reverse_iterator(ranges::next(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@))) +@\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} - -\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{end}{concat_view}% \begin{itemdecl} -constexpr reverse_iterator> begin() requires @\libconcept{common_range}@; -constexpr auto begin() const requires @\libconcept{common_range}@; +constexpr auto end() requires (!(@\exposconcept{simple-view}@ && ...)); +constexpr auto end() const + requires (@\libconcept{range}@ && ...) && @\exposconcept{concatable}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return make_reverse_iterator(ranges::end(\exposid{base_}));} +Let \exposid{is-const} be +\tcode{true} for the const-qualified overload, and +\tcode{false} otherwise. +Equivalent to: +\begin{codeblock} +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{itemdescr} -\indexlibrarymember{end}{reverse_view}% +\indexlibrarymember{size}{concat_view}% \begin{itemdecl} -constexpr reverse_iterator> end(); -constexpr auto end() const requires @\libconcept{common_range}@; +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 make_reverse_iterator(ranges::begin(\exposid{base_}));} +Equivalent to: +\begin{codeblock} +return apply( + [](auto... sizes) { + using CT = @\exposid{make-unsigned-like-t}@>; + return (CT(sizes) + ...); + }, + @\exposid{tuple-transform}@(ranges::size, @\exposid{views_}@)); +\end{codeblock} \end{itemdescr} -\rSec2[range.as.const]{As const view} +\rSec3[range.concat.iterator]{Class \tcode{concat_view::\exposid{iterator}}} -\rSec3[range.as.const.overview]{Overview} +\indexlibrarymember{iterator}{concat_view}% +\indexlibraryglobal{concat_view::\exposid{iterator}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && + @\exposconcept{concatable}@ + template + class concat_view::@\exposid{iterator}@ { -\pnum -\tcode{as_const_view} presents a \libconcept{view} of an underlying sequence as constant. -That is, the elements of an \tcode{as_const_view} cannot be modified. + public: + 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>...>; -\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: + private: + using @\exposid{base-iter}@ = // \expos + variant>...>; + + @\exposid{maybe-const}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposid{base-iter}@ @\exposid{it_}@; // \expos + + template + constexpr void @\exposid{satisfy}@(); // \expos + template + constexpr void @\exposid{prev}@(); // \expos + + 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); + + template + constexpr explicit @\exposid{iterator}@(@\exposid{maybe-const}@* parent, // \expos + Args&&... args) + requires @\libconcept{constructible_from}@<@\exposid{base-iter}@, Args&&...>; + + public: + @\exposid{iterator}@() = default; + + 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} + +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: \begin{itemize} \item -If \tcode{views::all_t} models \libconcept{constant_range}, -then \tcode{views::all(E)}. +If +\tcode{\exposconcept{concat-is-random-access}} is modeled, +then \tcode{iterator_concept} denotes \tcode{ran\-dom_access_iterator_tag}. \item -Otherwise, -if \tcode{U} denotes \tcode{span} -for some type \tcode{X} and some extent \tcode{Extent}, -then \tcode{span(E)}. +Otherwise, if +\tcode{\exposconcept{concat-is-bidirectional}} is modeled, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. \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))}. +Otherwise, if +\tcode{\exposconcept{all-forward}} is modeled, +then \tcode{iterator_concept} denotes \tcode{for\-ward_iterator_tag}. \item -Otherwise, \tcode{as_const_view(E)}. +Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. \end{itemize} \pnum -\begin{example} -\begin{codeblock} -template -void cant_touch_this(R&&); +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: -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} +\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}. -\rSec3[range.as.const.view]{Class template \tcode{as_const_view}} +\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} +template + constexpr void @\exposid{satisfy}@(); +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to: \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 +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} +\end{itemdescr} - public: - as_const_view() requires @\libconcept{default_initializable}@ = default; - constexpr explicit as_const_view(V base); +\indexlibrarymember{\exposid{prev}}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +template + constexpr void @\exposid{prev}@(); +\end{itemdecl} - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } +\begin{itemdescr} +\pnum +\effects +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} - constexpr auto begin() requires (!@\exposconcept{simple-view}@) { return ranges::cbegin(@\exposid{base_}@); } - constexpr auto begin() const requires @\libconcept{range}@ { return ranges::cbegin(@\exposid{base_}@); } +\indexlibrarymember{\exposid{advance-fwd}}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +template + constexpr void @\exposid{advance-fwd}@(difference_type offset, difference_type steps); +\end{itemdecl} - constexpr auto end() requires (!@\exposconcept{simple-view}@) { return ranges::cend(@\exposid{base_}@); } - constexpr auto end() const requires @\libconcept{range}@ { return ranges::cend(@\exposid{base_}@); } +\begin{itemdescr} +\pnum +\effects +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} - 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_}@); } - }; +\indexlibrarymember{\exposid{advance-bwd}}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +template + constexpr void @\exposid{advance-bwd}@(difference_type offset, difference_type steps); +\end{itemdecl} - template - as_const_view(R&&) -> as_const_view>; +\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} -constexpr explicit as_const_view(V base); +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{base_} with \tcode{std::move(base)}. +Initializes \exposid{parent_} with \tcode{parent}, and +initializes \exposid{it_} with \tcode{std::forward(args)...}. \end{itemdescr} -\rSec2[range.elements]{Elements view} - -\rSec3[range.elements.overview]{Overview} +\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 -\tcode{elements_view} takes -a \libconcept{view} of tuple-like values and a \tcode{size_t}, and -produces a \libconcept{view} with a value-type of the $N^\text{th}$ element -of the adapted \libconcept{view}'s value-type. +\expects +\tcode{it.\exposid{it_}.valueless_by_exception()} is \tcode{false}. \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 +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} -\begin{example} -\begin{codeblock} -auto historical_figures = map{ - pair{"Lovelace"sv, 1815}, - {"Turing"sv, 1912}, - {"Babbage"sv, 1791}, - {"Hamilton"sv, 1936} -}; +\indexlibrarymember{operator*}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr decltype(auto) operator*() const; +\end{itemdecl} -auto names = historical_figures | views::elements<0>; -for (auto&& name : names) { - cout << name << ' '; // prints \tcode{Babbage Hamilton Lovelace Turing } -} +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}. -auto birth_years = historical_figures | views::elements<1>; -for (auto&& born : birth_years) { - cout << born << ' '; // prints \tcode{1791 1936 1815 1912 } -} +\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{example} +\end{itemdescr} + +\indexlibrarymember{operator++}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} +\begin{itemdescr} \pnum -\tcode{keys_view} is an alias for \tcode{elements_view}, and -is useful for extracting keys from associative containers. +\expects +\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}. -\begin{example} +\pnum +\effects +Let \tcode{$i$} be \tcode{\exposid{it_}.index()}. +Equivalent to: \begin{codeblock} -auto names = historical_figures | views::keys; -for (auto&& name : names) { - cout << name << ' '; // prints \tcode{Babbage Hamilton Lovelace Turing } -} +++std::get<@$i$@>(@\exposid{it_}@); +@\exposid{satisfy}@<@$i$@>(); +return *this; \end{codeblock} -\end{example} +\end{itemdescr} + +\indexlibrarymember{operator++}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} +\begin{itemdescr} \pnum -\tcode{values_view} is an alias for \tcode{elements_view}, and -is useful for extracting values from associative containers. +\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} + +\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} + +\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 +\effects +Equivalent to: \tcode{return \exposid{iterator}\{x\} -= y;} +\end{itemdescr} + +\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 +\effects +Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{current_};} +\end{itemdescr} + +\rSec3[range.elements.sentinel]{Class template \tcode{elements_view::\exposid{sentinel}}} + +\indexlibraryglobal{elements_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 + 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: + @\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 sentinel_t<@\exposid{Base}@> base() const; + + 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}@& x, const @\exposid{iterator}@& y); + }; +} +\end{codeblock} + +\indexlibraryctor{elements_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{end}. +\end{itemdescr} + +\indexlibraryctor{elements_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +\end{itemdecl} + +\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 +\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 +\effects +Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};} +\end{itemdescr} + +\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} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};} +\end{itemdescr} + +\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 +\effects +Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};} +\end{itemdescr} + +\rSec2[range.enumerate]{Enumerate view} + +\rSec3[range.enumerate.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. + +\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} +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.enumerate.view]{Class template \tcode{enumerate_view}} + +\indexlibraryglobal{enumerate_view}% +\indexlibrarymember{begin}{enumerate_view}% +\indexlibrarymember{end}{enumerate_view}% +\indexlibrarymember{size}{enumerate_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 + + // \ref{range.enumerate.iterator}, class template \tcode{enumerate_view::\exposid{iterator}} + template + class @\exposidnc{iterator}@; // \expos + + // \ref{range.enumerate.sentinel}, class template \tcode{enumerate_view::\exposid{sentinel}} + template + class @\exposidnc{sentinel}@; // \expos + + public: + constexpr enumerate_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit enumerate_view(V 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() 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_}@); } + + 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_}@); } + + 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{enumerate_view}% +\begin{itemdecl} +constexpr explicit enumerate_view(V base); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. +\end{itemdescr} + +\rSec3[range.enumerate.iterator]{Class template \tcode{enumerate_view::\exposid{iterator}}} + +\indexlibraryglobal{enumerate_view::\exposid{iterator}}% +\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 + + constexpr explicit + @\exposidnc{iterator}@(iterator_t<@\exposidnc{Base}@> current, difference_type pos); // \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; + + constexpr auto operator*() const { + return @\exposid{reference-type}@(@\exposid{pos_}@, *@\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 auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@> + { return @\exposid{reference-type}@(@\exposid{pos_}@ + n, @\exposid{current_}@[n]); } + + 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}@>; + 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 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{\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, 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} + +\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} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})} and +\exposid{pos_} with \tcode{i.\exposid{pos_}}. +\end{itemdescr} + +\indexlibrarymember{base}{enumerate_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}{enumerate_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{index}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr difference_type index() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{pos_};} +\end{itemdescr} + +\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +++@\exposid{current_}@; +++@\exposid{pos_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{++*this}. +\end{itemdescr} + +\indexlibrarymember{operator++}{enumerate_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; +++*this; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{enumerate_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_}@; +--@\exposid{pos_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{enumerate_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; +--*this; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+=}{enumerate_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; +@\exposid{pos_}@ += n; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-=}{enumerate_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; +@\exposid{pos_}@ -= n; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator==}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{pos_} == y.\exposid{pos_};} +\end{itemdescr} + +\indexlibrarymember{operator<=>}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +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{pos_} <=> y.\exposid{pos_};} +\end{itemdescr} + +\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}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = x; +temp += y; +return temp; +\end{codeblock} +\end{itemdescr} + +\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}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return y + x;} +\end{itemdescr} + +\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}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = x; +temp -= y; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +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{pos_} - y.\exposid{pos_};} +\end{itemdescr} + +\rSec3[range.enumerate.sentinel]{Class template \tcode{enumerate_view::\exposid{sentinel}}} + +\indexlibraryglobal{enumerate_view::\exposid{sentinel}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\exposconcept{range-with-movable-references}@ + 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 + + 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; + + 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}@& x, const @\exposid{iterator}@& y); + }; +} +\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}}% +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}. +\end{itemdescr} + +\indexlibrarymember{base}{enumerate_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr sentinel_t<@\exposid{Base}@> base() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{end_};} +\end{itemdescr} + +\indexlibrarymember{operator==}{enumerate_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 +\effects +Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};} +\end{itemdescr} + +\indexlibrarymember{operator-}{enumerate_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} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};} +\end{itemdescr} + +\indexlibrarymember{operator-}{enumerate_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 +\effects +Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};} +\end{itemdescr} + +\rSec2[range.zip]{Zip view} + +\rSec3[range.zip.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. + +\pnum +\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} -auto is_even = [](const auto x) { return x % 2 == 0; }; -cout << ranges::count_if(historical_figures | views::values, is_even); // prints \tcode{2} +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.elements.view]{Class template \tcode{elements_view}} +\rSec3[range.zip.view]{Class template \tcode{zip_view}} -\indexlibraryglobal{elements_view}% -\indexlibrarymember{base}{elements_view}% -\indexlibrarymember{begin}{elements_view}% -\indexlibrarymember{end}{elements_view}% -\indexlibrarymember{size}{elements_view}% +\indexlibraryglobal{zip_view}% +\indexlibrarymember{begin}{zip_view}% +\indexlibrarymember{end}{zip_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); + 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}@ && ...)); - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) + class zip_view : public view_interface> { + tuple @\exposid{views_}@; // \expos - constexpr auto begin() requires (!@\exposconcept{simple-view}@) - { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@)); } + // \ref{range.zip.iterator}, class template \tcode{zip_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos - constexpr auto begin() const requires @\libconcept{range}@ - { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@)); } + // \ref{range.zip.sentinel}, class template \tcode{zip_view::\exposid{sentinel}} + template class @\exposidnc{sentinel}@; // \expos - constexpr auto end() requires (!@\exposconcept{simple-view}@ && !@\libconcept{common_range}@) - { return @\exposid{sentinel}@{ranges::end(@\exposid{base_}@)}; } + public: + zip_view() = default; + constexpr explicit zip_view(Views... views); - constexpr auto end() requires (!@\exposconcept{simple-view}@ && @\libconcept{common_range}@) - { return @\exposid{iterator}@{ranges::end(@\exposid{base_}@)}; } + constexpr auto begin() requires (!(@\exposconcept{simple-view}@ && ...)) { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); + } + constexpr auto begin() const requires (@\libconcept{range}@ && ...) { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); + } - constexpr auto end() const requires @\libconcept{range}@ - { return @\exposid{sentinel}@{ranges::end(@\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 auto end() const requires @\libconcept{common_range}@ - { return @\exposid{iterator}@{ranges::end(@\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}@ - { return ranges::size(@\exposid{base_}@); } + constexpr auto size() requires (@\libconcept{sized_range}@ && ...); + constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); + }; - constexpr auto size() const requires @\libconcept{sized_range}@ - { return ranges::size(@\exposid{base_}@); } + template + zip_view(Rs&&...) -> zip_view...>; +} +\end{codeblock} - private: - // \ref{range.elements.iterator}, class template \tcode{elements_view::\exposid{iterator}} - template class @\exposid{iterator}@; // \expos +\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} - // \ref{range.elements.sentinel}, class template \tcode{elements_view::\exposid{sentinel}} - template class @\exposid{sentinel}@; // \expos +\indexlibraryctor{zip_view}% +\begin{itemdecl} +constexpr explicit zip_view(Views... views); +\end{itemdecl} - V @\exposid{base_}@ = V(); // \expos - }; -} -\end{codeblock} +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{views_} with \tcode{std::move(views)...}. +\end{itemdescr} -\indexlibraryctor{elements_view}% +\indexlibrarymember{size}{zip_view}% \begin{itemdecl} -constexpr explicit elements_view(V base); +constexpr auto size() requires (@\libconcept{sized_range}@ && ...); +constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{base_} with \tcode{std::move(base)}. +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} \end{itemdescr} -\rSec3[range.elements.iterator]{Class template \tcode{elements_view::\exposid{iterator}}} +\rSec3[range.zip.iterator]{Class template \tcode{zip_view::\exposid{iterator}}} -\indexlibraryglobal{elements_view::iterator}% +\indexlibraryglobal{zip_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{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) 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 zip_view::@\exposid{iterator}@ { + tuple>...> @\exposid{current_}@;@\itcorr[-1]@ // \expos + constexpr explicit @\exposidnc{iterator}@(tuple>...>); + // \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}@>; + using iterator_category = input_iterator_tag; // not always present + using iterator_concept = @\seebelow@; + using value_type = tuple>...>; + using difference_type = common_type_t>...>; - @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; - constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); + @\exposid{iterator}@() = 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 decltype(auto) operator*() const - { return @\exposid{get-element}@(@\exposid{current_}@); } + 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 decltype(auto) operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@> - { return @\exposid{get-element}@(@\exposid{current_}@ + n); } + constexpr auto operator[](difference_type n) const + requires @\exposconcept{all-random-access}@; friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@>; + 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 @\exposconcept{all-random-access}@; - 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 @\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{Base}@>>; + 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{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}, -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}. +Otherwise, +if \tcode{\exposconcept{all-bidirectional}} is modeled, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. \item -Otherwise, \tcode{iterator_category} denotes \tcode{C}. +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} -\indexlibrarymember{\exposid{get-element}}{elements_view::iterator}% -\begin{itemdecl} -static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i); -\end{itemdecl} +\pnum +\tcode{\exposid{iterator}::iterator_category} is present +if and only if \tcode{\exposconcept{all-forward}} is modeled. -\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} +If the invocation of any non-const member function of \exposid{iterator} +exits via an exception, +the iterator acquires a singular value. -\indexlibraryctor{elements_view::iterator}% +\indexlibraryctor{zip_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); +constexpr explicit @\exposid{iterator}@(tuple>...> current); \end{itemdecl} \begin{itemdescr} @@ -8976,10 +11540,10 @@ Initializes \exposid{current_} with \tcode{std::move(current)}. \end{itemdescr} -\indexlibraryctor{elements_view::iterator}% +\indexlibraryctor{zip_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; + requires Const && (@\libconcept{convertible_to}@, iterator_t> && ...); \end{itemdecl} \begin{itemdescr} @@ -8988,29 +11552,21 @@ Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}. \end{itemdescr} -\indexlibrarymember{base}{elements_view::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::iterator}% +\indexlibrarymember{operator*}{izip_view::\exposid{iterator}}% \begin{itemdecl} -constexpr iterator_t<@\exposid{Base}@> base() &&; +constexpr auto operator*() const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return std::move(\exposid{current_});} +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{elements_view::iterator}% +\indexlibrarymember{operator++}{izip_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -9020,12 +11576,12 @@ \effects Equivalent to: \begin{codeblock} -++@\exposid{current_}@; +@\exposid{tuple-for-each}@([](auto& i) { ++i; }, @\exposid{current_}@); return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{elements_view::iterator}% +\indexlibrarymember{operator++}{izip_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -9033,12 +11589,12 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{++\exposid{current_}}. +Equivalent to \tcode{++*this}. \end{itemdescr} -\indexlibrarymember{operator++}{elements_view::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} @@ -9046,15 +11602,15 @@ \effects Equivalent to: \begin{codeblock} -auto temp = *this; -++@\exposid{current_}@; -return temp; +auto tmp = *this; +++*this; +return tmp; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{elements_view::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} @@ -9062,14 +11618,14 @@ \effects Equivalent to: \begin{codeblock} ---@\exposid{current_}@; +@\exposid{tuple-for-each}@([](auto& i) { --i; }, @\exposid{current_}@); return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{elements_view::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} @@ -9077,16 +11633,16 @@ \effects Equivalent to: \begin{codeblock} -auto temp = *this; ---@\exposid{current_}@; -return temp; +auto tmp = *this; +--*this; +return tmp; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+=}{elements_view::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} @@ -9094,15 +11650,15 @@ \effects Equivalent to: \begin{codeblock} -@\exposid{current_}@ += n; +@\exposid{tuple-for-each}@([&](I& i) { i += iter_difference_t(x); }, @\exposid{current_}@); return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-=}{elements_view::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} @@ -9110,173 +11666,202 @@ \effects Equivalent to: \begin{codeblock} -@\exposid{current_}@ -= n; +@\exposid{tuple-for-each}@([&](I& i) { i -= iter_difference_t(x); }, @\exposid{current_}@); return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator==}{elements_view::iterator}% +\indexlibrarymember{operator[]}{izip_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@<@\exposid{Base}@>; +constexpr auto operator[](difference_type n) const + requires @\exposconcept{all-random-access}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};} +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<}{elements_view::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) + requires (@\libconcept{equality_comparable}@>> && ...); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{current_} < y.\exposid{current_};} +\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>}{elements_view::iterator}% \begin{itemdecl} -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 @\exposconcept{all-random-access}@; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return y < x;} +\returns +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. \end{itemdescr} -\indexlibrarymember{operator<=}{elements_view::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}@& 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} \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>=}{elements_view::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}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(x < y);} +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator<=>}{elements_view::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}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};} -\end{itemdescr} - -\indexlibrarymember{operator+}{elements_view::iterator}% -\begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} +Let \tcode{\exposid{DIST}($i$)} be \tcode{difference_type(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{current_}))}. -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{iterator}\{x\} += y;} +\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+}{elements_view::iterator}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) - 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 y + x;} -\end{itemdescr} - -\indexlibrarymember{operator-}{elements_view::iterator}% -\begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@(ranges::iter_move, i.@\exposid{current_}@); +\end{codeblock} -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{iterator}\{x\} -= y;} +\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-}{elements_view::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 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{current_} - y.\exposid{current_};} +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.elements.sentinel]{Class template \tcode{elements_view::\exposid{sentinel}}} +\rSec3[range.zip.sentinel]{Class template \tcode{zip_view::\exposid{sentinel}}} -\indexlibraryglobal{elements_view::sentinel}% +\indexlibraryglobal{zip_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{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) 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 zip_view::@\exposid{sentinel}@ { + tuple>...> @\exposid{end_}@;@\itcorr[-1]@ // \expos + constexpr explicit @\exposidnc{sentinel}@(tuple>...> 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}@>>; - - 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{elements_view::sentinel}% +\indexlibraryctor{zip_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); +constexpr explicit @\exposid{sentinel}@(tuple>...> end); \end{itemdecl} \begin{itemdescr} @@ -9285,332 +11870,333 @@ Initializes \exposid{end_} with \tcode{end}. \end{itemdescr} -\indexlibraryctor{elements_view::sentinel}% -\begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) - requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}. -\end{itemdescr} - -\indexlibrarymember{base}{elements_view::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==}{elements_view::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-}{elements_view::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-}{elements_view::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 \libconcept{view}s and -produces a \libconcept{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 auto begin() const requires (@\libconcept{range}@ && ...) { - 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 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() { + if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { + 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()); + 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 size() requires (@\libconcept{sized_range}@ && ...); - constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); + constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> { + return @\exposid{zip_}@.size(); + } + + 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_view::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} @@ -9618,10 +12204,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} @@ -9631,11 +12226,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} @@ -9643,11 +12239,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} @@ -9661,8 +12258,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} @@ -9670,13 +12268,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} @@ -9690,9 +12289,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} @@ -9700,14 +12300,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} @@ -9715,14 +12316,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 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}@>; \end{itemdecl} \begin{itemdescr} @@ -9730,439 +12332,356 @@ \effects Equivalent to: \begin{codeblock} -return @\exposid{tuple-transform}@([&](I& i) -> decltype(auto) { - return i[iter_difference_t(n)]; -}, @\exposid{current_}@); +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} \begin{itemdecl} 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 @\libconcept{random_access_range}@<@\exposid{Base}@>; \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{itemdescr} - -\begin{itemdecl} -friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposconcept{all-random-access}@; -\end{itemdecl} +Let \placeholder{op} be the operator. -\begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\effects +Equivalent to: +\tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} \end{itemdescr} \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} \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} \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}@>> && ...); -\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} - -\begin{itemdecl} -friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); + requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects Equivalent to: -\begin{codeblock} -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} - -\begin{itemdecl} -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 -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)}$. +\tcode{return x.\exposid{inner_} - y.\exposid{inner_};} \end{itemdescr} -\rSec3[range.zip.sentinel]{Class template \tcode{zip_view::\exposid{sentinel}}} +\rSec3[range.zip.transform.sentinel]{Class template \tcode{zip_transform_view::\exposid{sentinel}}} -\indexlibraryglobal{zip_view::sentinel}% +\indexlibraryglobal{zip_transform_view::\exposid{sentinel}}% \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{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}@, sentinel_t> && ...); + requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; template - requires (@\libconcept{sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) + 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}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) - friend constexpr common_type_t>...> + 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}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) - friend constexpr common_type_t>...> - operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); + 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}@(tuple>...> end); +constexpr explicit @\exposid{sentinel}@(@\exposid{zentinel}@ inner); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{end}. +Initializes \exposid{inner_} with \tcode{inner}. \end{itemdescr} +\indexlibraryctor{zip_transform_view::\exposid{sentinel}}% \begin{itemdecl} constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && (@\libconcept{convertible_to}@, sentinel_t> && ...); + requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. +Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. \end{itemdescr} \begin{itemdecl} template - requires (@\libconcept{sentinel_for}@>, - iterator_t>> && ...) + 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 -\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: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} \end{itemdescr} \begin{itemdecl} template - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) -friend constexpr common_type_t>...> + 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); -\end{itemdecl} - -\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_}))}. - -\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} - -\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); + 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 -Equivalent to \tcode{return -(x - y);} +Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} \end{itemdescr} -\rSec2[range.zip.transform]{Zip transform view} +\rSec2[range.adjacent]{Adjacent view} -\rSec3[range.zip.transform.overview]{Overview} +\rSec3[range.adjacent.overview]{Overview} \pnum -\indexlibraryglobal{zip_transform_view}% -\tcode{zip_transform_view} takes an invocable object and -any number of \libconcept{view}s and -produces a \libconcept{view} -whose $M^\text{th}$ element is -the result of applying the invocable object -to the $M^\text{th}$ elements of all views. +\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{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}. +\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 -If \tcode{\libconcept{copy_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} +\tcode{((void)E, auto(views::empty>))} +if \tcode{N} is equal to \tcode{0} and +\tcode{decltype((E))} models \libconcept{forward_range}, \item -Otherwise, the expression \tcode{views::zip_transform(F, Es...)} -is expression-equivalent to \tcode{zip_trans\-form_view(F, Es...)}. +otherwise, \tcode{adjacent_view, N>(E)}. \end{itemize} -\pnum \begin{example} \begin{codeblock} -vector v1 = {1, 2}; -vector v2 = {4, 5, 6}; +vector v = {1, 2, 3, 4}; -for (auto i : views::zip_transform(plus(), v1, v2)) { - cout << i << ' '; // prints \tcode{5 7} +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} \end{example} -\rSec3[range.zip.transform.view]{Class template \tcode{zip_transform_view}} +\pnum +Define \tcode{\exposid{REPEAT}(T, N)} as a pack of \tcode{N} types, +each of which denotes the same type as \tcode{T}. -\indexlibrarymember{begin}{zip_transform_view}% -\indexlibrarymember{end}{zip_transform_view}% -\indexlibrarymember{size}{zip_transform_view}% +\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{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{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) + class adjacent_view : public view_interface> { + V @\exposid{base_}@ = V(); // \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.adjacent.iterator}, class template \tcode{adjacent_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.adjacent.sentinel}, class template \tcode{adjacent_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 + struct @\exposidnc{as-sentinel}@{}; // \expos public: - zip_transform_view() = default; + adjacent_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit adjacent_view(V base); - constexpr explicit zip_transform_view(F fun, Views... views); + 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{zip_}@.begin()); } + constexpr auto begin() requires (!@\exposconcept{simple-view}@) { + return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + } - 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}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); } - constexpr auto end() { - if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { - return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); + 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}@(@\exposid{zip_}@.end()); + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); } } - constexpr auto end() const - requires @\libconcept{range}@ && - @\libconcept{regular_invocable}@...> { - if constexpr (@\libconcept{common_range}@) { - return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); + 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}@(@\exposid{zip_}@.end()); + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); } } - 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(); - } + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; }; - - template - zip_transform_view(F, Rs&&...) -> zip_transform_view...>; } \end{codeblock} +\indexlibraryctor{adjacent_view}% \begin{itemdecl} -constexpr explicit zip_transform_view(F fun, Views... views); +constexpr explicit adjacent_view(V base); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{fun_} with \tcode{std::move(fun)} and -\exposid{zip_} with \tcode{std::move(views)...}. +Initializes \exposid{base_} with \tcode{std::move(base)}. \end{itemdescr} -\rSec3[range.zip.transform.iterator]{Class template \tcode{zip_transform_view::\exposid{iterator}}} +\indexlibrarymember{size}{adjacent_view}% +\begin{itemdecl} +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; +\end{itemdecl} -\indexlibraryglobal{zip_transform_view::iterator}% +\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 +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} - constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); // \expos +\indexlibrarymember{reserve_hint}{adjacent_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} +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} + +\rSec3[range.adjacent.iterator]{Class template \tcode{adjacent_view::\exposid{iterator}}} +\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 = @\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 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{iterator}@() = default; constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; - constexpr decltype(auto) operator*() const noexcept(@\seebelow@); + 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); 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}@>; - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@>; + constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + 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}@>; @@ -10171,73 +12690,78 @@ 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}@>; + 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 -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 -\begin{codeblock} -invoke_result_t<@\exposid{maybe-const}@&, range_reference_t<@\exposid{maybe-const}@>...> -\end{codeblock} -is not an lvalue reference, -\tcode{iterator_category} denotes \tcode{input_iterator_tag}. -\item -Otherwise, let \tcode{Cs} denote the pack of types -\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{random_access_iterator_tag}. -\item -Otherwise, -if \tcode{(\libconcept{derived_from} \&\& ...)} -is \tcode{true}, -\tcode{itera\-tor_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_cate\-gory} 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} +\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{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); +constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> first, sentinel_t<@\exposid{Base}@> last); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{parent_} with \tcode{addressof(parent)} and -\exposid{inner_} with \tcode{std::move(inner)}. +\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} + +\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} + +\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} +\indexlibraryctor{adjacent_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; + requires Const && @\libconcept{convertible_to}@, iterator_t<@\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_})}. +Initializes each element of \exposid{current_} +with the corresponding element of \tcode{i.\exposid{current_}} as an xvalue. \end{itemdescr} +\indexlibrarymember{operator*}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr decltype(auto) operator*() const noexcept(@\seebelow@); +constexpr auto operator*() const; \end{itemdecl} \begin{itemdescr} @@ -10245,20 +12769,33 @@ \effects Equivalent to: \begin{codeblock} -return apply([&](const auto&... iters) -> decltype(auto) { - return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); -}, @\exposid{inner_}@.@\exposid{current_}@); +return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); \end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{adjacent_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\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_})...))}. +\expects +\tcode{\exposid{current_}.back()} is incrementable. + +\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. + +\pnum +\returns +\tcode{*this}. \end{itemdescr} +\indexlibrarymember{operator++}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator++(); +constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} \begin{itemdescr} @@ -10266,23 +12803,35 @@ \effects Equivalent to: \begin{codeblock} -++@\exposid{inner_}@; -return *this; +auto tmp = *this; +++*this; +return tmp; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr void operator++(int); +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{++*this}. +\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} +\indexlibrarymember{operator--}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -10291,13 +12840,57 @@ Equivalent to: \begin{codeblock} auto tmp = *this; -++*this; +--*this; return tmp; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator+=}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\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}. +\end{itemdescr} + +\indexlibrarymember{operator-=}{adjacent_view::\exposid{iterator}}% +\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_}.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}. +\end{itemdescr} + +\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} @@ -10305,58 +12898,80 @@ \effects Equivalent to: \begin{codeblock} ---@\exposid{inner_}@; -return *this; +return @\exposid{tuple-transform}@([&](auto& i) -> decltype(auto) { return i[n]; }, @\exposid{current_}@); \end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +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} + +\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} + +\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: -\begin{codeblock} -auto tmp = *this; ---*this; -return tmp; -\end{codeblock} +Equivalent to: \tcode{return y < x;} \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type x) +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(y < x);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -@\exposid{inner_}@ += x; -return *this; -\end{codeblock} +Equivalent to: \tcode{return !(x < y);} \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type x) - 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}@>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{inner_}@ -= x; -return *this; -\end{codeblock} +\returns +\tcode{x.\exposid{current_}.back() <=> y.\exposid{current_}.back()}. \end{itemdescr} \begin{itemdecl} -constexpr decltype(auto) operator[](difference_type n) const +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} @@ -10365,313 +12980,359 @@ \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_}@); +auto r = i; +r += n; +return r; \end{codeblock} \end{itemdescr} \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) +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \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_};} +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) - 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{itemdecl} \begin{itemdescr} \pnum \effects Equivalent to: -\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} +\tcode{return x.\exposid{current_}.back() - y.\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}@>; +friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum \effects Equivalent to: -\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} +\tcode{return \exposid{tuple-transform}(ranges::iter_move, i.\exposid{current_});} + +\pnum +\remarks +The exception specification is equivalent to: +\begin{codeblock} +noexcept(ranges::iter_move(declval&>())) && +is_nothrow_move_constructible_v> +\end{codeblock} \end{itemdescr} \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; +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: -\tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +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} +noexcept(ranges::iter_swap(declval>(), declval>())) +\end{codeblock} \end{itemdescr} -\rSec3[range.zip.transform.sentinel]{Class template \tcode{zip_transform_view::\exposid{sentinel}}} +\rSec3[range.adjacent.sentinel]{Class template \tcode{adjacent_view::\exposid{sentinel}}} -\indexlibraryglobal{zip_transform_view::sentinel}% +\indexlibraryglobal{adjacent_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<@\libconcept{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) template - class zip_transform_view::@\exposid{sentinel}@ { - @\exposidnc{zentinel}@ @\exposid{inner_}@; // \expos - constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{zentinel}@ inner); // \expos + 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}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; template - requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> + 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}@<@\exposid{zentinel}@, @\exposid{ziperator}@> - friend constexpr range_difference_t<@\exposid{maybe-const}@> + 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}@<@\exposid{zentinel}@, @\exposid{ziperator}@> - 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 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 explicit @\exposid{sentinel}@(@\exposid{zentinel}@ inner); +constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{inner_} with \tcode{inner}. +Initializes \exposid{end_} with \tcode{end}. \end{itemdescr} +\indexlibraryctor{adjacent_view::\exposid{sentinel}}% \begin{itemdecl} constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. \end{itemdescr} \begin{itemdecl} template - requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} +Equivalent to: \tcode{return x.\exposid{current_}.back() == y.\exposid{end_};} \end{itemdescr} \begin{itemdecl} template - requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> -friend constexpr range_difference_t<@\exposid{maybe-const}@> + 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 +\effects +Equivalent to: \tcode{return x.\exposid{current_}.back() - y.\exposid{end_};} +\end{itemdescr} + +\begin{itemdecl} 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); + 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 x.\exposid{inner_} - y.\exposid{inner_};} +Equivalent to: \tcode{return y.\exposid{end_} - x.\exposid{current_}.back();} \end{itemdescr} -\rSec2[range.adjacent]{Adjacent view} +\rSec2[range.adjacent.transform]{Adjacent transform view} -\rSec3[range.adjacent.overview]{Overview} +\rSec3[range.adjacent.transform.overview]{Overview} \pnum -\indexlibraryglobal{adjacent_view}% -\tcode{adjacent_view} takes a \libconcept{view} and -produces a \libconcept{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. +\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}{views}% -The name \tcode{views::adjacent} denotes +\indexlibrarymember{adjacent_transform}{views}% +The name \tcode{views::adjacent_transform} 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 +Given subexpressions \tcode{E} and \tcode{F} and +a constant expression \tcode{N}: \begin{itemize} \item -\tcode{((void)E, auto(views::empty>))} -if \tcode{N} is equal to \tcode{0}, +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, \tcode{adjacent_view, N>(E)}. +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<2>) { - cout << "(" << std::get<0>(i) << ", " << std::get<1>(i) << ") "; // prints \tcode{(1, 2) (2, 3) (3, 4)} +for (auto i : v | views::adjacent_transform<2>(std::multiplies())) { + cout << i << ' '; // prints \tcode{2 6 12} } \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}} +\rSec3[range.adjacent.transform.view]{Class template \tcode{adjacent_transform_view}} -\indexlibrarymember{begin}{adjacent_view}% -\indexlibrarymember{end}{adjacent_view}% -\indexlibrarymember{size}{adjacent_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, size_t N> - requires @\libconcept{view}@ && (N > 0) - class adjacent_view : public view_interface> { - V @\exposid{base_}@ = V(); // \expos + 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 - // \ref{range.adjacent.iterator}, class template \tcode{adjacent_view::\exposid{iterator}} - template class @\exposidnc{iterator}@; // \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.sentinel}, class template \tcode{adjacent_view::\exposid{sentinel}} - template class @\exposidnc{sentinel}@; // \expos + // \ref{range.adjacent.transform.iterator}, class template \tcode{adjacent_transform_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos - struct @\exposidnc{as-sentinel}@{}; // \expos + // \ref{range.adjacent.transform.sentinel}, class template \tcode{adjacent_transform_view::\exposid{sentinel}} + template class @\exposidnc{sentinel}@; // \expos public: - adjacent_view() requires @\libconcept{default_initializable}@ = default; - constexpr explicit adjacent_view(V base); + adjacent_transform_view() = default; + constexpr explicit adjacent_transform_view(V base, F fun); - constexpr auto begin() requires (!@\exposconcept{simple-view}@) { - return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + 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}@ { - return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + 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 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 size() const requires @\libconcept{sized_range}@ { + return @\exposid{inner_}@.size(); } - 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 reserve_hint() requires @\libconcept{approximately_sized_range}@<@\exposid{InnerView}@> { + return @\exposid{inner_}@.reserve_hint(); } - constexpr auto size() requires @\libconcept{sized_range}@; - constexpr auto size() const requires @\libconcept{sized_range}@; + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@ { + return @\exposid{inner_}@.reserve_hint(); + } }; } \end{codeblock} +\indexlibraryctor{adjacent_transform_view}% \begin{itemdecl} -constexpr explicit adjacent_view(V base); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \exposid{base_} with \tcode{std::move(base)}. -\end{itemdescr} - -\begin{itemdecl} -constexpr auto size() requires @\libconcept{sized_range}@; -constexpr auto size() const requires @\libconcept{sized_range}@; +constexpr explicit adjacent_transform_view(V base, F fun); \end{itemdecl} \begin{itemdescr} \pnum \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); -\end{codeblock} +Initializes \exposid{fun_} with \tcode{std::move(fun)} and +\exposid{inner_} with \tcode{std::move(base)}. \end{itemdescr} -\rSec3[range.adjacent.iterator]{Class template \tcode{adjacent_view::\exposid{iterator}}} +\rSec3[range.adjacent.transform.iterator]{Class template \tcode{adjacent_transform_view::\exposid{iterator}}} -\indexlibraryglobal{adjacent_view::iterator}% +\indexlibraryglobal{adjacent_transform_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V, size_t N> - requires @\libconcept{view}@ && (N > 0) + 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_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 + 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: - using iterator_category = input_iterator_tag; - using iterator_concept = @\seebelow@; - using value_type = tuple<@\exposid{REPEAT}@(range_value_t<@\exposid{Base}@>, N)...>; + 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}@>; @\exposid{iterator}@() = default; constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; - constexpr auto operator*() const; + 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}@>; - 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 + 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); @@ -10684,8 +13345,7 @@ 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}@<@\exposid{inner-iterator}@>; friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -10694,74 +13354,71 @@ 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}@>; + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; }; } \end{codeblock} \pnum -\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +The member \grammarterm{typedef-name} \tcode{\exposid{iterator}::iterator_category} +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{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, if \exposid{Base} models \libconcept{bidirectional_range}, -then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +Otherwise, let \tcode{C} denote the type +\tcode{iterator_traits>::iterator_category}. +\begin{itemize} \item -Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +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} -\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}@> first, sentinel_t<@\exposid{Base}@> last); -\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}. -\end{itemdescr} - +\indexlibraryctor{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{as-sentinel}@, iterator_t<@\exposid{Base}@> first, iterator_t<@\exposid{Base}@> last); +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{inner-iterator}@ 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{parent_} with \tcode{addressof(parent)} and +\exposid{inner_} with \tcode{std::move(inner)}. \end{itemdescr} +\indexlibraryctor{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; \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{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} -constexpr auto operator*() const; +constexpr decltype(auto) operator*() const noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} @@ -10769,29 +13426,36 @@ \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, (N - 1)}. +The exception specification is equivalent to: +\begin{codeblock} +noexcept(invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *std::get(@\exposid{inner_}@.@\exposid{current_}@)...)) \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{\exposid{current_}.back()} is incrementable. - -\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. - -\pnum -\returns -\tcode{*this}. +\effects +Equivalent to: +\begin{codeblock} +++@\exposid{inner_}@; +return *this; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} @@ -10807,83 +13471,24 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \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. - -\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; +--@\exposid{inner_}@; +return *this; \end{codeblock} \end{itemdescr} +\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 -\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}. -\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_}.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}. -\end{itemdescr} - -\begin{itemdecl} -constexpr auto operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -10891,530 +13496,460 @@ \effects Equivalent to: \begin{codeblock} -return @\exposid{tuple-transform}@([&](auto& i) -> decltype(auto) { return i[n]; }, @\exposid{current_}@); +auto tmp = *this; +--*this; +return tmp; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator+=}{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_}.back() == y.\exposid{current_}.back()}. +\effects +Equivalent to: +\begin{codeblock} +@\exposid{inner_}@ += x; +return *this; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-=}{adjacent_transform_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-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_}.back() < y.\exposid{current_}.back()}. +\effects +Equivalent to: +\begin{codeblock} +@\exposid{inner_}@ -= x; +return *this; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator[]}{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) +constexpr decltype(auto) operator[](difference_type n) const requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return y < x;} +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} \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. + \pnum \effects -Equivalent to: \tcode{return !(y < x);} +Equivalent to: \tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} \end{itemdescr} \begin{itemdecl} -friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(x < y);} +Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} \end{itemdescr} \begin{itemdecl} -friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@> && - @\libconcept{three_way_comparable}@>; +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_}.back() <=> y.\exposid{current_}.back()}. +\effects +Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} \end{itemdescr} \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +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 \effects -Equivalent to: +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} -auto r = i; -r += n; -return r; +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} -\end{itemdescr} +\indexlibraryctor{adjacent_transform_view::\exposid{sentinel}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr explicit @\exposid{sentinel}@(@\exposid{inner-sentinel}@ inner); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -auto r = i; -r -= n; -return r; -\end{codeblock} +Initializes \exposid{inner_} with \tcode{inner}. \end{itemdescr} +\indexlibraryctor{adjacent_transform_view::\exposid{sentinel}}% \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{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return x.\exposid{current_}.back() - y.\exposid{current_}.back();} +Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. \end{itemdescr} \begin{itemdecl} -friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); +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: -\tcode{return \exposid{tuple-transform}(ranges::iter_move, i.\exposid{current_});} - -\pnum -\remarks -The exception specification is equivalent to: -\begin{codeblock} -noexcept(ranges::iter_move(declval&>())) && -is_nothrow_move_constructible_v> -\end{codeblock} +Equivalent to: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} \end{itemdescr} \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{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 -None of the iterators in \tcode{l.\exposid{current_}} is equal to -an iterator in \tcode{r.\exposid{current_}}. +\effects +Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} + +\rSec2[range.chunk]{Chunk view} + +\rSec3[range.chunk.overview]{Overview} \pnum -\effects -For every integer $0 \leq i < \tcode{N}$, -performs -\tcode{ranges::iter_swap(l.\exposid{current_}[$i$], r.\exposid{current_}[$i$])}. +\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 -\remarks -The exception specification is equivalent to: +\indexlibrarymember{chunk}{views}% +The name \tcode{views::chunk} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{N}, +the expression \tcode{views::chunk(E, N)} is expression-equivalent to +\tcode{chunk_view(E, N)}. + +\begin{example} \begin{codeblock} -noexcept(ranges::iter_swap(declval>(), declval>())) +vector v = {1, 2, 3, 4, 5}; + +for (auto r : v | views::chunk(2)) { + cout << '['; + auto sep = ""; + for (auto i : r) { + cout << sep << i; + sep = ", "; + } + cout << "] "; +} +// The above prints \tcode{[1, 2] [3, 4] [5]} \end{codeblock} -\end{itemdescr} +\end{example} -\rSec3[range.adjacent.sentinel]{Class template \tcode{adjacent_view::\exposid{sentinel}}} +\rSec3[range.chunk.view.input]{Class template \tcode{chunk_view} for input ranges} -\indexlibraryglobal{adjacent_view::sentinel}% +\indexlibraryglobal{chunk_view}% \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 + 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: - @\exposid{sentinel}@() = default; - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; + constexpr explicit chunk_view(V base, range_difference_t n); - 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 range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + constexpr @\exposid{outer-iterator}@ begin(); + constexpr default_sentinel_t end() const noexcept; - 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} + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; -\begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); -\end{itemdecl} + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; + }; -\begin{itemdescr} -\pnum -\effects -Initializes \exposid{end_} with \tcode{end}. -\end{itemdescr} + template + chunk_view(R&&, range_difference_t) -> chunk_view>; +} +\end{codeblock} +\indexlibraryctor{chunk_view}% \begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +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{end_} with \tcode{std::move(i.\exposid{end_})}. +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{n_} with \tcode{n}. \end{itemdescr} +\indexlibrarymember{begin}{chunk_view}% \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 @\exposid{outer-iterator}@ begin(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_}.back() == y.\exposid{end_};} +Equivalent to: +\begin{codeblock} +@\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} -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 default_sentinel_t end() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{current_}.back() - y.\exposid{end_};} +\returns +\tcode{default_sentinel}. \end{itemdescr} +\indexlibrarymember{size}{chunk_view}% \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 auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return y.\exposid{end_} - x.\exposid{current_}.back();} -\end{itemdescr} - -\rSec2[range.adjacent.transform]{Adjacent transform view} - -\rSec3[range.adjacent.transform.overview]{Overview} - -\pnum -\indexlibraryglobal{adjacent_transform_view}% -\tcode{adjacent_transform_view} takes an invocable object and -a \libconcept{view} and produces a \libconcept{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}, -\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}} - -\indexlibrarymember{begin}{adjacent_transform_view}% -\indexlibrarymember{end}{adjacent_transform_view}% -\indexlibrarymember{size}{adjacent_transform_view}% +Equivalent to: \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 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(); - } - }; -} +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 explicit adjacent_transform_view(V base, F fun); +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 -Initializes \exposid{fun_} with \tcode{std::move(fun)} and -\exposid{inner_} with \tcode{std::move(base)}. +Equivalent to: +\begin{codeblock} +auto s = static_cast>(ranges::reserve_hint(@\exposidnc{base_}@)); +return @\exposidnc{to-unsigned-like}@(@\exposidnc{div-ceil}@(s, @\exposidnc{n_}@)); +\end{codeblock} \end{itemdescr} -\rSec3[range.adjacent.transform.iterator]{Class template \tcode{adjacent_transform_view::\exposid{iterator}}} +\rSec3[range.chunk.outer.iter]{Class \tcode{chunk_view::\exposid{outer-iterator}}} -\indexlibraryglobal{adjacent_transform_view::iterator}% +\indexlibraryglobal{chunk_view::\exposid{outer-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 - 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 + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + class chunk_view::@\exposid{outer-iterator}@ { + chunk_view* @\exposid{parent_}@; // \expos - constexpr @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent, @\exposidnc{inner-iterator}@ inner); // \expos + constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); // \expos 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 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}@>; - - 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}@>; - - 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}@>; + using iterator_concept = input_iterator_tag; + using difference_type = range_difference_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}@>; - 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} + // \ref{range.chunk.outer.value}, class \tcode{chunk_view::\exposid{outer-iterator}::value_type} + struct value_type; -\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 an lvalue 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} + @\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} -constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{inner-iterator}@ inner); +constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{addressof(parent)} and -\exposid{inner_} with \tcode{std::move(inner)}. +Initializes \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} +\indexlibrarymember{operator*}{chunk_view::\exposid{outer-iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; +constexpr value_type operator*() 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_})}. +\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} -constexpr decltype(auto) operator*() const noexcept(@\seebelow@); +constexpr @\exposid{outer-iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + \pnum \effects Equivalent to: \begin{codeblock} -return apply([&](const auto&... iters) -> decltype(auto) { - return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); -}, @\exposid{inner_}@.@\exposid{current_}@); +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} +constexpr void operator++(int); +\end{itemdecl} +\begin{itemdescr} \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} +\effects +Equivalent to \tcode{++*this}. \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@& operator++(); +friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); \end{itemdecl} \begin{itemdescr} @@ -11422,13 +13957,13 @@ \effects Equivalent to: \begin{codeblock} -++@\exposid{inner_}@; -return *this; +return *x.@\exposid{parent_}@->@\exposid{current_}@ == ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) && x.@\exposid{parent_}@->@\exposid{remainder_}@ != 0; \end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int); +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} @@ -11436,28 +13971,85 @@ \effects Equivalent to: \begin{codeblock} -auto tmp = *this; -++*this; -return tmp; +const auto dist = ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) - *x.@\exposid{parent_}@->@\exposid{current_}@; +if (dist < x.@\exposid{parent_}@->@\exposid{remainder_}@) { + return dist == 0 ? 0 : 1; +} +return @\exposidnc{div-ceil}@(dist - x.@\exposid{parent_}@->@\exposid{remainder_}@, x.@\exposid{parent_}@->@\exposid{n_}@) + 1; \end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\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: +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} ---@\exposid{inner_}@; -return *this; +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>; + }; +} \end{codeblock} + +\indexlibraryctor{chunk_view::\exposid{outer-iterator}::value_type}% +\begin{itemdecl} +constexpr explicit value_type(chunk_view& parent); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} +\indexlibrarymember{begin}{chunk_view::\exposid{outer-iterator}::value_type}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr @\exposid{inner-iterator}@ begin() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{inner-iterator}(*\exposid{parent_})}. +\end{itemdescr} + +\indexlibrarymember{end}{chunk_view::\exposid{outer-iterator}::value_type}% +\begin{itemdecl} +constexpr default_sentinel_t end() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\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} @@ -11465,385 +14057,433 @@ \effects Equivalent to: \begin{codeblock} -auto tmp = *this; ---*this; -return tmp; +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} +\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{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} + +\indexlibraryctor{chunk_view::\exposid{inner-iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr explicit @\exposid{inner-iterator}@(chunk_view& parent) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -@\exposid{inner_}@ += x; -return *this; -\end{codeblock} +Initializes \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} +\indexlibrarymember{base}{chunk_view::\exposid{inner-iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr const iterator_t& base() const &; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return *\exposid{parent_}->\exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{operator*}{chunk_view::\exposid{inner-iterator}}% +\begin{itemdecl} +constexpr range_reference_t operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + +\pnum +\effects +Equivalent to: \tcode{return **\exposid{parent_}->\exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{operator++}{chunk_view::\exposid{inner-iterator}}% +\begin{itemdecl} +constexpr @\exposid{inner-iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + \pnum \effects Equivalent to: \begin{codeblock} -@\exposid{inner_}@ -= x; +++*@\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} -constexpr decltype(auto) operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr void operator++(int); \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} +Equivalent to \tcode{++*this}. \end{itemdescr} +\indexlibrarymember{operator==}{chunk_view::\exposid{inner-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}@>; +friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); \end{itemdecl} \begin{itemdescr} \pnum -Let \placeholder{op} be the operator. +\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 \effects -Equivalent to: \tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} +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 @\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-(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 \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} +Equivalent to: \tcode{return -(y - x);} \end{itemdescr} +\indexlibrarymember{iter_move}{chunk_view::\exposid{inner-iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +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} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} +Equivalent to: \tcode{return ranges::iter_move(*i.\exposid{parent_}->\exposid{current_});} \end{itemdescr} +\indexlibrarymember{iter_swap}{chunk_view::\exposid{inner-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 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} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +Equivalent to: \tcode{ranges::iter_swap(*x.\exposid{parent_}->\exposid{current_}, *y.\exposid{parent_}->\exposid{current_});} \end{itemdescr} -\rSec3[range.adjacent.transform.sentinel]{Class template \tcode{adjacent_transform_view::\exposid{sentinel}}} +\rSec3[range.chunk.view.fwd]{Class template \tcode{chunk_view} for forward ranges} -\indexlibraryglobal{adjacent_transform_view::sentinel}% +\indexlibraryglobal{chunk_view}% +\indexlibrarymember{begin}{chunk_view}% +\indexlibrarymember{end}{chunk_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)...>> - template - class adjacent_transform_view::@\exposid{sentinel}@ { - @\exposidnc{inner-sentinel}@ @\exposid{inner_}@; // \expos - constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{inner-sentinel}@ inner); // \expos + 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: - @\exposid{sentinel}@() = default; - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; + constexpr explicit chunk_view(V base, range_difference_t n); - template - requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> - 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}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + constexpr auto begin() requires (!@\exposconcept{simple-view}@) { + return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); + } - 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); + constexpr auto begin() const requires @\libconcept{forward_range}@ { + return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); + } + + constexpr auto end() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) { + auto missing = (@\exposid{n_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{n_}@) % @\exposid{n_}@; + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@), missing); + } else if constexpr (@\libconcept{common_range}@ && !@\libconcept{bidirectional_range}@) { + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@)); + } else { + return default_sentinel; + } + } + + constexpr auto end() const requires @\libconcept{forward_range}@ { + if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) { + auto missing = (@\exposid{n_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{n_}@) % @\exposid{n_}@; + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@), missing); + } else if constexpr (@\libconcept{common_range}@ && !@\libconcept{bidirectional_range}@) { + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@)); + } else { + return default_sentinel; + } + } + + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; + + 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 @\exposid{sentinel}@(@\exposid{inner-sentinel}@ inner); +constexpr explicit chunk_view(V base, range_difference_t n); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{inner_} with \tcode{inner}. -\end{itemdescr} - -\begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; -\end{itemdecl} +\expects +\tcode{n > 0} is \tcode{true}. -\begin{itemdescr} \pnum \effects -Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{n_} with \tcode{n}. \end{itemdescr} +\indexlibrarymember{size}{chunk_view}% \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); +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 x.\exposid{inner_} == y.\exposid{inner_};} +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} -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); +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{return x.\exposid{inner_} - y.\exposid{inner_};} -\end{itemdescr} - -\rSec2[range.chunk]{Chunk view} - -\rSec3[range.chunk.overview]{Overview} - -\pnum -\tcode{chunk_view} takes a \libconcept{view} and a number $N$ and -produces a range of \libconcept{view}s -that are $N$-sized non-overlapping successive chunks of -the elements of the original \libconcept{view}, in order. -The last \libconcept{view} in the range can have fewer than $N$ elements. - -\pnum -\indexlibrarymember{chunk}{views}% -The name \tcode{views::chunk} denotes -a range adaptor object\iref{range.adaptor.object}. -Given subexpressions \tcode{E} and \tcode{N}, -the expression \tcode{views::chunk(E, N)} is expression-equivalent to -\tcode{chunk_view(E, N)}. - -\begin{example} +Equivalent to: \begin{codeblock} -vector v = {1, 2, 3, 4, 5}; - -for (auto r : v | views::chunk(2)) { - cout << '['; - auto sep = ""; - for (auto i : r) { - cout << sep << i; - sep = ", "; - } - cout << "] "; -} -// The above prints \tcode{[1, 2] [3, 4] [5]} +auto s = static_cast>(ranges::reserve_hint(@\exposid{base_}@)); +return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(s, @\exposid{n_}@)); \end{codeblock} -\end{example} +\end{itemdescr} -\rSec3[range.chunk.view.input]{Class template \tcode{chunk_view} for input ranges} +\rSec3[range.chunk.fwd.iter]{Class template \tcode{chunk_view::\exposid{iterator}} for forward ranges} -\indexlibrarymember{begin}{chunk_view}% -\indexlibrarymember{end}{chunk_view}% -\indexlibrarymember{size}{chunk_view}% +\indexlibraryglobal{chunk_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template - constexpr I @\exposidnc{div-ceil}@(I num, I denom) { // \expos - I r = num / denom; - if (num % denom) - ++r; - return r; - } - template<@\libconcept{view}@ V> - requires @\libconcept{input_range}@ - class chunk_view : public view_interface> { - V @\exposid{base_}@; // \expos - range_difference_t @\exposid{n_}@; // \expos - range_difference_t @\exposid{remainder_}@ = 0; // \expos - - @\exposid{non-propagating-cache}@> @\exposid{current_}@; // \expos + requires @\libconcept{forward_range}@ + template + class chunk_view::@\exposid{iterator}@ { + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - // \ref{range.chunk.outer.iter}, class \tcode{chunk_view::\exposid{outer-iterator}} - class @\exposid{outer-iterator}@; // \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 - // \ref{range.chunk.inner.iter}, class \tcode{chunk_view::\exposid{inner-iterator}} - class @\exposid{inner-iterator}@; // \expos + constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, // \expos + range_difference_t<@\exposid{Base}@> missing = 0); public: - constexpr explicit chunk_view(V base, range_difference_t 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}@>; - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> + && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; - constexpr @\exposid{outer-iterator}@ begin(); - constexpr default_sentinel_t end() const noexcept; + constexpr iterator_t<@\exposid{Base}@> base() const; - constexpr auto size() requires @\libconcept{sized_range}@; - constexpr auto size() const requires @\libconcept{sized_range}@; - }; + constexpr value_type operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); - template - chunk_view(R&& r, range_difference_t) -> chunk_view>; -} -\end{codeblock} + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; -\begin{itemdecl} -constexpr explicit chunk_view(V base, range_difference_t n); -\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 -\expects -\tcode{n > 0} is \tcode{true}. + constexpr value_type operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\pnum -\effects -Initializes \exposid{base_} with \tcode{std::move(base)} and -\exposid{n_} with \tcode{n}. -\end{itemdescr} + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); + + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && + @\libconcept{three_way_comparable}@>; + + friend constexpr @\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}@>>; -\begin{itemdecl} -constexpr @\exposid{outer-iterator}@ begin(); -\end{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 difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + }; +} +\end{codeblock} -\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{current_}@ = ranges::begin(@\exposid{base_}@); -@\exposid{remainder_}@ = @\exposid{n_}@; -return @\exposid{outer-iterator}@(*this); -\end{codeblock} -\end{itemdescr} +\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_view::\exposid{iterator}}% \begin{itemdecl} -constexpr default_sentinel_t end() const noexcept; +constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, + range_difference_t<@\exposid{Base}@> missing = 0); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{default_sentinel}. +\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 auto size() requires @\libconcept{sized_range}@; -constexpr auto size() const requires @\libconcept{sized_range}@; +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: -\begin{codeblock} -return @\exposid{to-unsigned-like}@(@\exposidnc{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{n_}@)); -\end{codeblock} +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} -\rSec3[range.chunk.outer.iter]{Class \tcode{chunk_view::\exposid{outer-iterator}}} - -\indexlibraryglobal{chunk_view::outer-iterator}% -\begin{codeblock} -namespace std::ranges { - template<@\libconcept{view}@ V> - requires @\libconcept{input_range}@ - class chunk_view::@\exposid{outer-iterator}@ { - chunk_view* @\exposid{parent_}@; // \expos - - constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); // \expos - - public: - using iterator_concept = input_iterator_tag; - using difference_type = range_difference_t; - - // \ref{range.chunk.outer.value}, class \tcode{chunk_view::\exposid{outer-iterator}::value_type} - struct value_type; - - @\exposid{outer-iterator}@(@\exposid{outer-iterator}@&&) = default; - @\exposid{outer-iterator}@& operator=(@\exposid{outer-iterator}@&&) = default; - - constexpr value_type operator*() const; - constexpr @\exposid{outer-iterator}@& operator++(); - constexpr void operator++(int); - - friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); - - friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{outer-iterator}@& x) - requires @\libconcept{sized_sentinel_for}@, iterator_t>; - friend constexpr difference_type operator-(const @\exposid{outer-iterator}@& x, default_sentinel_t y) - requires @\libconcept{sized_sentinel_for}@, iterator_t>; - }; -} -\end{codeblock} - +\indexlibrarymember{base}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); +constexpr iterator_t<@\exposid{Base}@> base() const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{parent_} with \tcode{addressof(parent)}. +\returns +\exposid{current_}. \end{itemdescr} +\indexlibrarymember{operator*}{chunk_view::\exposid{iterator}}% \begin{itemdecl} constexpr value_type operator*() const; \end{itemdecl} @@ -11851,44 +14491,51 @@ \begin{itemdescr} \pnum \expects -\tcode{*this == default_sentinel} is \tcode{false}. +\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. \pnum \returns -\tcode{value_type(*\exposid{parent_})}. +\tcode{views::take(subrange(\exposid{current_}, \exposid{end_}), \exposid{n_})}. \end{itemdescr} +\indexlibrarymember{operator++}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{outer-iterator}@& operator++(); +constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{*this == default_sentinel} is \tcode{false}. +\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. \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_}@; +@\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 void operator++(int); +constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to \tcode{++*this}. +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -11896,13 +14543,15 @@ \effects Equivalent to: \begin{codeblock} -return *x.@\exposid{parent_}@->@\exposid{current_}@ == ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) && x.@\exposid{parent_}@->@\exposid{remainder_}@ != 0; +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} -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) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -11910,223 +14559,214 @@ \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+=}{chunk_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+=(difference_type x) + requires @\libconcept{random_access_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}} +\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} -\indexlibraryglobal{chunk_view::outer-iterator::value_type}% +\pnum +\effects +Equivalent to: \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>; - }; +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 explicit value_type(chunk_view& parent); +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{addressof(parent)}. +Equivalent to: \tcode{return *this += -x;} \end{itemdescr} +\indexlibrarymember{operator[]}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{inner-iterator}@ begin() const noexcept; +constexpr value_type operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{\exposid{inner-iterator}(*\exposid{parent_})}. +\tcode{*(*this + n)}. \end{itemdescr} +\indexlibrarymember{operator-=}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr default_sentinel_t end() const noexcept; +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{default_sentinel}. +\tcode{x.\exposid{current_} == y.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator==}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr auto size() const - requires @\libconcept{sized_sentinel_for}@, iterator_t>; +friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); \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} +\returns +\tcode{x.\exposid{current_} == x.\exposid{end_}}. \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 &; +\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} - constexpr range_reference_t operator*() const; - constexpr @\exposid{inner-iterator}@& operator++(); - constexpr void operator++(int); +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} < y.\exposid{current_}}. +\end{itemdescr} - friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); +\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} - 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>; - }; -} -\end{codeblock} +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return y < x;} +\end{itemdescr} +\indexlibrarymember{operator<=}{chunk_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) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{addressof(parent)}. +Equivalent to: \tcode{return !(y < x);} \end{itemdescr} +\indexlibrarymember{operator>=}{chunk_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_};} +Equivalent to: \tcode{return !(x < y);} \end{itemdescr} +\indexlibrarymember{operator<=>}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr range_reference_t operator*() const; +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 -\expects -\tcode{*this == default_sentinel} is \tcode{false}. - -\pnum -\effects -Equivalent to: \tcode{return **\exposid{parent_}->\exposid{current_};} +\returns +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator+}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{inner-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} -\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; +auto r = i; +r += n; +return r; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-}{chunk_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-}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{x.\exposid{parent_}->\exposid{remainder_} == 0}. +\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} -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-(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: -\begin{codeblock} -return ranges::min(x.@\exposid{parent_}@->@\exposid{remainder_}@, - ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) - *x.@\exposid{parent_}@->@\exposid{current_}@); -\end{codeblock} +\returns +\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{n_})}. \end{itemdescr} +\indexlibrarymember{operator-}{chunk_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>; +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} @@ -12135,66 +14775,95 @@ Equivalent to: \tcode{return -(y - x);} \end{itemdescr} -\rSec3[range.chunk.view.fwd]{Class template \tcode{chunk_view} for forward ranges} +\rSec2[range.slide]{Slide view} -\indexlibrarymember{begin}{chunk_view}% -\indexlibrarymember{end}{chunk_view}% -\indexlibrarymember{size}{chunk_view}% +\rSec3[range.slide.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. + +\pnum +\indexlibrarymember{slide}{views}% +The name \tcode{views::slide} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{N}, +the expression \tcode{views::slide(E, N)} is expression-equivalent to +\tcode{slide_view(E, N)}. +\begin{example} +\begin{codeblock} +vector v = {1, 2, 3, 4}; + +for (auto i : v | views::slide(2)) { + cout << '[' << i[0] << ", " << i[1] << "] "; // prints \tcode{[1, 2] [2, 3] [3, 4]} +} +\end{codeblock} +\end{example} + +\rSec3[range.slide.view]{Class template \tcode{slide_view}} + +\indexlibraryglobal{slide_view}% +\indexlibraryctor{slide_view}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{view}@ V> - requires @\libconcept{forward_range}@ - class chunk_view : public view_interface> { + template + concept @\defexposconcept{slide-caches-nothing}@ = @\libconcept{random_access_range}@ && @\libconcept{sized_range}@; // \expos + + template + concept @\defexposconcept{slide-caches-last}@ = // \expos + !@\exposconcept{slide-caches-nothing}@ && @\libconcept{bidirectional_range}@ && @\libconcept{common_range}@; + + template + concept @\defexposconcept{slide-caches-first}@ = // \expos + !@\exposconcept{slide-caches-nothing}@ && !@\exposconcept{slide-caches-last}@; + + template<@\libconcept{forward_range}@ V> + requires @\libconcept{view}@ + class slide_view : public view_interface> { V @\exposid{base_}@; // \expos range_difference_t @\exposid{n_}@; // \expos - // \ref{range.chunk.fwd.iter}, class template \tcode{chunk_view::\exposid{iterator}} + // \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 auto begin() requires (!@\exposconcept{simple-view}@) { - return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); - } - - constexpr auto begin() const requires @\libconcept{forward_range}@ { - return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); - } - - constexpr auto end() requires (!@\exposconcept{simple-view}@) { - if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) { - auto missing = (@\exposid{n_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{n_}@) % @\exposid{n_}@; - return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@), missing); - } else if constexpr (@\libconcept{common_range}@ && !@\libconcept{bidirectional_range}@) { - return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@)); - } else { - return default_sentinel; - } - } + constexpr auto begin() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); + constexpr auto begin() const requires @\exposconcept{slide-caches-nothing}@; - constexpr auto end() const requires @\libconcept{forward_range}@ { - if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) { - auto missing = (@\exposid{n_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{n_}@) % @\exposid{n_}@; - return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@), missing); - } else if constexpr (@\libconcept{common_range}@ && !@\libconcept{bidirectional_range}@) { - return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@)); - } else { - return default_sentinel; - } - } + constexpr auto 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 + 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} @@ -12204,13 +14873,120 @@ \pnum \effects -Initializes \exposid{base_} with \tcode{std::move(base)} and -\exposid{n_} with \tcode{n}. +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{n_} with \tcode{n}. +\end{itemdescr} + +\indexlibrarymember{begin}{slide_view}% +\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}. +\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 auto end() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +If \tcode{V} models \exposconcept{slide-caches-nothing}, +\begin{codeblock} +@\exposid{iterator}@(ranges::begin(@\exposid{base_}@) + range_difference_t(size()), @\exposid{n_}@) +\end{codeblock} +\item +Otherwise, if \tcode{V} models \exposconcept{slide-caches-last}, +\begin{codeblock} +@\exposid{iterator}@(ranges::prev(ranges::end(@\exposid{base_}@), @\exposid{n_}@ - 1, ranges::begin(@\exposid{base_}@)), @\exposid{n_}@) +\end{codeblock} +\item +Otherwise, if \tcode{V} models \libconcept{common_range}, +\begin{codeblock} +@\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::end(@\exposid{base_}@), @\exposid{n_}@) +\end{codeblock} +\item +Otherwise, \tcode{\exposid{sentinel}(ranges::end(\exposid{base_}))}. +\end{itemize} + +\pnum +\remarks +In order to provide the amortized constant-time complexity +required by the \libconcept{range} concept, +this function caches the result within the \tcode{slide_view} +for use on subsequent calls +when \tcode{V} models \exposconcept{slide-caches-last}. +\end{itemdescr} + +\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}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto sz = ranges::distance(@\exposid{base_}@) - @\exposid{n_}@ + 1; +if (sz < 0) sz = 0; +return @\exposid{to-unsigned-like}@(sz); +\end{codeblock} \end{itemdescr} +\indexlibrarymember{reserve_hint}{slide_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} @@ -12218,44 +14994,46 @@ \effects Equivalent to: \begin{codeblock} -return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{n_}@)); +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.chunk.fwd.iter]{Class template \tcode{chunk_view::\exposid{iterator}} for forward ranges} +\rSec3[range.slide.iterator]{Class template \tcode{slide_view::\exposid{iterator}}} -\indexlibraryglobal{chunk_view::iterator}% +\indexlibraryglobal{slide_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{view}@ V> - requires @\libconcept{forward_range}@ + template<@\libconcept{forward_range}@ V> + requires @\libconcept{view}@ template - class chunk_view::@\exposid{iterator}@ { - using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos - using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + 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 - 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}@(iterator_t<@\exposid{Base}@> current, range_difference_t<@\exposid{Base}@> n) // \expos + requires (!@\exposconcept{slide-caches-first}@<@\exposid{Base}@>); - constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, // \expos - range_difference_t<@\exposid{Base}@> missing = 0); + constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, iterator_t<@\exposid{Base}@> last_ele, // \expos + range_difference_t<@\exposid{Base}@> n) + requires @\exposconcept{slide-caches-first}@<@\exposid{Base}@>; public: using iterator_category = input_iterator_tag; using iterator_concept = @\seebelow@; - using value_type = decltype(views::take(subrange(@\exposid{current_}@, @\exposid{end_}@), @\exposid{n_}@)); + using value_type = decltype(views::counted(@\exposid{current_}@, @\exposid{n_}@)); using difference_type = range_difference_t<@\exposid{Base}@>; @\exposid{iterator}@() = default; constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> - && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; - - constexpr iterator_t<@\exposid{Base}@> base() const; + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; - constexpr value_type operator*() const; + constexpr auto operator*() const; constexpr @\exposid{iterator}@& operator++(); constexpr @\exposid{iterator}@ operator++(int); @@ -12267,11 +15045,10 @@ constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - constexpr value_type operator[](difference_type n) const + 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, default_sentinel_t); friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -12293,11 +15070,6 @@ requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; - - friend constexpr 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} @@ -12315,59 +15087,68 @@ 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 @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, - range_difference_t<@\exposid{Base}@> missing = 0); +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}, -\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{current_} with \tcode{current} and +\exposid{n_} with \tcode{n}. \end{itemdescr} +\indexlibraryctor{slide_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}@(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{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_}}. +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 iterator_t<@\exposid{Base}@> base() const; +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\exposid{current_}. +\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} +\indexlibrarymember{operator*}{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr value_type operator*() const; +constexpr auto operator*() const; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. - \pnum \returns -\tcode{views::take(subrange(\exposid{current_}, \exposid{end_}), \exposid{n_})}. +\tcode{views::counted(\exposid{current_}, \exposid{n_})}. \end{itemdescr} +\indexlibrarymember{operator++}{slide_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -12375,17 +15156,20 @@ \begin{itemdescr} \pnum \expects -\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. +\exposid{current_} and \exposid{last_ele_} (if present) are incrementable. \pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@, @\exposid{end_}@); -return *this; -\end{codeblock} +\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} constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} @@ -12401,21 +15185,28 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{slide_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} -ranges::advance(@\exposid{current_}@, @\exposid{missing_}@ - @\exposid{n_}@); -@\exposid{missing_}@ = 0; -return *this; -\end{codeblock} +\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} +\indexlibrarymember{operator--}{slide_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} @@ -12431,6 +15222,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator+=}{slide_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -12439,27 +15231,21 @@ \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} +\tcode{\exposid{current_} + x} and \tcode{\exposid{last_ele_} + x} (if \exposid{last_ele_} is present) +have well-defined behavior. \pnum -\effects -Equivalent to: -\begin{codeblock} -if (x > 0) { - @\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * x, @\exposid{end_}@); -} else if (x < 0) { - ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * x + @\exposid{missing_}@); - @\exposid{missing_}@ = 0; -} -return *this; -\end{codeblock} +\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} +\indexlibrarymember{operator-=}{slide_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -12467,41 +15253,47 @@ \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return *this += -x;} -\end{itemdescr} +\expects +\tcode{\exposid{current_} - x} and \tcode{\exposid{last_ele_} - x} (if \exposid{last_ele_} is present) +have well-defined behavior. -\begin{itemdecl} -constexpr value_type operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} +\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. -\begin{itemdescr} \pnum \returns -\tcode{*(*this + n)}. +\tcode{*this}. \end{itemdescr} +\indexlibrarymember{operator[]}{slide_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_} == y.\exposid{current_}}. +\effects +Equivalent to: \tcode{return views::counted(\exposid{current_} + n, \exposid{n_});} \end{itemdescr} +\indexlibrarymember{operator==}{slide_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{x.\exposid{current_} == x.\exposid{end_}}. +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} friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -12513,6 +15305,7 @@ \tcode{x.\exposid{current_} < y.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator>}{slide_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -12524,6 +15317,7 @@ Equivalent to: \tcode{return y < x;} \end{itemdescr} +\indexlibrarymember{operator<=}{slide_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -12535,6 +15329,7 @@ Equivalent to: \tcode{return !(y < x);} \end{itemdescr} +\indexlibrarymember{operator>=}{slide_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -12546,6 +15341,7 @@ Equivalent to: \tcode{return !(x < y);} \end{itemdescr} +\indexlibrarymember{operator<=>}{slide_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @@ -12558,6 +15354,7 @@ \tcode{x.\exposid{current_} <=> y.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator+}{slide_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -12565,332 +15362,339 @@ requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -auto r = i; -r += n; -return r; +\begin{itemdescr} +\pnum +\effects +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 @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-}{slide_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 +\returns +If \exposid{last_ele_} is present, +\tcode{x.\exposid{last_ele_} - y.\exposid{last_ele_}}; +otherwise, \tcode{x.\exposid{current_} - y.\exposid{cur\-rent_}}. +\end{itemdescr} + +\rSec3[range.slide.sentinel]{Class \tcode{slide_view::\exposid{sentinel}}} + +\indexlibraryglobal{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} -\end{itemdescr} +\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} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr explicit @\exposid{sentinel}@(sentinel_t end); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -auto r = i; -r -= n; -return r; -\end{codeblock} +Initializes \exposid{end_} with \tcode{end}. \end{itemdescr} +\indexlibrarymember{operator==}{slide_view::\exposid{sentinel}}% \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 bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{(x.\exposid{current_} - y.\exposid{current_} + x.\exposid{missing_} - y.\exposid{missing_}) / x.\exposid{n_}}. +\tcode{x.\exposid{last_ele_} == y.\exposid{end_}}. \end{itemdescr} +\indexlibrarymember{operator-}{slide_view::\exposid{sentinel}}% \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 range_difference_t + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{n_})}. +\tcode{x.\exposid{last_ele_} - y.\exposid{end_}}. \end{itemdescr} +\indexlibrarymember{operator-}{slide_view::\exposid{sentinel}}% \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 range_difference_t + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return -(y - x);} +\returns +\tcode{y.\exposid{end_} - x.\exposid{last_ele_}}. \end{itemdescr} -\rSec2[range.slide]{Slide view} +\rSec2[range.chunk.by]{Chunk by view} -\rSec3[range.slide.overview]{Overview} +\rSec3[range.chunk.by.overview]{Overview} \pnum -\tcode{slide_view} takes a \libconcept{view} and a number $N$ and -produces a \libconcept{view} -whose $M^\text{th}$ element is a \libconcept{view} over -the $M^\text{th}$ through -$(M + N - 1)^\text{th}$ elements -of the original \libconcept{view}. -If the original \libconcept{view} has fewer than $N$ elements, -the resulting \libconcept{view} is empty. +\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{slide}{views}% -The name \tcode{views::slide} denotes +\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{N}, -the expression \tcode{views::slide(E, N)} is expression-equivalent to -\tcode{slide_view(E, N)}. +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, 3, 4}; +vector v = {1, 2, 2, 3, 0, 4, 5, 2}; -for (auto i : v | views::slide(2)) { - cout << '[' << i[0] << ", " << i[1] << "] "; // prints \tcode{[1, 2] [2, 3] [3, 4]} +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.slide.view]{Class template \tcode{slide_view}} +\rSec3[range.chunk.by.view]{Class template \tcode{chunk_by_view}} -\indexlibrarymember{begin}{slide_view}% -\indexlibrarymember{end}{slide_view}% -\indexlibrarymember{size}{slide_view}% +\indexlibraryglobal{chunk_by_view}% \begin{codeblock} namespace std::ranges { - template - concept @\defexposconcept{slide-caches-nothing}@ = @\libconcept{random_access_range}@ && @\libconcept{sized_range}@; // \expos - - template - concept @\defexposconcept{slide-caches-last}@ = // \expos - !@\exposconcept{slide-caches-nothing}@ && @\libconcept{bidirectional_range}@ && @\libconcept{common_range}@; - - template - concept @\defexposconcept{slide-caches-first}@ = // \expos - !@\exposconcept{slide-caches-nothing}@ && !@\exposconcept{slide-caches-last}@; - - template<@\libconcept{forward_range}@ V> - requires @\libconcept{view}@ - class slide_view : public view_interface> { - V @\exposid{base_}@; // \expos - range_difference_t @\exposid{n_}@; // \expos - - // \ref{range.slide.iterator}, class template \tcode{slide_view::\exposid{iterator}} - template class @\exposid{iterator}@; // \expos + 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.slide.sentinel}, class \tcode{slide_view::\exposid{sentinel}} - class @\exposid{sentinel}@; // \expos + // \ref{range.chunk.by.iter}, class \tcode{chunk_by_view::\exposid{iterator}} + class @\exposidnc{iterator}@; // \expos public: - constexpr explicit slide_view(V base, range_difference_t n); + chunk_by_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; + constexpr explicit chunk_by_view(V base, Pred pred); - constexpr auto begin() - requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); - constexpr auto begin() const requires @\exposconcept{slide-caches-nothing}@; + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } - constexpr auto end() - requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); - constexpr auto end() const requires @\exposconcept{slide-caches-nothing}@; + constexpr const Pred& pred() const; - constexpr auto size() requires @\libconcept{sized_range}@; - constexpr auto size() const requires @\libconcept{sized_range}@; + 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 - slide_view(R&& r, range_difference_t) -> slide_view>; + template + chunk_by_view(R&&, Pred) -> chunk_by_view, Pred>; } \end{codeblock} +\indexlibraryctor{chunk_by_view}% \begin{itemdecl} -constexpr explicit slide_view(V base, range_difference_t n); +constexpr explicit chunk_by_view(V base, Pred pred); \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}. +\exposid{pred_} with \tcode{std::move(pred)}. \end{itemdescr} +\indexlibrarymember{pred}{chunk_by_view}% \begin{itemdecl} -constexpr auto begin() - requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); +constexpr const Pred& pred() const; \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}. +\effects +Equivalent to: \tcode{return *\exposid{pred_};} \end{itemdescr} +\indexlibrarymember{begin}{chunk_by_view}% \begin{itemdecl} -constexpr auto begin() const requires @\exposconcept{slide-caches-nothing}@; +constexpr @\exposid{iterator}@ begin(); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. + \pnum \returns -\tcode{\exposid{iterator}(ranges::begin(\exposid{base_}), \exposid{n_})}. +\tcode{\exposid{iterator}(*this, ranges::begin(\exposid{base_}), \exposid{find-next}(ranges::begin(\exposid{base_})))}. + +\pnum +\remarks +In order to provide +the amortized constant-time complexity required by the \libconcept{range} concept, +this function caches the result within the \tcode{chunk_by_view} +for use on subsequent calls. \end{itemdescr} +\indexlibrarymember{end}{chunk_by_view}% \begin{itemdecl} -constexpr auto end() - requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); +constexpr auto end(); \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_}@) +if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(*this, ranges::end(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); +} else { + return default_sentinel; +} \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}@; +constexpr iterator_t @\exposid{find-next}@(iterator_t current); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. + \pnum \returns -\tcode{begin() + range_difference_t(size())}. +\begin{codeblock} +ranges::next(ranges::adjacent_find(current, ranges::end(@\exposid{base_}@), not_fn(ref(*@\exposid{pred_}@))), + 1, ranges::end(@\exposid{base_}@)) +\end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr auto size() requires @\libconcept{sized_range}@; -constexpr auto size() const requires @\libconcept{sized_range}@; +constexpr iterator_t @\exposid{find-prev}@(iterator_t current) requires @\libconcept{bidirectional_range}@; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto sz = ranges::distance(@\exposid{base_}@) - @\exposid{n_}@ + 1; -if (sz < 0) sz = 0; -return @\exposid{to-unsigned-like}@(sz); -\end{codeblock} +\expects +\begin{itemize} +\item +\tcode{current} is not equal to \tcode{ranges::begin(\exposid{base_})}. +\item +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. +\end{itemize} + +\pnum +\returns +An iterator \tcode{i} +in the range \range{ranges::begin(\exposid{base_})}{current} such that: +\begin{itemize} +\item +\tcode{ranges::adjacent_find(i, current, not_fn(ref(*\exposid{pred_})))} is equal to \tcode{current}; and +\item +if \tcode{i} is not equal to \tcode{ranges::begin(\exposid{base_})}, +then \tcode{bool(invoke(*\exposid{pred_}, *ranges::prev(i), *i))} +is \tcode{false}. +\end{itemize} \end{itemdescr} -\rSec3[range.slide.iterator]{Class template \tcode{slide_view::\exposid{iterator}}} +\rSec3[range.chunk.by.iter]{Class \tcode{chunk_by_view::\exposid{iterator}}} -\indexlibraryglobal{slide_view::iterator}% +\indexlibraryglobal{chunk_by_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V> - requires @\libconcept{view}@ - template - class slide_view::@\exposid{iterator}@ { - using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos - iterator_t<@\exposid{Base}@> @\exposid{last_ele_}@ = iterator_t<@\exposid{Base}@>(); // \expos, - // present only if \tcode{\exposid{Base}} models \tcode{\exposconcept{slide-caches-first}} - range_difference_t<@\exposid{Base}@> @\exposid{n_}@ = 0; // \expos - - constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, range_difference_t<@\exposid{Base}@> n) // \expos - requires (!@\exposconcept{slide-caches-first}@<@\exposid{Base}@>); + template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@, iterator_t> Pred> + requires @\libconcept{view}@ && is_object_v + class chunk_by_view::@\exposid{iterator}@ { + chunk_by_view* @\exposid{parent_}@ = nullptr; // \expos + iterator_t @\exposid{current_}@ = iterator_t(); // \expos + iterator_t @\exposid{next_}@ = iterator_t(); // \expos - constexpr @\exposid{iterator}@(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}@>; + constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, // \expos + iterator_t next); public: + using value_type = subrange>; + using difference_type = range_difference_t; using iterator_category = input_iterator_tag; using iterator_concept = @\seebelow@; - using value_type = decltype(views::counted(@\exposid{current_}@, @\exposid{n_}@)); - using difference_type = range_difference_t<@\exposid{Base}@>; @\exposid{iterator}@() = default; - constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; - constexpr auto operator*() const; + constexpr 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 auto operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); - - friend constexpr bool operator<(const @\exposid{iterator}@& x, 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 bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); }; } \end{codeblock} @@ -12899,72 +15703,41 @@ \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}, +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} -\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} - +\indexlibraryctor{chunk_by_view::\exposid{iterator}}% \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}@>; +constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, iterator_t next); \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}. +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} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +constexpr value_type operator*() const; \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} +\expects +\exposid{current_} is not equal to \exposid{next_}. -\begin{itemdescr} \pnum \returns -\tcode{views::counted(\exposid{current_}, \exposid{n_})}. +\tcode{subrange(\exposid{current_}, \exposid{next_})}. \end{itemdescr} +\indexlibrarymember{operator++}{chunk_by_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -12972,19 +15745,19 @@ \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. +\exposid{current_} is not equal to \exposid{next_}. \pnum -\returns -\tcode{*this}. +\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} constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} @@ -13000,28 +15773,25 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{chunk_by_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; \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}. +\effects +Equivalent to: +\begin{codeblock} +@\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} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; \end{itemdecl} \begin{itemdescr} @@ -13035,134 +15805,146 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator==}{chunk_by_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \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}. +\tcode{x.\exposid{current_} == y.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator==}{chunk_by_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); \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}. +\tcode{x.\exposid{current_} == x.\exposid{next_}}. \end{itemdescr} -\begin{itemdecl} -constexpr auto operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} +\rSec2[range.stride]{Stride view} + +\rSec3[range.stride.overview]{Overview} -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return views::counted(\exposid{current_} + n, \exposid{n_});} -\end{itemdescr} +\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. -\begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); -\end{itemdecl} +\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)}. -\begin{itemdescr} \pnum -\returns -If \exposid{last_ele_} is present, -\tcode{x.\exposid{last_ele_} == y.\exposid{last_ele_}}; -otherwise, \tcode{x.\exposid{current_} == y.\exposid{cur\-rent_}}. -\end{itemdescr} +\begin{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}} + +\indexlibraryglobal{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_}@)); + } -\begin{itemdecl} -friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} + 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; + } + } -\begin{itemdescr} -\pnum -\returns -\tcode{x.\exposid{current_} < y.\exposid{current_}}. -\end{itemdescr} + 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; + } + } -\begin{itemdecl} -friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return y < x;} -\end{itemdescr} + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; + }; + + template + stride_view(R&&, range_difference_t) -> stride_view>; +} +\end{codeblock} +\indexlibraryctor{stride_view}% \begin{itemdecl} -friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr stride_view(V base, range_difference_t stride); \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{stride > 0} is \tcode{true}. -\begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(x < y);} +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{stride_} with \tcode{stride}. \end{itemdescr} +\indexlibrarymember{stride}{stride_view}% \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 range_difference_t stride() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\exposid{stride_}. \end{itemdescr} +\indexlibrarymember{size}{stride_view}% \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 auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; \end{itemdecl} \begin{itemdescr} @@ -13170,15 +15952,14 @@ \effects Equivalent to: \begin{codeblock} -auto r = i; -r += n; -return r; +return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{stride_}@)); \end{codeblock} \end{itemdescr} +\indexlibrarymember{reserve_hint}{stride_view}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - 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} @@ -13186,216 +15967,256 @@ \effects Equivalent to: \begin{codeblock} -auto r = i; -r -= n; -return r; +auto s = static_cast>(ranges::reserve_hint(@\exposid{base_}@)); +return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(s, @\exposid{stride_}@)); \end{codeblock} \end{itemdescr} -\begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -If \exposid{last_ele_} is present, -\tcode{x.\exposid{last_ele_} - y.\exposid{last_ele_}}; -otherwise, \tcode{x.\exposid{current_} - y.\exposid{cur\-rent_}}. -\end{itemdescr} - -\rSec3[range.slide.sentinel]{Class \tcode{slide_view::\exposid{sentinel}}} +\rSec3[range.stride.iterator]{Class template \tcode{stride_view::\exposid{iterator}}} -\indexlibraryglobal{chunk_view::sentinel}% +\indexlibraryglobal{stride_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V> + template<@\libconcept{input_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 + 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); public: - @\exposid{sentinel}@() = default; + 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 - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; - friend constexpr range_difference_t - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y) - requires @\libconcept{sized_sentinel_for}@, iterator_t>; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ other) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> + && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; - friend constexpr range_difference_t - operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x) - requires @\libconcept{sized_sentinel_for}@, iterator_t>; + constexpr iterator_t<@\exposid{Base}@> base() &&; + constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; + + constexpr decltype(auto) operator*() const { return *@\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 n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type n) 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, 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}@>; + + 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}@>>; + + 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} \pnum -\begin{note} -\exposid{sentinel} is used -only when \tcode{\exposconcept{slide-caches-first}} is \tcode{true}. -\end{note} +\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, 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{\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 explicit @\exposid{sentinel}@(sentinel_t end); +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{end_} with \tcode{end}. +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} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +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 -\returns -\tcode{x.\exposid{last_ele_} == y.\exposid{end_}}. +\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_}}. \end{itemdescr} +\indexlibrarymember{base}{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 iterator_t<@\exposid{Base}@> base() &&; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{x.\exposid{last_ele_} - y.\exposid{end_}}. +\tcode{std::move(\exposid{current_})}. \end{itemdescr} +\indexlibrarymember{base}{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>; +constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{y.\exposid{end_} - x.\exposid{last_ele_}}. +\exposid{current_}. \end{itemdescr} -\rSec2[range.chunk.by]{Chunk by view} - -\rSec3[range.chunk.by.overview]{Overview} +\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} +\begin{itemdescr} \pnum -\tcode{chunk_by_view} takes a \libconcept{view} and a predicate, and -splits the \libconcept{view} into \tcode{subrange}s -between each pair of adjacent elements -for which the predicate returns \tcode{false}. +\expects +\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. \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}} - +\effects +Equivalent to: \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_}@ = 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_}@); } - - 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>; -} +@\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{stride_}@, @\exposid{end_}@); +return *this; \end{codeblock} +\end{itemdescr} +\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit chunk_by_view(V base, Pred pred); +constexpr void operator++(int); \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{++*this;} \end{itemdescr} -\indexlibrarymember{pred}{chunk_by_view}% +\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr const Pred& pred() const; +constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return *\exposid{pred_};} +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ begin(); +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{\exposid{pred_}.has_value()} is \tcode{true}. - -\pnum -\returns -\tcode{\exposid{iterator}(*this, ranges::begin(\exposid{base_}), \exposid{find-next}(ranges::begin(\exposid{base_})))}. - -\pnum -\remarks -In order to provide -the amortized constant-time complexity required by the \libconcept{range} concept, -this function caches the result within the \tcode{chunk_by_view} -for use on subsequent calls. +\effects +Equivalent to: +\begin{codeblock} +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} -constexpr auto end(); +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -13403,151 +16224,160 @@ \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 tmp = *this; +--*this; +return tmp; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator+=}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr iterator_t @\exposid{find-next}@(iterator_t current); +constexpr @\exposid{iterator}@& operator+=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{\exposid{pred_}.has_value()} is \tcode{true}. +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} \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_}@)) +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} -constexpr iterator_t @\exposid{find-prev}@(iterator_t current) requires @\libconcept{bidirectional_range}@; +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\begin{itemize} -\item -\tcode{current} is not equal to \tcode{ranges::begin(\exposid{base_})}. -\item -\tcode{\exposid{pred_}.has_value()} is \tcode{true}. -\end{itemize} +\effects +Equivalent to: \tcode{return *this += -x;} +\end{itemdescr} + +\indexlibrarymember{operator==}{stride_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); +\end{itemdecl} +\begin{itemdescr} \pnum \returns -An iterator \tcode{i} -in the range \range{ranges::begin(\exposid{base_})}{current} such that: -\begin{itemize} -\item -\tcode{ranges::adjacent_find(i, current, not_fn(ref(*\exposid{pred_})))} is equal to \tcode{current}; and -\item -if \tcode{i} is not equal to \tcode{ranges::begin(\exposid{base_})}, -then \tcode{bool(invoke(*\exposid{pred_}, *ranges::prev(i), *i))} -is \tcode{false}. -\end{itemize} +\tcode{x.\exposid{current_} == x.\exposid{end_}}. \end{itemdescr} -\rSec3[range.chunk.by.iter]{Class \tcode{chunk_by_view::\exposid{iterator}}} - -\begin{codeblock} -namespace std::ranges { - template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@, iterator_t> Pred> - requires @\libconcept{view}@ && is_object_v - class chunk_by_view::@\exposid{iterator}@ { - chunk_by_view* @\exposid{parent_}@ = nullptr; // \expos - iterator_t @\exposid{current_}@ = iterator_t(); // \expos - iterator_t @\exposid{next_}@ = iterator_t(); // \expos - - constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, // \expos - iterator_t next); - - public: - using value_type = subrange>; - using difference_type = range_difference_t; - using iterator_category = input_iterator_tag; - using iterator_concept = @\seebelow@; +\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} - @\exposid{iterator}@() = default; +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} == y.\exposid{current_}}. +\end{itemdescr} - constexpr value_type operator*() const; - constexpr @\exposid{iterator}@& operator++(); - constexpr @\exposid{iterator}@ operator++(int); +\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} - constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; - constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} < y.\exposid{current_}}. +\end{itemdescr} - 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} +\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} +\begin{itemdescr} \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} +\effects +Equivalent to: \tcode{return y < x;} +\end{itemdescr} +\indexlibrarymember{operator<=}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, iterator_t next); +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)}, -\exposid{current_} with \tcode{current}, and -\exposid{next_} with \tcode{next}. +Equivalent to: \tcode{return !(y < x);} \end{itemdescr} +\indexlibrarymember{operator>=}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr value_type 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 -\exposid{current_} is not equal to \exposid{next_}. +\effects +Equivalent to: \tcode{return !(x < y);} +\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}@>; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{subrange(\exposid{current_}, \exposid{next_})}. +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator+}{stride_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} -\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; +auto r = i; +r += n; +return r; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ 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} @@ -13555,386 +16385,582 @@ \effects Equivalent to: \begin{codeblock} -auto tmp = *this; -++*this; -return tmp; +auto r = i; +r -= n; +return r; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() 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 -\effects -Equivalent to: -\begin{codeblock} -@\exposid{next_}@ = @\exposid{current_}@; -@\exposid{current_}@ = @\exposid{parent_}@->@\exposid{find-prev}@(@\exposid{next_}@); -return *this; -\end{codeblock} +\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} \end{itemdescr} +\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; +friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{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: -\begin{codeblock} -auto tmp = *this; ---*this; -return tmp; -\end{codeblock} +Equivalent to: \tcode{return -(y - x);} \end{itemdescr} +\indexlibrarymember{iter_move}{stride_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +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 -\returns -\tcode{x.\exposid{current_} == y.\exposid{current_}}. +\effects +Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});} \end{itemdescr} +\indexlibrarymember{iter_swap}{stride_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); +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 -\returns -\tcode{x.\exposid{current_} == x.\exposid{next_}}. +\effects +Equivalent to: +\tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_});} \end{itemdescr} -\rSec2[range.stride]{Stride view} +\rSec2[range.cartesian]{Cartesian product view} -\rSec3[range.stride.overview]{Overview} +\rSec3[range.cartesian.overview]{Overview} +\indexlibraryglobal{cartesian_product_view}% \pnum -\tcode{stride_view} presents a \libconcept{view} of an underlying sequence, -advancing over $n$ elements at a time, -as opposed to the usual single-step succession. +\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::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)}. +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} -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} +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.stride.view]{Class template \tcode{stride_view}} +\rSec3[range.cartesian.view]{Class template \tcode{cartesian_product_view}} +\indexlibraryglobal{cartesian_product_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); + 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}@>)); - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } + template + concept @\defexposconcept{cartesian-product-common-arg}@ = // \expos + @\libconcept{common_range}@ || (@\libconcept{sized_range}@ && @\libconcept{random_access_range}@); - constexpr range_difference_t stride() const noexcept; + 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}@>)); - constexpr auto begin() requires (!@\exposconcept{simple-view}@) { - return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); - } + template + concept @\defexposconcept{cartesian-product-is-common}@ = // \expos + @\exposconcept{cartesian-product-common-arg}@; - constexpr auto begin() const requires @\libconcept{range}@ { - return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); - } + template + concept @\defexposconcept{cartesian-product-is-sized}@ = // \expos + (@\libconcept{sized_range}@ && ...); - 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; - } - } + 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}@>>)); - 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; - } + 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 auto size() requires @\libconcept{sized_range}@; - constexpr auto size() const requires @\libconcept{sized_range}@; + 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: + constexpr cartesian_product_view() = default; + constexpr explicit cartesian_product_view(First first_base, Vs... bases); + + constexpr @\exposid{iterator}@ begin() + requires (!@\exposconcept{simple-view}@ || ... || !@\exposconcept{simple-view}@); + constexpr @\exposid{iterator}@ begin() const + requires (@\libconcept{range}@ && ... && @\libconcept{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; + + constexpr @\seebelow@ size() + requires @\exposconcept{cartesian-product-is-sized}@; + constexpr @\seebelow@ size() const + requires @\exposconcept{cartesian-product-is-sized}@; }; - template - stride_view(R&&, range_difference_t) -> stride_view>; -} + template + cartesian_product_view(Vs&&...) -> cartesian_product_view...>; +} +\end{codeblock} + +\indexlibraryctor{cartesian_product_view}% +\begin{itemdecl} +constexpr explicit cartesian_product_view(First first_base, Vs... bases); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{bases_} +with \tcode{std::move(first_base), std::move(bases)...}. +\end{itemdescr} + +\indexlibrarymember{begin}{cartesian_product_view}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ begin() + requires (!@\exposconcept{simple-view}@ || ... || !@\exposconcept{simple-view}@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +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}@ begin() const + requires (@\libconcept{range}@ && ... && @\libconcept{range}@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{iterator}@(*this, @\exposid{tuple-transform}@(ranges::begin, @\exposid{bases_}@)); \end{codeblock} +\end{itemdescr} -\indexlibraryctor{stride_view}% +\indexlibrarymember{end}{cartesian_product_view}% \begin{itemdecl} -constexpr stride_view(V base, range_difference_t stride); +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 -\expects -\tcode{stride > 0} is \tcode{true}. +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} \pnum \effects -Initializes \exposid{base_} with \tcode{std::move(base)} and -\exposid{stride_} with \tcode{stride}. +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; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{stride}{stride_view}% +\indexlibrarymember{end}{cartesian_product_view}% \begin{itemdecl} -constexpr range_difference_t stride() const noexcept; +constexpr default_sentinel_t end() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\exposid{stride_}. +\tcode{default_sentinel}. \end{itemdescr} -\indexlibrarymember{size}{stride_view}% +\indexlibrarymember{size}{cartesian_product_view}% \begin{itemdecl} -constexpr auto size() requires @\libconcept{sized_range}@; -constexpr auto size() const requires @\libconcept{sized_range}@; +constexpr @\seebelow@ size() + requires @\exposconcept{cartesian-product-is-sized}@; +constexpr @\seebelow@ size() const + requires @\exposconcept{cartesian-product-is-sized}@; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{stride_}@)); -\end{codeblock} +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$. \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} -\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, 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 +\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} + +\pnum +\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. + +\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} + +\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} + +\begin{itemdecl} +template + constexpr difference_type @\exposid{distance-from}@(const Tuple& t) const; +\end{itemdecl} +\begin{itemdescr} \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: +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::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::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::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::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::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::iterator}% +\indexlibrarymember{operator++}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -13942,12 +16968,12 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{++*this;} +Equivalent to \tcode{++*this}. \end{itemdescr} -\indexlibrarymember{operator++}{stride_view::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} @@ -13961,9 +16987,10 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{stride_view::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} @@ -13971,15 +16998,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::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} @@ -13993,48 +17020,88 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+=}{stride_view::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) { - @\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{stride_}@ * n, @\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::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==}{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==}{stride_view::iterator}% +\indexlibrarymember{operator==}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); \end{itemdecl} @@ -14042,946 +17109,786 @@ \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::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::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::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::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::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::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::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{iter_move}{cartesian_product_view::\exposid{iterator}}% +\begin{itemdecl} +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{operator-}{stride_view::iterator}% +\indexlibrarymember{iter_swap}{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 void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires (@\libconcept{indirectly_swappable}@>> && ... && + @\libconcept{indirectly_swappable}@>>); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: +For every integer $0 \le i \le \tcode{sizeof...(Vs)}$, performs: \begin{codeblock} -auto r = i; -r -= n; -return r; +ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@)) \end{codeblock} -\end{itemdescr} - -\indexlibrarymember{operator-}{stride_view::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 -\returns -Let \tcode{N} be \tcode{(x.\exposid{current_} - y.\exposid{current_})}. +\remarks +The exception specification is equivalent to the logical \logop{and} of the following expressions: \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_})}. +\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} -\indexlibrarymember{operator-}{stride_view::iterator}% +\rSec2[range.cache.latest]{Cache latest view} + +\rSec3[range.cache.latest.overview]{Overview} + +\pnum +\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} +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}@; + }; + + template + cache_latest_view(R&&) -> cache_latest_view>; +} +\end{codeblock} + +\indexlibraryctor{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 explicit cache_latest_view(V base); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{stride_})}. +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. \end{itemdescr} -\indexlibrarymember{operator-}{stride_view::iterator}% +\indexlibrarymember{begin}{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 begin(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return -(y - x);} +Equivalent to: \tcode{return \exposid{iterator}(*this);} \end{itemdescr} -\indexlibrarymember{iter_move}{stride_view::iterator}% +\indexlibrarymember{end}{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 end(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});} +Equivalent to: \tcode{return \exposid{sentinel}(*this);} \end{itemdescr} -\indexlibrarymember{iter_swap}{stride_view::iterator}% +\indexlibrarymember{size}{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 size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{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::size(\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<@\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-common}@ = // \expos - @\exposconcept{cartesian-product-common-arg}@; + constexpr explicit @\exposid{iterator}@(cache_latest_view& parent); // \expos - template - concept @\defexposconcept{cartesian-product-is-sized}@ = // \expos - (@\libconcept{sized_range}@ && ...); + public: + using difference_type = range_difference_t; + using value_type = range_value_t; + using iterator_concept = input_iterator_tag; - 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}@>>)); + @\exposid{iterator}@(@\exposid{iterator}@&&) = default; + @\exposid{iterator}@& operator=(@\exposid{iterator}@&&) = default; - 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 iterator_t base() &&; + constexpr const iterator_t& base() const & noexcept; - 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{ranges.cartesian.iterator}, class template \tcode{cartesian_product_view::\exposid{iterator}} - template class @\exposid{iterator}@; // \expos - 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); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \exposid{bases_} -with \tcode{std::move(first_base), std::move(bases)...}. -\end{itemdescr} - -\begin{itemdecl} -constexpr @\exposid{iterator}@ begin() - requires (!@\exposconcept{simple-view}@ || ... || !@\exposconcept{simple-view}@); +constexpr explicit @\exposid{iterator}@(cache_latest_view& parent); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return \exposid{iterator}(\exposid{tuple-transform}(ranges::begin, \exposid{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() const - requires (@\libconcept{range}@ && ... && @\libconcept{range}@); +constexpr iterator_t base() &&; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\tcode{return \exposid{iterator}(\exposid{tuple-transform}(ranges::begin, \exposid{bases_}));} +\returns +\tcode{std::move(\exposid{current_})}. \end{itemdescr} +\indexlibrarymember{base}{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 const iterator_t& base() const & noexcept; \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) : \exposid{cartesian-common-arg-end}(rng)} -if \tcode{rng} is the first underlying range and -\tcode{ranges::begin(rng)} otherwise. -\end{itemize} +\returns +\exposid{current_}. +\end{itemdescr} + +\indexlibrarymember{operator++}{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} +\begin{itemdescr} \pnum \effects Equivalent to: \begin{codeblock} -@\exposid{iterator}@<@\exposid{is-const}@> it(@\exposid{tuple-transform}@( - [](auto& rng){ return @\exposid{begin-or-first-end}@(rng); }, @\exposid{bases_}@)); -return it; +@\exposid{parent_}@->@\exposid{cache_}@.reset(); +++@\exposid{current_}@; +return *this; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{cache_latest_view::\exposid{iterator}}% \begin{itemdecl} -constexpr default_sentinel_t end() const noexcept; +constexpr void operator++(int); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{default_sentinel}. +\effects +Equivalent to: \tcode{++*this}. \end{itemdescr} +\indexlibrarymember{operator*}{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}@; +constexpr range_reference_t& operator*() const; \end{itemdecl} \begin{itemdescr} \pnum -The return type is an \impldef{return type of \tcode{cartesian_product_view::size}} unsigned-integer-like type. +\effects +Equivalent to: +\begin{codeblock} +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} -\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. +\indexlibrarymember{iter_move}{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +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 -Let $p$ be the product of the sizes of all the ranges in \exposid{bases_}. +\effects +Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});} +\end{itemdescr} -\pnum -\expects -$p$ can be represented by the return type. +\indexlibrarymember{iter_swap}{cache_latest_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 -\returns -$p$. +\effects +Equivalent to +\tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_})}. \end{itemdescr} -\rSec3[ranges.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}@() requires @\libconcept{forward_range}@<@\exposid{maybe-const}@> = 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-(@\exposid{iterator}@ i, default_sentinel_t) - requires @\exposconcept{cartesian-is-sized-sentinel}@; - friend constexpr difference_type operator-(default_sentinel_t, @\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: - @\exposid{maybe-const}@* @\exposid{parent_}@ = nullptr; // \expos - tuple>, - iterator_t<@\exposid{maybe-const}@>...> @\exposid{current_}@; // \expos + constexpr explicit @\exposid{sentinel}@(cache_latest_view& parent); // \expos - template - constexpr void @\exposid{next}@(); // \expos + public: + @\exposid{sentinel}@() = default; - template - constexpr void @\exposid{prev}@(); // \expos + constexpr sentinel_t base() const; - template - constexpr difference_type @\exposid{distance-from}@(Tuple t); // \expos + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); - constexpr explicit @\exposid{iterator}@(tuple>, - iterator_t<@\exposid{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 (it == ranges::begin(std::get(@\exposid{parent_}@->@\exposid{bases_}@))) { - it = @\exposid{cartesian-common-arg-end}@(std::get(@\exposid{parent_}@->@\exposid{bases_}@)); - if constexpr (N > 0) { - @\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}@(Tuple t); +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 < \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} +\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}@; + }; + + template + to_input_view(R&&) -> to_input_view>; +} +\end{codeblock} \begin{itemdecl} -constexpr explicit @\exposid{iterator}@(tuple>, - iterator_t<@\exposid{maybe-const}@>...> current); +constexpr explicit to_input_view(V base); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{current_} with \tcode{std::move(current)}. +Initializes \exposid{base_} with \tcode{std::move(base)}. \end{itemdescr} \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{current_} with \tcode{std::move(i.\exposid{current_})}. +Equivalent to: \tcode{return \exposid{iterator}(ranges::begin(\exposid{base_}));} \end{itemdescr} \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} \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} \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} -\begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{maybe-const}@>; -\end{itemdecl} +\rSec3[range.to.input.iterator]{Class template \tcode{to_input_view::\exposid{iterator}}} -\begin{itemdescr} -\pnum -\effects -Equivalent to: \begin{codeblock} -auto tmp = *this; -++*this; -return tmp; -\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--() - 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} -@\exposid{prev}@(); -return *this; -\end{codeblock} -\end{itemdescr} + constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); // \expos -\begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) - requires @\exposconcept{cartesian-product-is-bidirectional}@; -\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 -\effects -Equivalent to: -\begin{codeblock} -auto tmp = *this; ---*this; -return tmp; -\end{codeblock} -\end{itemdescr} + @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; -\begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\exposconcept{cartesian-product-is-random-access}@; -\end{itemdecl} + @\exposid{iterator}@(@\exposid{iterator}@&&) = default; + @\exposid{iterator}@& operator=(@\exposid{iterator}@&&) = default; -\begin{itemdescr} -\pnum -Let \tcode{orig} be the value of \tcode{*this} before the call. + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; -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} + constexpr iterator_t<@\exposid{Base}@> base() &&; + constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; -\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 decltype(auto) operator*() const { return *@\exposid{current_}@; } -\pnum -\effects -Sets the value of \tcode{*this} to \tcode{ret}. + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); -\pnum -\returns -\tcode{*this}. + friend constexpr bool operator==(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y); -\pnum -\complexity -Constant. -\end{itemdescr} + 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}@>>; -\begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\exposconcept{cartesian-product-is-random-access}@; -\end{itemdecl} + friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -*this += -x; -return *this; + 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} \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} \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} \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} \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} \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} \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} \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} \begin{itemdecl} -friend constexpr difference_type operator-(@\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} \begin{itemdecl} -friend constexpr difference_type operator-(default_sentinel_t s, @\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} \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} \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} @@ -14990,7 +17897,7 @@ \pnum Class template \tcode{generator} presents -a \libconcept{view} of the elements yielded by the evaluation of a coroutine. +a view of the elements yielded by the evaluation of a coroutine. \pnum A \tcode{generator} generates a sequence of elements by @@ -15021,8 +17928,13 @@ \begin{codeblock} namespace std { // \ref{coro.generator.class}, class template \tcode{generator} - template + template class generator; + + namespace pmr { + template + using generator = std::generator>; + } } \end{codeblock} @@ -15030,11 +17942,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 @@ -15116,7 +18028,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} @@ -15220,8 +18132,8 @@ \begin{codeblock} namespace std { - template - class generator::promise_type { + template + class generator::promise_type { public: generator get_return_object() noexcept; @@ -15235,12 +18147,15 @@ @\libconcept{constructible_from}@, const remove_reference_t&>; template - requires @\libconcept{same_as}@::yielded, yielded> - auto yield_value(ranges::elements_of&&, Unused> g) noexcept; + 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> - auto yield_value(ranges::elements_of r) noexcept; + auto yield_value(ranges::elements_of r); void await_transform() = delete; @@ -15251,13 +18166,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; @@ -15338,7 +18251,7 @@ A handle referring to the coroutine whose promise object is \tcode{*this} is at the top of \tcode{*\exposid{active_}} -of some \tcode{generator} object \tcode{x}. +of some \tcode{generator} object. \pnum \returns @@ -15361,9 +18274,12 @@ \indexlibrarymember{yield_value}{generator::promise_type}% \begin{itemdecl} -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{same_as}@::yielded, yielded> + auto yield_value(ranges::elements_of&, Unused> g) noexcept; \end{itemdecl} \begin{itemdescr} @@ -15396,7 +18312,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} @@ -15404,7 +18320,7 @@ \begin{itemdecl} template requires @\libconcept{convertible_to}@, yielded> - auto yield_value(ranges::elements_of r) noexcept; + auto yield_value(ranges::elements_of r); \end{itemdecl} \begin{itemdescr} @@ -15413,7 +18329,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); } @@ -15423,9 +18339,10 @@ \end{codeblock} \pnum -\remarks +\begin{note} A \grammarterm{yield-expression} that calls this function has type \tcode{void}\iref{expr.yield}. +\end{note} \end{itemdescr} \indexlibrarymember{unhandled_exception}{generator::promise_type}% @@ -15445,8 +18362,8 @@ If the handle referring to the coroutine whose promise object is \tcode{*this} is the sole element of \tcode{*x.\exposid{active_}}, -equivalent to: \tcode{throw;} -Otherwise, assigns \tcode{current_exception()} to \exposid{except_}. +equivalent to \tcode{throw}, +otherwise, assigns \tcode{current_exception()} to \exposid{except_}. \end{itemdescr} \indexlibrarymember{operator new}{generator::promise_type}% @@ -15455,11 +18372,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} @@ -15482,6 +18397,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 @@ -15522,8 +18440,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; @@ -15535,7 +18453,7 @@ @\exposid{iterator}@& operator++(); void operator++(int); - friend bool operator==(@\exposid{iterator}@ i, default_sentinel_t); + friend bool operator==(const @\exposid{iterator}@& i, default_sentinel_t); private: coroutine_handle @\exposid{coroutine_}@; // \expos @@ -15543,7 +18461,7 @@ } \end{codeblock} -\indexlibraryctor{generator::iterator}% +\indexlibraryctor{generator::\exposid{iterator}}% \begin{itemdecl} @\exposid{iterator}@(@\exposid{iterator}@&& other) noexcept; \end{itemdecl} @@ -15555,7 +18473,7 @@ with \tcode{exchange(other.\exposid{coroutine_}, \{\})}. \end{itemdescr} -\indexlibrarymember{operator=}{generator::iterator}% +\indexlibrarymember{operator=}{generator::\exposid{iterator}}% \begin{itemdecl} @\exposid{iterator}@& operator=(@\exposid{iterator}@&& other) noexcept; \end{itemdecl} @@ -15571,7 +18489,7 @@ \tcode{*this}. \end{itemdescr} -\indexlibrarymember{operator*}{generator::iterator}% +\indexlibrarymember{operator*}{generator::\exposid{iterator}}% \begin{itemdecl} @\exposid{reference}@ operator*() const noexcept(is_nothrow_copy_constructible_v<@\exposid{reference}@>); \end{itemdecl} @@ -15590,7 +18508,7 @@ \tcode{return static_cast<\exposid{reference}>(*p.\exposid{value_});} \end{itemdescr} -\indexlibrarymember{operator++}{generator::iterator}% +\indexlibrarymember{operator++}{generator::\exposid{iterator}}% \begin{itemdecl} @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -15610,7 +18528,7 @@ \tcode{*this}. \end{itemdescr} -\indexlibrarymember{operator++}{generator::iterator}% +\indexlibrarymember{operator++}{generator::\exposid{iterator}}% \begin{itemdecl} void operator++(int); \end{itemdecl} @@ -15621,9 +18539,9 @@ Equivalent to \tcode{++*this}. \end{itemdescr} -\indexlibrarymember{operator==}{generator::iterator}% +\indexlibrarymember{operator==}{generator::\exposid{iterator}}% \begin{itemdecl} -friend bool operator==(@\exposid{iterator}@ i, default_sentinel_t); +friend bool operator==(const @\exposid{iterator}@& i, default_sentinel_t); \end{itemdecl} \begin{itemdescr} diff --git a/source/regex.tex b/source/regex.tex deleted file mode 100644 index 1503118992..0000000000 --- a/source/regex.tex +++ /dev/null @@ -1,3944 +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} - -\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 \keyword{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; - }; -} -\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} - -\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 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 = @{\impdef}@; - 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&); - match_results(const match_results& m); - match_results(match_results&& m) noexcept; - 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 -\ensures -\tcode{ready()} returns \tcode{false}. -\tcode{size()} returns \tcode{0}. -\end{itemdescr} - -\indexlibraryctor{match_results}% -\begin{itemdecl} -match_results(const match_results& m); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -As specified in \tref{re.results.const}. -\end{itemdescr} - -\indexlibraryctor{match_results}% -\begin{itemdecl} -match_results(match_results&& m) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The stored \tcode{Allocator} value is move constructed from \tcode{m.get_allocator()}. - -\pnum -\ensures -As specified in \tref{re.results.const}. -\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 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 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 bca992c936..ba75c744d2 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 @@ -19,6 +19,7 @@ \opt{attribute-specifier-seq} selection-statement\br \opt{attribute-specifier-seq} iteration-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,7 +34,8 @@ \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} The optional \grammarterm{attribute-specifier-seq} appertains to the respective statement. @@ -57,6 +59,7 @@ \end{note} \pnum +\indextext{statement!enclosing}% A \grammarterm{statement} \tcode{S1} \defnx{encloses}{enclosing statement} a \grammarterm{statement} \tcode{S2} if \begin{itemize} @@ -74,14 +77,23 @@ \item \tcode{S1} encloses a statement \tcode{S3} and \tcode{S3} encloses \tcode{S2}. \end{itemize} +\indextext{statement!enclosed by}% +A statement \tcode{S1} is +\defnx{enclosed by}{enclosed by statement} +a statement \tcode{S2} if +\tcode{S2} encloses \tcode{S1}. \pnum \indextext{\idxgram{condition}{s}!rules for}% -The rules for \grammarterm{condition}{s} apply both to -\grammarterm{selection-statement}{s} 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}. +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}. +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 @@ -89,16 +101,20 @@ 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. The value of a -\grammarterm{condition} that is an initialized declaration in a -\keyword{switch} statement is the value of the declared variable if it has -integral or enumeration type, or of that variable implicitly converted -to integral or enumeration type otherwise. The value of a +conversion is ill-formed, the program is ill-formed. +The value of a \grammarterm{condition} that is an expression is the value of the expression, contextually converted to \tcode{bool} for statements other @@ -113,7 +129,10 @@ 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}, +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}. @@ -148,9 +167,12 @@ before its introduction. \pnum +\indextext{\idxgram{labeled-statement}}% \indextext{label!\idxcode{case}}% \indextext{label!\idxcode{default}}% -Case labels and default labels shall occur only in \keyword{switch} statements. +A \grammarterm{labeled-statement} +whose \grammarterm{label} is a \keyword{case} or \keyword{default} label +shall be enclosed by\iref{stmt.pre} a \keyword{switch} statement\iref{stmt.switch}. \pnum A \defnadj{control-flow-limited}{statement} is a statement \tcode{S} for which: @@ -181,10 +203,9 @@ \indextext{side effects}% side effects from an expression statement are completed before the next statement is executed. -\indextext{statement!null}% \indextext{statement!empty}% -An expression statement with the expression missing is called -a \defn{null statement}. +An expression statement with the \grammarterm{expression} missing is called +a \defnadj{null}{statement}. \begin{note} Most statements are expression statements --- usually assignments or function calls. A null statement is useful to supply a null body to an @@ -206,14 +227,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} @@ -262,7 +281,7 @@ \indextext{statement!\idxcode{if}} \pnum -If the condition\iref{stmt.select} 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 @@ -403,7 +422,10 @@ several statements depending on the value of a condition. \pnum -The condition shall be of integral type, enumeration type, or class +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 an integral or enumeration type. @@ -500,7 +522,7 @@ \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{]} + structured-binding-declaration \end{bnf} \begin{bnf} @@ -537,12 +559,43 @@ 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}} \pnum -In the \keyword{while} statement the substatement is executed repeatedly -until the value of the condition\iref{stmt.select} becomes +In the \keyword{while} statement, the substatement is executed repeatedly +until the value of the condition\iref{stmt.pre} becomes \tcode{false}. The test takes place before each execution of the substatement. @@ -589,7 +642,7 @@ if that conversion is ill-formed, the program is ill-formed. \pnum -In the \keyword{do} statement the substatement is executed repeatedly +In the \keyword{do} statement, the substatement is executed repeatedly until the value of the expression becomes \tcode{false}. The test takes place after each execution of the statement. @@ -620,7 +673,7 @@ re-evaluating \grammarterm{condition}. \begin{note} Thus the first statement specifies initialization for the loop; the -condition\iref{stmt.select} specifies a test, sequenced before each +condition\iref{stmt.pre} specifies a test, sequenced before each iteration, such that the loop is exited when the condition becomes \tcode{false}; the expression often specifies incrementing that is sequenced after each iteration. @@ -668,15 +721,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, @@ -694,7 +747,6 @@ \end{note} \end{itemize} \end{itemize} - \begin{example} \begin{codeblock} int array[5] = { 1, 2, 3, 4, 5 }; @@ -702,6 +754,23 @@ x *= 2; \end{codeblock} \end{example} +\begin{note} +The lifetime of some temporaries in the \grammarterm{for-range-initializer} +is extended to cover the entire loop\iref{class.temporary}. +\end{note} +\begin{example} +\begin{codeblock} +using T = std::list; +const T& f1(const T& t) { return t; } +const T& f2(T t) { return t; } +T g(); + +void foo() { + for (auto e : f1(g())) {} // OK, lifetime of return value of \tcode{g()} extended + for (auto e : f2(g())) {} // undefined behavior +} +\end{codeblock} +\end{example} \pnum In the \grammarterm{decl-specifier-seq} of a \grammarterm{for-range-declaration}, @@ -740,7 +809,7 @@ \begin{note} On exit from a scope (however accomplished), objects with automatic storage duration\iref{basic.stc.auto} that have been constructed in that scope are destroyed -in the reverse order of their construction. +in the reverse order of their construction\iref{stmt.dcl}. For temporaries, see~\ref{class.temporary}. However, the program can be terminated (by calling \indextext{\idxcode{exit}}% @@ -759,25 +828,27 @@ \indextext{statement!\idxcode{break}} \pnum -The \keyword{break} statement shall occur only in an +A \keyword{break} statement shall be enclosed by\iref{stmt.pre} \indextext{\idxgram{iteration-statement}}% \indextext{statement!\idxcode{switch}}% -\grammarterm{iteration-statement} or a \keyword{switch} statement and causes -termination of the smallest enclosing \grammarterm{iteration-statement} or -\keyword{switch} statement; control passes to the statement following the +an \grammarterm{iteration-statement}\iref{stmt.iter} or +a \keyword{switch} statement\iref{stmt.switch}. +The \keyword{break} statement causes +termination of the smallest such enclosing statement; +control passes to the statement following the terminated statement, if any. \rSec2[stmt.cont]{The \keyword{continue} statement}% \indextext{statement!\idxcode{continue}} \pnum -The -\keyword{continue} -statement shall occur only in an +A \keyword{continue} +statement shall be enclosed by\iref{stmt.pre} an \indextext{\idxgram{iteration-statement}}% -\grammarterm{iteration-statement} -and causes control to pass to the loop-continuation portion of the -smallest enclosing \grammarterm{iteration-statement}, that is, to the end +\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} @@ -819,7 +890,7 @@ \indextext{function return|see{\tcode{return}}}% \pnum -A function returns to its caller by the \tcode{return} statement. +A function returns control to its caller by the \tcode{return} statement. \pnum The \grammarterm{expr-or-braced-init-list} @@ -877,6 +948,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}}% @@ -888,8 +992,8 @@ \end{bnf} \pnum -A coroutine returns to its caller or resumer\iref{dcl.fct.def.coroutine} -by the \keyword{co_return} statement or when suspended\iref{expr.await}. +A \keyword{co_return} statement transfers control to +the caller or resumer of a coroutine\iref{dcl.fct.def.coroutine}. A coroutine shall not enclose a \tcode{return} statement\iref{stmt.return}. \begin{note} @@ -923,7 +1027,8 @@ \end{itemize} \pnum -If \placeholder{p}\tcode{.return_void()} is a valid expression, +If a search for the name \tcode{return_void} in the scope of the promise type +finds any declarations, flowing off the end of a coroutine's \grammarterm{function-body} is equivalent to a \keyword{co_return} with no operand; otherwise flowing off the end of a coroutine's \grammarterm{function-body} @@ -938,6 +1043,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} @@ -963,16 +1110,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. @@ -1053,7 +1200,8 @@ conversion\iref{expr.type.conv} as its leftmost subexpression can be indistinguishable from a \grammarterm{declaration} where the first \grammarterm{declarator} starts with a \tcode{(}. In those cases the -\grammarterm{statement} is a \grammarterm{declaration}. +\grammarterm{statement} is considered a \grammarterm{declaration}, +except as specified below. \pnum \begin{note} @@ -1065,7 +1213,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 @@ -1135,4 +1283,35 @@ } \end{codeblock} \end{example} + +\pnum +A syntactically ambiguous statement that can syntactically be +a \grammarterm{declaration} with an outermost \grammarterm{declarator} +with a \grammarterm{trailing-return-type} +is considered a \grammarterm{declaration} only if it starts with \keyword{auto}. +\begin{example} +\begin{codeblock} +struct M; +struct S { + S* operator()(); + int N; + int M; + + void mem(S s) { + auto(s)()->M; // expression, \tcode{S::M} hides \tcode{::M} + } +}; + +void f(S s) { + { + auto(s)()->N; // expression + auto(s)()->M; // function declaration + } + { + S(s)()->N; // expression + S(s)()->M; // expression + } +} +\end{codeblock} +\end{example} \indextext{statement|)} diff --git a/source/std.tex b/source/std.tex index 040decb135..0170e31451 100644 --- a/source/std.tex +++ b/source/std.tex @@ -13,6 +13,7 @@ {listings} % code listings \usepackage{longtable} % auto-breaking tables \usepackage{ltcaption} % fix captions for long tables +\usepackage{caption} % caption style \usepackage{relsize} % provide relative font size changes \usepackage{textcomp} % provide \text{l,r}angle \usepackage{underscore} % remove special status of '_' in ordinary text @@ -23,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} @@ -34,17 +36,17 @@ \hypersetup{pdftitle={C++ Working Draft}, pdfsubject={ISO/IEC JTC1 SC22 WG21, C++}, pdfcreator={Thomas K\"{o}ppe}, - bookmarks=true, bookmarksnumbered=true, - pdfpagelabels=true, pdfpagemode=UseOutlines, pdfstartview=FitH, 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} @@ -55,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} @@ -76,6 +82,7 @@ \pdfstringdefDisableCommands{\def\textbf#1{#1}} \pdfstringdefDisableCommands{\def\raisebox#1{}} \pdfstringdefDisableCommands{\def\hspace#1{}} +\pdfstringdefDisableCommands{\def\frenchspacing{}} %%-------------------------------------------------- %% add special hyphenation rules @@ -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 @@ -144,6 +156,11 @@ \immediate\write\@auxout{\noexpand\@writefile{toc}{\noexpand\let\noexpand\chapternumberlinebox\noexpand\annexnumberlinebox}} \makeatother +\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 d9bd3cef43..a9615c7d91 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 -\tcode{p} not in \tcode{[s,s+n)}.\par +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. @@ -533,33 +532,33 @@ \indexheader{string_view}% \begin{codeblock} +// mostly freestanding #include // see \ref{compare.syn} namespace std { // \ref{string.view.template}, class template \tcode{basic_string_view} template> - class basic_string_view; + class basic_string_view; // partially freestanding template - inline constexpr bool ranges::enable_view> = true; + constexpr bool ranges::@\libspec{enable_view}{basic_string_view}@> = true; template - inline constexpr bool ranges::enable_borrowed_range> = true; + constexpr bool ranges::@\libspec{enable_borrowed_range}{basic_string_view}@> = true; // \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 basic_ostream& operator<<(basic_ostream& os, - basic_string_view str); + basic_string_view str); // hosted // \tcode{basic_string_view} \grammarterm{typedef-name}s using string_view = basic_string_view; @@ -577,14 +576,14 @@ template<> struct hash; inline namespace literals { - inline namespace string_view_literals { - // \ref{string.view.literals}, suffix for \tcode{basic_string_view} literals - constexpr string_view operator""sv(const char* str, size_t len) noexcept; - constexpr u8string_view operator""sv(const char8_t* str, size_t len) noexcept; - constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept; - constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept; - constexpr wstring_view operator""sv(const wchar_t* str, size_t len) noexcept; - } + inline namespace string_view_literals { + // \ref{string.view.literals}, suffix for \tcode{basic_string_view} literals + constexpr string_view operator""sv(const char* str, size_t len) noexcept; + constexpr u8string_view operator""sv(const char8_t* str, size_t len) noexcept; + constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept; + constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept; + constexpr wstring_view operator""sv(const wchar_t* str, size_t len) noexcept; + } } } \end{codeblock} @@ -659,11 +658,11 @@ 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; - constexpr const_reference at(size_type pos) const; + constexpr const_reference at(size_type pos) const; // freestanding-deleted constexpr const_reference front() const; constexpr const_reference back() const; constexpr const_pointer data() const noexcept; @@ -674,17 +673,22 @@ constexpr void swap(basic_string_view& s) noexcept; // \ref{string.view.ops}, string operations - constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; + constexpr size_type copy(charT* s, size_type n, + size_type pos = 0) const; // freestanding-deleted - constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; + constexpr basic_string_view substr(size_type pos = 0, + size_type n = npos) const; // freestanding-deleted constexpr int compare(basic_string_view s) const noexcept; - constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const; + constexpr int compare(size_type pos1, size_type n1, + basic_string_view s) const; // freestanding-deleted constexpr int compare(size_type pos1, size_type n1, basic_string_view s, - size_type pos2, size_type n2) const; + size_type pos2, size_type n2) const; // freestanding-deleted constexpr int compare(const charT* s) const; - constexpr int compare(size_type pos1, size_type n1, const charT* s) const; - constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; + constexpr int compare(size_type pos1, size_type n1, + const charT* s) const; // freestanding-deleted + constexpr int compare(size_type pos1, size_type n1, const charT* s, + size_type n2) const; // freestanding-deleted constexpr bool starts_with(basic_string_view x) const noexcept; constexpr bool starts_with(charT x) const noexcept; @@ -751,10 +755,10 @@ any operation that invalidates a pointer in the range \begin{codeblock} -@\range{str.data()}{\brk{}str.data() + str.size()}@ +@\range{str.data()}{str.data() + str.size()}@ \end{codeblock} invalidates pointers, iterators, and references -returned from \tcode{str}'s member functions. +to elements of \tcode{str}. \pnum The complexity of \tcode{basic_string_view} member functions is \bigoh{1} @@ -868,14 +872,10 @@ \item \tcode{is_same_v, charT>} is \tcode{true}, \item -\tcode{is_convertible_v} is \tcode{false}, +\tcode{is_convertible_v} is \tcode{false}, and \item \tcode{d.operator ::std::basic_string_view()} -is not a valid expression, and -\item -if the \grammarterm{qualified-id} \tcode{remove_reference_t::traits_type} -is valid and denotes a type, -\tcode{is_same_v::traits_type, traits>} is \tcode{true}. +is not a valid expression. \end{itemize} \pnum @@ -1020,7 +1020,7 @@ \indexlibrarymember{empty}{basic_string_view}% \begin{itemdecl} -[[nodiscard]] constexpr bool empty() const noexcept; +constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -1038,8 +1038,11 @@ \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 @@ -1048,12 +1051,6 @@ \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}% @@ -1078,8 +1075,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum \returns @@ -1097,8 +1094,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum \returns @@ -1136,8 +1133,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{n <= size()}. +\hardexpects +\tcode{n <= size()} is \tcode{true}. \pnum \effects @@ -1151,8 +1148,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{n <= size()}. +\hardexpects +\tcode{n <= size()} is \tcode{true}. \pnum \effects @@ -1315,9 +1312,12 @@ \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{rlen} be the smaller of \tcode{size()} and \tcode{x.size()}. + \pnum \effects -Equivalent to: \tcode{return substr(0, x.size()) == x;} +Equivalent to: \tcode{return basic_string_view(data(), rlen) == x;} \end{itemdescr} \indexlibrarymember{starts_with}{basic_string_view}% @@ -1348,11 +1348,14 @@ \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{rlen} be the smaller of \tcode{size()} and \tcode{x.size()}. + \pnum \effects Equivalent to: \begin{codeblock} -return size() >= x.size() && compare(size() - x.size(), npos, x) == 0; +return basic_string_view(data() + (size() - rlen), rlen) == x; \end{codeblock} \end{itemdescr} @@ -1443,7 +1446,7 @@ \item \tcode{xpos + str.size() <= size()} \item -\tcode{traits::eq(at(xpos + I), str.at(I))} for all elements \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos + I], str[I])} for all elements \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1470,7 +1473,7 @@ \item \tcode{xpos + str.size() <= size()} \item -\tcode{traits::eq(at(xpos + I), str.at(I))} for all elements \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos + I], str[I])} for all elements \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1497,7 +1500,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(at(xpos), str.at(I))} for some element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos], str[I])} for some element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1524,7 +1527,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(at(xpos), str.at(I))} for some element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos], str[I])} for some element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1551,7 +1554,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos], str[I])} for no element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1577,7 +1580,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos], str[I])} for no element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1592,47 +1595,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} @@ -1645,7 +1612,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} @@ -1661,6 +1628,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} @@ -1687,7 +1663,7 @@ \pnum \returns -\tcode{os} +\tcode{os}. \end{itemdescr} \rSec2[string.view.hash]{Hash support} @@ -1797,12 +1773,12 @@ namespace std { // \ref{char.traits}, character traits - template struct char_traits; - template<> struct char_traits; - template<> struct char_traits; - template<> struct char_traits; - template<> struct char_traits; - template<> struct char_traits; + template struct char_traits; // freestanding + template<> struct char_traits; // freestanding + template<> struct char_traits; // freestanding + template<> struct char_traits; // freestanding + template<> struct char_traits; // freestanding + template<> struct char_traits; // freestanding // \ref{basic.string}, \tcode{basic_string} template, class Allocator = allocator> @@ -1856,6 +1832,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 @@ -1908,7 +1900,7 @@ basic_string& str); // \ref{string.erasure}, erasure - template + template constexpr typename basic_string::size_type erase(basic_string& c, const U& value); template @@ -1979,14 +1971,14 @@ template struct hash, A>>; inline namespace literals { - inline namespace string_literals { - // \ref{basic.string.literals}, suffix for \tcode{basic_string} literals - constexpr string operator""s(const char* str, size_t len); - constexpr u8string operator""s(const char8_t* str, size_t len); - constexpr u16string operator""s(const char16_t* str, size_t len); - constexpr u32string operator""s(const char32_t* str, size_t len); - constexpr wstring operator""s(const wchar_t* str, size_t len); - } + inline namespace string_literals { + // \ref{basic.string.literals}, suffix for \tcode{basic_string} literals + constexpr string operator""s(const char* str, size_t len); + constexpr u8string operator""s(const char8_t* str, size_t len); + constexpr u16string operator""s(const char16_t* str, size_t len); + constexpr u32string operator""s(const char32_t* str, size_t len); + constexpr wstring operator""s(const wchar_t* str, size_t len); + } } } \end{codeblock} @@ -2010,7 +2002,7 @@ is designated by \tcode{charT}. \pnum -A specialization of \tcode{basic_string} is a contiguous container\iref{container.requirements.general}. +A specialization of \tcode{basic_string} is a contiguous container\iref{container.reqmts}. \pnum In all cases, @@ -2127,7 +2119,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; @@ -2372,21 +2364,21 @@ function or operator has no other effect on the \tcode{basic_string} object. \pnum -In every specialization \tcode{basic_string}, -the type \tcode{allocator_traits::value_type} shall name the same type -as \tcode{charT}. Every object of type +Every object of type \tcode{basic_string} uses an object of type \tcode{Allocator} to allocate and free storage for the contained \tcode{charT} objects as needed. The \tcode{Allocator} object used is -obtained as described in \ref{container.requirements.general}. +obtained as described in \ref{container.reqmts}. In every specialization \tcode{basic_string}, the type \tcode{traits} shall meet the character traits requirements\iref{char.traits}. \begin{note} Every specialization \tcode{basic_string} is -an allocator-aware container, +an allocator-aware container\iref{container.alloc.reqmts}, but does not use the allocator's \tcode{construct} and \tcode{destroy} -member functions\iref{container.requirements.general}. +member functions\iref{container.requirements.pre}. +The program is ill-formed if +\tcode{Allocator::value_type} is not the same type as \tcode{charT}. \end{note} \begin{note} The program is ill-formed if \tcode{traits::char_type} @@ -2573,7 +2565,7 @@ \pnum \constraints \tcode{Allocator} is a type -that qualifies as an allocator\iref{container.requirements.general}. +that qualifies as an allocator\iref{container.reqmts}. \begin{note} This affects class template argument deduction. \end{note} @@ -2592,7 +2584,7 @@ \pnum \constraints \tcode{Allocator} is a type -that qualifies as an allocator\iref{container.requirements.general}. +that qualifies as an allocator\iref{container.reqmts}. \begin{note} This affects class template argument deduction. \end{note} @@ -2612,7 +2604,7 @@ \pnum \constraints \tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. +iterator\iref{container.reqmts}. \pnum \effects @@ -2676,7 +2668,7 @@ \pnum \constraints \tcode{InputIterator} is a type that qualifies as an input iterator, -and \tcode{Allocator} is a type that qualifies as an allocator\iref{container.requirements.general}. +and \tcode{Allocator} is a type that qualifies as an allocator\iref{container.reqmts}. \end{itemdescr} \begin{itemdecl} @@ -2699,7 +2691,7 @@ \pnum \constraints \tcode{Allocator} is a type that qualifies as -an allocator\iref{container.requirements.general}. +an allocator\iref{container.reqmts}. \end{itemdescr} \indexlibrarymember{operator=}{basic_string}% @@ -2728,7 +2720,7 @@ \begin{itemdescr} \pnum \effects -Move assigns as a sequence container\iref{container.requirements}, +Move assigns as a sequence container\iref{sequence.reqmts}, except that iterators, pointers and references may be invalidated. \pnum @@ -2944,37 +2936,40 @@ \item \tcode{k} be \tcode{min(o, n)}. \item -\tcode{p} be a \tcode{charT*}, +\tcode{p} be a value of type \tcode{charT*} or \tcode{charT* const}, such that the range \crange{p}{p + n} is valid and \tcode{this->compare(0, k, p, k) == 0} is \tcode{true} before the call. The values in the range \crange{p + k}{p + n} may be indeterminate\iref{basic.indet}. \item -$OP$ be the expression \tcode{std::move(op)(p, n)}. +\tcode{m} be a value of type \tcode{size_type} or \tcode{const size_type} +equal to \tcode{n}. +\item +\tcode{\placeholder{OP}} be the expression \tcode{std::move(op)(p, m)}. \item -\tcode{r} = $OP$. +\tcode{r} = \tcode{\placeholder{OP}}. \end{itemize} \pnum \mandates -$OP$ has an integer-like type\iref{iterator.concept.winc}. +\tcode{\placeholder{OP}} has an integer-like type\iref{iterator.concept.winc}. \pnum \expects \begin{itemize} \item -$OP$ does not throw an exception or modify \tcode{p} or \tcode{n}. +\tcode{\placeholder{OP}} does not throw an exception or modify \tcode{p} or \tcode{m}. \item $\tcode{r} \geq 0$. \item -$\tcode{r} \leq \tcode{n}$. +$\tcode{r} \leq \tcode{m}$. \item -After evaluating $OP$ +After evaluating \tcode{\placeholder{OP}} there are no indeterminate values in the range \range{p}{p + r}. \end{itemize} \pnum \effects -Evaluates $OP$, +Evaluates \tcode{\placeholder{OP}}, replaces the contents of \tcode{*this} with \range{p}{p + r}, and invalidates all pointers and references to the range \crange{p}{p + n}. @@ -2982,7 +2977,7 @@ \recommended Implementations should avoid unnecessary copies and allocations by, for example, making \tcode{p} a pointer into internal storage and -by restoring \tcode{*(p + r)} to \tcode{charT()} after evaluating $OP$. +by restoring \tcode{*(p + r)} to \tcode{charT()} after evaluating \tcode{\placeholder{OP}}. \end{itemdescr} \indexlibrarymember{capacity}{basic_string}% @@ -3010,8 +3005,8 @@ \effects A directive that informs a \tcode{basic_string} of a planned change in size, so that the storage allocation can be managed accordingly. -After -\tcode{reserve()}, +Following a call to +\tcode{reserve}, \tcode{capacity()} is greater or equal to the argument of \tcode{reserve} @@ -3020,7 +3015,7 @@ \tcode{capacity()} otherwise. Reallocation happens at this point if and only if -the current capacity is less than the argument of \tcode{reserve()}. +the current capacity is less than the argument of \tcode{reserve}. \pnum \throws @@ -3075,7 +3070,7 @@ \indexlibrarymember{empty}{basic_string}% \begin{itemdecl} -[[nodiscard]] constexpr bool empty() const noexcept; +constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3095,8 +3090,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{pos <= size()}. +\hardexpects +\tcode{pos <= size()} is \tcode{true}. \pnum \returns @@ -3140,8 +3135,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum \effects @@ -3156,8 +3151,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum \effects @@ -3378,7 +3373,7 @@ \pnum \constraints \tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. +iterator\iref{container.reqmts}. \pnum \effects @@ -3583,7 +3578,7 @@ \pnum \constraints \tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. +iterator\iref{container.reqmts}. \pnum \effects @@ -3739,7 +3734,7 @@ \pnum \returns -\tcode{*this} +\tcode{*this}. \pnum \throws @@ -3801,7 +3796,7 @@ \pnum \constraints \tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. +iterator\iref{container.reqmts}. \pnum \expects @@ -3919,7 +3914,7 @@ \pnum \effects Removes the characters in the range -\tcode{[first, last)}. +\range{first}{last}. \pnum \returns @@ -3941,8 +3936,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum \effects @@ -4199,7 +4194,7 @@ \pnum \constraints \tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. +iterator\iref{container.reqmts}. \pnum \effects @@ -4868,6 +4863,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 @@ -4961,10 +5035,9 @@ object is destroyed. \pnum -If the function extracts no characters, it calls -\tcode{is.setstate(ios_base::failbit)}, -which may throw -\tcode{ios_base::fail\-ure}\iref{iostate.flags}. +If the function extracts no characters, +\tcode{ios_base::failbit} is set in the input function's local error state +before \tcode{setstate} is called. \pnum \returns @@ -5015,24 +5088,19 @@ until any of the following occurs: \begin{itemize} \item -end-of-file occurs on the input sequence -(in which case, the -\tcode{getline} -function calls -\tcode{is.setstate(\brk{}ios_base::eofbit)}). +end-of-file occurs on the input sequence; \item \tcode{traits::eq(c, delim)} for the next available input character \textit{c} (in which case, \textit{c} -is extracted but not appended)\iref{iostate.flags} +is extracted but not appended); \item \tcode{str.max_size()} characters are stored (in which case, -the function calls -\tcode{is.setstate(ios_base::fail\-bit))}\iref{iostate.flags} +\tcode{ios_base::failbit} is set in the input function's local error state). \end{itemize} \pnum @@ -5043,10 +5111,9 @@ object is destroyed. \pnum -If the function extracts no characters, it calls -\tcode{is.setstate(ios_base::fail\-bit)} -which may throw -\tcode{ios_base::fail\-ure}\iref{iostate.flags}. +If the function extracts no characters, +\tcode{ios_base::failbit} is set in the input function's local error state +before \tcode{setstate} is called. \pnum \returns @@ -5075,7 +5142,7 @@ \indexlibrarymember{erase}{basic_string}% \begin{itemdecl} -template +template constexpr typename basic_string::size_type erase(basic_string& c, const U& value); \end{itemdecl} @@ -5203,18 +5270,7 @@ \begin{itemdescr} \pnum \returns -Each function returns a \tcode{string} object holding the character -representation of the value of its argument that would be generated by calling -\tcode{sprintf(buf, fmt, val)} with a format specifier of -\tcode{"\%d"}, -\tcode{"\%u"}, -\tcode{"\%ld"}, -\tcode{"\%lu"}, -\tcode{"\%lld"}, \tcode{"\%llu"}, -\tcode{"\%f"}, -\tcode{"\%f"}, -or \tcode{"\%Lf"}, respectively, where \tcode{buf} designates an internal -character buffer of sufficient size. +\tcode{format("\{\}", val)}. \end{itemdescr} \indexlibraryglobal{stoi}% @@ -5301,19 +5357,7 @@ \begin{itemdescr} \pnum \returns -Each function returns a \tcode{wstring} object holding the character -representation of the value of its argument that would be generated by calling -\tcode{swprintf(buf, buffsz, fmt, val)} with a format specifier of -\tcode{L"\%d"}, -\tcode{L"\%u"}, -\tcode{L"\%ld"}, -\tcode{L"\%lu"}, -\tcode{L"\%lld"}, -\tcode{L"\%llu"}, -\tcode{L"\%f"}, -\tcode{L"\%f"}, -or \tcode{L"\%Lf"}, respectively, where \tcode{buf} designates an -internal character buffer of sufficient size \tcode{buffsz}. +\tcode{format(L"\{\}", val)}. \end{itemdescr} \rSec2[basic.string.hash]{Hash support} @@ -5395,106 +5439,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}% @@ -5522,38 +5466,38 @@ \indexlibraryglobal{strxfrm}% \begin{codeblock} namespace std { - using size_t = @\textit{see \ref{support.types.layout}}@; - - void* memcpy(void* s1, const void* s2, size_t n); - void* memmove(void* s1, const void* s2, size_t n); - char* strcpy(char* s1, const char* s2); - char* strncpy(char* s1, const char* s2, size_t n); - char* strcat(char* s1, const char* s2); - char* strncat(char* s1, const char* s2, size_t n); - int memcmp(const void* s1, const void* s2, size_t n); - int strcmp(const char* s1, const char* s2); + using size_t = @\textit{see \ref{support.types.layout}}@; // freestanding + + void* memcpy(void* s1, const void* s2, 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* strcat(char* s1, const char* s2); // freestanding + char* strncat(char* s1, const char* s2, size_t n); // freestanding + int memcmp(const void* s1, const void* s2, size_t n); // freestanding + int strcmp(const char* s1, const char* s2); // freestanding int strcoll(const char* s1, const char* s2); - int strncmp(const char* s1, const char* s2, size_t n); + int strncmp(const char* s1, const char* s2, size_t n); // freestanding size_t strxfrm(char* s1, const char* s2, size_t n); - const void* memchr(const void* s, int c, size_t n); // see \ref{library.c} - void* memchr(void* s, int c, size_t n); // see \ref{library.c} - const char* strchr(const char* s, int c); // see \ref{library.c} - char* strchr(char* s, int c); // see \ref{library.c} - size_t strcspn(const char* s1, const char* s2); - const char* strpbrk(const char* s1, const char* s2); // see \ref{library.c} - char* strpbrk(char* s1, const char* s2); // see \ref{library.c} - const char* strrchr(const char* s, int c); // see \ref{library.c} - char* strrchr(char* s, int c); // see \ref{library.c} - size_t strspn(const char* s1, const char* s2); - const char* strstr(const char* s1, const char* s2); // see \ref{library.c} - char* strstr(char* s1, const char* s2); // see \ref{library.c} + const void* memchr(const void* s, int c, size_t n); // freestanding; see \ref{library.c} + void* memchr(void* s, int c, size_t n); // freestanding; see \ref{library.c} + const char* strchr(const char* s, int c); // freestanding; see \ref{library.c} + char* strchr(char* s, int c); // freestanding; see \ref{library.c} + size_t strcspn(const char* s1, const char* s2); // freestanding + const char* strpbrk(const char* s1, const char* s2); // freestanding; see \ref{library.c} + char* strpbrk(char* s1, const char* s2); // freestanding; see \ref{library.c} + const char* strrchr(const char* s, int c); // freestanding; see \ref{library.c} + char* strrchr(char* s, int c); // freestanding; see \ref{library.c} + size_t strspn(const char* s1, const char* s2); // freestanding + const char* strstr(const char* s1, const char* s2); // freestanding; see \ref{library.c} + char* strstr(char* s1, const char* s2); // freestanding; see \ref{library.c} char* strtok(char* s1, const char* s2); - void* memset(void* s, int c, size_t n); + void* memset(void* s, int c, size_t n); // freestanding char* strerror(int errnum); - size_t strlen(const char* s); + size_t strlen(const char* s); // freestanding } -#define NULL @\textit{see \ref{support.types.nullptr}}@ +#define NULL @\textit{see \ref{support.types.nullptr}}@ // freestanding \end{codeblock} \pnum @@ -5568,9 +5512,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} @@ -5581,373 +5527,3 @@ \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}}@; - using mbstate_t = @\seebelow@; - using wint_t = @\seebelow@; - - 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); - wchar_t* wcsncpy(wchar_t* s1, const wchar_t* s2, size_t n); - wchar_t* wmemcpy(wchar_t* s1, const wchar_t* s2, size_t n); - wchar_t* wmemmove(wchar_t* s1, const wchar_t* s2, size_t n); - wchar_t* wcscat(wchar_t* s1, const wchar_t* s2); - wchar_t* wcsncat(wchar_t* s1, const wchar_t* s2, size_t n); - int wcscmp(const wchar_t* s1, const wchar_t* s2); - int wcscoll(const wchar_t* s1, const wchar_t* s2); - int wcsncmp(const wchar_t* s1, const wchar_t* s2, size_t n); - 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); - const wchar_t* wcschr(const wchar_t* s, wchar_t c); // see \ref{library.c} - wchar_t* wcschr(wchar_t* s, wchar_t c); // see \ref{library.c} - size_t wcscspn(const wchar_t* s1, const wchar_t* s2); - const wchar_t* wcspbrk(const wchar_t* s1, const wchar_t* s2); // see \ref{library.c} - wchar_t* wcspbrk(wchar_t* s1, const wchar_t* s2); // see \ref{library.c} - const wchar_t* wcsrchr(const wchar_t* s, wchar_t c); // see \ref{library.c} - wchar_t* wcsrchr(wchar_t* s, wchar_t c); // see \ref{library.c} - size_t wcsspn(const wchar_t* s1, const wchar_t* s2); - const wchar_t* wcsstr(const wchar_t* s1, const wchar_t* s2); // see \ref{library.c} - wchar_t* wcsstr(wchar_t* s1, const wchar_t* s2); // see \ref{library.c} - wchar_t* wcstok(wchar_t* s1, const wchar_t* s2, wchar_t** ptr); - const wchar_t* wmemchr(const wchar_t* s, wchar_t c, size_t n); // see \ref{library.c} - wchar_t* wmemchr(wchar_t* s, wchar_t c, size_t n); // see \ref{library.c} - size_t wcslen(const wchar_t* s); - wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n); - 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}}@ -#define WCHAR_MAX @\seebelow@ -#define WCHAR_MIN @\seebelow@ -#define WEOF @\seebelow@ -\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} diff --git a/source/styles.tex b/source/styles.tex index a5dd6c9ee9..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,9 +96,9 @@ %%-------------------------------------------------- % set heading style for annexes -\newcommand{\Annex}[3]{\chapter[#2]{(#3)\protect\\#2\hfill[#1]}\relax\annexlabel{#1}} -\newcommand{\infannex}[2]{\Annex{#1}{#2}{informative}\addxref{#1}} -\newcommand{\normannex}[2]{\Annex{#1}{#2}{normative}\addxref{#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}} %%-------------------------------------------------- %% set footnote style @@ -111,8 +121,10 @@ leftmargin=\bnfindentrest, listparindent=-\bnfindentinc, itemindent=\listparindent} %%-------------------------------------------------- -%% set caption style -\captionstyle{\centering} +%% set caption styles +\DeclareCaptionLabelSeparator{emdash}{ --- } +\captionsetup{justification=centering,labelsep=emdash,font+=bf} +\captionsetup[lstlisting]{justification=raggedright,singlelinecheck=false,font=normal} %%-------------------------------------------------- %% set global styles that get reset by \mainmatter @@ -142,14 +154,6 @@ %% (copied verbatim from listings.sty version 1.6 except where commented) \makeatletter -\lst@CheckVersion{1.8d}{\lst@CheckVersion{1.8c}{\lst@CheckVersion{1.8b}{\lst@CheckVersion{1.7}{\lst@CheckVersion{1.6}{\lst@CheckVersion{1.5b}{ - \typeout{^^J% - ***^^J% - *** This file requires listings.sty version 1.6.^^J% - *** You have version \lst@version; exiting ...^^J% - ***^^J}% - \batchmode \@@end}}}}}} - \def\lst@Init#1{% \begingroup \ifx\lst@float\relax\else @@ -171,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 @@ -262,7 +268,7 @@ \ifvmode\else\par\fi\lst@emptylinepenalty \vskip\parskip \vskip\baselineskip - % \lsthk@EveryLine has \lst@parshape, i.e. \parshape, which causes an \hbox + % \lsthk@EveryLine has \lst@parshape, i.e., \parshape, which causes an \hbox % \lsthk@EveryPar increments line counters; \refstepcounter balloons the PDF \global\advance\lst@newlines\m@ne \lst@newlinetrue} diff --git a/source/support.tex b/source/support.tex index 3ea8ec79c5..7d53612aad 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}. @@ -26,14 +27,14 @@ \tcode{}, \tcode{} \\ \rowsep \ref{support.limits} & Implementation properties & \tcode{}, \tcode{}, \tcode{}, \tcode{} \\ \rowsep -\ref{cstdint} & Integer types & \tcode{} \\ \rowsep -\ref{stdfloat.syn} & Header \libheader{stdfloat} synopsis & \tcode{} \\ \rowsep +\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 & @@ -151,14 +152,14 @@ \begin{codeblock} namespace std { using size_t = @\seebelow@; // freestanding - using div_t = @\seebelow@; - using ldiv_t = @\seebelow@; - using lldiv_t = @\seebelow@; + using div_t = @\seebelow@; // freestanding + using ldiv_t = @\seebelow@; // freestanding + using lldiv_t = @\seebelow@; // freestanding } #define NULL @\seebelow@ // freestanding -#define EXIT_FAILURE @\seebelow@ -#define EXIT_SUCCESS @\seebelow@ +#define EXIT_FAILURE @\seebelow@ // freestanding +#define EXIT_SUCCESS @\seebelow@ // freestanding #define RAND_MAX @\seebelow@ #define MB_CUR_MAX @\seebelow@ @@ -209,31 +210,31 @@ 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, + void* bsearch(const void* key, const 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, + void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, // freestanding @\placeholder{compare-pred}@*@\itcorr[-1]@ compar); - void qsort(void* base, size_t nmemb, size_t size, @\placeholder{c-compare-pred}@*@\itcorr[-1]@ compar); - void qsort(void* base, size_t nmemb, 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 // \ref{c.math.rand}, low-quality random number generation int rand(); void srand(unsigned int seed); // \ref{c.math.abs}, absolute values - constexpr int abs(int j); - constexpr long int abs(long int j); - constexpr long long int abs(long long int j); - constexpr @\placeholder{floating-point-type}@ abs(@\placeholder{floating-point-type}@ j); - - constexpr long int labs(long int j); - constexpr long long int llabs(long long int j); - - constexpr div_t div(int numer, int denom); - constexpr ldiv_t div(long int numer, long int denom); // see \ref{library.c} - constexpr lldiv_t div(long long int numer, long long int denom); // see \ref{library.c} - constexpr ldiv_t ldiv(long int numer, long int denom); - constexpr lldiv_t lldiv(long long int numer, long long int denom); + constexpr int abs(int j); // freestanding + constexpr long int abs(long int j); // freestanding + constexpr long long int abs(long long int j); // freestanding + constexpr @\placeholder{floating-point-type}@ abs(@\placeholder{floating-point-type}@ j); // freestanding-deleted + + constexpr long int labs(long int j); // freestanding + constexpr long long int llabs(long long int j); // freestanding + + constexpr div_t div(int numer, int denom); // freestanding + constexpr ldiv_t div(long int numer, long int denom); // freestanding; see \ref{library.c} + constexpr lldiv_t div(long long int numer, long long int denom); // freestanding; see \ref{library.c} + constexpr ldiv_t ldiv(long int numer, long int denom); // freestanding + constexpr lldiv_t lldiv(long long int numer, long long int denom); // freestanding } \end{codeblock} @@ -334,9 +335,10 @@ \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} @@ -542,226 +544,361 @@ (e.g., version number and release date). \pnum +\indextext{macro!feature-test}% Each of the macros defined in \libheader{version} is also defined 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} -// all freestanding -#define @\defnlibxname{cpp_lib_addressof_constexpr}@ 201603L // also in \libheader{memory} +#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_allocate_at_least}@ 202106L // also in \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 - // 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_adaptor_iterator_pair_constructor}@ 202106L // also in \libheader{stack}, \libheader{queue} + // 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 // also in \libheader{tuple} +#define @\defnlibxname{cpp_lib_apply}@ 201603L // freestanding, also in \libheader{tuple} #define @\defnlibxname{cpp_lib_array_constexpr}@ 201811L // also in \libheader{iterator}, \libheader{array} -#define @\defnlibxname{cpp_lib_as_const}@ 201510L // also in \libheader{utility} +#define @\defnlibxname{cpp_lib_as_const}@ 201510L // freestanding, also in \libheader{utility} #define @\defnlibxname{cpp_lib_associative_heterogeneous_erasure}@ 202110L // also in \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set} -#define @\defnlibxname{cpp_lib_assume_aligned}@ 201811L // also in \libheader{memory} -#define @\defnlibxname{cpp_lib_atomic_flag_test}@ 201907L // also in \libheader{atomic} -#define @\defnlibxname{cpp_lib_atomic_float}@ 201711L // also in \libheader{atomic} -#define @\defnlibxname{cpp_lib_atomic_is_always_lock_free}@ 201603L // also in \libheader{atomic} +#define @\defnlibxname{cpp_lib_associative_heterogeneous_insertion}@ 202306L + // also in \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set} +#define @\defnlibxname{cpp_lib_assume_aligned}@ 201811L // freestanding, also in \libheader{memory} +#define @\defnlibxname{cpp_lib_atomic_flag_test}@ 201907L // freestanding, also in \libheader{atomic} +#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 // also in \libheader{atomic} +#define @\defnlibxname{cpp_lib_atomic_min_max}@ 202403L // 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 // also in \libheader{atomic}, \libheader{memory} -#define @\defnlibxname{cpp_lib_atomic_wait}@ 201907L // also in \libheader{atomic} -#define @\defnlibxname{cpp_lib_barrier}@ 201907L // also in \libheader{barrier} -#define @\defnlibxname{cpp_lib_bind_back}@ 202202L // also in \libheader{functional} -#define @\defnlibxname{cpp_lib_bind_front}@ 201907L // also in \libheader{functional} -#define @\defnlibxname{cpp_lib_bit_cast}@ 201806L // also in \libheader{bit} -#define @\defnlibxname{cpp_lib_bitops}@ 201907L // also in \libheader{bit} -#define @\defnlibxname{cpp_lib_bool_constant}@ 201505L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_bounded_array_traits}@ 201902L // also in \libheader{type_traits} +#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} +#define @\defnlibxname{cpp_lib_barrier}@ 202302L // also in \libheader{barrier} +#define @\defnlibxname{cpp_lib_bind_back}@ 202306L // freestanding, also in \libheader{functional} +#define @\defnlibxname{cpp_lib_bind_front}@ 202306L // freestanding, also in \libheader{functional} +#define @\defnlibxname{cpp_lib_bit_cast}@ 201806L // freestanding, also in \libheader{bit} +#define @\defnlibxname{cpp_lib_bitops}@ 201907L // freestanding, also in \libheader{bit} +#define @\defnlibxname{cpp_lib_bitset}@ 202306L // also in \libheader{bitset} +#define @\defnlibxname{cpp_lib_bool_constant}@ 201505L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_bounded_array_traits}@ 201902L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_boyer_moore_searcher}@ 201603L // also in \libheader{functional} -#define @\defnlibxname{cpp_lib_byte}@ 201603L // also in \libheader{cstddef} -#define @\defnlibxname{cpp_lib_byteswap}@ 202110L // also in \libheader{bit} +#define @\defnlibxname{cpp_lib_byte}@ 201603L // freestanding, also in \libheader{cstddef} +#define @\defnlibxname{cpp_lib_byteswap}@ 202110L // freestanding, also in \libheader{bit} #define @\defnlibxname{cpp_lib_char8_t}@ 201907L - // also in \libheader{atomic}, \libheader{filesystem}, \libheader{istream}, \libheader{limits}, \libheader{locale}, \libheader{ostream}, \libheader{string}, \libheader{string_view} -#define @\defnlibxname{cpp_lib_chrono}@ 201907L // also in \libheader{chrono} + // freestanding, also in \libheader{atomic}, \libheader{filesystem}, \libheader{istream}, \libheader{limits}, \libheader{locale}, \libheader{ostream}, \libheader{string}, + // \libheader{string_view} +#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 // 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 // also in \libheader{concepts}, \libheader{compare} -#define @\defnlibxname{cpp_lib_constexpr_algorithms}@ 201806L // also in \libheader{algorithm} -#define @\defnlibxname{cpp_lib_constexpr_bitset}@ 202202L // also in \libheader{bitset} -#define @\defnlibxname{cpp_lib_constexpr_charconv}@ 202207L // also in \libheader{charconv} -#define @\defnlibxname{cpp_lib_constexpr_cmath}@ 202202L // also in \libheader{cmath}, \libheader{cstdlib} -#define @\defnlibxname{cpp_lib_constexpr_complex}@ 201711L // also in \libheader{complex} +#define @\defnlibxname{cpp_lib_concepts}@ 202207L + // freestanding, also in \libheader{concepts}, \libheader{compare} +#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 // 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_functional}@ 201907L // also in \libheader{functional} -#define @\defnlibxname{cpp_lib_constexpr_iterator}@ 201811L // also in \libheader{iterator} -#define @\defnlibxname{cpp_lib_constexpr_memory}@ 202202L // 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_list}@ 202502L // also in \libheader{list} +#define @\defnlibxname{cpp_lib_constexpr_map}@ 202502L // also in \libheader{map} +#define @\defnlibxname{cpp_lib_constexpr_memory}@ 202202L // 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 // also in \libheader{tuple} -#define @\defnlibxname{cpp_lib_constexpr_typeinfo}@ 202106L // also in \libheader{typeinfo} -#define @\defnlibxname{cpp_lib_constexpr_utility}@ 201811L // also in \libheader{utility} +#define @\defnlibxname{cpp_lib_constexpr_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_coroutine}@ 201902L // also in \libheader{coroutine} -#define @\defnlibxname{cpp_lib_destroying_delete}@ 201806L // also in \libheader{new} +#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 // freestanding, also in \libheader{coroutine} +#define @\defnlibxname{cpp_lib_debugging}@ 202403L // freestanding, also in \libheader{debugging} +#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 // also in \libheader{bit} +#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_exchange_function}@ 201304L // also in \libheader{utility} +#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}@ 202202L // also in \libheader{expected} +#define @\defnlibxname{cpp_lib_expected}@ 202211L // also in \libheader{expected} #define @\defnlibxname{cpp_lib_filesystem}@ 201703L // also in \libheader{filesystem} -#define @\defnlibxname{cpp_lib_find_last}@ 202207L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_flat_map}@ 202207L // also in \libheader{flat_map} -#define @\defnlibxname{cpp_lib_format}@ 202207L // also in \libheader{format} -#define @\defnlibxname{cpp_lib_forward_like}@ 202207L // also in \libheader{utility} +#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}@ 202403L // 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}@ 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} +#define @\defnlibxname{cpp_lib_freestanding_cstdlib}@ 202306L // freestanding, also in \libheader{cstdlib}, \libheader{cmath} +#define @\defnlibxname{cpp_lib_freestanding_cstring}@ 202311L // freestanding, also in \libheader{cstring} +#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}@ 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_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} +#define @\defnlibxname{cpp_lib_freestanding_tuple}@ 202306L // freestanding, also in \libheader{tuple} +#define @\defnlibxname{cpp_lib_freestanding_utility}@ 202306L // freestanding, also in \libheader{utility} +#define @\defnlibxname{cpp_lib_freestanding_variant}@ 202311L // freestanding, also in \libheader{variant} +#define @\defnlibxname{cpp_lib_fstream_native_handle}@ 202306L // also in \libheader{fstream} +#define @\defnlibxname{cpp_lib_function_ref}@ 202306L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_gcd_lcm}@ 201606L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_generator}@ 202207L // also in \libheader{generator} #define @\defnlibxname{cpp_lib_generic_associative_lookup}@ 201304L // also in \libheader{map}, \libheader{set} #define @\defnlibxname{cpp_lib_generic_unordered_lookup}@ 201811L // also in \libheader{unordered_map}, \libheader{unordered_set} -#define @\defnlibxname{cpp_lib_hardware_interference_size}@ 201703L // also in \libheader{new} -#define @\defnlibxname{cpp_lib_has_unique_object_representations}@ 201606L // also in \libheader{type_traits} +#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_int_pow2}@ 202002L // also in \libheader{bit} +#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 // also in \libheader{utility} -#define @\defnlibxname{cpp_lib_integral_constant_callable}@ 201304L // also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_integer_sequence}@ 201304L // freestanding, also in \libheader{utility} +#define @\defnlibxname{cpp_lib_integral_constant_callable}@ 201304L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_interpolate}@ 201902L // also in \libheader{cmath}, \libheader{numeric} -#define @\defnlibxname{cpp_lib_invoke}@ 201411L // also in \libheader{functional} -#define @\defnlibxname{cpp_lib_invoke_r}@ 202106L // also in \libheader{functional} +#define @\defnlibxname{cpp_lib_invoke}@ 201411L // freestanding, also in \libheader{functional} +#define @\defnlibxname{cpp_lib_invoke_r}@ 202106L // freestanding, also in \libheader{functional} #define @\defnlibxname{cpp_lib_ios_noreplace}@ 202207L // also in \libheader{ios} -#define @\defnlibxname{cpp_lib_is_aggregate}@ 201703L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_constant_evaluated}@ 201811L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_final}@ 201402L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_invocable}@ 201703L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_layout_compatible}@ 201907L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_nothrow_convertible}@ 201806L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_null_pointer}@ 201309L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_pointer_interconvertible}@ 201907L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_scoped_enum}@ 202011L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_swappable}@ 201603L // also in \libheader{type_traits} +#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 // 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_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 // also in \libheader{new} +#define @\defnlibxname{cpp_lib_launder}@ 201606L // freestanding, also in \libheader{new} +#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 // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_make_from_tuple}@ 201606L // also in \libheader{tuple} -#define @\defnlibxname{cpp_lib_make_reverse_iterator}@ 201402L // also in \libheader{iterator} +#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} +#define @\defnlibxname{cpp_lib_make_reverse_iterator}@ 201402L // freestanding, also in \libheader{iterator} #define @\defnlibxname{cpp_lib_make_unique}@ 201304L // also in \libheader{memory} #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 -#define @\defnlibxname{cpp_lib_move_iterator_concept}@ 202207L // also in \libheader{iterator} +#define @\defnlibxname{cpp_lib_modules}@ 202207L // freestanding +#define @\defnlibxname{cpp_lib_move_iterator_concept}@ 202207L // freestanding, also in \libheader{iterator} #define @\defnlibxname{cpp_lib_move_only_function}@ 202110L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_node_extract}@ 201606L // also in \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set} #define @\defnlibxname{cpp_lib_nonmember_container_access}@ 201411L - // also in \libheader{array}, \libheader{deque}, \libheader{forward_list}, \libheader{iterator}, \libheader{list}, \libheader{map}, \libheader{regex}, \libheader{set}, \libheader{string}, - // \libheader{unordered_map}, \libheader{unordered_set}, \libheader{vector} -#define @\defnlibxname{cpp_lib_not_fn}@ 201603L // also in \libheader{functional} -#define @\defnlibxname{cpp_lib_null_iterators}@ 201304L // also in \libheader{iterator} + // freestanding, also in \libheader{array}, \libheader{deque}, \libheader{forward_list}, \libheader{iterator}, \libheader{list}, \libheader{map}, \libheader{regex}, \libheader{set}, + // \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_out_ptr}@ 202106L // also in \libheader{memory} +#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_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}@ 202207L +#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}@ 202207L // also in \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_as_rvalue}@ 202207L // also in \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_cartesian_product}@ 202207L // also in \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_chunk}@ 202202L // also in \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_chunk_by}@ 202202L // also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_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} +#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_iota}@ 202202L // also in \libheader{numeric} -#define @\defnlibxname{cpp_lib_ranges_join_with}@ 202202L // also in \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_repeat}@ 202207L // also in \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_slide}@ 202202L // also in \libheader{ranges} +#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 // also in \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // also in \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // also in \libheader{ranges}, \libheader{tuple}, \libheader{utility} -#define @\defnlibxname{cpp_lib_raw_memory_algorithms}@ 201606L // also in \libheader{memory} -#define @\defnlibxname{cpp_lib_reference_from_temporary}@ 202202L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_remove_cvref}@ 201711L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_result_of_sfinae}@ 201210L // also in \libheader{functional}, \libheader{type_traits} +#define @\defnlibxname{cpp_lib_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 // 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_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} #define @\defnlibxname{cpp_lib_robust_nonmodifying_seq_ops}@ 201304L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_sample}@ 201603L // also in \libheader{algorithm} +#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}@ 202406L // 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}@ 202502L // also in \libheader{simd} +#define @\defnlibxname{cpp_lib_simd_complex}@ 202502L // also in \libheader{simd} #define @\defnlibxname{cpp_lib_smart_ptr_for_overwrite}@ 202002L // also in \libheader{memory} -#define @\defnlibxname{cpp_lib_source_location}@ 201907L // also in \libheader{source_location} -#define @\defnlibxname{cpp_lib_span}@ 202002L // also in \libheader{span} +#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 // freestanding, also in \libheader{span} #define @\defnlibxname{cpp_lib_spanstream}@ 202106L // also in \libheader{spanstream} -#define @\defnlibxname{cpp_lib_ssize}@ 201902L // also in \libheader{iterator} +#define @\defnlibxname{cpp_lib_ssize}@ 201902L // freestanding, also in \libheader{iterator} +#define @\defnlibxname{cpp_lib_sstream_from_string_view}@ 202306L // also in \libheader{sstream} #define @\defnlibxname{cpp_lib_stacktrace}@ 202011L // also in \libheader{stacktrace} -#define @\defnlibxname{cpp_lib_start_lifetime_as}@ 202207L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_start_lifetime_as}@ 202207L // freestanding, also in \libheader{memory} #define @\defnlibxname{cpp_lib_starts_ends_with}@ 201711L // also in \libheader{string}, \libheader{string_view} #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_udls}@ 201304L // also in \libheader{string} -#define @\defnlibxname{cpp_lib_string_view}@ 201803L // also in \libheader{string}, \libheader{string_view} +#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_three_way_comparison}@ 201907L // also in \libheader{compare} -#define @\defnlibxname{cpp_lib_to_address}@ 201711L // also in \libheader{memory} -#define @\defnlibxname{cpp_lib_to_array}@ 201907L // also in \libheader{array} -#define @\defnlibxname{cpp_lib_to_chars}@ 201611L // also in \libheader{charconv} -#define @\defnlibxname{cpp_lib_to_underlying}@ 202102L // also in \libheader{utility} -#define @\defnlibxname{cpp_lib_transformation_trait_aliases}@ 201304L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_transparent_operators}@ 201510L // also in \libheader{memory}, \libheader{functional} -#define @\defnlibxname{cpp_lib_tuple_like}@ 202207L +#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 // 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_tuple_element_t}@ 201402L // also in \libheader{tuple} -#define @\defnlibxname{cpp_lib_tuples_by_type}@ 201304L // also in \libheader{utility}, \libheader{tuple} -#define @\defnlibxname{cpp_lib_type_identity}@ 201806L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_type_trait_variable_templates}@ 201510L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_uncaught_exceptions}@ 201411L // also in \libheader{exception} +#define @\defnlibxname{cpp_lib_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_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} -#define @\defnlibxname{cpp_lib_unreachable}@ 202202L // also in \libheader{utility} -#define @\defnlibxname{cpp_lib_unwrap_ref}@ 201811L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_variant}@ 202106L // also in \libheader{variant} -#define @\defnlibxname{cpp_lib_void_t}@ 201411L // also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_unreachable}@ 202202L // freestanding, also in \libheader{utility} +#define @\defnlibxname{cpp_lib_unwrap_ref}@ 201811L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_variant}@ 202306L // also in \libheader{variant} +#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_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_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_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} +\end{codeblock} + +\pnum +The macro \xname{cpp_lib_freestanding_operator_new} is defined to +the integer literal \tcode{202306L} +if all the default versions of the replaceable global allocation functions meet +the requirements of a hosted implementation, and +to the integer literal \tcode{0} otherwise\iref{new.delete}. + +\pnum +\recommended +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}% \indextext{\idxcode{numeric_limits}}% \indexlibraryglobal{numeric_limits}% \indexlibraryglobal{float_round_style}% -\indexlibraryglobal{float_denorm_style}% \begin{codeblock} // all freestanding namespace std { - // \ref{fp.style}, floating-point type properties + // \ref{round.style}, enumeration \tcode{float_round_style} enum float_round_style; - enum float_denorm_style; // \ref{numeric.limits}, class template \tcode{numeric_limits} template class numeric_limits; @@ -795,9 +932,7 @@ } \end{codeblock} -\rSec2[fp.style]{Floating-point type properties} - -\rSec3[round.style]{Type \tcode{float_round_style}} +\rSec2[round.style]{Enum \tcode{float_round_style}} \indexlibraryglobal{float_round_style}% \begin{codeblock} @@ -838,41 +973,6 @@ if the rounding style is toward negative infinity \end{itemize} -\rSec3[denorm.style]{Type \tcode{float_denorm_style}} - -\indexlibraryglobal{float_denorm_style}% -\begin{codeblock} -namespace std { - enum float_denorm_style { - denorm_indeterminate = -1, - denorm_absent = 0, - denorm_present = 1 - }; -} -\end{codeblock} - -\indextext{denormalized value|see{number, subnormal}}% -\indextext{value!denormalized|see{number, subnormal}}% -\indextext{subnormal number|see{number, subnormal}}% -\indextext{number!subnormal}% -\pnum -The presence or absence of subnormal numbers (variable number of exponent bits) -is characterized by the values: -\begin{itemize} -\item -\indexlibraryglobal{denorm_indeterminate}% -\tcode{denorm_indeterminate} -if it cannot be determined whether or not the type allows subnormal values -\item -\indexlibraryglobal{denorm_absent}% -\tcode{denorm_absent} -if the type does not allow subnormal values -\item -\indexlibraryglobal{denorm_present}% -\tcode{denorm_present} -if the type does allow subnormal values -\end{itemize} - \rSec2[numeric.limits]{Class template \tcode{numeric_limits}} \rSec3[numeric.limits.general]{General} @@ -913,8 +1013,6 @@ static constexpr bool has_infinity = false; static constexpr bool has_quiet_NaN = false; static constexpr bool has_signaling_NaN = false; - static constexpr float_denorm_style has_denorm = denorm_absent; - static constexpr bool has_denorm_loss = false; static constexpr T infinity() noexcept { return T(); } static constexpr T quiet_NaN() noexcept { return T(); } static constexpr T signaling_NaN() noexcept { return T(); } @@ -977,6 +1075,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} @@ -1056,7 +1159,7 @@ \pnum For floating-point types, the number of \tcode{radix} digits in the -mantissa. +significand. \begin{footnote} Equivalent to \tcode{FLT_MANT_DIG}, \tcode{DBL_MANT_DIG}, \tcode{LDBL_MANT_DIG}. @@ -1154,8 +1257,7 @@ For integer types, specifies the base of the representation. \begin{footnote} -Distinguishes types with bases other than 2 (e.g. -BCD). +Distinguishes types with bases other than 2 (e.g., BCD). \end{footnote} \pnum @@ -1188,16 +1290,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} @@ -1217,7 +1317,7 @@ \indexlibrarymember{min_exponent10}{numeric_limits}% \begin{itemdecl} -static constexpr int min_exponent10; +static constexpr int min_exponent10; \end{itemdecl} \begin{itemdescr} @@ -1235,7 +1335,7 @@ \indexlibrarymember{max_exponent}{numeric_limits}% \begin{itemdecl} -static constexpr int max_exponent; +static constexpr int max_exponent; \end{itemdecl} \begin{itemdescr} @@ -1255,7 +1355,7 @@ \indexlibrarymember{max_exponent10}{numeric_limits}% \begin{itemdecl} -static constexpr int max_exponent10; +static constexpr int max_exponent10; \end{itemdecl} \begin{itemdescr} @@ -1300,7 +1400,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 @@ -1322,7 +1422,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 @@ -1335,46 +1435,6 @@ \tcode{is_iec559 != false}. \end{itemdescr} -\indexlibrarymember{float_denorm_style}{numeric_limits}% -\begin{itemdecl} -static constexpr float_denorm_style has_denorm; -\end{itemdecl} - -\indextext{number!subnormal}% -\begin{itemdescr} -\pnum -\tcode{denorm_present} -if the type allows subnormal values -(variable number of exponent bits), -\begin{footnote} -Required by LIA-1. -\end{footnote} -\tcode{denorm_absent} -if the type does not allow subnormal values, -and -\tcode{denorm_indeterminate} -if it is indeterminate at compile time whether the type allows -subnormal values. - -\pnum -Meaningful for all floating-point types. -\end{itemdescr} - -\indexlibrarymember{has_denorm_loss}{numeric_limits}% -\begin{itemdecl} -static constexpr bool has_denorm_loss; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\tcode{true} if loss of accuracy is detected as a -denormalization loss, rather than as an inexact result. -\begin{footnote} -See -ISO/IEC/IEEE 60559. -\end{footnote} -\end{itemdescr} - \indexlibrarymember{infinity}{numeric_limits}% \begin{itemdecl} static constexpr T infinity() noexcept; @@ -1384,7 +1444,7 @@ \pnum Representation of positive infinity, if available. \begin{footnote} -Required by LIA-1. +Required by ISO/IEC 10967-1:2012. \end{footnote} \pnum @@ -1403,7 +1463,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 @@ -1422,7 +1482,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 @@ -1440,18 +1500,14 @@ \begin{itemdescr} \indextext{number!subnormal}% \pnum -Minimum positive subnormal value. +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. \pnum Meaningful for all floating-point types. - -\pnum -In specializations for which -\tcode{has_denorm == false}, -returns the minimum positive normalized value. \end{itemdescr} \indexlibrarymember{is_iec559}{numeric_limits}% @@ -1461,9 +1517,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 @@ -1484,7 +1540,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 @@ -1504,7 +1560,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 @@ -1533,7 +1589,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 @@ -1551,8 +1607,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 @@ -1569,7 +1625,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 @@ -1622,11 +1678,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 float_denorm_style has_denorm = denorm_absent; - static constexpr bool has_denorm_loss = false; + 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}@; } @@ -1652,47 +1706,45 @@ \indexlibraryglobal{numeric_limits}% \begin{codeblock} namespace std { - template<> class numeric_limits { - public: - static constexpr bool is_specialized = true; - static constexpr bool min() noexcept { return false; } - static constexpr bool max() noexcept { return true; } - static constexpr bool lowest() noexcept { return false; } - - static constexpr int digits = 1; - static constexpr int digits10 = 0; - static constexpr int max_digits10 = 0; - - static constexpr bool is_signed = false; - static constexpr bool is_integer = true; - static constexpr bool is_exact = true; - static constexpr int radix = 2; - static constexpr bool epsilon() noexcept { return 0; } - static constexpr bool round_error() noexcept { return 0; } - - static constexpr int min_exponent = 0; - static constexpr int min_exponent10 = 0; - static constexpr int max_exponent = 0; - static constexpr int max_exponent10 = 0; - - static constexpr bool has_infinity = false; - static constexpr bool has_quiet_NaN = false; - static constexpr bool has_signaling_NaN = false; - static constexpr float_denorm_style has_denorm = denorm_absent; - static constexpr bool has_denorm_loss = false; - static constexpr bool infinity() noexcept { return 0; } - static constexpr bool quiet_NaN() noexcept { return 0; } - static constexpr bool signaling_NaN() noexcept { return 0; } - static constexpr bool denorm_min() noexcept { return 0; } - - static constexpr bool is_iec559 = false; - static constexpr bool is_bounded = true; - static constexpr bool is_modulo = false; - - static constexpr bool traps = false; - static constexpr bool tinyness_before = false; - static constexpr float_round_style round_style = round_toward_zero; - }; + template<> class numeric_limits { + public: + static constexpr bool is_specialized = true; + static constexpr bool min() noexcept { return false; } + static constexpr bool max() noexcept { return true; } + static constexpr bool lowest() noexcept { return false; } + + static constexpr int digits = 1; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 0; + + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + static constexpr bool epsilon() noexcept { return 0; } + static constexpr bool round_error() noexcept { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr bool infinity() noexcept { return 0; } + static constexpr bool quiet_NaN() noexcept { return 0; } + static constexpr bool signaling_NaN() noexcept { return 0; } + static constexpr bool denorm_min() noexcept { return 0; } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + + static constexpr bool traps = false; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; + }; } \end{codeblock} @@ -1745,8 +1797,9 @@ The header \libheader{climits} defines all macros the same as the C standard library header \libheader{limits.h}. \begin{note} -The types of the constants defined by macros in \libheader{climits} are not -required to match the types to which the macros refer. +Except for \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} \xrefc{5.2.4.2.1} @@ -1844,18 +1897,15 @@ \xrefc{5.2.4.2.2} -\rSec1[cstdint]{Integer types} +\rSec1[support.arith.types]{Arithmetic types} -\rSec2[cstdint.general]{General} +\rSec2[cstdint.syn]{Header \tcode{} synopsis} \pnum -The header -\libheaderref{cstdint} +The header \libheader{cstdint} supplies integer types having specified widths, and macros that specify limits of integer types. -\rSec2[cstdint.syn]{Header \tcode{} synopsis} - \indexheader{cstdint}% \indexlibraryglobal{int8_t}% \indexlibraryglobal{int16_t}% @@ -1885,6 +1935,34 @@ \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 namespace std { @@ -1997,9 +2075,19 @@ respectively. \end{note} -\rSec1[stdfloat.syn]{Header \tcode{} synopsis} +\rSec2[stdfloat.syn]{Header \tcode{} synopsis} + +\pnum +The header \libheader{stdfloat} defines type aliases for +the optional extended floating-point types that are specified in +\ref{basic.extended.fp}. \indexheader{stdfloat}% +\indexlibraryglobal{float16_t}% +\indexlibraryglobal{float32_t}% +\indexlibraryglobal{float64_t}% +\indexlibraryglobal{float128_t}% +\indexlibraryglobal{bfloat16_t}% \begin{codeblock} namespace std { #if defined(__STDCPP_FLOAT16_T__) @@ -2040,7 +2128,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}}% @@ -2271,7 +2359,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{}@; @@ -2279,36 +2367,35 @@ } // \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 delete(void* ptr) noexcept; -void operator delete(void* ptr, std::size_t size) noexcept; -void operator delete(void* ptr, std::align_val_t alignment) noexcept; -void operator delete(void* ptr, std::size_t size, std::align_val_t alignment) noexcept; -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 delete[](void* ptr) noexcept; -void operator delete[](void* ptr, std::size_t size) noexcept; -void operator delete[](void* ptr, std::align_val_t alignment) noexcept; -void operator delete[](void* ptr, std::size_t size, std::align_val_t alignment) noexcept; -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; -void operator delete (void* ptr, void*) noexcept; -void operator delete[](void* ptr, void*) 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; +void operator delete(void* ptr, std::align_val_t alignment) noexcept; +void operator delete(void* ptr, std::size_t size, std::align_val_t alignment) noexcept; +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; + +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; +void operator delete[](void* ptr, std::align_val_t alignment) noexcept; +void operator delete[](void* ptr, std::size_t size, std::align_val_t alignment) noexcept; +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; + +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} \rSec2[new.delete]{Storage allocation and deallocation} @@ -2324,18 +2411,31 @@ is not a valid alignment value, the behavior is undefined. -\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.% -} +\pnum +On freestanding implementations, +it is \impldef{whether freestanding default replaceable global allocation functions satisfy required behavior} +whether the default versions of the replaceable global allocation functions +satisfy the required behaviors +described in \ref{new.delete.single} and \ref{new.delete.array}. +\begin{note} +A freestanding implementation's default versions of +the replaceable global allocation functions +can cause undefined behavior when invoked. +During constant evaluation, +the behaviors of those default versions are irrelevant, +as those calls are omitted\iref{expr.new}. +\end{note} + +\recommended +If any of the default versions of the replaceable global allocation functions +meet the requirements of a hosted implementation, they all should. \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} @@ -2350,10 +2450,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}, @@ -2390,13 +2486,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} @@ -2409,10 +2508,6 @@ \tcode{bad_alloc} exception. -\pnum -\replaceable -\replaceabledesc{either} - \pnum \required Return a non-null pointer to suitably aligned storage\iref{basic.stc.dynamic}, @@ -2440,6 +2535,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}% @@ -2482,20 +2581,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} @@ -2516,7 +2601,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 @@ -2538,6 +2623,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}% @@ -2576,23 +2677,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} @@ -2624,10 +2725,6 @@ to obtain space to store supplemental information. \end{footnote} -\pnum -\replaceable -\replaceabledesc{either} - \pnum \required Same as for @@ -2641,13 +2738,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} @@ -2660,10 +2760,6 @@ \tcode{bad_alloc} exception. -\pnum -\replaceable -\replaceabledesc{either} - \pnum \required Return a non-null pointer to suitably aligned storage\iref{basic.stc.dynamic}, @@ -2683,6 +2779,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}% @@ -2725,20 +2825,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[]} @@ -2761,6 +2847,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}% @@ -2799,15 +2904,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} @@ -2820,7 +2925,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} @@ -2845,7 +2950,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} @@ -2922,7 +3027,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} @@ -2935,7 +3040,7 @@ \indexlibrarymember{what}{bad_alloc}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -2953,7 +3058,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} @@ -2966,7 +3071,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} @@ -3052,7 +3157,7 @@ \indexlibraryglobal{launder}% \begin{itemdecl} -template [[nodiscard]] constexpr T* launder(T* p) noexcept; +template constexpr T* launder(T* p) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3161,12 +3266,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}% @@ -3192,8 +3301,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} @@ -3287,7 +3396,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} @@ -3303,7 +3412,7 @@ \indexlibrarymember{what}{bad_cast}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3321,7 +3430,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} @@ -3337,7 +3446,7 @@ \indexlibrarymember{what}{bad_typeid}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3346,6 +3455,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} @@ -3393,11 +3662,10 @@ The type \tcode{source_location} meets the \oldconcept{DefaultConstructible}, \oldconcept{CopyConstructible}, -\oldconcept{Copy\-Assignable}, and +\oldconcept{Copy\-Assignable}, +\oldconcept{Swappable}, and \oldconcept{Destructible} -requirements\iref{utility.arg.requirements}. -Lvalues of type \tcode{source_location} -are swappable\iref{swappable.requirements}. +requirements\iref{utility.arg.requirements,swappable.requirements}. All of the following conditions are \tcode{true}: \begin{itemize} \item \tcode{is_nothrow_move_constructible_v} @@ -3483,7 +3751,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 @@ -3593,16 +3861,16 @@ 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 [[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} @@ -3614,11 +3882,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} @@ -3632,7 +3900,8 @@ expressions, to report errors detected during program execution. \pnum -Each standard library class \tcode{T} that derives from class \tcode{exception} +Except where explicitly specified otherwise, +each standard library class \tcode{T} that derives from class \tcode{exception} has the following publicly accessible member functions, each of them having a non-throwing exception specification\iref{except.spec}: \begin{itemize} @@ -3650,8 +3919,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} @@ -3663,7 +3932,7 @@ \indexlibrarydtor{exception}% \begin{itemdecl} -virtual ~exception(); +constexpr virtual ~exception(); \end{itemdecl} \begin{itemdescr} @@ -3675,13 +3944,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 @@ -3702,7 +3973,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} @@ -3717,7 +3988,7 @@ \indexlibrarymember{what}{bad_exception}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3824,13 +4095,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 @@ -3885,11 +4156,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} @@ -3912,16 +4186,15 @@ returns an \tcode{exception_ptr} object that refers to the thrown exception or, if this is not possible, to an instance of \tcode{bad_exception}. \begin{note} -The -copy constructor of the thrown exception can also fail, so the implementation is allowed -to substitute a \tcode{bad_exception} object to avoid infinite -recursion. +The copy constructor of the thrown exception can also fail, +so the implementation can substitute a \tcode{bad_exception} object +to avoid infinite recursion. \end{note} \end{itemdescr} \indexlibraryglobal{rethrow_exception}% \begin{itemdecl} -[[noreturn]] void rethrow_exception(exception_ptr p); +[[noreturn]] constexpr void rethrow_exception(exception_ptr p); \end{itemdecl} \begin{itemdescr} @@ -3949,7 +4222,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} @@ -3978,18 +4251,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} @@ -4006,7 +4279,7 @@ \indexlibraryctor{nested_exception}% \begin{itemdecl} -nested_exception() noexcept; +constexpr nested_exception() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4017,7 +4290,7 @@ \indexlibrarymember{rethrow_nested}{nested_exception}% \begin{itemdecl} -[[noreturn]] void rethrow_nested() const; +[[noreturn]] constexpr void rethrow_nested() const; \end{itemdecl} \begin{itemdescr} @@ -4029,7 +4302,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} @@ -4040,7 +4313,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} @@ -4063,7 +4336,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} @@ -4079,6 +4352,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} @@ -4127,7 +4662,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} @@ -4320,7 +4855,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 @@ -4772,7 +5307,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}, @@ -4783,7 +5318,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 @@ -4808,7 +5343,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}, @@ -4858,7 +5393,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, @@ -4920,8 +5455,8 @@ \item Otherwise, \tcode{strong_ordering(strong_order(E, F))} if it is a well-formed expression - with overload resolution performed in a context - that does not include a declaration of \tcode{std::strong_order}. + where the meaning of \tcode{strong_order} is established as-if by performing + argument-dependent lookup only\iref{basic.lookup.argdep}. \item Otherwise, if the decayed type \tcode{T} of \tcode{E} is a floating-point type, @@ -4930,7 +5465,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. @@ -4958,8 +5493,8 @@ \item Otherwise, \tcode{weak_ordering(weak_order(E, F))} if it is a well-formed expression - with overload resolution performed in a context - that does not include a declaration of \tcode{std::weak_order}. + where the meaning of \tcode{weak_order} is established as-if by performing + argument-dependent lookup only\iref{basic.lookup.argdep}. \item Otherwise, if the decayed type \tcode{T} of \tcode{E} is a floating-point type, @@ -5010,8 +5545,8 @@ \item Otherwise, \tcode{partial_ordering(partial_order(E, F))} if it is a well-formed expression - with overload resolution performed in a context - that does not include a declaration of \tcode{std::partial_order}. + where the meaning of \tcode{partial_order} is established as-if by performing + argument-dependent lookup only\iref{basic.lookup.argdep}. \item Otherwise, \tcode{partial_ordering(compare_three_way()(E, F))} if it is a well-formed expression. @@ -5032,7 +5567,7 @@ \pnum The name \tcode{compare_strong_order_fallback} denotes a customization point object\iref{customization.point.object}. -Given subexpressions \tcode{E} and {F}, +Given subexpressions \tcode{E} and \tcode{F}, the expression \tcode{compare_strong_order_fallback(E, F)} is expression-equivalent\iref{defns.expression.equivalent} to: \begin{itemize} @@ -5043,7 +5578,9 @@ Otherwise, \tcode{strong_order(E, F)} if it is a well-formed expression. \item Otherwise, if the expressions \tcode{E == F} and \tcode{E < F} - are both well-formed and convertible to \tcode{bool}, + are both well-formed and + each of \tcode{decltype(E == F)} and \tcode{decltype(E < F)} models + \exposconcept{boolean-testable}, \begin{codeblock} E == F ? strong_ordering::equal : E < F ? strong_ordering::less : @@ -5075,7 +5612,9 @@ Otherwise, \tcode{weak_order(E, F)} if it is a well-formed expression. \item Otherwise, if the expressions \tcode{E == F} and \tcode{E < F} - are both well-formed and convertible to \tcode{bool}, + are both well-formed and + each of \tcode{decltype(E == F)} and \tcode{decltype(E < F)} models + \exposconcept{boolean-testable}, \begin{codeblock} E == F ? weak_ordering::equivalent : E < F ? weak_ordering::less : @@ -5108,7 +5647,10 @@ \item Otherwise, if the expressions \tcode{E == F}, \tcode{E < F}, and \tcode{F < E} - are all well-formed and convertible to \tcode{bool}, + are all well-formed and + 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 : E < F ? partial_ordering::less : @@ -5188,6 +5730,7 @@ \rSec3[coroutine.traits.primary]{Class template \tcode{coroutine_traits}} +\indexlibraryglobal{coroutine_traits}% \pnum The header \libheader{coroutine} defines the primary template \tcode{coroutine_traits} such that @@ -5547,6 +6090,8 @@ \rSec3[coroutine.handle.noop]{Class \tcode{coroutine_handle}} +\rSec4[coroutine.handle.noop.general]{General} + \indexlibraryglobal{coroutine_handle}% \begin{codeblock} namespace std { @@ -5761,29 +6306,28 @@ \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 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, P) @\seebelow@ \end{codeblock} \pnum The contents of the header \libheaderdef{cstdarg} are the same as the C standard library header \libheader{stdarg.h}, with the following changes: -The restrictions that ISO C places on the second parameter to the -\indexlibraryglobal{va_start}% -\tcode{va_start} macro in header \libheader{stdarg.h} +\begin{itemize} +\item +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 C places on the second parameter to the +\libmacro{va_start} macro in header \libheader{stdarg.h} are different in this document. The parameter \tcode{parmN} @@ -5806,6 +6350,7 @@ 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. +\end{itemize} \xrefc{7.16.1.1} @@ -5898,6 +6443,13 @@ \item \tcode{f} is the member function \tcode{is_lock_free()}, or +\item +\tcode{f} is a non-static member function of class \tcode{atomic_flag}, or + +\item +\tcode{f} is a non-member function, and +the first parameter of \tcode{f} has type \cv{}~\tcode{atomic_flag*}, or + \item \tcode{f} is a non-static member function invoked on an object \tcode{A}, such that \tcode{A.is_lock_free()} yields \tcode{true}, or @@ -5967,8 +6519,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} @@ -5979,7 +6531,7 @@ 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} @@ -6013,16 +6565,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} \\ @@ -6069,11 +6623,6 @@ \rSec2[stdalign.h.syn]{Header \tcode{} synopsis} \indexheader{stdalign.h}% -\indexlibraryglobal{__alignas_is_defined}% -\begin{codeblock} -#define @\xname{alignas_is_defined}@ 1 -\end{codeblock} - \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: @@ -6085,12 +6634,6 @@ \rSec2[stdbool.h.syn]{Header \tcode{} synopsis} \indexheader{stdbool.h}% -\indexhdr{stdbool.h}% -\indexlibraryglobal{__bool_true_false_are_defined}% -\begin{codeblock} -#define @\xname{bool_true_false_are_defined}@ 1 -\end{codeblock} - \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: @@ -6136,7 +6679,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 @@ -6148,6 +6693,7 @@ header is placed within the global namespace scope, except for the functions described in \ref{sf.cmath}, +the \tcode{std::lerp} function overloads\iref{c.math.lerp}, the declaration of \tcode{std::byte}\iref{cstddef.syn}, and the functions and function templates described in \ref{support.types.byteops}. It is unspecified whether these names are first declared or defined within @@ -6164,6 +6710,6 @@ The header \libheader{stdlib.h} assuredly provides the same declarations and definitions within the global namespace, -much as in the C Standard. It may also provide these names within +much as in \IsoCUndated{}. It may also provide these names within the namespace \tcode{std}. \end{example} diff --git a/source/tables.tex b/source/tables.tex index b5c14fa689..678ec5d98b 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} @@ -63,7 +64,7 @@ % General Usage: TITLE is the title of the table, XREF is the % cross-reference for the table. LAYOUT is a sequence of column -% type specifiers (e.g. cp{1.0}c), without '|' for the left edge +% type specifiers (e.g., cp{1.0}c), without '|' for the left edge % or right edge. % usage: \begin{floattablebase}{TITLE}{XREF}{LAYOUT}{PLACEMENT} @@ -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} @@ -490,7 +492,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 873ad16891..bf283e46da 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}. @@ -123,7 +121,7 @@ \pnum In a \grammarterm{template-declaration}, -explicit specialization, or explicit instantiation the +explicit specialization, or explicit instantiation, the \grammarterm{init-declarator-list} in the declaration shall contain at most one declarator. When such a declaration is used to declare a class template, @@ -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 @@ -172,6 +184,13 @@ templated entity is a templated entity. \end{note} +A \defnadj{templated}{function} is +a function template or a function that is templated. +A \defnadj{templated}{class} is +a class template or a class that is templated. +A \defnadj{templated}{variable} is +a variable template or a variable that is templated. + \pnum A \grammarterm{template-declaration} is written in terms of its template parameters. @@ -218,7 +237,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} @@ -226,9 +248,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} @@ -243,6 +263,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 @@ -250,12 +294,81 @@ \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 +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} @@ -270,18 +383,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}. @@ -291,57 +393,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 storage class shall not be specified in a -\grammarterm{template-parameter} -declaration. -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$'$}, @@ -371,7 +460,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), @@ -385,6 +474,7 @@ are ignored when determining its type. \pnum +\label{term.structural.type}% A \defnadj{structural}{type} is one of the following: \begin{itemize} \item a scalar type, or @@ -394,25 +484,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 multi-dimensional) 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}, -whose value is that of the corresponding template argument +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}. -All such template parameters in the program of the same type -with the same value denote the same template parameter object. -A template parameter object shall have constant destruction\iref{expr.const}. +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}. @@ -422,10 +511,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 @@ -436,8 +525,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} @@ -448,8 +536,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}% @@ -469,47 +556,34 @@ \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} for the invented type corresponding to the placeholder\iref{dcl.fct}. \pnum -A -\defnx{default template-argument}{\idxgram{template-argument}!default} -is a -\grammarterm{template-argument}\iref{temp.arg} specified after -\tcode{=} -in a -\grammarterm{template-parameter}. -A default -\grammarterm{template-argument} -may be specified for any kind of -\grammarterm{template-parameter} -(type, non-type, template) +A \defnadj{default}{template argument} is +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 template parameter that is not a template parameter pack\iref{temp.variadic}. -A default -\grammarterm{template-argument} -may be specified in a template declaration. -A default -\grammarterm{template-argument} -shall not be specified in the -\grammarterm{template-parameter-list}{s} -of the definition of a member of a class template that appears outside -of the member's class. -A default -\grammarterm{template-argument} +A default template argument may be specified in a template declaration. +A default template argument shall not be specified in +the \grammarterm{template-parameter-list}{s} +of the definition of a member of a class template +that appears outside of the member's class. +A default template argument shall not be specified in a friend class template declaration. If a friend function template declaration $D$ -specifies a default \grammarterm{template-argument}, +specifies a default template argument, that declaration shall be a definition and there shall be no other declaration of the function template which is reachable from $D$ or from which $D$ is reachable. \pnum -The set of default -\grammarterm{template-argument}{s} +The set of default template arguments available for use is obtained by merging the default arguments from all prior declarations of the template in the same way default function arguments are\iref{dcl.fct.default}. @@ -525,29 +599,25 @@ \end{example} \pnum -If a -\grammarterm{template-parameter} -of a class template, variable template, or alias template has a default -\grammarterm{template-argument}, -each subsequent -\grammarterm{template-parameter} -shall either have a default -\grammarterm{template-argument} -supplied -or be 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, 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 -parameter-type-list\iref{dcl.fct} of the function template or has a -default argument\iref{temp.deduct}. +If a \grammarterm{template-parameter} +of a class template, variable template, or alias template has +a default template argument, +each subsequent \grammarterm{template-parameter} +shall either have a default template argument supplied or +declare a template parameter pack. +If a \grammarterm{template-parameter} of +a primary class template, primary variable template, or alias template +declares a template parameter pack, +it shall be the last \grammarterm{template-parameter}. +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} -that does not have a default argument -shall be deducible -from the parameter-type-list -of the deduction guide template. +that does not have a default argument shall be deducible +from the parameter-type-list of the deduction guide template. \begin{example} \begin{codeblock} template class B; // error @@ -560,15 +630,10 @@ \indextext{\idxcode{<}!template and}% \pnum -When parsing a -default -\grammarterm{template-argument} -for a non-type -\grammarterm{template-parameter}, -the first non-nested -\tcode{>} -is taken as the end of the -\grammarterm{template-parameter-list} +When parsing a default template argument +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. \begin{example} \begin{codeblock} @@ -581,16 +646,12 @@ \end{example} \pnum -A -\grammarterm{template-parameter} -of a template -\grammarterm{template-parameter} -is permitted to have a default -\grammarterm{template-argument}. -When such default arguments are specified, they apply to the template -\grammarterm{template-parameter} -in the scope of the template -\grammarterm{template-parameter}. +A \grammarterm{template-parameter} of +a template \grammarterm{template-parameter} +is permitted to have a default template argument. +When such default arguments are specified, +they apply to the template \grammarterm{template-parameter} +in the scope of the template \grammarterm{template-parameter}. \begin{example} \begin{codeblock} template