diff --git a/papers/n5033.html b/papers/n5033.html new file mode 100644 index 0000000000..0886ba768a --- /dev/null +++ b/papers/n5033.html @@ -0,0 +1,2614 @@ + + + + + +N5033 + + +

N5033 Editors’ Report:
Programming Languages — C++

+ +

Date: 2025-12-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

+ +

Acknowledgments

+ +

Thanks to all those who have +submitted editorial issues, +to those who have provided pull requests with fixes, +and to everyone who drafted motion applications. +Special thanks to Alisdair Meredith and Jan Schultke +for drafting a lot of motion applications, +and to Andreas Krug for ongoing careful reviews.

+ +

New papers

+ + + + +

Motions incorporated into working draft

+ +

Notes on motions

+ +

Note the unusual numbering of CWG motions. +In particular, CWG Motion 3a is not associated +with a change to the working draft.

+ +

In LWG Motion 1, the library issue +LWG4300 +had already previously been +applied editorially.

+ +

In LWG Motions 16 and 19, the resolution of +“NB US 227-346 and US 229-347” +in the latter has substantial overlap with paper +P3815R1 +of the former; the changes were reconciled and integrated.

+ +

All other motions were applied cleanly.

+ +

Core working group polls

+ +

CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues +except issues 1670, 2917, 2923, 3005, 3043, 3044, 3045, 3048, 3053, 3061, 3063, 3074, +3082, 3084, 3089, 3092, 3093, 3094, 3095, 3098, 3099, 3101, 3108, 3109, 3110, 3113, +3114, 3115, 3117, and 3118 in +P3921R0 +(Core Language Working Group “ready” Issues for the November, 2025 meeting) to the C++ Working Paper.

+ +

CWG Poll 2. Apply the proposed resolutions of issues +2917, 2923, 3005, 3043, 3044, 3045, 3048, 3053, 3061, 3063, 3074, 3082, 3084, 3089, 3092, +3093, 3094, 3095, 3098, 3099, 3101, 3108, 3109, 3110, 3113, 3114, 3115, 3117, and 3118 in +P3921R0 +(Core Language Working Group “ready” Issues for the November, 2025 meeting) to the C++ Working Paper.

+ +

CWG Poll 2b. Accept as Defect Reports and apply the proposed resolutions of issue 1670 in +P3921R0 +(Core Language Working Group “ready” Issues for the November, 2025 meeting) to the C++ Working Paper.

+ +

CWG Poll 3a. (Not relevant; poll did not pass, and did not propose a change to the working paper.)

+ +

CWG Poll 3b. Apply the changes in +P3920R0 +(Wording for NB comment resolution on trivial relocation) to the C++ Working Paper. +This addresses numerous ballot comments (see paper).

+ +

CWG Poll 4. Accept as a Defect Report and apply the changes in +P3868R1 +(Allow #line before module declarations) to the C++ Working Paper. +This addresses ballot comment US 55-102.

+ +

CWG Poll 5. Apply the changes in +P3684R1 +(Fix erroneous behaviour termination semantics for C++26) to the C++ Working Paper. +This addresses ballot comment GB 02-036.

+ +

Library working group polls

+ +

LWG Poll 1. Apply the changes in +P3905R0 +(C++ Standard Library Ready Issues to be moved in Kona, Nov. 2025) to the C++ working paper.

+ +

LWG Poll 2. Apply the changes in +P3906R0 +(C++ Standard Library Immediate Issues to be moved in Kona, Nov. 2025) to the C++ working paper.

+ +

LWG Poll 3. Apply the changes in +P3016R6 +(Resolve inconsistencies in begin/end for valarray and braced initializer lists) to the C++ working paper.

+ +

LWG Poll 4. Apply the changes in +P3567R2 +(flat_meow fixes) to the C++ working paper.

+ +

LWG Poll 5. Apply the changes in +P3663R3 +(Future-proof submdspan_mapping) to the C++ working paper. +This addresses ballot comments US 66-117 and PL 009.

+ +

LWG Poll 6. Apply the changes in +P3914R0 +(Assorted NB comment resolutions for Kona 2025) to the C++ working paper. +This addresses ballot comments US 160-260, US 209-332, US 228-348, US 263-396, US 265-398, US 266-399, US 112-172, and US 130-193.

+ +

LWG Poll 7. Apply the changes in +P3836R2 +(Make optional<T&> trivially copyable) to the C++ working paper. +This addresses ballot comment US 134-215.

+ +

LWG Poll 8. Apply the changes in +P3860R1 +(Proposed Resolution for NB Comment GB13-309 atomic_ref<T> is not convertible to atomic_ref<const T>) +to the C++ working paper, as a Defect Report for C++20. This addresses ballot comment GB13-309.

+ +

LWG Poll 9. Apply the changes in +P3388R3 +(When Do You Know connect Doesn’t Throw?) to the C++ working paper.

+ +

LWG Poll 10. Apply the changes in +P3774R1 +(Rename std::nontype, and make it broadly useful) to the C++ working paper. +This addresses ballot comments FR-021-218 and FR-019-210.

+ +

LWG Poll 11. Apply the changes in +P3819R0 +(Remove evaluation_exception() from contract-violation handling for C++26) +to the C++ working paper. +This addresses ballot comments NL, US 69-125,GB 04-124.

+ +

LWG Poll 12. Apply the changes in +P3612R1 +(Harmonize proxy-reference operations (LWG 3638 and 4187)) to the C++ working paper.

+ +

LWG Poll 13. Apply the changes in +P3778R0 +(Fix for type_order template definition) to the C++ working paper.

+ +

LWG Poll 14. Apply the changes in +P1789R3 +(Library Support for Expansion Statements) to the C++ working paper. +This addresses ballot comments NC IT-002, FR 007-011-142, CZ 2-143, US 78-144.

+ +

LWG Poll 15. Apply the changes in +P3922R1 +(Missing deduction guide from simd::mask to simd::vec) to the C++ working paper. +This addresses ballot comment DE-287.

+ +

LWG Poll 16. Apply the changes in +P3815R1 +(Add scope_association concept to P3149) to the C++ working paper. +This addresses ballot comments CA-393 and FI-392.

+ +

LWG Poll 17. Apply the changes in +P3878R1 +(Standard library hardening should not use the ‘observe’ semantic) to the C++ working paper. +This addresses ballot comments RU-016, FR-001-014, FR-010-113, US 3-015, and US 61-112.

+ +

LWG Poll 18. Apply the changes in +P3887R1 +(Make when_all a Ronseal Algorithm) to the C++ working paper.

+ +

LWG Poll 19. Apply the changes in +P3923R0 +(Additional NB comment resolutions for Kona 2025) to the C++ working paper. +This addresses ballot comments AT 7-213, US 140-233, US 141-235, US 145-234, +US 147-240, US 164-203, US 126-189, US 227-346, US 229-347, US 221-339, and US 225-341.

+ +

LWG Poll 20. Apply the changes in +P3371R5 +(Fix C++26 by making the rank-1, rank-2, rank-k, and rank-2k updates consistent with the BLAS) +to the C++ working paper. This addresses ballot comment US 168-277.

+ +

LWG Poll 21. Apply the changes in +P3391R2 +(constexpr std::format) to the C++ working paper. +This addresses ballot comment FR 028-271 and US 167-270.

+ +

LWG Poll 22. Apply the changes in +P3913R1 +(Optimize for std::optional in range adaptors) to the C++ working paper. +This addresses ballot comment PL-011.

+ +

National body comment resolution

+ +

A large number of national body comments for the C++26 Committee Draft have been +addressed in this working draft.

+ +

Editorial comments

+ +

All editorial national body comments were addressed before the Kona 2025 meeting:

+ + + + +

Non-editorial comments

+ +

The following national body comments were addressed by the motions approved at the Kona 2025 meeting:

+ + + + +

Editorial changes

+ +

Major editorial changes

+ +

There have not been any major editorial changes.

+ +

Minor editorial changes

+ +

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

+ +
commit 7ff7a571b82550f2d099ad982b010d7749ed51f7
+Author: Dmitriy Sobolev <Dmitriy.Sobolev@intel.com>
+Date:   Thu Aug 14 17:45:59 2025 +0100
+
+    [specialized.algorithms] Fix a typo: iter_difference_t<T> -> iter_difference_t<I> (#8143)
+
+    A misapplication of P3179R9.
+
+commit 4df4951bd456cc473643fa5d434ce5bf789f0f54
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Sat Aug 2 13:36:14 2025 +0800
+
+    [locale.operators] Qualify `collate`
+
+commit c4eaf7276f43642b414ba9bd01a9112b6f792ad2
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Fri Aug 1 08:36:53 2025 -0400
+
+    [lex.phases] Identifiers do not have linkage, names do
+
+commit 939c73b400a418643c2e1885137a8baea04943d8
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Aug 14 15:08:44 2025 -0400
+
+    [lex.phases, lex.token] Provide unicode name for control characters (#7404)
+
+commit 8fe775ad322ed8837ec4d4bed55e6074c684930a
+Author: SainoNamkho <23036788+SainoNamkho@users.noreply.github.com>
+Date:   Fri Aug 15 03:51:41 2025 +0800
+
+    [dcl.init.ref] Fix misapplication of CWG2879 (#8147)
+
+commit 2ad9269583a4d62765e94154c7e97624083c21fe
+Author: A. Jiang <de34@live.cn>
+Date:   Fri Aug 15 13:37:12 2025 +0800
+
+    [span.syn] Fix typo of `remove_cvref_t`
+
+commit 51a5bbae2fd449a7217d935ac069187b23fb6d22
+Author: A. Jiang <de34@live.cn>
+Date:   Fri Aug 15 17:05:43 2025 +0800
+
+    [optional.optional.ref.general] Fix reference to [optional.ref.iterators]
+
+    Currently the comment mistakenly refer to [optional.iterators], while [optional.ref.iterators] should be referred to instead.
+
+commit 50930e22025e115d2c24451d4ba289f302020eee
+Author: Frank Birbacher <frank.birbacher@gmail.com>
+Date:   Fri Aug 15 13:08:42 2025 +0200
+
+    [meta.reflection.queries]/4.3 Fix syntax in example (#8152)
+
+    A misapplication of P2996R13.
+
+commit 6a6fb0655eeabbdf526b74e65016e0be5eb6f4b3
+Author: Frank Birbacher <frank.birbacher@gmail.com>
+Date:   Fri Aug 15 13:10:17 2025 +0200
+
+    [meta.reflection.queries]/1 Use info return type (#8153)
+
+    A misapplication of P2996R13.
+
+commit a44930586b09a269fbe5def4d9821239a23b6d6b
+Author: Frank Birbacher <frank.birbacher@gmail.com>
+Date:   Fri Aug 15 13:16:55 2025 +0200
+
+    [hive.cons] Add noexcept to move constructor (#8154)
+
+    The synopsis specifies noexcept for this constructor (and the effects
+    don't invoke behavior that could throw), so the missing noexcept on the
+    \itemdecl looks like an oversight in P0447R28.
+
+commit a3bdbd11810a24fe3edc7aef9dc8ac39e796e303
+Author: Frank Birbacher <frank.birbacher@gmail.com>
+Date:   Fri Aug 15 18:47:33 2025 +0200
+
+    [expr.const] Add splice-specifier to list of converted constant expressions (#8161)
+
+    This is a back-reference, because [expr.splice] refers to here already.
+
+commit d9b6f26dd6f92de0cd4ab3cd94d3a7daa44d3021
+Author: morinmorin <mimomorin@gmail.com>
+Date:   Mon Aug 18 20:04:47 2025 +0900
+
+    [back] Fix journal article entries in bibliography
+
+    This change applies the following corrections.
+    - Corrects misspelling of name to R. Clint Whaley.
+    - Adds missing page numbers.
+
+commit 648267c99a7a226b3a7433335e6136f70676d8d4
+Author: Rageking8 <106309953+Rageking8@users.noreply.github.com>
+Date:   Sat Aug 16 18:43:40 2025 +0800
+
+    [rand.dist.norm.f] Fix typo
+
+commit d13a034038e4956e02a6ab58f56109d109fab591
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Aug 18 16:45:22 2025 +0200
+
+    [unord.set.overview] Add "and" at end of list (#8167)
+
+commit 611d2ecc07a39403311783b5862df6319447eb7f
+Author: Rageking8 <106309953+Rageking8@users.noreply.github.com>
+Date:   Tue Aug 19 04:35:05 2025 +0800
+
+    [simd.syn] Remove duplicate `using simd::abs;` (#8163)
+
+commit 430b1b20565310bea11906ae8eabf746c0f7b8c5
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Aug 19 08:49:07 2025 +0200
+
+    [atomics.types.float] Fix typo
+
+commit 675155b5ab52d101de297a150120dccaedec2735
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Aug 21 14:58:47 2025 +0800
+
+    [stringbuf.members] Remove `// exposition only` from `itemdecl` (#8179)
+
+commit 171454e98de36de7f9f3b7dfea241be79fc96ec7
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Aug 21 13:32:14 2025 +0800
+
+    [locale.facet] Avoid improperly defining `explicit`
+
+commit 41014b4db993215816a2d855d161f7136b59a3db
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Aug 21 14:17:40 2025 +0200
+
+    [multiset.overview] Add "and" at end of list (#8182)
+
+commit 1bccf914e4ec88fd3b2dc4e54c9053f46349176f
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Aug 26 11:57:14 2025 -0400
+
+    [basic.def] Better link do defintion of declaration (#8191)
+
+    The plain text term in this sentence refer to the definition in [basic.pre]
+    and not the grammar production defined in [dcl].
+
+commit e593dc1a1f54d6e22179c26e246ded4e7dcf9588
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Aug 27 22:42:37 2025 +0200
+
+    [exec.counting.scopes.general] Fix typo (#8193)
+
+commit b1093176914ce5ec0be3b2e02e5ff5e3c4f5e3f6
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Aug 28 12:30:14 2025 -0400
+
+    [basic.pre] Clarify that *declaration*s are not declarations (#8187)
+
+    * [basic.pre] Clarify that *declaration*s are not declarations
+
+    The grammar production _declaration_ is distinct from the term "declaration" defined in [basic.pre].
+
+commit 73ba7d1d81f6ef8bf92683c9071f0c4fc8afe7ad
+Author: Rageking8 <tomleetyt@gmail.com>
+Date:   Fri Aug 29 00:31:47 2025 +0800
+
+    [meta] Fix several typos (#8157)
+
+commit 0b4ceb5dc35ebc736bfeb99ae629fdb0622ddf27
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sun Aug 31 19:26:32 2025 +0200
+
+    [tab:meta.unary.prop] Fix punctuation (#8197)
+
+commit bed3aab4b763ee5077d5cab997c020e389fc8092
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Sep 11 21:16:36 2025 +0800
+
+    [lex.phases] Fix typo in "instantiation" (#8223)
+
+commit 8d0144fc2e7ee8a1b38e9a69375fdedc430ec154
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Mon Sep 15 15:23:18 2025 +0800
+
+    [func.wrap.move.class, func.wrap.copy.class] Fix singular and plural in subclause titles (#8232)
+
+commit ed15cb52358664ae8a5b4c1df366dd2056c144e4
+Author: EienMiku <EienMiku@outlook.com>
+Date:   Tue Sep 16 18:43:45 2025 +0800
+
+    [map.overview] Fix typo of constructor of map
+
+commit c85cdf2d0bc4a559d4092575b70025f259a68c22
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sat Sep 27 10:52:22 2025 +0200
+
+    [meta.reflection.define.aggregate] Replace "is_enumeration_type" with "is_enum_type"
+
+    This fixes a wording bug in P2996R13.
+
+commit 020140713799934d623241627c6aaef917e5039d
+Author: Luc Grosheintz <luc.grosheintz@gmail.com>
+Date:   Sat Sep 27 22:26:43 2025 +0200
+
+    [views.multidim] Fix template arguments for submdspan_extents (#8243)
+
+commit 82bf75bc09e4ab5781e4f9149a59a41fe4c8581e
+Author: Luc Grosheintz <luc.grosheintz@gmail.com>
+Date:   Mon Sep 29 20:06:16 2025 +0200
+
+    [mdspan.sub.sub] Fix typos in submdspan effects (#8248)
+
+    The class `mdspan` doesn't have a member `data`, it has `data_handle`
+    (which returns a generalized pointer).
+
+    The `AccessorPolify::offset_policy` is a type alias and therefore needs
+    a preceeding `typename`.
+
+commit 3f8865632f916f52993f342393a016aa2d732792
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Tue Sep 30 04:07:15 2025 +0800
+
+    [simd.mask.comparison] Add missing parameter names (#8262)
+
+commit 9db1d3b6121e092ed89e84ba9a1e45bf2b7504fc
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Wed Oct 1 00:07:58 2025 +0800
+
+    [simd.permute.mask] Fix typo (#8268)
+
+commit 3c0ac909441ced78a097456fbfeec1b83f2da218
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Wed Oct 1 00:04:57 2025 +0800
+
+    [stringstream.members] Add missing param
+
+commit f5c6e4ef5fd303d07a0cd691913a5317164bb5d5
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 18:58:19 2025 +0200
+
+    [meta.reflection.names] Fix formatting for 'N'
+
+    Fixes NB US 94-201 (C++26 CD).
+
+commit c6dc1e60202fea04b1d26769479c7063b3f867d1
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 19:02:43 2025 +0200
+
+    [meta.reflection.queries] Fix typo in comment in example
+
+    Fixes NB US 96-206 (C++26 CD).
+
+commit eb87240307c7bb80937eda95c3077e41e096550f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 18:39:29 2025 +0200
+
+    [meta.reflection.operators] Remove superfluous 'the'
+
+    Fixes NB US 91-198 (C++26 CD).
+
+commit 7c3eb729ab66113a5ca02c90efce4ef5e944810b
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 17:46:51 2025 +0200
+
+    [meta.reflection.member.queries] Remove superfluous 'of'
+
+    Fixes NB US 103-164 (C++23 CD).
+
+commit 9793e558b81c133e1237cd96ce37171f79b63245
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 18:54:11 2025 +0200
+
+    [meta.reflection.operators] Fix table formatting
+
+    Fixes NB US 92-199 (C++26 CD).
+
+commit 0c8df65ab760e827363591f95f127de98771238b
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 15:32:15 2025 +0200
+
+    [basic.life] Remove spurious commas
+
+    Fixes NB US 18-035 (C++26 CD).
+
+commit f8d44da79bc497b8a3ab6fc3fce728e40206922a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 17:38:08 2025 +0200
+
+    [meta.syn] Fix phrasing in note
+
+    Fixes NB US 88-163 (C++26 CD).
+
+commit 9add78e448d5900d57f4e15da2f08eaceedab419
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 18:49:55 2025 +0200
+
+    [meta.reflection.define.aggregate] Fix declarations of name-type constructors
+
+    Fixes NB US 123-187 (C++26 CD).
+
+commit 0b085787cb519c8904e951f5fd23e1d4df5b7682
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 22:17:27 2025 +0200
+
+    [exec.snd] Fix cross-references for 'impls-for'
+
+    Fixes NB US 208-333 (C++26 CD).
+
+commit 47992d448b6cb6f31e78d27193853b6dd4783fb0
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 23:36:18 2025 +0200
+
+    [execution.syn] Add comments to cross-references in synopsis
+
+    Fixes NB US 200-323 (C++26 CD).
+
+commit 969776f2676316422ae1e7c92718326efa3c357f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 23:54:24 2025 +0200
+
+    [exec.snd.expos] Move specification of default template argument for 'Data'
+
+    Fixes NB US 212-352 (C++26 CD).
+
+commit 5ba4be405536256e4498086dc78e1013e7b06920
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 23:45:05 2025 +0200
+
+    [execution.syn] Add enable_sender to synopsis
+
+    Fixes NB US 199-324 (C++26 CD).
+
+commit 40c2499440d42ac93e889bb7604173f01abb50a7
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 22:29:10 2025 +0200
+
+    [exec.write.env] De-bulletize specification of check-types
+
+    Fixes NB US 218-349 (C++26 CD).
+
+commit 7c31fb08d42cb48eb2a5f63ed4406aff8f1eed4a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 15:43:54 2025 +0200
+
+    [temp.variadic] Add separate bullet for annotation-list
+
+    Fixes NB US 51-095 (C++26 CD).
+
+commit 322d38022bb292fbdb6d668af4ecd753eb104a53
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 15:39:10 2025 +0200
+
+    [class.pre] Adjust phrasing around 'identifer'
+
+    Fixes NB CA-083 (C++26 CD).
+
+commit be1585aeff253d6d87e41f08a4e617e96ac0e17a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 12:12:27 2025 +0200
+
+    [meta.reflection.extract] Apply code font to "U"
+
+    Fixes NB US 111-174 (C++26 CD).
+
+commit 9bd9e43f43d669d5fd353fa390818a47a42dad18
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 12:01:45 2025 +0200
+
+    [meta.reflection.layout] Remove incorrect 'of'
+
+    Fixes NB US 108-169 (C++26 CD).
+
+commit a7e6101939985870e128b742c616e5c6da357b2b
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 08:23:03 2025 +0200
+
+    [exec.par.scheduler] Use 'has the value' for an expression
+
+    Fixes NB US 262-394 (C++26 CD).
+
+commit 6f3ef53700441dd46c369ab9e4a14e722206ffc6
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 08:14:43 2025 +0200
+
+    [dcl.fct.def.replace] Add 'replaceable function' to index
+
+    Also add a label 'term.replaceable.function' for subclause-agnostic
+    cross-referencing.
+
+    Fixes NB US 269-406 (C++26 CD).
+
+commit 9d74d451e7ea2cf09e71f09b9e283047d713eab6
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 07:44:02 2025 +0200
+
+    [algorithms.parallel.overloads] Rename subclause title
+
+    Fixes NB US 156-254 (C++26 CD).
+
+commit e70c392421cce818ae5edc0d4fde6d94184b8a4a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 12:18:08 2025 +0200
+
+    [meta.reflection.extract] Remove stray 'T is' and format 'X' in code font
+
+    Fixes NB US 110-171 (C++26 CD).
+
+commit 7c829315eb135f4df6326e35974c41983dc18ffd
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 14:14:23 2025 +0200
+
+    [atomics.syn,atomics.ref.pointer] Remove partial specialization atomic_ref<T*>
+
+    A misapplication of paper P3323R1.
+
+    Fixes NB US 194-314 (C++26 CD).
+
+commit 7e30ea001b274cc74dc165e32e3908bd6d13a54a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 14:26:06 2025 +0200
+
+    [atomics.types.int,atomics.types.float] Excise uses of undeclared 'T'
+
+    Fixes NB US 196-315 (C++26 CD).
+
+commit 196df1a7a97c0f11286816baa22d365d202db8ad
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 15:00:21 2025 +0200
+
+    [atomics.ref.generic] Avoid use of undeclared 'T'
+
+    Fixes NB US 192-312 (C++26 CD).
+
+commit 13a5c431dde2bff1ee02fa655806ffaedfc1b70f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 09:42:48 2025 +0200
+
+    [task.promise] Remove trailing semicolons in comments in examples
+
+    Fixes NB US 259-380 (C++26 CD).
+
+commit 0bce45bb287307c828c69fee1942da0c17793a15
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 11:51:29 2025 +0200
+
+    [exec.task.scheduler] Fix punctuation and add 'the'
+
+    Fixes NB US 241-371 (C++26 CD).
+
+commit cd66127ccb165d4d0fcfb1594475a12600986697
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 17:54:17 2025 +0200
+
+    [exec.getcomplsigs] Fix misplaced \end{itemdescr} (#8301)
+
+    Fixes NB US 217-359 (C++26 CD).
+
+commit 122cc4abe30c0cdc39e7f7d4d09222ddfc298292
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 12:49:46 2025 +0200
+
+    [exec.snd.expos] Amend specification for allocator-aware-forward
+
+    Fixes NB US 216-357 (C++26 CD).
+
+commit 63c59140eda9f020f1d516657d2c1ab25c5a2d2d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 12:30:21 2025 +0200
+
+    [meta.reflection.substitute] Add 'in order'
+
+    A misapplication of P2996R13.
+
+    Fixes NB US 115-176 (C++26 CD).
+
+commit e2511592b653984301b7a13559c0e6e06d1243aa
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 12:23:48 2025 +0200
+
+    [meta.reflection.substitute] Clarify error message in example
+
+    Fixes US 116-177 (C++26 CD).
+
+commit 42793d0ce36d4fe09a4c7ebdceeadef2e343fee4
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 09:38:01 2025 +0200
+
+    [exec.sysctxrepl.psb] Make 'one of the expressions below' more explicit
+
+    Fixes NB US 266-399 (C++26 CD).
+
+commit 776bc2892e2480fb69296cd404fc4bd5136cc44a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 19:51:24 2025 +0200
+
+    [exec.snd] Harmonize subclause titles
+
+    Drop unnecessary 'std::' prefix
+
+    Fixes NB FR-033-335 (C++26 CD).
+
+commit e7e5b69c13ce5c358065fd989d64c4253693d415
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 11:42:14 2025 +0200
+
+    [task.promise] Refer to parameter types of the completion signatures
+
+    Fixes NB US 260-390 (C++26 CD).
+
+commit 600fe56064ee41722607e4c45d56919a1f153b87
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 19:59:38 2025 +0200
+
+    [simd.syn] Compactify presentation of gather/scatter functions
+
+commit bab708de50b834d5144cef2d2fb0872954ca47b9
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 18:55:20 2025 +0200
+
+    [simd.traits] Rename subclause heading to 'Type traits'
+
+    The subclause applies to both vecs and masks.
+
+    Fixes NB US 177-284 (C++26 CD).
+
+commit 597cc85b49cfed8daab129fceca2c8d78b58dc6c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 18:07:17 2025 +0200
+
+    [simd.mask.namedconv] folded into [simd.mask.conv]
+
+    Fixes NB US 185-299 (C++26 CD).
+
+commit f3778a37d4a5c40f2ecc64b6ed47e3b8548b1eb6
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 19:12:14 2025 +0200
+
+    [simd.complex.access] Move into [simd.class]
+
+    The complex accessors are member functions.
+    Also adjust the subclause heading to fit the new surroundings.
+
+    Fixes NB US 179-293 (C++26 CD).
+
+commit 2dbfcc5c7a759d6fbd6c09ecbc7f4439cc4eb5f5
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 18:02:01 2025 +0200
+
+    [simd.mask.nonmembers] Add 'basic_mask' to subclause heading
+
+    Fixes NB US 186-300 (C++26 CD).
+
+commit 95a10a601b3e2c33713724b514b47162fefa73ef
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 11:46:40 2025 +0200
+
+    [task.state] Fix formatting of subclause heading
+
+    Fixes NB US 248-378 (C++26 CD).
+
+commit ae124b4ce071453365f5b89fcb815ee731fdd2f8
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 22:37:15 2025 +0200
+
+    [exec.when.all] Fix spelling of 'get_stop_token_t'
+
+    Fixes NB US 223-343 (C++26 CD).
+
+commit b1949378f3174e8177890dac5fff62cc7ffdc0e3
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 6 14:08:35 2025 +0200
+
+    [atomics.ref.pointer,atomics.types.pointer] Use 'see above' for fetch_key declaration
+
+    Fixes NB US 198-317 (C++26 CD).
+
+commit bc71d74ab0b0717973cbaf28a4f1931bd42fa848
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 11 10:28:16 2025 +0200
+
+    [exec.cmplsig] Add 'value_types_of_t' to index (#8326)
+
+commit adca52baba9f75d1190cbb9cc7dc7e4c04fa7152
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sun Oct 12 04:38:49 2025 -0400
+
+    [lex.phases] Move dropping whitespace to end of phase 4 (#8117)
+
+    Move the dropping of whitespace to the end of phase 4, after preprocessing directives are deleted.
+
+commit e1d47e006183ef8e2c778587b5fdcf0ce6d15da6
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Oct 16 22:27:11 2025 +0200
+
+    [basic.def] Remove incorrect \grammarterm formatting for "declaration" (#8337)
+
+    Fixes NB US 12-026 (C++26 CD).
+
+commit fb46e16c6ce0d91c6bd21ca497d1823c997d1926
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sat Oct 18 00:33:16 2025 +0200
+
+    [streambuf.virt.put] Replace "effects" with "affects" in footnote (#8329)
+
+    Fixes NB US 188-303 (C++26 CD).
+
+commit 8fc2944d469666f68b595a47b6f2f1d38547b402
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Sat Oct 18 13:01:39 2025 +0100
+
+    [meta.type.synop] Remove redundant cast in constant_wrapper declaration (#8218)
+
+    The use of `decltype(cw-fixed-value(X))` instead of just `decltype(X)`
+    is a workaround for a GCC bug: https://gcc.gnu.org/PR117392
+
+    There's no need for the standard to specify it this way.
+
+    Fixes NB US 79-146 (C++26 CD).
+
+commit 05e4d8d991ec3a4d013b90c1317e9f76b68c8532
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 11 10:39:17 2025 +0200
+
+    [simd] Canonicalize subclause headings
+
+    Remove parts redundant with headings of superordinate subclauses.
+
+commit 7fffa1fb521b9432b769e0f83d6a60c732f3cfb8
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Mon Oct 20 16:20:31 2025 +0100
+
+    [vector.bool.pscp] say "vector primary template" (#8351)
+
+    Not primary vector template.
+
+commit c914b3bf857daea1c30ffbb330c0a4e5a44edc70
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Mon Oct 20 17:24:12 2025 +0200
+
+    [meta.reflection.access.context] Remove stray "static" in declaration of "via" (#8272)
+
+    A misapplication of P2996R13.
+
+    Fixes NB US 101-208 (C++26 CD).
+
+commit ca77cdb10021c757b0fbe4d83b5991ac7d935db8
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Mon Oct 20 16:28:59 2025 +0100
+
+    [fs.path.native.obs,fs.path.generic.obs] Qualify std::format (#8350)
+
+    Fixes NB US 190-305 (C++26 CD).
+
+commit 29465f5bec52bbfe1d81cd17c20527c911801447
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Oct 23 21:40:25 2025 +0200
+
+    [linalg.conj.conjugatedaccessor] Fix typos and constructor missing from synopsis (#8106)
+
+commit 0d90bd108f9cba10d206a300a64684a0244004e4
+Author: Hana Dusíková <hanicka@hanicka.net>
+Date:   Fri Oct 24 17:13:42 2025 +0200
+
+    [meta] reflect_constant_array of an empty range returns const array<T,0>
+
+commit cab90b37139473d67cba49397ff6666228ca4db3
+Author: Keith Thompson <Keith.S.Thompson@gmail.com>
+Date:   Fri Oct 24 12:20:54 2025 -0700
+
+    [diff.expr] Remove commentary about good practice in C (#8356)
+
+commit 2f53f313f5b1aac5f9547b39e78863e23ca9c047
+Author: A. Jiang <de34@live.cn>
+Date:   Sun Oct 26 19:22:13 2025 +0800
+
+    [lib] Fix C23 subclause numbers in `\xrefc` and `\IsoC` (#8113)
+
+commit 96fa31012b50a32d96a49fa8060124bcb70e3e5a
+Author: Kilian Henneberger <kilis-mail@web.de>
+Date:   Mon Oct 27 21:39:41 2025 +0100
+
+    [meta.reflection.substitute] Name correct function in comments (#8372)
+
+commit 3ba26a48c7a72f7ed7d17d6380457ff6f985489a
+Author: Matthias Kretz <M.Kretz@gsi.de>
+Date:   Wed Oct 29 22:58:21 2025 +0100
+
+    [simd.math] Add missing return keywords (#8374)
+
+commit 512372387083cdc2d112bfba157c463220b43476
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Aug 1 11:16:35 2025 +0100
+
+    [expr.reflect] Delete sentence from "interpretation" list item that is redundant with the next item.
+
+    The next item already describes the case where R represents a namespace.
+
+commit 03f0c9f631c5e2d70cfe8e8476016771cc7d9d51
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Aug 1 11:57:08 2025 +0100
+
+    [dcl.attr.grammar] Delete redundant "and no alignment-specifier".
+
+    Now that we say "an attribute-list with no attributes", the additional
+    "and no alignment-specifier" is redundant.
+
+commit 2a9a4e3c3757ace0ec8c24ca6f8c31e77f3a8ec5
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Aug 21 09:57:22 2025 +0800
+
+    [expected.object.monadic] Add missing necessary `typename`
+
+commit 617a9f1254bb930c80ad4e5f13fb27ca4e8ded51
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Aug 21 09:57:44 2025 +0800
+
+    [expected.void.monadic] Add missing necessary `typename`
+
+commit 266cb2bc567f00797ca4d0ebc6b425f98f5167bf
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Aug 21 15:16:09 2025 -0400
+
+    [cpp.replace.general] Add a cross-reference to 'see below'
+
+    The 'below' in 'see below' as actually five sublauses away.
+    Adding a cross-reference establishes the link more clearly.
+
+commit 262d37f0b19c91c795fd89872789ca7bcf200a42
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Aug 21 15:23:38 2025 -0400
+
+    [lex.phases] Clarify the sequence of characters for line splicing
+
+commit 6d42e2f96acf42060adcb018053f562a45510671
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Oct 30 08:39:52 2025 -0400
+
+    [basic.pre] Clarify definition of variable (#8186)
+
+    Reorder the positive and negative terms to avoid confusion with the binding of "other than".
+
+commit da231804706780368a6f6becc4d45000b31c19eb
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Aug 23 21:47:47 2025 -0400
+
+    [syntax] Replace plain text with grammar terms where intended
+
+    For the examples of X-seq and X-list forms of specifiaction,
+    ensure that the thing in the sequence or list is the corresponding
+    grammar element rather than a plain text term, as the two are not
+    always synonyms, notably not the case for the cited *declaration*.
+
+commit 1722e1f2b9ddc3b7f172b8f7503eda6e451c3012
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Jun 18 10:04:59 2025 +0800
+
+    [dcl.constexpr], [dcl.init.aggr] A constructor is a member function
+
+commit 494ddd03d3e7272727451126c264cb47ba698030
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Jun 18 10:08:50 2025 +0800
+
+    [expr.call], [expr.const] A constructor is a (member) function
+
+commit 683be0af96d1cfb1fa971cca17b10cf460445cd3
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Jun 18 10:11:23 2025 +0800
+
+    [temp.spec.general], [temp.inst] A member function is a function
+
+commit f7c7befc7f03236ca968c1003f1d65247519a51b
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Jun 18 10:12:09 2025 +0800
+
+    [constexpr.functions] A constructor is a function
+
+commit 729a91c79e408b89329ecdd6345a43c31931da2d
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Jun 18 10:12:51 2025 +0800
+
+    [pairs.pair] A constructor is a member function
+
+commit be930a9c8e7a6ae0e5c37bab6e741a878f046085
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Jun 18 10:15:49 2025 +0800
+
+    [container.reqmts], [flat.map.overview], [flat.multimap.overview], [flat.set.overview], [flat.multiset.overview] A constructor is a member function
+
+commit a81ecaa88443f7e23ef1dddc99a10b4b1488d21b
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Jun 18 10:20:07 2025 +0800
+
+    [diff.cpp17.depr] A constructor is a member function
+
+commit d411b5731711c02cbd140ff25fc514f0ef682817
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Feb 25 17:31:01 2024 +0100
+
+    [container.reqmts] Remove stray semicolon in description of expression
+
+commit 755202dc393ca6e9a87344ec9e810163c3b59d6b
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Jul 22 09:38:31 2025 +0800
+
+    [conv.rank] Update and fix the reference to C23 H.4.3
+
+commit 11b56197263aa8af89596e69e663de3cc873e360
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Jul 22 09:39:34 2025 +0800
+
+    [numerics.c] Use `\xrefc` to refer to C23 7.20
+
+    ... addressing the `%% TODO` comments
+
+commit 4917ad917b62e8065910c3c34ae1cd490747075b
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Jul 22 09:40:19 2025 +0800
+
+    [stdbit.h.syn] Use `\xrefc` to refer to C23 7.18
+
+    ... addressing the `%% TODO` comments
+
+commit 0b6b2b0cde8b878dbbf19b7f514e99be1e23aa87
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Sun Jul 27 23:39:23 2025 +0800
+
+    [range.refinements]  Fix template parameter name
+
+commit acb132bb75c3bedb159b26d151aae1469c68883b
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Jul 31 16:07:43 2025 +0100
+
+    [expr.prim.lambda.closure] Use "incomplete" instead of "not complete".
+
+    The former is a defined term.
+
+commit 7e9c2b7f29605a3f195f30ef1821a88f55dec950
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Fri Oct 31 01:35:27 2025 +0800
+
+    [const.wrap.class] Add missing namespace std (#8247)
+
+commit fde9d1f6047ed65e52483fa40162b966628162b2
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Oct 26 07:32:34 2025 +0100
+
+    [basic.scope.pdecl], [temp] Replace "expansion statement" with "expansion-statement"
+    Fixes NB US 2-404 (C++26 CD).
+
+commit 887c88157c52a8fb4f1acc3d49b40d4c5ef9af6c
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Oct 24 18:11:27 2025 +0100
+
+    [meta.reflection.layout] change 'entity' to 'construct'
+
+    Fixes NB US 104-165 (C++26 CD).
+
+commit 6042d48bc8467d7f73516e045f440e3b80a0961e
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Oct 21 13:59:35 2025 -0400
+
+    [cpp.pre] Move paragraph introducing preprocessor to first
+
+    The paragraph with no normative text that outlines the broad capabilities
+    of the preprocessor has slippee further down this clause as new text is added.
+    The most appropriate place for introductory text is the first sentence of the
+    introductory clause, so moved accordingly.
+
+commit 41c80d6cb744df0c8c409d3d72228c57fbf9d6cd
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Oct 17 19:19:23 2025 +0100
+
+    [simd.permute.static] use satisfies for satisfaction
+
+    Fixes NB US 182-296 (C++26 CD).
+
+commit a019163776f16b4ed4ac9b7ec22d9b8abcd9314d
+Author: Eisenwave <me@eisenwave.net>
+Date:   Thu Oct 9 11:34:21 2025 +0200
+
+    [class.temporary] Clarify that list of contexts is exhaustive, say "temporary objects"
+    Fixes NB US 19-037 (C++26 CD).
+
+commit 45dca420c08b9ce05b58140bc0572ff65dc24a1f
+Author: Eisenwave <me@eisenwave.net>
+Date:   Thu Oct 9 12:07:28 2025 +0200
+
+    [simd.syn] Reorder declarations to match subclause order
+    Fixes NB US 175-281 (C++26 CD).
+
+commit 2c60d60528470f5c1c7e53c345a77d2b88085483
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Oct 23 06:15:51 2025 +0200
+
+    [diff.expr] Include conversions involving pointers to cv void in the changes
+
+commit 210d61f6d4c10316975c9aa02ebeb2383b225983
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 25 18:22:16 2025 +0200
+
+    [dcl.init.general] Add cross-references for mandatory copy elision
+
+commit bfcdd7250785909bc2fdd9eeb381680129ec9628
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 5 22:25:03 2025 +0200
+
+    [exec.par.scheduler] Move class definition from synopsis
+
+    Fixes NB US 204-321 (C++26 CD).
+
+commit c82d84c417ee6c1e0407162c487a810a2baaa562
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Oct 31 01:44:23 2025 +0100
+
+    [meta.reflection.{layout, annotation}] Harmonize phrasing about complete types (#8347)
+
+    Fixes NB US 107-168 (C++26 CD).
+
+commit 3de77e4c3112eaa54a7cd44ef11ba6a26bff1d00
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Aug 8 13:37:41 2024 +0800
+
+    [class.ctor.general] Remove a dangling paragraph and associated index
+
+    The paragraph was made dangling by P1787R6.
+
+commit 8525f9150a7fe8c63fb593b65b80b09b55f94f30
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Oct 17 19:20:01 2025 +0100
+
+    [simd.permute.mask] clarify list is in ascending order
+
+    Fixes NB US 183-290 (C++26 CD).
+
+commit ffd997cb108c7b3be749ba1abb4ac727117f65ee
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Oct 24 17:53:32 2025 +0100
+
+    [meta.reflection.result] move declaration of TCls earlier
+
+    Fixes NB US 117-178 (C++26 CD).
+
+commit c53c1789779b1f6ccd95d0ab27aca50658830b07
+Author: Jeff Garland <jeff@crystalclearsoftware.com>
+Date:   Thu Oct 30 17:58:13 2025 -0700
+
+    [meta.reflection.extract] Remove second "constexpr if"
+
+    Fixes NB US 113-173 (C++26 CD).
+
+commit 65236d7d5fca9ccc8f3cff2d9c248f02f1f9d5bf
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 17:54:14 2025 +0200
+
+    [meta.reflection.layout] Fix phrasing in bulleted list
+
+    Fixes NB US 105-166 (C++26 CD).
+
+commit 088768b5b613a29af165f2c99fe86e8bd918677a
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Sep 3 10:40:42 2025 +0200
+
+    [temp.deduct.general] Replace "nontype template argument" with "constant template argument"
+
+commit 19a9248ff8c5b0008f805e0353b697a5692ea354
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 26 12:53:22 2025 +0100
+
+    [lib] Remove superfluous `typename` in alias declarations
+
+    Also add an automatic check.
+
+    Fixes NB US 64-127 (C++26 CD).
+
+commit 1fcd55fceb8aca33f2e4d82c577aa47e94bb0e93
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Oct 31 10:11:58 2025 +0100
+
+    [exec.sysctxrepl.recvproxy] Create new subclause for receiver proxies
+
+    Fixes NB US 264-397 (C++26 CD).
+
+commit 42129859dd633cd3f497ef9dd80b5d1dd4b35672
+Author: Eisenwave <me@eisenwave.net>
+Date:   Tue Oct 28 19:25:45 2025 +0100
+
+    [concept.regularinvocable], [iterator.concept.winc] Replace "annotation" with "comment"
+    Fixes NB US 71-128 (C++26 CD).
+
+commit 42fad0f0b26d87235bb0cf8524de3f7628150a10
+Author: A. Jiang <de34@live.cn>
+Date:   Fri Oct 31 19:22:56 2025 +0800
+
+    [basic.fundamental] Complete examples for reflections (#8265)
+
+    Fixes NB US 22-042 (C++26 CD).
+
+commit bf6acb1d651f1960f287b8d98b62b1f0092d0a30
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Oct 31 12:05:49 2025 +0000
+
+    [meta.define.static] qualify names from namespace meta
+
+    Within library wording we don't do ADL, only unqualified lookup (as per
+    [contents] p3). This means that all the metafunctions in namespace std
+    need to qualify names from namespace std::meta in order to find them.
+
+    This also fixes the bug that name lookup in the Effects: of
+    define_static_array would find std::extent and not perform ADL to find
+    std::meta::extent, even if ADL was performed here.
+
+commit dfe8e0b2de8df3cd890351055352e742b8ad5a5f
+Author: YexuanXiao <bizwen@nykz.org>
+Date:   Fri Oct 10 00:01:05 2025 +0800
+
+    [meta.type.synop] Indexing the unindexed type aliases and variable templates
+
+commit 69837e72cebb65063a7f63b751e2ab8d70318823
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Fri Oct 31 22:14:47 2025 +0800
+
+    [unord.multiset.overview] Add missing "typename" (#8271)
+
+commit 54d9b47b3fcbb42ec7c24c89a00fa64f7fe4ad4e
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sat Sep 27 11:06:41 2025 +0200
+
+    [concepts.callable.general] Replace "function objects" with "callable types"
+
+commit 7089fb216f5ac4afa9c6e977a31921c2a0eff714
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Fri Oct 31 22:30:04 2025 +0800
+
+    [simd.overview] Remove obsolete "noexcept" (#8250)
+
+    The "noexcept" specifier was removed from the design by P3430R0,
+    but the paper omitted the corresponding change of the synopsis.
+
+commit 7f1926bbb287cccf27d0edccce860badbfc743b2
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Sep 5 19:14:38 2025 +0100
+
+    [flat.map.modifiers] Remove redundancy in 'insert(sorted_unique, i, j)'
+
+    We can specify this in terms of the overload without the `sorted_unique`
+    tag. That is consistent with how the equivalent functions in `flat_set`
+    and `flat_multiset` are specified.
+
+commit 13a33aca7b93142f63c68f426511291dc899032b
+Author: Masaki Moriguchi (a.k.a. Michel Morin) <mimomorin@gmail.com>
+Date:   Sat Nov 1 00:22:21 2025 +0900
+
+    [locale.moneypunct.virtuals] remove redundant backslash-space (#8159)
+
+    TeX already treats a period after uppercase as an acronym (which yields normal spacing).
+
+commit 1ff1e63b14f530389585bcee43401619f7edc139
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Oct 31 16:32:02 2025 +0100
+
+    [optional.optional.{general, ref.general}] Say "object of type optional<T&>" (#8220)
+
+commit daf06c9f3445bd46678dc660e55debbb6feb7d97
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Tue Sep 30 02:17:45 2025 +0800
+
+    [mdspan.accessor.aligned.overview] Remove std:: in example
+
+commit 4bf58f81313e940295281a58d6520f8d9af18a56
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Sep 29 10:11:17 2025 +0800
+
+    [filebuf.virtuals] Add missing `const` to pointer variables
+
+    The fourth parameter of `codecvt::out` and `codecvt::in` are
+    `const C*&`, but _Effects_ use `C*` variables, which makes the call
+    ill-formed.
+
+    The intent seems sufficient clear and we should probably use `const C*`
+    variables in these places.
+
+commit 2e003dac4f1658e3ccbfd22c4e477f7b1d0ec3f1
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Oct 31 16:39:18 2025 +0100
+
+    [{hive,vector}.capacity] Move remarks from Complexity to Remarks element (#8323)
+
+commit 04df25f524e692e0484f04779debcbaf59e83e2d
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Tue Oct 7 20:33:03 2025 +0800
+
+    [allocator.requirements.general] Add namespace std for exposition-only concept
+
+commit 1e54f58f5a5cf0a283b90c0db30fff76d42efb51
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Oct 31 22:08:15 2025 +0100
+
+    [basic.link] Use maths font in defn of direct base class relationship (#8333)
+
+    Fixes NB US 1-405 (C++26 CD).
+
+commit 3b14ec1d5f19882e628bfa09b96eeaeebdb622b7
+Author: Eisenwave <me@eisenwave.net>
+Date:   Thu Oct 9 09:49:44 2025 +0200
+
+    [atomics.types.float] Align parameters in function declarations
+
+    Fixes NB US 197-316 (C++26 CD).
+
+commit 15186e75cb77cc410db4e5343bcd17dd0a3c66ac
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Nov 1 13:32:39 2025 +0800
+
+    [text], [numerics], [exec] Remove remaining `typename` in aliases
+
+commit 5d916dc6cc99a6d548942ebf85fc1551ad4b7a84
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Nov 1 14:37:09 2025 +0100
+
+    [meta.reflection.annotation] Move to before [meta.reflection.extract]
+
+    Fixes NB US 87-156 (C++26 CD).
+
+commit 363c3a545ef54fe35499b26bcf438dbd8f84538d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 4 18:23:56 2025 +0200
+
+    [meta.reflection.array] Integrate subclause into [meta.define.static]
+
+    Fixes NB US 86-157 (C++26 CD).
+    Fixes NB US 119-180 (C++26 CD).
+    Fixes NB US 89-196 (C++26 CD).
+
+commit 7409cb04365a0a2ee19e100f663b1174aa204710
+Author: Vincent X <77327828+ckwastra@users.noreply.github.com>
+Date:   Sat Nov 1 22:14:17 2025 +0800
+
+    [temp.explicit] Fix comment in example (#8225)
+
+commit acee2087d1d72a94ebb5309459c9dae69cedfa5b
+Author: Corentin Jabot <corentinjabot@gmail.com>
+Date:   Sat Nov 1 11:21:06 2025 -0700
+
+    [class.protected] Change "naming class" to "designating class" (#8251)
+
+    The term was changed to "designating class" by P2996
+    (https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2996r13.html#pnum_397),
+    and these remaining uses had not been updated accordingly.
+
+commit bbcf99022649b569ad21feb5e3a893d1e907c9a6
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Jul 26 08:05:33 2025 +0200
+
+    [dcl.ptr] Move "See also" from normative paragraph to example
+
+commit c98a54b8a1a641c74c017767092a8d65827267d8
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Jul 26 10:38:11 2025 +0200
+
+    [conv.rank] Add missing hyphen in "floating point"
+
+commit 31c4868b3e3323aa931aeb66cb83c8c1135ccdf7
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Jul 26 10:38:52 2025 +0200
+
+    [diff.cpp03.locale] Add missing hyphen in "floating point"
+
+commit dcfad093c246a09594d401340e195315db61220c
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Jul 26 10:40:00 2025 +0200
+
+    [linalg.reqs.alg] Add missing hyphen in "floating point"
+
+commit 2be3924b5b7249d6d7b085f8a1e4321e7645a54c
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Sep 23 21:45:59 2025 +0800
+
+    [meta.member] Properly introduce intended implicit conversion
+
+    Previously, the `static_assert` the example failed due to deduction
+    failure but not `false` results. This PR makes the template arguments
+    fully specified, which allows intended implicit conversion.
+
+commit 4452e28fde3c647a59fe261a1ced3906b901ca3f
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Aug 26 11:35:55 2025 -0400
+
+    [basic.def] Turn list of examples into a nute
+
+    The list of example side effects should neither be deemed normtaive nor
+    exhaustive (although we will try).  It should be demoted to a note.
+
+commit 77893aadc587df5131c3cf5d8388cbf6f7633c80
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Nov 2 09:19:46 2025 +0100
+
+    [indirect.assign] Replace incorrect "_t" with "_v" in Mandates
+
+commit cc53316dfe22765154a025462261dfd007be7a93
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Mon Nov 3 01:41:03 2025 -0400
+
+    [bit.cast] Adjust cross-reference for definition of consteval-only type (#8391)
+
+commit cedfad4418057ccc2e79eae26d22c0e567e1ce8f
+Author: Eisenwave <me@eisenwave.net>
+Date:   Mon Nov 3 15:25:41 2025 +0100
+
+    [const.wrap.class] Add constant_wrapper to index
+
+commit 749103f9d1fee0d04d4921ae7bb51c1ca47b73cd
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Jul 31 08:53:59 2025 -0400
+
+    [pre] No names in the preprocessor
+
+    The term "name" applies specifically to entities in phase 7
+    of translation.  Macros have macro names, headers are parsed
+    as *header-name*s, etc.
+
+commit 75e3e48524c21e179535177c96c4ad80fe6e7f81
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Nov 3 14:38:09 2025 +0100
+
+    [set.difference] Fix sentence
+
+    A misapplication of P3179R9.
+
+    Fixes NB US 165-264 (C++26 CD).
+
+commit 842616437ca1a6efd0c01ba37bafee3a9fd85967
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Nov 3 15:16:34 2025 +0100
+
+    [meta.reflection] Move examples to the end of their respective section
+
+    Fixes NB US 83-152 (C++26 NB).
+
+commit 1844b9d9d27d39f0cd2c05e1ecc738f11e2c8845
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Nov 3 16:09:06 2025 +0100
+
+    [execution.syn] Reorder entries to match subclause order
+
+    Fixes NB US 201-322 (C++26 CD).
+
+commit 019260f1fabe96078e7b331c41485558c7ea5eee
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Nov 3 14:46:27 2025 +0100
+
+    [const.wrap.class] Remove superfluous parameter in trailing requires clause
+
+    Fixes NB US 80-148 (C++26 CD).
+
+commit ab094f1a706c73c3da3d7bd0061a62ff632cb1ad
+Author: Eisenwave <me@eisenwave.net>
+Date:   Mon Nov 3 18:42:57 2025 +0100
+
+    [cmath.syn] Add fmaximum, fmaximum_num, fminimum, and fminimum_num to index
+
+commit ca8bf9ae97d48ed3a6024511f79d306fd2da83de
+Author: Eisenwave <me@eisenwave.net>
+Date:   Mon Nov 3 18:53:20 2025 +0100
+
+    [basic.fundamental] Use "std::" prefix consistently for library type aliases
+
+commit 726f6860757a35b1037202454f4656195964cfb0
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Nov 4 11:58:41 2025 +0800
+
+    [re.regex.general] Fix indentation for members of `basic_regex` (#8399)
+
+commit f5ab0cbe8b939538427caa7cec139ca59afc186f
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Nov 4 15:11:01 2025 +0100
+
+    [queue.defn] Remove superfluous whitespaces (#8401)
+
+commit 35696224964df56c0e01fe1c1127dc41555d6556
+Author: Eisenwave <me@eisenwave.net>
+Date:   Tue Jun 4 17:11:54 2024 +0200
+
+    [basic.indet] Convert reference to [conv.lval] into note
+
+commit acab9e553267137d6ac25e5568bafce734b70257
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Nov 4 06:31:59 2025 -1000
+
+    [container.adaptors.general] Remove using typename from expos-only alias template
+
+commit ad99d5224a03821bcff46081195fed20f0afee31
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Nov 2 20:57:23 2025 +0100
+
+    [simd] Synchronize synopsis references with subclause headings
+
+    Fixes NB US 181-294 (C++26 CD).
+
+commit 5a445cf41b9deab8412c0d6a8c61a7ff3f41645a
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Tue Nov 4 11:11:23 2025 -1000
+
+    [library] Remove references to typedef-name
+
+    Fixes NB US 62-114 (C++26 CD).
+
+commit a1e15352cc6115024fe5cf92901497a2fad92786
+Author: Damien L-G <dalg24+github@gmail.com>
+Date:   Tue Nov 4 14:42:31 2025 -1000
+
+    [atomics.ref.pointer] Do not refer to T (#8413)
+
+    Fixes NB US 195-313 (C++26 CD).
+
+commit b560873553e304cbc76d8f883f29371d97525aef
+Author: Damien L-G <dalg24@gmail.com>
+Date:   Tue Nov 4 15:56:23 2025 -1000
+
+    [atomics.syn] Simplify synopsis using "mostly freestanding" (#8411)
+
+    Mark the `<atomic>` header `// mostly freestanding`, remove all the
+    `// freestanding` comments, and add `// hosted` comments for
+    `atomic_signed_lock_free` and `atomic_unsigned_lock_free`.
+
+    Fixes NB US 191-307 (C++26 CD).
+
+commit 230067ea57ca080c89010ffac8750a114068f8e3
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Tue Nov 4 15:47:21 2025 -1000
+
+    [exec.snd.expos] Move Remarks into itemdescr
+
+commit a7b71b33710c3fc7e22c6ed169581d242b839f28
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sun Jul 27 11:23:47 2025 -0400
+
+    [dcl.inline] inline specifier is for ODR
+
+    The key use of the inline specifier since C++11, if not before,
+    has been to allow multiple declarations to satisfy the ODR rather
+    than to provide a hint that compilers routinely ignore.
+
+    This change moves but does not change wording, in order to move
+    the comment making the connection with the ODR more prominent
+    than the normative wording suggestings core transformation.
+
+    It might be desirable to demote the normative coding hint to
+    a note, but that goes beyond the remit of a simple editorial
+    chsnge.
+
+commit f731f304049a1b26a0be369ac89988910b6d52ee
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Nov 4 14:37:27 2025 -1000
+
+    [lex.pptoken] Simplify sentences with common cause
+
+commit ba59ef5f76a3d45add0f70322a1dad57109f17d5
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Nov 5 05:43:47 2025 -1000
+
+    [alg.find.first.of] Rename subclause title (#8428)
+
+    Fixes NB US 158-256 (C++26 CD).
+
+commit 6d884babd1e6dc956d795c404525248d31028e46
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Nov 5 16:17:54 2025 +0100
+
+    [expr.const] Unmark introduction of "constant expression" as definition
+
+commit f4c608518c77fad9f28a864c517c442c186037c4
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Nov 6 00:42:50 2025 +0800
+
+    [linalg.transp.layout.transpose] Fix misplaced data members of `layout_transpose::mapping` (#8423)
+
+    The intent is that _`nested-mapping_`_ and _`extents_`_ belong to
+    `layout_transpose::mapping` but not `layout_transpose`. This was a
+    mistake in the original paper P1673R13, confirmed by the author, and
+    it can also be inferred from their usages.
+
+commit c84e2cbcd13536a8083d4b3b1788f1b411a2334e
+Author: Jakub Jelinek <jakub@redhat.com>
+Date:   Wed Nov 5 14:40:13 2025 +0100
+
+    [expr.const] Use different classes for unrelated parts of the example
+
+commit 9f7a711b52aee884594eb4e01cc770ba071fffb0
+Author: Hana Dusíková <hanicka@hanicka.net>
+Date:   Thu Nov 6 03:43:58 2025 +0900
+
+    [class] removing redundant "constexpr-suitable" wording (#8108)
+
+    Constructors and destructors can't be coroutines (since P3533R2),
+    therefore they are always constexpr-suitable, and any wording
+    that states this explicitly is not needed and is removed in this change.
+
+commit ff9797db1da40fff8cf4710c845331e0b56d275b
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Tue Nov 4 16:16:37 2025 -1000
+
+    [task.class] Improve error_types wording
+
+    Fixes NB US 247-377 (C++26 CD).
+
+commit 23c89d40df26c387e5b6bd171189f18d6355b0b3
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Nov 5 22:52:36 2025 -1000
+
+    [cpp.pre] Apply unicode markup (#8410)
+
+commit 2847e62c3440302c3694db06cf4795bbcf3e8951
+Author: Braden Ganetsky <braden.ganetsky@gmail.com>
+Date:   Wed Nov 5 18:07:36 2025 -1000
+
+    [exec.bulk] Fix structured binding presentation
+
+    Fixes NB US 222-340 (C++26 CD).
+
+commit 18c441799049759c5a18afb9b89725ef3d86b977
+Author: Braden Ganetsky <braden.ganetsky@gmail.com>
+Date:   Wed Nov 5 17:54:01 2025 -1000
+
+    [meta.reflection.layout] Reverse logic in specification
+
+    Fixes NB US 106-167 (C++26 CD).
+
+commit 1e37bdba0c01da86b3012f9b4249e242103bea6a
+Author: Eisenwave <me@eisenwave.net>
+Date:   Thu Nov 6 11:48:52 2025 +0100
+
+    [meta.syn] Synchronize reflect_constant/reflect_object parameters with definition
+
+commit 50ded6933a01226babb7f15b95784012a59cb046
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Nov 6 17:48:21 2025 +0100
+
+    [exec.run.loop] Reword references to "count" and "state" (#8307)
+
+    "Count" and "state" are locally defined notions, not actual (exposition-only) variables.
+
+    Fixes NB US 231-361 (C++26 CD).
+
+commit 7693f862e21e36076fef3c190de83751d28103c2
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Nov 6 10:39:41 2025 -1000
+
+    [character.seq.general, time.general] Define STATICALLY-WIDEN in a better place
+
+    The facility is now used from two different places ([time] and
+    [format]) and is now better defined in the library introduction.
+
+commit 76b2c464a2d1e737ab126fb2291b7ea5d483d36e
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Wed Dec 25 16:15:29 2024 +0000
+
+    [tab:cpp17.destructible] Use the correct placeholder in requirement
+
+commit 7ba83f99fd4e060bbb607463eb994b0df49caef4
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Nov 7 01:04:07 2025 +0100
+
+    [{multimap,multiset,set}.overview] Fix typos of constructors (#8237)
+
+commit b931610d0a6116a214b120b20dfd1475593be0cd
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Feb 13 20:32:10 2025 +0000
+
+    [mdspan.layout.{left,right}pad] Fix malformed expression
+
+commit b9571b87d5de5ecdeb83a184efc7585ef6b13429
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Nov 6 14:54:10 2025 -1000
+
+    [func.wrap.ref.class] Fix use of template parameter name "ArgTypes".
+
+    Also use a codeblock to make the code presentation a bit tidier,
+    and add descriptive nouns before symbolic references.
+
+commit a451a97aafaae586df5b4f09df6ec168fb0a31c1
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Nov 2 10:36:06 2025 +0100
+
+    [simd.alg] Avoid the word "shall" in Preconditions
+
+commit bb1af1aeb02eb9bc75e430e25b4143b54eb9fcf4
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Jul 19 13:39:23 2025 +0200
+
+    [meta.reflection.member.queries] Add commas
+
+commit 17b6a3fa096663954a5737e8d6e0447fc4392da9
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Fri Jul 18 11:39:48 2025 -0400
+
+    [basic.link] Fix cross-reference to translation unit
+
+    Tranalation units are defined in phase 7 of translation,
+    [lex.phases] not [lex.separate].
+
+commit f65ab95e4f443cd0ab467d494513b606301acd98
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Nov 6 16:20:43 2025 -1000
+
+    [utilities] Use "Result:" element in \itemdescrs of types to describe the type.
+
+    This replaces the use of the ad-hoc element "Type:" in three places with "Result:",
+    and adds "Result:" in other cases that didn't have an element at all.
+
+commit 35a6fb8ce7ee7dc95f8930804a23964827c889da
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Nov 7 08:26:54 2025 +0100
+
+    [intro.scope] Modernize by removing overly verbose description
+
+    Fixes NB GB01-013 (C++26 CD).
+
+commit 8d375c7cdc626c252788547f10a060f10cb82dcf
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sun Nov 9 04:44:50 2025 +0100
+
+    [exec.run.loop.members] Remove extraneous period (#8451)
+
+commit f2b0254e2dd7428f1a160a04e1d11c467eb331ca
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Nov 8 17:52:30 2025 -1000
+
+    [mdspan.sub.map.{left,right}] Fix typos: "layout_left" => "layout_right", "_rank" => "rank_"
+
+    This was a misapplication of P2642R6.
+
+    Also improves linebreaking for clarity.
+
+commit fad2722986e8cb9bee11d94fc15afb088b3fa940
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Nov 9 13:09:31 2025 +0000
+
+    [temp.names] Restore braced-init-list in definition of template-argument
+
+    It was unintentionally deleted by commit
+    e3f552ff09eb42cec8ee0590e4b8aa716996b282.
+
+commit 605dcaa51e45a9b55dedea2ab88f593dd590f6a5
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Nov 8 23:31:49 2025 +0100
+
+    [inplace.vector.modifiers] Ensure correct type of returned iterator
+
+commit 99e4ffd66b61fce502e319b4ade56df7373301ef
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Nov 10 23:44:35 2025 +0800
+
+    [dcl.pre] Fix grammatical error in lambda trailing-return-type (#8497)
+
+    This seems to be an error in P2996R13.
+
+commit 15c21a586c5bc67917256d03ce89c9a43e5a4cee
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Sun Nov 9 23:39:45 2025 -0500
+
+    [except.handle] Mark as note: exception object access via handler decl
+
+    The subject paragraph is merely an observation and is redundant as
+    normative text. Make it a note, and strike the end of the last sentence
+    as it creates an impression that the exception object cannot be observed
+    without rethrowing.
+
+commit 2a7f36abe6e93e9c5f750df000ab4ea781580d39
+Author: Luc Grosheintz <luc.grosheintz@gmail.com>
+Date:   Thu Sep 4 15:49:24 2025 +0200
+
+    [mdspan.layout.left.cons] Fix typo in precondition.
+
+    Here `other` is a layout mapping and layout mappings don't have this API
+    to access the `i`th extent. They only have `extents()` to get the
+    std::extents object.
+
+commit 8ee8d2d0292dde2ca72c300177752f4a2e4457df
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Wed Nov 12 17:01:53 2025 +0800
+
+    [cpp.predefined] Sort `__cpp_consteval` before `__cpp_constexpr` (#8504)
+
+commit 9770db7bf288ad56ae98bdabd19935decab9da9f
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Wed Nov 12 17:02:48 2025 +0800
+
+    [version.syn] Sort `__cpp_lib_format_path` before `__cpp_lib_format_ranges` (#8505)
+
+commit ccf746ffbabd5f74dece4a983cd52bd31b999f0a
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Tue Nov 11 01:07:29 2025 -0500
+
+    [class.base.init] Add "direct" for _mem-initializer-id_-named members
+
+    A _mem-initializer-id_ cannot be used to initialize a base class
+    data member from a derived class constructor; therefore, we mean
+    _direct_ non-static data member.
+
+commit e6150e3fa6d6dbbb901b4b7ccc075219d4515d5d
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Mon Nov 10 23:37:24 2025 -0500
+
+    [class.mem.general] Fix data member definition to include anonymous union members
+
+    Anonymous union members are not introduced by _member-declarator_.
+
+    Fixes cplusplus/draft#4939.
+
+commit 4d9edbf31f8ea0cb870fd0512c29756f2c4a292c
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Mon Nov 10 21:40:37 2025 -0500
+
+    [special] Add "direct" when defining "potentially constructed subobjects"
+
+    The definition has "non-static data members". Only the direct ones are
+    intended.
+
+commit 4b9d4f6a4356de8630cd8b0981c6b1960d510230
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Nov 12 19:23:00 2025 +0100
+
+    [optional.ref.assign] Add missing Returns element
+
+commit 784cc65a741dfefc95328b8bc58199bc63ea661b
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Nov 12 19:46:55 2025 +0100
+
+    [cpp.predefined] Sort __cpp_impl_reflection before __cpp_impl_three_way_comparison
+
+commit 2ab6288129c4f3708f728b0f1a492e5d72b5c821
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Nov 10 09:19:20 2025 +0800
+
+    [locale.categories] Index base classes and members of category classes
+
+    Enumerators of each unscoped enumeration type are indexed as members of
+    the enclosing class of the enumeration.
+
+commit 5e49effdce370fd445ce3218f14f37892d1f1629
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Nov 14 09:17:28 2025 +0100
+
+    [range.to.input.iterator] Move closing parentheses after @\exposid
+
+commit 19ad41dbd3446c34da01e3c5ea79ecce539ccd94
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Nov 4 19:08:45 2025 -1000
+
+    [specialized.algorithms] Remove typename after new
+
+    The `typename` keyword is not needed to identify a dependant
+    type in a `new` expression.
+
+commit 2e6b09beb01daad3d87914dfe9a0031de5816013
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Nov 8 23:05:37 2025 +0100
+
+    [cpp.predefined] Update value of __cpp_deduction_guides to 202207L
+
+commit 9ddf7e6d2937028b8c4ca99502d73d7a726ab737
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Nov 12 20:38:34 2025 +0100
+
+    [temp.arg.template] Add missing "template" when referring to template template parameters
+
+commit c097654ed3d7bf7f840c6eb8bfc10cebb74f26ea
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Nov 16 18:47:34 2025 +0100
+
+    [exec.when.all] Reverse the nesting of \exposid and \tcode for impls-for<when_all_t>::complete (#8537)
+
+commit 3e707873fffd713c9daea0bb9e6e3f3a9f5ebcd8
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Nov 16 18:50:16 2025 +0100
+
+    [atomics.types.generic.general] Replace "same_as" with "is_same_v" (#8538)
+
+commit 85128063cd29e93c28555d7a4a3b70b31c7e3337
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Nov 16 22:37:35 2025 +0100
+
+    [numerics.c.ckdint] Add cross-reference to [basic.fundamental] (#8541)
+
+commit 7eacc15f859c44eb8b8f5c955b971e95428cd07b
+Author: Eisenwave <me@eisenwave.net>
+Date:   Mon Nov 17 10:46:10 2025 +0100
+
+    [format.args] Move "Implementations should ..." part into Recommended practice paragraph
+
+commit c6da41e3ade36f51f0f8a9cbb2aebea801ceeac2
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Tue Nov 18 04:31:38 2025 +0800
+
+    [algorithm.syn] Add missing comma (#8551)
+
+commit ff706ad6a5a40831d99984e69c0245aacb9613f7
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Wed Nov 19 10:41:16 2025 +0000
+
+    [class.temporary] Change "class type" to "type"
+
+    Missed edit from P2900R14.
+
+commit 3ddbebd0eddd1b0418523e6a93864ce090d6d674
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Nov 20 22:27:47 2025 +0100
+
+    [linalg.scaled.scaledaccessor] Add scaling_factor and nested_accessor to index (#8549)
+
+commit ebd315d92ab4ddb73d6ad8b30fb131329f4b434d
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Apr 24 11:02:34 2025 +0800
+
+    [lib] Replace uses of `add_meow_t` with plain cv-qualifiers
+
+    ...except for [tab:meta.trans.cv], because the wording change for
+    `add_cv` seems a bit non-trivial, and for the return type of `as_const`,
+    because the the change would affect mangled name.
+
+commit 1175936bde2c81012c7aa3b45b3ece46c32d19ff
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Nov 29 17:21:46 2025 +0800
+
+    [container.node] Exposition-only formatting for node_handle members (#8555)
+
+    Also changes `container_node_type` and `ator_traits` to
+    `container-node-type` and `ator-traits`, respectively.
+
+    Adds missed "is `true`".
+
+commit 5b6fb19cc60d3a1b23e0124dc16a1fd69f33a40b
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Sun Nov 30 19:20:43 2025 +0800
+
+    [algorithm.syn] Fix typo (#8572)
+
+commit ca1969050e652308a38d9b2990c980cf3cf654b5
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Dec 2 11:13:11 2025 +0000
+
+    [expr.prim.id.unqual] Remove unused meta-variable (#8574)
+
+commit 417bf3b746747f80bfa9f0ee50547522685cf5da
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Dec 4 00:46:57 2025 +0100
+
+    [cmath.syn] Align function parameters of ellint_3 (#8581)
+
+commit 69fe27f02385f16a7a1070eb66797ee6d5795cb8
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Dec 4 15:07:48 2025 +0000
+
+    [range.slide.view] Fix names of reserve_hint overloads
+
+    Fixes #8585
+
+commit 371d28425eaa09138c3d1cdf34865d44ffc93fa3
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Dec 6 00:39:17 2025 +0700
+
+    [cpp.predefined] Tidy specification of __FILE__ and __LINE__ (#8584)
+
+    Promotes the footnotes to notes and adds cross-references.
+
+commit 940a063808899cde646274a185d7565fc0e09533
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Sun Dec 7 03:01:39 2025 -0400
+
+    [temp.constr.concept] Fix "no diagnostics is" (#8587)
+
+commit 0bb977830decd94822c024aff0e187d77c480f5b
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Wed Dec 10 20:06:58 2025 +0000
+
+    [basic.def.odr] Add punctuation (#8598)
+
+commit 62fc52e4d874d895d5e323421b54cfba1e568857
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Dec 11 21:52:45 2025 +0000
+
+    [basic.lookup.qual.general] Markup definition of "member-qualified name" (#8609)
+
+commit 8b2a7da97bb7779dbb060f7cd62dd9d596626ccd
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Dec 11 21:54:40 2025 +0000
+
+    [basic.lookup.elab] Replace "the" with "an" (#8612)
+
+commit 0bee9a0a02b3f5ed38ff30dc12f59bf378b0f5e5
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Apr 1 14:44:07 2025 +0000
+
+    [temp.constr.concept] Improve phrasing of note
+
+commit 284ffb85f96822d79e89124ef77e548a3f8362fb
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Nov 17 11:29:12 2025 +0800
+
+    [string] Consistently spell return types and types of data members
+
+    Affected sections:
+    - [basic.string.general] Align both overloads of `data`
+    - [basic.string.general] Use `(const_)reference` for consistency with
+    other sequence containers
+    - [string.access] Use `(const_)reference` for consistency with other
+    sequence containers
+    - [string.view.template.general] Use `const charT*` for `data` and a
+    data member, for the consistency with `basic_string`.
+    -[string.view.access] Use `const charT*` for `data` for consistency with
+    `basic_string`
+
+commit 0fa93a34dd25859212a708bbd9b5fb4f7e5d22d9
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sun Nov 2 17:13:39 2025 -1000
+
+    [module.global.frag] Remove irrelevant note about preprocessor
+
+    [module.global.frag] is entirely part of phase 7 of translation,
+    and it makes no sense to talk of preprocessing directive in the
+    grammar term *declaration-seq*.  Strike the note rather than try
+    to turn it into something meaningful.
+
+commit 967ffd74041ba52334bbb3525485bbed0a3bd6cf
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Nov 8 22:46:28 2025 +0100
+
+    [dcl.init.general] Prevent contradiction for initialization of aggregates
+
+commit 99914bdc2d932422d6c5c5e448f8d81e35dc0e97
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Dec 13 18:21:49 2025 +0700
+
+    [cpp.cond] Keywords are not identifiers while preprocessing (#8518)
+
+commit 143f3a692399843796a005508d35096225b39146
+Author: Eisenwave <me@eisenwave.net>
+Date:   Mon Nov 17 08:32:57 2025 +0100
+
+    [numerics.c.ckdint] Remove unnecessary "cv-unqualified"
+
+commit 7acb34c3ce9cffaf30da3935acbb52c38887daea
+Author: Eisenwave <me@eisenwave.net>
+Date:   Mon Nov 17 08:33:47 2025 +0100
+
+    [charconv.syn] Remove unnecessary "cv-unqualified"
+
+commit 1efa5fec0153e3682bc3c8dc99a35281ea11bb1c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Nov 29 11:01:59 2025 +0100
+
+    [expr.add] Simplify phrasing around ptrdiff_t and avoid redundancy
+
+commit 68ea567df58609cab0e41fa805b0cd55db37784c
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Dec 2 23:39:03 2025 +0700
+
+    [lex.literal.kinds] Strike incomplete footnote
+
+    It may be that the notion of literal in C++ and constant in C
+    were at one point close to a 1-1 mapping, but that it not
+    strictly the case any more.  C++ has user-defined literals,
+    in C string-literals are distinct from constants, and C
+    specifies enumerators as literals too.
+
+    Rather thsn clean up the footnote, or make clear that the
+    correspondance is weak, simply strike it.
+
+commit 3280bf769d88e21883e49f3fab41c93322e3a0f8
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Dec 13 18:27:17 2025 +0700
+
+    [intro.memory] Convert footnote on CHAR_BIT into note (#8577)
+
+    The information in the footnote is relevant to the main text.
+
+commit 6c8a056ee7d1fb3aabd9f96c8c9a03c8720e3c28
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Dec 13 18:28:00 2025 +0700
+
+    [lex.string] Remove unused term from the index (#8588)
+
+commit d5b9659a0e7e3fc68914e30ffb3b5528246828f2
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Dec 8 18:18:07 2025 +0000
+
+    [lex] Avoid "shall" when not stating a direct requirement
+
+commit 0598cb129f4160467502bfd7870f285d9124e642
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Dec 13 18:29:51 2025 +0700
+
+    [dcl.type.general] Strike irrelevant footnote (#8578)
+
+    The reference to the "implicit int" rule in C has been out-dated for a long time.
+
+commit 6db574b1f0df2e279ab658bfc57b6929d325ad9b
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Dec 9 23:40:50 2025 +0000
+
+    [basic.scope.contract] Fix typo
+
+commit 21cc64a281ba7167d7c1c596afed63dd9f64ce80
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Dec 9 23:46:38 2025 +0000
+
+    [basic.scope.param] Use "of" when referring to the containing production
+
+commit 6c240f69beeb9dc3164684c583eef03643c40abf
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Dec 9 23:23:57 2025 +0000
+
+    [basic.def.odr] Fix use of undefined term
+
+    Change "function definition scope" to "function parameter scope".
+
+commit 176d615e86a9e796cf14bd6546bfd8804984ee8d
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Dec 11 14:33:03 2025 +0000
+
+    [basic.lookup.argdep] Add missing words
+
+commit a091468825ef477a9d8110085f2963306dee9cfc
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Dec 14 13:27:11 2025 +0000
+
+    [meta.define.static] Reword list to produce a proper sentence.
+
+commit 165c05c9203171a12a2f6ad9afdd593b9ac21bd3
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sun Dec 14 19:31:46 2025 +0100
+
+    [version.syn] Sort __cpp_lib_initializer_list before __cpp_lib_inplace_vector
+
+commit 488b2fa35c373b0bd425087bf3658635ac9338a0
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sun Dec 14 22:21:01 2025 +0100
+
+    [mdspan.sub.extents] Fix typo
+
+commit 002e9784d3ebbf94288181573017860f1c3ce065
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Nov 4 15:07:50 2025 -1000
+
+    [lex.pptoken] Turn non-normative text into a note
+
+    The last part of this paragraph is non-normative, so turn it
+    into a note.  Also, the preceding sentence defining whitespace
+    characters is mostly unrelated to the precedingd defintion of
+    preprocessing tokens, so start a new paragraph to more clearly
+    show the comment assoication.
+
+commit c1fcb2b43946acb89857caf29c3cd7a95c568736
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Nov 4 12:36:34 2025 -1000
+
+    [lex.token] Strike mention of whitespace in phase 7
+
+    It is meaningless to talk of whitespace separating tokens
+    in phase 7 as whitespace is discarded at the end of phase 4.
+
+commit 08ab900f50fa30a511d38b1f7faa6715b2749a29
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Dec 2 23:02:35 2025 +0700
+
+    [lex.token] Strike useless footnote
+
+commit dd1c71e10912d1ee91c96d5a0a9f59df3f849863
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Wed Dec 10 11:34:16 2025 +0800
+
+    [expr.prim.id.unqual] Fix misplaced example
+
+commit d2fff2b231512a469b1f503722ad2136f116346c
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Dec 13 19:53:04 2025 +0100
+
+    [basic.def.odr] Remove duplicate "a"
+
+commit 93914a36c1945d330a7c7d5c4488e1d10e5bbe75
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Dec 14 07:35:31 2025 +0100
+
+    [utility.intcmp] Rephrase integer type constraint of "standard or extended" as "signed or unsigned"
+
+commit 508c4f902d4c65b80b40d7fb1f764b7b18293ef3
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Tue Nov 18 09:08:21 2025 +0100
+
+    [atomics.types.int] Use the terms "character type" and "standard integer type" instead of listing each type
+
+    Revised description of atomic class template specializations.
+
+commit b37dc196a8e4feacd5f5292022bdde90f95d7c4a
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Dec 15 08:54:51 2025 +0100
+
+    [range.reverse.overview] Add indefinite article
+
+commit 8ef4e628d6da638b5a5880df11b1bf1e2185a964
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Dec 15 12:16:12 2025 +0100
+
+    [hive.operations] Fix singular/plural mismatch (#8621)
+
+commit 9a06fbfd9379224c6efb77adab77cc3f9595b63d
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Nov 4 15:48:11 2025 -1000
+
+    [lex.charset] Move reference to glyphs to appropriate place
+
+    The statement that glyphs are used to identify members of the
+    basic character set does not belong separating two sentences
+    introducing and then defining preprocessing tokens.
+
+    Also, we do not *exlusively* use glyphs for this purpose but
+    also directly call out Unicode code points too, so tone down
+    the phrasing to glyphs are *often* used to ...
+
+commit a2289f6652c4b09811dfda76b0e0fd2208c71617
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Dec 15 11:46:12 2025 +0000
+
+    [exec.bulk, exec.spawn.future] Fix escaping and comment alignment
+
+commit 37201bf548ab64a72dee297cef56a67c88326ee3
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Dec 4 11:58:20 2025 +0700
+
+    [cpp.replace.general] Promote footnote to note
+
+    We now have a paragraph where the footnote would be more
+    appropriately attached as a note.
+
+commit 20eff244639825d616061d7155967840c337582e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Dec 15 12:11:55 2025 +0000
+
+    [iterator.range] Turn long sentence listing headers into list
+
+ + diff --git a/papers/n5033.md b/papers/n5033.md new file mode 100644 index 0000000000..2067c41193 --- /dev/null +++ b/papers/n5033.md @@ -0,0 +1,2466 @@ +# N5033 Editors' Report -- Programming Languages -- C++ + +Date: 2025-12-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` + +## Acknowledgments + +Thanks to all those who have +[submitted editorial issues](https://github.com/cplusplus/draft/wiki/How-to-submit-an-editorial-issue), +to those who have provided pull requests with fixes, +and to everyone who drafted motion applications. +Special thanks to Alisdair Meredith and Jan Schultke +for drafting a lot of motion applications, +and to Andreas Krug for ongoing careful reviews. + +## New papers + + * [N5032](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5032.pdf) is the + current working draft for C++26. It replaces + [N5014](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5014.pdf). + * N5033 is this Editors' Report. + +## Motions incorporated into working draft + +### Notes on motions + +Note the unusual numbering of CWG motions. +In particular, CWG Motion 3a is not associated +with a change to the working draft. + +In LWG Motion 1, the library issue +[LWG4300](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html#4300) +had already previously been +applied [editorially](https://github.com/cplusplus/draft/commit/4b9d4f6a4356de8630cd8b0981c6b1960d510230). + +In LWG Motions 16 and 19, the resolution of +[“NB US 227-346 and US 229-347”](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html#us-227-346-and-us-229-347) +in the latter has substantial overlap with paper +[P3815R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3815r1.html) +of the former; the changes were reconciled and integrated. + +All other motions were applied cleanly. + +### Core working group polls + +CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues +except issues 1670, 2917, 2923, 3005, 3043, 3044, 3045, 3048, 3053, 3061, 3063, 3074, +3082, 3084, 3089, 3092, 3093, 3094, 3095, 3098, 3099, 3101, 3108, 3109, 3110, 3113, +3114, 3115, 3117, and 3118 in +[P3921R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) +(Core Language Working Group “ready” Issues for the November, 2025 meeting) to the C++ Working Paper. + +CWG Poll 2. Apply the proposed resolutions of issues +2917, 2923, 3005, 3043, 3044, 3045, 3048, 3053, 3061, 3063, 3074, 3082, 3084, 3089, 3092, +3093, 3094, 3095, 3098, 3099, 3101, 3108, 3109, 3110, 3113, 3114, 3115, 3117, and 3118 in +[P3921R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) +(Core Language Working Group “ready” Issues for the November, 2025 meeting) to the C++ Working Paper. + +CWG Poll 2b. Accept as Defect Reports and apply the proposed resolutions of issue 1670 in +[P3921R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) +(Core Language Working Group “ready” Issues for the November, 2025 meeting) to the C++ Working Paper. + +CWG Poll 3a. (Not relevant; poll did not pass, and did not propose a change to the working paper.) + +CWG Poll 3b. Apply the changes in +[P3920R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) +(Wording for NB comment resolution on trivial relocation) to the C++ Working Paper. +This addresses numerous ballot comments (see paper). + +CWG Poll 4. Accept as a Defect Report and apply the changes in +[P3868R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3868r1.html) +(Allow `#line` before module declarations) to the C++ Working Paper. +This addresses ballot comment US 55-102. + +CWG Poll 5. Apply the changes in +[P3684R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3684r1.pdf) +(Fix erroneous behaviour termination semantics for C++26) to the C++ Working Paper. +This addresses ballot comment GB 02-036. + +### Library working group polls + +LWG Poll 1. Apply the changes in +[P3905R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) +(C++ Standard Library Ready Issues to be moved in Kona, Nov. 2025) to the C++ working paper. + +LWG Poll 2. Apply the changes in +[P3906R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) +(C++ Standard Library Immediate Issues to be moved in Kona, Nov. 2025) to the C++ working paper. + +LWG Poll 3. Apply the changes in +[P3016R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3016r6.html) +(Resolve inconsistencies in `begin`/`end` for `valarray` and braced initializer lists) to the C++ working paper. + +LWG Poll 4. Apply the changes in +[P3567R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3567r2.html) +(`flat_meow` fixes) to the C++ working paper. + +LWG Poll 5. Apply the changes in +[P3663R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3663r3.html) +(Future-proof `submdspan_mapping`) to the C++ working paper. +This addresses ballot comments US 66-117 and PL 009. + +LWG Poll 6. Apply the changes in +[P3914R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3914r0.html) +(Assorted NB comment resolutions for Kona 2025) to the C++ working paper. +This addresses ballot comments US 160-260, US 209-332, US 228-348, US 263-396, US 265-398, US 266-399, US 112-172, and US 130-193. + +LWG Poll 7. Apply the changes in +[P3836R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3836r2.html) +(Make `optional` trivially copyable) to the C++ working paper. +This addresses ballot comment US 134-215. + +LWG Poll 8. Apply the changes in +[P3860R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3860r1.html) +(Proposed Resolution for NB Comment GB13-309 `atomic_ref` is not convertible to `atomic_ref`) +to the C++ working paper, as a Defect Report for C++20. This addresses ballot comment GB13-309. + +LWG Poll 9. Apply the changes in +[P3388R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3388r3.pdf) +(When Do You Know `connect` Doesn’t Throw?) to the C++ working paper. + +LWG Poll 10. Apply the changes in +[P3774R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3774r1.html) +(Rename `std::nontype`, and make it broadly useful) to the C++ working paper. +This addresses ballot comments FR-021-218 and FR-019-210. + +LWG Poll 11. Apply the changes in +[P3819R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3819r0.pdf) +(Remove `evaluation_exception()` from contract-violation handling for C++26) +to the C++ working paper. +This addresses ballot comments NL, US 69-125,GB 04-124. + +LWG Poll 12. Apply the changes in +[P3612R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3612r1.html) +(Harmonize proxy-reference operations (LWG 3638 and 4187)) to the C++ working paper. + +LWG Poll 13. Apply the changes in +[P3778R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3778r0.html) +(Fix for `type_order` template definition) to the C++ working paper. + +LWG Poll 14. Apply the changes in +[P1789R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1789r3.pdf) +(Library Support for Expansion Statements) to the C++ working paper. +This addresses ballot comments NC IT-002, FR 007-011-142, CZ 2-143, US 78-144. + +LWG Poll 15. Apply the changes in +[P3922R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3922r1.pdf) +(Missing deduction guide from simd::mask to simd::vec) to the C++ working paper. +This addresses ballot comment DE-287. + +LWG Poll 16. Apply the changes in +[P3815R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3815r1.html) +(Add `scope_association` concept to P3149) to the C++ working paper. +This addresses ballot comments CA-393 and FI-392. + +LWG Poll 17. Apply the changes in +[P3878R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3878r1.html) +(Standard library hardening should not use the 'observe' semantic) to the C++ working paper. +This addresses ballot comments RU-016, FR-001-014, FR-010-113, US 3-015, and US 61-112. + +LWG Poll 18. Apply the changes in +[P3887R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3887r1.pdf) +(Make `when_all` a Ronseal Algorithm) to the C++ working paper. + +LWG Poll 19. Apply the changes in +[P3923R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) +(Additional NB comment resolutions for Kona 2025) to the C++ working paper. +This addresses ballot comments AT 7-213, US 140-233, US 141-235, US 145-234, +US 147-240, US 164-203, US 126-189, US 227-346, US 229-347, US 221-339, and US 225-341. + +LWG Poll 20. Apply the changes in +[P3371R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3371r5.html) +(Fix C++26 by making the rank-1, rank-2, rank-k, and rank-2k updates consistent with the BLAS) +to the C++ working paper. This addresses ballot comment US 168-277. + +LWG Poll 21. Apply the changes in +[P3391R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3391r2.html) +(constexpr `std::format`) to the C++ working paper. +This addresses ballot comment FR 028-271 and US 167-270. + +LWG Poll 22. Apply the changes in +[P3913R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3913r1.pdf) +(Optimize for `std::optional` in range adaptors) to the C++ working paper. +This addresses ballot comment PL-011. + +## National body comment resolution + +A large number of national body comments for the C++26 Committee Draft have been +addressed in this working draft. + +### Editorial comments + +All editorial national body comments were addressed before the Kona 2025 meeting: + + * CA 083 [322d38022bb292fbdb6d668af4ecd753eb104a53](https://github.com/cplusplus/draft/commit/322d38022bb292fbdb6d668af4ecd753eb104a53) + * FR 033-335 [776bc2892e2480fb69296cd404fc4bd5136cc44a](https://github.com/cplusplus/draft/commit/776bc2892e2480fb69296cd404fc4bd5136cc44a) + * GB 001-013 [35a6fb8ce7ee7dc95f8930804a23964827c889da](https://github.com/cplusplus/draft/commit/35a6fb8ce7ee7dc95f8930804a23964827c889da) + * US 001-405 [1e54f58f5a5cf0a283b90c0db30fff76d42efb51](https://github.com/cplusplus/draft/commit/1e54f58f5a5cf0a283b90c0db30fff76d42efb51) + * US 002-404 [fde9d1f6047ed65e52483fa40162b966628162b2](https://github.com/cplusplus/draft/commit/fde9d1f6047ed65e52483fa40162b966628162b2) + * US 012-026 [e1d47e006183ef8e2c778587b5fdcf0ce6d15da6](https://github.com/cplusplus/draft/commit/e1d47e006183ef8e2c778587b5fdcf0ce6d15da6) + * US 018-035 [0c8df65ab760e827363591f95f127de98771238b](https://github.com/cplusplus/draft/commit/0c8df65ab760e827363591f95f127de98771238b) + * US 019-037 [a019163776f16b4ed4ac9b7ec22d9b8abcd9314d](https://github.com/cplusplus/draft/commit/a019163776f16b4ed4ac9b7ec22d9b8abcd9314d) + * US 022-042 [42fad0f0b26d87235bb0cf8524de3f7628150a10](https://github.com/cplusplus/draft/commit/42fad0f0b26d87235bb0cf8524de3f7628150a10) + * US 051-095 [7c31fb08d42cb48eb2a5f63ed4406aff8f1eed4a](https://github.com/cplusplus/draft/commit/7c31fb08d42cb48eb2a5f63ed4406aff8f1eed4a) + * US 062-114 [5a445cf41b9deab8412c0d6a8c61a7ff3f41645a](https://github.com/cplusplus/draft/commit/5a445cf41b9deab8412c0d6a8c61a7ff3f41645a) + * US 064-127 [19a9248ff8c5b0008f805e0353b697a5692ea354](https://github.com/cplusplus/draft/commit/19a9248ff8c5b0008f805e0353b697a5692ea354) + * US 071-128 [42129859dd633cd3f497ef9dd80b5d1dd4b35672](https://github.com/cplusplus/draft/commit/42129859dd633cd3f497ef9dd80b5d1dd4b35672) + * US 079-146 [8fc2944d469666f68b595a47b6f2f1d38547b402](https://github.com/cplusplus/draft/commit/8fc2944d469666f68b595a47b6f2f1d38547b402) + * US 080-148 [019260f1fabe96078e7b331c41485558c7ea5eee](https://github.com/cplusplus/draft/commit/019260f1fabe96078e7b331c41485558c7ea5eee) + * US 086-157 [363c3a545ef54fe35499b26bcf438dbd8f84538d](https://github.com/cplusplus/draft/commit/363c3a545ef54fe35499b26bcf438dbd8f84538d) + * US 087-156 [5d916dc6cc99a6d548942ebf85fc1551ad4b7a84](https://github.com/cplusplus/draft/commit/5d916dc6cc99a6d548942ebf85fc1551ad4b7a84) + * US 088-163 [f8d44da79bc497b8a3ab6fc3fce728e40206922a](https://github.com/cplusplus/draft/commit/f8d44da79bc497b8a3ab6fc3fce728e40206922a) + * US 089-196 363c3a545ef54fe35499b26bcf438dbd8f84538d (see US 86-157) + * US 091-198 [eb87240307c7bb80937eda95c3077e41e096550f](https://github.com/cplusplus/draft/commit/eb87240307c7bb80937eda95c3077e41e096550f) + * US 092-199 [9793e558b81c133e1237cd96ce37171f79b63245](https://github.com/cplusplus/draft/commit/9793e558b81c133e1237cd96ce37171f79b63245) + * US 094-201 [f5c6e4ef5fd303d07a0cd691913a5317164bb5d5](https://github.com/cplusplus/draft/commit/f5c6e4ef5fd303d07a0cd691913a5317164bb5d5) + * US 096-206 [c6dc1e60202fea04b1d26769479c7063b3f867d1](https://github.com/cplusplus/draft/commit/c6dc1e60202fea04b1d26769479c7063b3f867d1) + * US 101-208 [c914b3bf857daea1c30ffbb330c0a4e5a44edc70](https://github.com/cplusplus/draft/commit/c914b3bf857daea1c30ffbb330c0a4e5a44edc70) + * US 104-165 [887c88157c52a8fb4f1acc3d49b40d4c5ef9af6c](https://github.com/cplusplus/draft/commit/887c88157c52a8fb4f1acc3d49b40d4c5ef9af6c) + * US 105-166 [65236d7d5fca9ccc8f3cff2d9c248f02f1f9d5bf](https://github.com/cplusplus/draft/commit/65236d7d5fca9ccc8f3cff2d9c248f02f1f9d5bf) + * US 106-167 [18c441799049759c5a18afb9b89725ef3d86b977](https://github.com/cplusplus/draft/commit/18c441799049759c5a18afb9b89725ef3d86b977) + * US 107-168 [c82d84c417ee6c1e0407162c487a810a2baaa562](https://github.com/cplusplus/draft/commit/c82d84c417ee6c1e0407162c487a810a2baaa562) + * US 108-169 [9bd9e43f43d669d5fd353fa390818a47a42dad18](https://github.com/cplusplus/draft/commit/9bd9e43f43d669d5fd353fa390818a47a42dad18) + * US 110-171 [e70c392421cce818ae5edc0d4fde6d94184b8a4a](https://github.com/cplusplus/draft/commit/e70c392421cce818ae5edc0d4fde6d94184b8a4a) + * US 111-174 [be1585aeff253d6d87e41f08a4e617e96ac0e17a](https://github.com/cplusplus/draft/commit/be1585aeff253d6d87e41f08a4e617e96ac0e17a) + * US 113-173 [c53c1789779b1f6ccd95d0ab27aca50658830b07](https://github.com/cplusplus/draft/commit/c53c1789779b1f6ccd95d0ab27aca50658830b07) + * US 115-176 [63c59140eda9f020f1d516657d2c1ab25c5a2d2d](https://github.com/cplusplus/draft/commit/63c59140eda9f020f1d516657d2c1ab25c5a2d2d) + * US 117-178 [ffd997cb108c7b3be749ba1abb4ac727117f65ee](https://github.com/cplusplus/draft/commit/ffd997cb108c7b3be749ba1abb4ac727117f65ee) + * US 119-180 363c3a545ef54fe35499b26bcf438dbd8f84538d (see US 86-157) + * US 123-187 [9add78e448d5900d57f4e15da2f08eaceedab419](https://github.com/cplusplus/draft/commit/9add78e448d5900d57f4e15da2f08eaceedab419) + * US 156-254 [9d74d451e7ea2cf09e71f09b9e283047d713eab6](https://github.com/cplusplus/draft/commit/9d74d451e7ea2cf09e71f09b9e283047d713eab6) + * US 158-256 [ba59ef5f76a3d45add0f70322a1dad57109f17d5](https://github.com/cplusplus/draft/commit/ba59ef5f76a3d45add0f70322a1dad57109f17d5) + * US 165-264 [75e3e48524c21e179535177c96c4ad80fe6e7f81](https://github.com/cplusplus/draft/commit/75e3e48524c21e179535177c96c4ad80fe6e7f81) + * US 175-281 [45dca420c08b9ce05b58140bc0572ff65dc24a1f](https://github.com/cplusplus/draft/commit/45dca420c08b9ce05b58140bc0572ff65dc24a1f) + * US 177-284 [bab708de50b834d5144cef2d2fb0872954ca47b9](https://github.com/cplusplus/draft/commit/bab708de50b834d5144cef2d2fb0872954ca47b9) + * US 179-293 [f3778a37d4a5c40f2ecc64b6ed47e3b8548b1eb6](https://github.com/cplusplus/draft/commit/f3778a37d4a5c40f2ecc64b6ed47e3b8548b1eb6) + * US 181-294 [ad99d5224a03821bcff46081195fed20f0afee31](https://github.com/cplusplus/draft/commit/ad99d5224a03821bcff46081195fed20f0afee31) + * US 182-296 [41c80d6cb744df0c8c409d3d72228c57fbf9d6cd](https://github.com/cplusplus/draft/commit/41c80d6cb744df0c8c409d3d72228c57fbf9d6cd) + * US 183-290 [8525f9150a7fe8c63fb593b65b80b09b55f94f30](https://github.com/cplusplus/draft/commit/8525f9150a7fe8c63fb593b65b80b09b55f94f30) + * US 185-299 [597cc85b49cfed8daab129fceca2c8d78b58dc6c](https://github.com/cplusplus/draft/commit/597cc85b49cfed8daab129fceca2c8d78b58dc6c) + * US 186-300 [2dbfcc5c7a759d6fbd6c09ecbc7f4439cc4eb5f5](https://github.com/cplusplus/draft/commit/2dbfcc5c7a759d6fbd6c09ecbc7f4439cc4eb5f5) + * US 188-303 [fb46e16c6ce0d91c6bd21ca497d1823c997d1926](https://github.com/cplusplus/draft/commit/fb46e16c6ce0d91c6bd21ca497d1823c997d1926) + * US 190-305 [ca77cdb10021c757b0fbe4d83b5991ac7d935db8](https://github.com/cplusplus/draft/commit/ca77cdb10021c757b0fbe4d83b5991ac7d935db8) + * US 191-307 [b560873553e304cbc76d8f883f29371d97525aef](https://github.com/cplusplus/draft/commit/b560873553e304cbc76d8f883f29371d97525aef) + * US 192-312 [196df1a7a97c0f11286816baa22d365d202db8ad](https://github.com/cplusplus/draft/commit/196df1a7a97c0f11286816baa22d365d202db8ad) + * US 194-314 [7c829315eb135f4df6326e35974c41983dc18ffd](https://github.com/cplusplus/draft/commit/7c829315eb135f4df6326e35974c41983dc18ffd) + * US 195-313 [a1e15352cc6115024fe5cf92901497a2fad92786](https://github.com/cplusplus/draft/commit/a1e15352cc6115024fe5cf92901497a2fad92786) + * US 196-315 [7e30ea001b274cc74dc165e32e3908bd6d13a54a](https://github.com/cplusplus/draft/commit/7e30ea001b274cc74dc165e32e3908bd6d13a54a) + * US 197-316 [3b14ec1d5f19882e628bfa09b96eeaeebdb622b7](https://github.com/cplusplus/draft/commit/3b14ec1d5f19882e628bfa09b96eeaeebdb622b7) + * US 198-317 [b1949378f3174e8177890dac5fff62cc7ffdc0e3](https://github.com/cplusplus/draft/commit/b1949378f3174e8177890dac5fff62cc7ffdc0e3) + * US 199-324 [5ba4be405536256e4498086dc78e1013e7b06920](https://github.com/cplusplus/draft/commit/5ba4be405536256e4498086dc78e1013e7b06920) + * US 200-323 [47992d448b6cb6f31e78d27193853b6dd4783fb0](https://github.com/cplusplus/draft/commit/47992d448b6cb6f31e78d27193853b6dd4783fb0) + * US 201-322 [1844b9d9d27d39f0cd2c05e1ecc738f11e2c8845](https://github.com/cplusplus/draft/commit/1844b9d9d27d39f0cd2c05e1ecc738f11e2c8845) + * US 204-321 [bfcdd7250785909bc2fdd9eeb381680129ec9628](https://github.com/cplusplus/draft/commit/bfcdd7250785909bc2fdd9eeb381680129ec9628) + * US 208-333 [0b085787cb519c8904e951f5fd23e1d4df5b7682](https://github.com/cplusplus/draft/commit/0b085787cb519c8904e951f5fd23e1d4df5b7682) + * US 212-352 [969776f2676316422ae1e7c92718326efa3c357f](https://github.com/cplusplus/draft/commit/969776f2676316422ae1e7c92718326efa3c357f) + * US 216-357 [122cc4abe30c0cdc39e7f7d4d09222ddfc298292](https://github.com/cplusplus/draft/commit/122cc4abe30c0cdc39e7f7d4d09222ddfc298292) + * US 217-359 [cd66127ccb165d4d0fcfb1594475a12600986697](https://github.com/cplusplus/draft/commit/cd66127ccb165d4d0fcfb1594475a12600986697) + * US 218-349 [40c2499440d42ac93e889bb7604173f01abb50a7](https://github.com/cplusplus/draft/commit/40c2499440d42ac93e889bb7604173f01abb50a7) + * US 222-340 [2847e62c3440302c3694db06cf4795bbcf3e8951](https://github.com/cplusplus/draft/commit/2847e62c3440302c3694db06cf4795bbcf3e8951) + * US 223-343 [ae124b4ce071453365f5b89fcb815ee731fdd2f8](https://github.com/cplusplus/draft/commit/ae124b4ce071453365f5b89fcb815ee731fdd2f8) + * US 231-361 [50ded6933a01226babb7f15b95784012a59cb046](https://github.com/cplusplus/draft/commit/50ded6933a01226babb7f15b95784012a59cb046) + * US 241-371 [0bce45bb287307c828c69fee1942da0c17793a15](https://github.com/cplusplus/draft/commit/0bce45bb287307c828c69fee1942da0c17793a15) + * US 247-377 [ff9797db1da40fff8cf4710c845331e0b56d275b](https://github.com/cplusplus/draft/commit/ff9797db1da40fff8cf4710c845331e0b56d275b) + * US 248-378 [95a10a601b3e2c33713724b514b47162fefa73ef](https://github.com/cplusplus/draft/commit/95a10a601b3e2c33713724b514b47162fefa73ef) + * US 259-380 [13a5c431dde2bff1ee02fa655806ffaedfc1b70f](https://github.com/cplusplus/draft/commit/13a5c431dde2bff1ee02fa655806ffaedfc1b70f) + * US 260-390 [e7e5b69c13ce5c358065fd989d64c4253693d415](https://github.com/cplusplus/draft/commit/e7e5b69c13ce5c358065fd989d64c4253693d415) + * US 262-394 [a7e6101939985870e128b742c616e5c6da357b2b](https://github.com/cplusplus/draft/commit/a7e6101939985870e128b742c616e5c6da357b2b) + * US 264-397 [1fcd55fceb8aca33f2e4d82c577aa47e94bb0e93](https://github.com/cplusplus/draft/commit/1fcd55fceb8aca33f2e4d82c577aa47e94bb0e93) + * US 266-399 [42793d0ce36d4fe09a4c7ebdceeadef2e343fee4](https://github.com/cplusplus/draft/commit/42793d0ce36d4fe09a4c7ebdceeadef2e343fee4) + * US 269-406 [6f3ef53700441dd46c369ab9e4a14e722206ffc6](https://github.com/cplusplus/draft/commit/6f3ef53700441dd46c369ab9e4a14e722206ffc6) + +### Non-editorial comments + +The following national body comments were addressed by the motions approved at the Kona 2025 meeting: + + * AT 003-098 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * AT 004-099 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * AT 004-099 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * AT 007-213 via [LWG Poll 19](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) + * BDS 002-034 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * CA 040 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * CA 041 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * CA 045 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * CA 092 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * CA 104 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * CA 133 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * CA 136 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * CA 137 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * CA 329 via [LWG Poll 9](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3388r3.pdf) + * CA 334 via [LWG Poll 9](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3388r3.pdf) + * CA 393 via [LWG Poll 16](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3815r1.html) + * CN (write-in) via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * CZ 002-143 via [LWG Poll 14](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1789r3.pdf) + * DE 285 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * DE 287 via [LWG Poll 15](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3922r1.pdf) + * DE 288 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * DE 297 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * DE 298 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * FI 392 via [LWG Poll 16](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3815r1.html) + * FR 001-014 via [LWG Poll 17](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3878r1.html) + * FR 002-025 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * FR 007-011 via [LWG Poll 14](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1789r3.pdf) + * FR 010-113 via [LWG Poll 17](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3878r1.html) + * FR 019-210 via [LWG Poll 10](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3774r1.html) + * FR 021-218 via [LWG Poll 10](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3774r1.html) + * FR 028-271 via [LWG Poll 21](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3391r2.html) + * FR 032-330 via [LWG Poll 9](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3388r3.pdf) + * FR 155 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * GB 002-036 via [CWG Poll 5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3684r1.pdf) + * GB 004-124 via [LWG Poll 11](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3819r0.pdf) + * GB 013-309 via [LWG Poll 8](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3860r1.html) + * IT 002 via [LWG Poll 14](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1789r3.pdf) + * NL (write-in) via [LWG Poll 11](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3819r0.pdf) + * PL 005 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * PL 009 via [LWG Poll 5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3663r3.html) + * PL 011 via [LWG Poll 22](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3913r1.pdf) + * RU 016 via [LWG Poll 17](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3878r1.html) + * US 003-015 via[LWG Poll 17](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3878r1.html) + * US 006-020 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 007-019 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 009-024 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * US 010-023 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * US 015-032 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 021-038 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 023-043 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 027-059 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 029-062 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 030-061 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 034-067 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 035-066 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 036-069 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 039-076 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 041-079 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 043-080 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 044-082 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * US 045-081 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * US 046-085 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * US 047-084 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * US 050-091 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 053-097 via [CWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) (mistakenly spelled "US 097" in P3921R0) + * US 055-102 via [CWG Poll 4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3868r1.html) + * US 060-110 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + * US 061-112 via [LWG Poll 17](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3878r1.html) + * US 065-116 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 066-117 via [LWG Poll 5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3663r3.html) + * US 069-125 via [LWG Poll 11](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3819r0.pdf) + * US 073-131 via [CWG Poll 3b](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3920r0.html) + * US 076-139 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 078-144 via [LWG Poll 14](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1789r3.pdf) + * US 097-203 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 099-205 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 102-209 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 109-170 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 112-172 via [LWG Poll 6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3914r0.html) + * US 114-175 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 118-179 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 120-181 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 121-182 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 125-188 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 126-189 via [LWG Poll 19](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) + * US 127-190 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 130-193 via [LWG Poll 6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3914r0.html) + * US 134-215 via [LWG Poll 7](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3836r2.html) + * US 140-233 via [LWG Poll 19](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) + * US 141-235 via [LWG Poll 19](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) + * US 145-234 via [LWG Poll 19](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) + * US 147-240 via [LWG Poll 19](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) + * US 154-252 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 155-253 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 159-259 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 160-260 via [LWG Poll 6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3914r0.html) + * US 161-258 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 162-261 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 163-262 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 164-263 via [LWG Poll 19](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) + * US 167-270 via [LWG Poll 21](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3391r2.html) + * US 168-277 via [LWG Poll 20](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3371r5.html) + * US 169-276 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 170-278 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * US 171-274 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * US 172-275 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * US 174-282 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * US 193-311 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 206-325 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 209-332 via [LWG Poll 6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3914r0.html) + * US 211-351 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 214-355 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 215-356 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 219-350 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 220-344 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 221-339 via [LWG Poll 19](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) + * US 224-342 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 225-341 via [LWG Poll 19](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) + * US 227-346 via [LWG Poll 19](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) + * US 228-348 via [LWG Poll 6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3914r0.html) + * US 229-347 via [LWG Poll 19](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3923r0.html) + * US 230-360 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 237-369 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * US 239-367 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 240-370 via [LWG Poll 2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3906r0.html) + * US 243-376 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * US 244-375 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * US 250-389 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * US 251-388 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * US 252-387 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * US 258-381 via [LWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3905r0.html) + * US 263-396 via [LWG Poll 6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3914r0.html) + * US 265-398 via [LWG Poll 6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3914r0.html) + * US 266-399 via [LWG Poll 6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3914r0.html) + * US 267-401 via [CWG Poll 1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3921r0.html) + +## Editorial changes + +### Major editorial changes + +There have not been any major editorial changes. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N5008 is below. This +list excludes changes that do not affect the body text or only affect whitespace +or typeface. For a complete list including such changes (or for the actual +deltas applied by these changes), consult the +[draft sources on GitHub](https://github.com/cplusplus/draft/compare/n5014...n5032). + + commit 7ff7a571b82550f2d099ad982b010d7749ed51f7 + Author: Dmitriy Sobolev + Date: Thu Aug 14 17:45:59 2025 +0100 + + [specialized.algorithms] Fix a typo: iter_difference_t -> iter_difference_t (#8143) + + A misapplication of P3179R9. + + commit 4df4951bd456cc473643fa5d434ce5bf789f0f54 + Author: S. B. Tam + Date: Sat Aug 2 13:36:14 2025 +0800 + + [locale.operators] Qualify `collate` + + commit c4eaf7276f43642b414ba9bd01a9112b6f792ad2 + Author: Alisdair Meredith + Date: Fri Aug 1 08:36:53 2025 -0400 + + [lex.phases] Identifiers do not have linkage, names do + + commit 939c73b400a418643c2e1885137a8baea04943d8 + Author: Alisdair Meredith + Date: Thu Aug 14 15:08:44 2025 -0400 + + [lex.phases, lex.token] Provide unicode name for control characters (#7404) + + commit 8fe775ad322ed8837ec4d4bed55e6074c684930a + Author: SainoNamkho <23036788+SainoNamkho@users.noreply.github.com> + Date: Fri Aug 15 03:51:41 2025 +0800 + + [dcl.init.ref] Fix misapplication of CWG2879 (#8147) + + commit 2ad9269583a4d62765e94154c7e97624083c21fe + Author: A. Jiang + Date: Fri Aug 15 13:37:12 2025 +0800 + + [span.syn] Fix typo of `remove_cvref_t` + + commit 51a5bbae2fd449a7217d935ac069187b23fb6d22 + Author: A. Jiang + Date: Fri Aug 15 17:05:43 2025 +0800 + + [optional.optional.ref.general] Fix reference to [optional.ref.iterators] + + Currently the comment mistakenly refer to [optional.iterators], while [optional.ref.iterators] should be referred to instead. + + commit 50930e22025e115d2c24451d4ba289f302020eee + Author: Frank Birbacher + Date: Fri Aug 15 13:08:42 2025 +0200 + + [meta.reflection.queries]/4.3 Fix syntax in example (#8152) + + A misapplication of P2996R13. + + commit 6a6fb0655eeabbdf526b74e65016e0be5eb6f4b3 + Author: Frank Birbacher + Date: Fri Aug 15 13:10:17 2025 +0200 + + [meta.reflection.queries]/1 Use info return type (#8153) + + A misapplication of P2996R13. + + commit a44930586b09a269fbe5def4d9821239a23b6d6b + Author: Frank Birbacher + Date: Fri Aug 15 13:16:55 2025 +0200 + + [hive.cons] Add noexcept to move constructor (#8154) + + The synopsis specifies noexcept for this constructor (and the effects + don't invoke behavior that could throw), so the missing noexcept on the + \itemdecl looks like an oversight in P0447R28. + + commit a3bdbd11810a24fe3edc7aef9dc8ac39e796e303 + Author: Frank Birbacher + Date: Fri Aug 15 18:47:33 2025 +0200 + + [expr.const] Add splice-specifier to list of converted constant expressions (#8161) + + This is a back-reference, because [expr.splice] refers to here already. + + commit d9b6f26dd6f92de0cd4ab3cd94d3a7daa44d3021 + Author: morinmorin + Date: Mon Aug 18 20:04:47 2025 +0900 + + [back] Fix journal article entries in bibliography + + This change applies the following corrections. + - Corrects misspelling of name to R. Clint Whaley. + - Adds missing page numbers. + + commit 648267c99a7a226b3a7433335e6136f70676d8d4 + Author: Rageking8 <106309953+Rageking8@users.noreply.github.com> + Date: Sat Aug 16 18:43:40 2025 +0800 + + [rand.dist.norm.f] Fix typo + + commit d13a034038e4956e02a6ab58f56109d109fab591 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Aug 18 16:45:22 2025 +0200 + + [unord.set.overview] Add "and" at end of list (#8167) + + commit 611d2ecc07a39403311783b5862df6319447eb7f + Author: Rageking8 <106309953+Rageking8@users.noreply.github.com> + Date: Tue Aug 19 04:35:05 2025 +0800 + + [simd.syn] Remove duplicate `using simd::abs;` (#8163) + + commit 430b1b20565310bea11906ae8eabf746c0f7b8c5 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Aug 19 08:49:07 2025 +0200 + + [atomics.types.float] Fix typo + + commit 675155b5ab52d101de297a150120dccaedec2735 + Author: A. Jiang + Date: Thu Aug 21 14:58:47 2025 +0800 + + [stringbuf.members] Remove `// exposition only` from `itemdecl` (#8179) + + commit 171454e98de36de7f9f3b7dfea241be79fc96ec7 + Author: A. Jiang + Date: Thu Aug 21 13:32:14 2025 +0800 + + [locale.facet] Avoid improperly defining `explicit` + + commit 41014b4db993215816a2d855d161f7136b59a3db + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Aug 21 14:17:40 2025 +0200 + + [multiset.overview] Add "and" at end of list (#8182) + + commit 1bccf914e4ec88fd3b2dc4e54c9053f46349176f + Author: Alisdair Meredith + Date: Tue Aug 26 11:57:14 2025 -0400 + + [basic.def] Better link do defintion of declaration (#8191) + + The plain text term in this sentence refer to the definition in [basic.pre] + and not the grammar production defined in [dcl]. + + commit e593dc1a1f54d6e22179c26e246ded4e7dcf9588 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Aug 27 22:42:37 2025 +0200 + + [exec.counting.scopes.general] Fix typo (#8193) + + commit b1093176914ce5ec0be3b2e02e5ff5e3c4f5e3f6 + Author: Alisdair Meredith + Date: Thu Aug 28 12:30:14 2025 -0400 + + [basic.pre] Clarify that *declaration*s are not declarations (#8187) + + * [basic.pre] Clarify that *declaration*s are not declarations + + The grammar production _declaration_ is distinct from the term "declaration" defined in [basic.pre]. + + commit 73ba7d1d81f6ef8bf92683c9071f0c4fc8afe7ad + Author: Rageking8 + Date: Fri Aug 29 00:31:47 2025 +0800 + + [meta] Fix several typos (#8157) + + commit 0b4ceb5dc35ebc736bfeb99ae629fdb0622ddf27 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sun Aug 31 19:26:32 2025 +0200 + + [tab:meta.unary.prop] Fix punctuation (#8197) + + commit bed3aab4b763ee5077d5cab997c020e389fc8092 + Author: A. Jiang + Date: Thu Sep 11 21:16:36 2025 +0800 + + [lex.phases] Fix typo in "instantiation" (#8223) + + commit 8d0144fc2e7ee8a1b38e9a69375fdedc430ec154 + Author: Hewill Kang + Date: Mon Sep 15 15:23:18 2025 +0800 + + [func.wrap.move.class, func.wrap.copy.class] Fix singular and plural in subclause titles (#8232) + + commit ed15cb52358664ae8a5b4c1df366dd2056c144e4 + Author: EienMiku + Date: Tue Sep 16 18:43:45 2025 +0800 + + [map.overview] Fix typo of constructor of map + + commit c85cdf2d0bc4a559d4092575b70025f259a68c22 + Author: Jan Schultke + Date: Sat Sep 27 10:52:22 2025 +0200 + + [meta.reflection.define.aggregate] Replace "is_enumeration_type" with "is_enum_type" + + This fixes a wording bug in P2996R13. + + commit 020140713799934d623241627c6aaef917e5039d + Author: Luc Grosheintz + Date: Sat Sep 27 22:26:43 2025 +0200 + + [views.multidim] Fix template arguments for submdspan_extents (#8243) + + commit 82bf75bc09e4ab5781e4f9149a59a41fe4c8581e + Author: Luc Grosheintz + Date: Mon Sep 29 20:06:16 2025 +0200 + + [mdspan.sub.sub] Fix typos in submdspan effects (#8248) + + The class `mdspan` doesn't have a member `data`, it has `data_handle` + (which returns a generalized pointer). + + The `AccessorPolify::offset_policy` is a type alias and therefore needs + a preceeding `typename`. + + commit 3f8865632f916f52993f342393a016aa2d732792 + Author: Hewill Kang + Date: Tue Sep 30 04:07:15 2025 +0800 + + [simd.mask.comparison] Add missing parameter names (#8262) + + commit 9db1d3b6121e092ed89e84ba9a1e45bf2b7504fc + Author: Hewill Kang + Date: Wed Oct 1 00:07:58 2025 +0800 + + [simd.permute.mask] Fix typo (#8268) + + commit 3c0ac909441ced78a097456fbfeec1b83f2da218 + Author: Hewill Kang + Date: Wed Oct 1 00:04:57 2025 +0800 + + [stringstream.members] Add missing param + + commit f5c6e4ef5fd303d07a0cd691913a5317164bb5d5 + Author: Jens Maurer + Date: Sat Oct 4 18:58:19 2025 +0200 + + [meta.reflection.names] Fix formatting for 'N' + + Fixes NB US 94-201 (C++26 CD). + + commit c6dc1e60202fea04b1d26769479c7063b3f867d1 + Author: Jens Maurer + Date: Sat Oct 4 19:02:43 2025 +0200 + + [meta.reflection.queries] Fix typo in comment in example + + Fixes NB US 96-206 (C++26 CD). + + commit eb87240307c7bb80937eda95c3077e41e096550f + Author: Jens Maurer + Date: Sat Oct 4 18:39:29 2025 +0200 + + [meta.reflection.operators] Remove superfluous 'the' + + Fixes NB US 91-198 (C++26 CD). + + commit 7c3eb729ab66113a5ca02c90efce4ef5e944810b + Author: Jens Maurer + Date: Sat Oct 4 17:46:51 2025 +0200 + + [meta.reflection.member.queries] Remove superfluous 'of' + + Fixes NB US 103-164 (C++23 CD). + + commit 9793e558b81c133e1237cd96ce37171f79b63245 + Author: Jens Maurer + Date: Sat Oct 4 18:54:11 2025 +0200 + + [meta.reflection.operators] Fix table formatting + + Fixes NB US 92-199 (C++26 CD). + + commit 0c8df65ab760e827363591f95f127de98771238b + Author: Jens Maurer + Date: Sat Oct 4 15:32:15 2025 +0200 + + [basic.life] Remove spurious commas + + Fixes NB US 18-035 (C++26 CD). + + commit f8d44da79bc497b8a3ab6fc3fce728e40206922a + Author: Jens Maurer + Date: Sat Oct 4 17:38:08 2025 +0200 + + [meta.syn] Fix phrasing in note + + Fixes NB US 88-163 (C++26 CD). + + commit 9add78e448d5900d57f4e15da2f08eaceedab419 + Author: Jens Maurer + Date: Sat Oct 4 18:49:55 2025 +0200 + + [meta.reflection.define.aggregate] Fix declarations of name-type constructors + + Fixes NB US 123-187 (C++26 CD). + + commit 0b085787cb519c8904e951f5fd23e1d4df5b7682 + Author: Jens Maurer + Date: Sat Oct 4 22:17:27 2025 +0200 + + [exec.snd] Fix cross-references for 'impls-for' + + Fixes NB US 208-333 (C++26 CD). + + commit 47992d448b6cb6f31e78d27193853b6dd4783fb0 + Author: Jens Maurer + Date: Sat Oct 4 23:36:18 2025 +0200 + + [execution.syn] Add comments to cross-references in synopsis + + Fixes NB US 200-323 (C++26 CD). + + commit 969776f2676316422ae1e7c92718326efa3c357f + Author: Jens Maurer + Date: Sat Oct 4 23:54:24 2025 +0200 + + [exec.snd.expos] Move specification of default template argument for 'Data' + + Fixes NB US 212-352 (C++26 CD). + + commit 5ba4be405536256e4498086dc78e1013e7b06920 + Author: Jens Maurer + Date: Sat Oct 4 23:45:05 2025 +0200 + + [execution.syn] Add enable_sender to synopsis + + Fixes NB US 199-324 (C++26 CD). + + commit 40c2499440d42ac93e889bb7604173f01abb50a7 + Author: Jens Maurer + Date: Sat Oct 4 22:29:10 2025 +0200 + + [exec.write.env] De-bulletize specification of check-types + + Fixes NB US 218-349 (C++26 CD). + + commit 7c31fb08d42cb48eb2a5f63ed4406aff8f1eed4a + Author: Jens Maurer + Date: Sat Oct 4 15:43:54 2025 +0200 + + [temp.variadic] Add separate bullet for annotation-list + + Fixes NB US 51-095 (C++26 CD). + + commit 322d38022bb292fbdb6d668af4ecd753eb104a53 + Author: Jens Maurer + Date: Sat Oct 4 15:39:10 2025 +0200 + + [class.pre] Adjust phrasing around 'identifer' + + Fixes NB CA-083 (C++26 CD). + + commit be1585aeff253d6d87e41f08a4e617e96ac0e17a + Author: Jens Maurer + Date: Sun Oct 5 12:12:27 2025 +0200 + + [meta.reflection.extract] Apply code font to "U" + + Fixes NB US 111-174 (C++26 CD). + + commit 9bd9e43f43d669d5fd353fa390818a47a42dad18 + Author: Jens Maurer + Date: Sun Oct 5 12:01:45 2025 +0200 + + [meta.reflection.layout] Remove incorrect 'of' + + Fixes NB US 108-169 (C++26 CD). + + commit a7e6101939985870e128b742c616e5c6da357b2b + Author: Jens Maurer + Date: Sun Oct 5 08:23:03 2025 +0200 + + [exec.par.scheduler] Use 'has the value' for an expression + + Fixes NB US 262-394 (C++26 CD). + + commit 6f3ef53700441dd46c369ab9e4a14e722206ffc6 + Author: Jens Maurer + Date: Sun Oct 5 08:14:43 2025 +0200 + + [dcl.fct.def.replace] Add 'replaceable function' to index + + Also add a label 'term.replaceable.function' for subclause-agnostic + cross-referencing. + + Fixes NB US 269-406 (C++26 CD). + + commit 9d74d451e7ea2cf09e71f09b9e283047d713eab6 + Author: Jens Maurer + Date: Sun Oct 5 07:44:02 2025 +0200 + + [algorithms.parallel.overloads] Rename subclause title + + Fixes NB US 156-254 (C++26 CD). + + commit e70c392421cce818ae5edc0d4fde6d94184b8a4a + Author: Jens Maurer + Date: Sun Oct 5 12:18:08 2025 +0200 + + [meta.reflection.extract] Remove stray 'T is' and format 'X' in code font + + Fixes NB US 110-171 (C++26 CD). + + commit 7c829315eb135f4df6326e35974c41983dc18ffd + Author: Jens Maurer + Date: Sun Oct 5 14:14:23 2025 +0200 + + [atomics.syn,atomics.ref.pointer] Remove partial specialization atomic_ref + + A misapplication of paper P3323R1. + + Fixes NB US 194-314 (C++26 CD). + + commit 7e30ea001b274cc74dc165e32e3908bd6d13a54a + Author: Jens Maurer + Date: Sun Oct 5 14:26:06 2025 +0200 + + [atomics.types.int,atomics.types.float] Excise uses of undeclared 'T' + + Fixes NB US 196-315 (C++26 CD). + + commit 196df1a7a97c0f11286816baa22d365d202db8ad + Author: Jens Maurer + Date: Sun Oct 5 15:00:21 2025 +0200 + + [atomics.ref.generic] Avoid use of undeclared 'T' + + Fixes NB US 192-312 (C++26 CD). + + commit 13a5c431dde2bff1ee02fa655806ffaedfc1b70f + Author: Jens Maurer + Date: Sun Oct 5 09:42:48 2025 +0200 + + [task.promise] Remove trailing semicolons in comments in examples + + Fixes NB US 259-380 (C++26 CD). + + commit 0bce45bb287307c828c69fee1942da0c17793a15 + Author: Jens Maurer + Date: Sun Oct 5 11:51:29 2025 +0200 + + [exec.task.scheduler] Fix punctuation and add 'the' + + Fixes NB US 241-371 (C++26 CD). + + commit cd66127ccb165d4d0fcfb1594475a12600986697 + Author: Jens Maurer + Date: Sun Oct 5 17:54:17 2025 +0200 + + [exec.getcomplsigs] Fix misplaced \end{itemdescr} (#8301) + + Fixes NB US 217-359 (C++26 CD). + + commit 122cc4abe30c0cdc39e7f7d4d09222ddfc298292 + Author: Jens Maurer + Date: Sun Oct 5 12:49:46 2025 +0200 + + [exec.snd.expos] Amend specification for allocator-aware-forward + + Fixes NB US 216-357 (C++26 CD). + + commit 63c59140eda9f020f1d516657d2c1ab25c5a2d2d + Author: Jens Maurer + Date: Sun Oct 5 12:30:21 2025 +0200 + + [meta.reflection.substitute] Add 'in order' + + A misapplication of P2996R13. + + Fixes NB US 115-176 (C++26 CD). + + commit e2511592b653984301b7a13559c0e6e06d1243aa + Author: Jens Maurer + Date: Sun Oct 5 12:23:48 2025 +0200 + + [meta.reflection.substitute] Clarify error message in example + + Fixes US 116-177 (C++26 CD). + + commit 42793d0ce36d4fe09a4c7ebdceeadef2e343fee4 + Author: Jens Maurer + Date: Sun Oct 5 09:38:01 2025 +0200 + + [exec.sysctxrepl.psb] Make 'one of the expressions below' more explicit + + Fixes NB US 266-399 (C++26 CD). + + commit 776bc2892e2480fb69296cd404fc4bd5136cc44a + Author: Jens Maurer + Date: Sat Oct 4 19:51:24 2025 +0200 + + [exec.snd] Harmonize subclause titles + + Drop unnecessary 'std::' prefix + + Fixes NB FR-033-335 (C++26 CD). + + commit e7e5b69c13ce5c358065fd989d64c4253693d415 + Author: Jens Maurer + Date: Sun Oct 5 11:42:14 2025 +0200 + + [task.promise] Refer to parameter types of the completion signatures + + Fixes NB US 260-390 (C++26 CD). + + commit 600fe56064ee41722607e4c45d56919a1f153b87 + Author: Jens Maurer + Date: Sun Oct 5 19:59:38 2025 +0200 + + [simd.syn] Compactify presentation of gather/scatter functions + + commit bab708de50b834d5144cef2d2fb0872954ca47b9 + Author: Jens Maurer + Date: Sun Oct 5 18:55:20 2025 +0200 + + [simd.traits] Rename subclause heading to 'Type traits' + + The subclause applies to both vecs and masks. + + Fixes NB US 177-284 (C++26 CD). + + commit 597cc85b49cfed8daab129fceca2c8d78b58dc6c + Author: Jens Maurer + Date: Sun Oct 5 18:07:17 2025 +0200 + + [simd.mask.namedconv] folded into [simd.mask.conv] + + Fixes NB US 185-299 (C++26 CD). + + commit f3778a37d4a5c40f2ecc64b6ed47e3b8548b1eb6 + Author: Jens Maurer + Date: Sun Oct 5 19:12:14 2025 +0200 + + [simd.complex.access] Move into [simd.class] + + The complex accessors are member functions. + Also adjust the subclause heading to fit the new surroundings. + + Fixes NB US 179-293 (C++26 CD). + + commit 2dbfcc5c7a759d6fbd6c09ecbc7f4439cc4eb5f5 + Author: Jens Maurer + Date: Sun Oct 5 18:02:01 2025 +0200 + + [simd.mask.nonmembers] Add 'basic_mask' to subclause heading + + Fixes NB US 186-300 (C++26 CD). + + commit 95a10a601b3e2c33713724b514b47162fefa73ef + Author: Jens Maurer + Date: Sun Oct 5 11:46:40 2025 +0200 + + [task.state] Fix formatting of subclause heading + + Fixes NB US 248-378 (C++26 CD). + + commit ae124b4ce071453365f5b89fcb815ee731fdd2f8 + Author: Jens Maurer + Date: Sun Oct 5 22:37:15 2025 +0200 + + [exec.when.all] Fix spelling of 'get_stop_token_t' + + Fixes NB US 223-343 (C++26 CD). + + commit b1949378f3174e8177890dac5fff62cc7ffdc0e3 + Author: Jens Maurer + Date: Mon Oct 6 14:08:35 2025 +0200 + + [atomics.ref.pointer,atomics.types.pointer] Use 'see above' for fetch_key declaration + + Fixes NB US 198-317 (C++26 CD). + + commit bc71d74ab0b0717973cbaf28a4f1931bd42fa848 + Author: Jens Maurer + Date: Sat Oct 11 10:28:16 2025 +0200 + + [exec.cmplsig] Add 'value_types_of_t' to index (#8326) + + commit adca52baba9f75d1190cbb9cc7dc7e4c04fa7152 + Author: Alisdair Meredith + Date: Sun Oct 12 04:38:49 2025 -0400 + + [lex.phases] Move dropping whitespace to end of phase 4 (#8117) + + Move the dropping of whitespace to the end of phase 4, after preprocessing directives are deleted. + + commit e1d47e006183ef8e2c778587b5fdcf0ce6d15da6 + Author: Jan Schultke + Date: Thu Oct 16 22:27:11 2025 +0200 + + [basic.def] Remove incorrect \grammarterm formatting for "declaration" (#8337) + + Fixes NB US 12-026 (C++26 CD). + + commit fb46e16c6ce0d91c6bd21ca497d1823c997d1926 + Author: Jan Schultke + Date: Sat Oct 18 00:33:16 2025 +0200 + + [streambuf.virt.put] Replace "effects" with "affects" in footnote (#8329) + + Fixes NB US 188-303 (C++26 CD). + + commit 8fc2944d469666f68b595a47b6f2f1d38547b402 + Author: Jonathan Wakely + Date: Sat Oct 18 13:01:39 2025 +0100 + + [meta.type.synop] Remove redundant cast in constant_wrapper declaration (#8218) + + The use of `decltype(cw-fixed-value(X))` instead of just `decltype(X)` + is a workaround for a GCC bug: https://gcc.gnu.org/PR117392 + + There's no need for the standard to specify it this way. + + Fixes NB US 79-146 (C++26 CD). + + commit 05e4d8d991ec3a4d013b90c1317e9f76b68c8532 + Author: Jens Maurer + Date: Sat Oct 11 10:39:17 2025 +0200 + + [simd] Canonicalize subclause headings + + Remove parts redundant with headings of superordinate subclauses. + + commit 7fffa1fb521b9432b769e0f83d6a60c732f3cfb8 + Author: Jonathan Wakely + Date: Mon Oct 20 16:20:31 2025 +0100 + + [vector.bool.pscp] say "vector primary template" (#8351) + + Not primary vector template. + + commit c914b3bf857daea1c30ffbb330c0a4e5a44edc70 + Author: Jan Schultke + Date: Mon Oct 20 17:24:12 2025 +0200 + + [meta.reflection.access.context] Remove stray "static" in declaration of "via" (#8272) + + A misapplication of P2996R13. + + Fixes NB US 101-208 (C++26 CD). + + commit ca77cdb10021c757b0fbe4d83b5991ac7d935db8 + Author: Jonathan Wakely + Date: Mon Oct 20 16:28:59 2025 +0100 + + [fs.path.native.obs,fs.path.generic.obs] Qualify std::format (#8350) + + Fixes NB US 190-305 (C++26 CD). + + commit 29465f5bec52bbfe1d81cd17c20527c911801447 + Author: Jan Schultke + Date: Thu Oct 23 21:40:25 2025 +0200 + + [linalg.conj.conjugatedaccessor] Fix typos and constructor missing from synopsis (#8106) + + commit 0d90bd108f9cba10d206a300a64684a0244004e4 + Author: Hana Dusíková + Date: Fri Oct 24 17:13:42 2025 +0200 + + [meta] reflect_constant_array of an empty range returns const array + + commit cab90b37139473d67cba49397ff6666228ca4db3 + Author: Keith Thompson + Date: Fri Oct 24 12:20:54 2025 -0700 + + [diff.expr] Remove commentary about good practice in C (#8356) + + commit 2f53f313f5b1aac5f9547b39e78863e23ca9c047 + Author: A. Jiang + Date: Sun Oct 26 19:22:13 2025 +0800 + + [lib] Fix C23 subclause numbers in `\xrefc` and `\IsoC` (#8113) + + commit 96fa31012b50a32d96a49fa8060124bcb70e3e5a + Author: Kilian Henneberger + Date: Mon Oct 27 21:39:41 2025 +0100 + + [meta.reflection.substitute] Name correct function in comments (#8372) + + commit 3ba26a48c7a72f7ed7d17d6380457ff6f985489a + Author: Matthias Kretz + Date: Wed Oct 29 22:58:21 2025 +0100 + + [simd.math] Add missing return keywords (#8374) + + commit 512372387083cdc2d112bfba157c463220b43476 + Author: Thomas Köppe + Date: Fri Aug 1 11:16:35 2025 +0100 + + [expr.reflect] Delete sentence from "interpretation" list item that is redundant with the next item. + + The next item already describes the case where R represents a namespace. + + commit 03f0c9f631c5e2d70cfe8e8476016771cc7d9d51 + Author: Thomas Köppe + Date: Fri Aug 1 11:57:08 2025 +0100 + + [dcl.attr.grammar] Delete redundant "and no alignment-specifier". + + Now that we say "an attribute-list with no attributes", the additional + "and no alignment-specifier" is redundant. + + commit 2a9a4e3c3757ace0ec8c24ca6f8c31e77f3a8ec5 + Author: A. Jiang + Date: Thu Aug 21 09:57:22 2025 +0800 + + [expected.object.monadic] Add missing necessary `typename` + + commit 617a9f1254bb930c80ad4e5f13fb27ca4e8ded51 + Author: A. Jiang + Date: Thu Aug 21 09:57:44 2025 +0800 + + [expected.void.monadic] Add missing necessary `typename` + + commit 266cb2bc567f00797ca4d0ebc6b425f98f5167bf + Author: Alisdair Meredith + Date: Thu Aug 21 15:16:09 2025 -0400 + + [cpp.replace.general] Add a cross-reference to 'see below' + + The 'below' in 'see below' as actually five sublauses away. + Adding a cross-reference establishes the link more clearly. + + commit 262d37f0b19c91c795fd89872789ca7bcf200a42 + Author: Alisdair Meredith + Date: Thu Aug 21 15:23:38 2025 -0400 + + [lex.phases] Clarify the sequence of characters for line splicing + + commit 6d42e2f96acf42060adcb018053f562a45510671 + Author: Alisdair Meredith + Date: Thu Oct 30 08:39:52 2025 -0400 + + [basic.pre] Clarify definition of variable (#8186) + + Reorder the positive and negative terms to avoid confusion with the binding of "other than". + + commit da231804706780368a6f6becc4d45000b31c19eb + Author: Alisdair Meredith + Date: Sat Aug 23 21:47:47 2025 -0400 + + [syntax] Replace plain text with grammar terms where intended + + For the examples of X-seq and X-list forms of specifiaction, + ensure that the thing in the sequence or list is the corresponding + grammar element rather than a plain text term, as the two are not + always synonyms, notably not the case for the cited *declaration*. + + commit 1722e1f2b9ddc3b7f172b8f7503eda6e451c3012 + Author: A. Jiang + Date: Wed Jun 18 10:04:59 2025 +0800 + + [dcl.constexpr], [dcl.init.aggr] A constructor is a member function + + commit 494ddd03d3e7272727451126c264cb47ba698030 + Author: A. Jiang + Date: Wed Jun 18 10:08:50 2025 +0800 + + [expr.call], [expr.const] A constructor is a (member) function + + commit 683be0af96d1cfb1fa971cca17b10cf460445cd3 + Author: A. Jiang + Date: Wed Jun 18 10:11:23 2025 +0800 + + [temp.spec.general], [temp.inst] A member function is a function + + commit f7c7befc7f03236ca968c1003f1d65247519a51b + Author: A. Jiang + Date: Wed Jun 18 10:12:09 2025 +0800 + + [constexpr.functions] A constructor is a function + + commit 729a91c79e408b89329ecdd6345a43c31931da2d + Author: A. Jiang + Date: Wed Jun 18 10:12:51 2025 +0800 + + [pairs.pair] A constructor is a member function + + commit be930a9c8e7a6ae0e5c37bab6e741a878f046085 + Author: A. Jiang + Date: Wed Jun 18 10:15:49 2025 +0800 + + [container.reqmts], [flat.map.overview], [flat.multimap.overview], [flat.set.overview], [flat.multiset.overview] A constructor is a member function + + commit a81ecaa88443f7e23ef1dddc99a10b4b1488d21b + Author: A. Jiang + Date: Wed Jun 18 10:20:07 2025 +0800 + + [diff.cpp17.depr] A constructor is a member function + + commit d411b5731711c02cbd140ff25fc514f0ef682817 + Author: Jan Schultke + Date: Sun Feb 25 17:31:01 2024 +0100 + + [container.reqmts] Remove stray semicolon in description of expression + + commit 755202dc393ca6e9a87344ec9e810163c3b59d6b + Author: A. Jiang + Date: Tue Jul 22 09:38:31 2025 +0800 + + [conv.rank] Update and fix the reference to C23 H.4.3 + + commit 11b56197263aa8af89596e69e663de3cc873e360 + Author: A. Jiang + Date: Tue Jul 22 09:39:34 2025 +0800 + + [numerics.c] Use `\xrefc` to refer to C23 7.20 + + ... addressing the `%% TODO` comments + + commit 4917ad917b62e8065910c3c34ae1cd490747075b + Author: A. Jiang + Date: Tue Jul 22 09:40:19 2025 +0800 + + [stdbit.h.syn] Use `\xrefc` to refer to C23 7.18 + + ... addressing the `%% TODO` comments + + commit 0b6b2b0cde8b878dbbf19b7f514e99be1e23aa87 + Author: Hewill Kang + Date: Sun Jul 27 23:39:23 2025 +0800 + + [range.refinements] Fix template parameter name + + commit acb132bb75c3bedb159b26d151aae1469c68883b + Author: Thomas Köppe + Date: Thu Jul 31 16:07:43 2025 +0100 + + [expr.prim.lambda.closure] Use "incomplete" instead of "not complete". + + The former is a defined term. + + commit 7e9c2b7f29605a3f195f30ef1821a88f55dec950 + Author: Hewill Kang + Date: Fri Oct 31 01:35:27 2025 +0800 + + [const.wrap.class] Add missing namespace std (#8247) + + commit fde9d1f6047ed65e52483fa40162b966628162b2 + Author: Eisenwave + Date: Sun Oct 26 07:32:34 2025 +0100 + + [basic.scope.pdecl], [temp] Replace "expansion statement" with "expansion-statement" + Fixes NB US 2-404 (C++26 CD). + + commit 887c88157c52a8fb4f1acc3d49b40d4c5ef9af6c + Author: Jonathan Wakely + Date: Fri Oct 24 18:11:27 2025 +0100 + + [meta.reflection.layout] change 'entity' to 'construct' + + Fixes NB US 104-165 (C++26 CD). + + commit 6042d48bc8467d7f73516e045f440e3b80a0961e + Author: Alisdair Meredith + Date: Tue Oct 21 13:59:35 2025 -0400 + + [cpp.pre] Move paragraph introducing preprocessor to first + + The paragraph with no normative text that outlines the broad capabilities + of the preprocessor has slippee further down this clause as new text is added. + The most appropriate place for introductory text is the first sentence of the + introductory clause, so moved accordingly. + + commit 41c80d6cb744df0c8c409d3d72228c57fbf9d6cd + Author: Jonathan Wakely + Date: Fri Oct 17 19:19:23 2025 +0100 + + [simd.permute.static] use satisfies for satisfaction + + Fixes NB US 182-296 (C++26 CD). + + commit a019163776f16b4ed4ac9b7ec22d9b8abcd9314d + Author: Eisenwave + Date: Thu Oct 9 11:34:21 2025 +0200 + + [class.temporary] Clarify that list of contexts is exhaustive, say "temporary objects" + Fixes NB US 19-037 (C++26 CD). + + commit 45dca420c08b9ce05b58140bc0572ff65dc24a1f + Author: Eisenwave + Date: Thu Oct 9 12:07:28 2025 +0200 + + [simd.syn] Reorder declarations to match subclause order + Fixes NB US 175-281 (C++26 CD). + + commit 2c60d60528470f5c1c7e53c345a77d2b88085483 + Author: Jan Schultke + Date: Thu Oct 23 06:15:51 2025 +0200 + + [diff.expr] Include conversions involving pointers to cv void in the changes + + commit 210d61f6d4c10316975c9aa02ebeb2383b225983 + Author: Jens Maurer + Date: Sat Oct 25 18:22:16 2025 +0200 + + [dcl.init.general] Add cross-references for mandatory copy elision + + commit bfcdd7250785909bc2fdd9eeb381680129ec9628 + Author: Jens Maurer + Date: Sun Oct 5 22:25:03 2025 +0200 + + [exec.par.scheduler] Move class definition from synopsis + + Fixes NB US 204-321 (C++26 CD). + + commit c82d84c417ee6c1e0407162c487a810a2baaa562 + Author: Jens Maurer + Date: Fri Oct 31 01:44:23 2025 +0100 + + [meta.reflection.{layout, annotation}] Harmonize phrasing about complete types (#8347) + + Fixes NB US 107-168 (C++26 CD). + + commit 3de77e4c3112eaa54a7cd44ef11ba6a26bff1d00 + Author: A. Jiang + Date: Thu Aug 8 13:37:41 2024 +0800 + + [class.ctor.general] Remove a dangling paragraph and associated index + + The paragraph was made dangling by P1787R6. + + commit 8525f9150a7fe8c63fb593b65b80b09b55f94f30 + Author: Jonathan Wakely + Date: Fri Oct 17 19:20:01 2025 +0100 + + [simd.permute.mask] clarify list is in ascending order + + Fixes NB US 183-290 (C++26 CD). + + commit ffd997cb108c7b3be749ba1abb4ac727117f65ee + Author: Jonathan Wakely + Date: Fri Oct 24 17:53:32 2025 +0100 + + [meta.reflection.result] move declaration of TCls earlier + + Fixes NB US 117-178 (C++26 CD). + + commit c53c1789779b1f6ccd95d0ab27aca50658830b07 + Author: Jeff Garland + Date: Thu Oct 30 17:58:13 2025 -0700 + + [meta.reflection.extract] Remove second "constexpr if" + + Fixes NB US 113-173 (C++26 CD). + + commit 65236d7d5fca9ccc8f3cff2d9c248f02f1f9d5bf + Author: Jens Maurer + Date: Sat Oct 4 17:54:14 2025 +0200 + + [meta.reflection.layout] Fix phrasing in bulleted list + + Fixes NB US 105-166 (C++26 CD). + + commit 088768b5b613a29af165f2c99fe86e8bd918677a + Author: Jan Schultke + Date: Wed Sep 3 10:40:42 2025 +0200 + + [temp.deduct.general] Replace "nontype template argument" with "constant template argument" + + commit 19a9248ff8c5b0008f805e0353b697a5692ea354 + Author: Jens Maurer + Date: Sun Oct 26 12:53:22 2025 +0100 + + [lib] Remove superfluous `typename` in alias declarations + + Also add an automatic check. + + Fixes NB US 64-127 (C++26 CD). + + commit 1fcd55fceb8aca33f2e4d82c577aa47e94bb0e93 + Author: Jens Maurer + Date: Fri Oct 31 10:11:58 2025 +0100 + + [exec.sysctxrepl.recvproxy] Create new subclause for receiver proxies + + Fixes NB US 264-397 (C++26 CD). + + commit 42129859dd633cd3f497ef9dd80b5d1dd4b35672 + Author: Eisenwave + Date: Tue Oct 28 19:25:45 2025 +0100 + + [concept.regularinvocable], [iterator.concept.winc] Replace "annotation" with "comment" + Fixes NB US 71-128 (C++26 CD). + + commit 42fad0f0b26d87235bb0cf8524de3f7628150a10 + Author: A. Jiang + Date: Fri Oct 31 19:22:56 2025 +0800 + + [basic.fundamental] Complete examples for reflections (#8265) + + Fixes NB US 22-042 (C++26 CD). + + commit bf6acb1d651f1960f287b8d98b62b1f0092d0a30 + Author: Jonathan Wakely + Date: Fri Oct 31 12:05:49 2025 +0000 + + [meta.define.static] qualify names from namespace meta + + Within library wording we don't do ADL, only unqualified lookup (as per + [contents] p3). This means that all the metafunctions in namespace std + need to qualify names from namespace std::meta in order to find them. + + This also fixes the bug that name lookup in the Effects: of + define_static_array would find std::extent and not perform ADL to find + std::meta::extent, even if ADL was performed here. + + commit dfe8e0b2de8df3cd890351055352e742b8ad5a5f + Author: YexuanXiao + Date: Fri Oct 10 00:01:05 2025 +0800 + + [meta.type.synop] Indexing the unindexed type aliases and variable templates + + commit 69837e72cebb65063a7f63b751e2ab8d70318823 + Author: Hewill Kang + Date: Fri Oct 31 22:14:47 2025 +0800 + + [unord.multiset.overview] Add missing "typename" (#8271) + + commit 54d9b47b3fcbb42ec7c24c89a00fa64f7fe4ad4e + Author: Jan Schultke + Date: Sat Sep 27 11:06:41 2025 +0200 + + [concepts.callable.general] Replace "function objects" with "callable types" + + commit 7089fb216f5ac4afa9c6e977a31921c2a0eff714 + Author: Hewill Kang + Date: Fri Oct 31 22:30:04 2025 +0800 + + [simd.overview] Remove obsolete "noexcept" (#8250) + + The "noexcept" specifier was removed from the design by P3430R0, + but the paper omitted the corresponding change of the synopsis. + + commit 7f1926bbb287cccf27d0edccce860badbfc743b2 + Author: Jonathan Wakely + Date: Fri Sep 5 19:14:38 2025 +0100 + + [flat.map.modifiers] Remove redundancy in 'insert(sorted_unique, i, j)' + + We can specify this in terms of the overload without the `sorted_unique` + tag. That is consistent with how the equivalent functions in `flat_set` + and `flat_multiset` are specified. + + commit 13a33aca7b93142f63c68f426511291dc899032b + Author: Masaki Moriguchi (a.k.a. Michel Morin) + Date: Sat Nov 1 00:22:21 2025 +0900 + + [locale.moneypunct.virtuals] remove redundant backslash-space (#8159) + + TeX already treats a period after uppercase as an acronym (which yields normal spacing). + + commit 1ff1e63b14f530389585bcee43401619f7edc139 + Author: Jan Schultke + Date: Fri Oct 31 16:32:02 2025 +0100 + + [optional.optional.{general, ref.general}] Say "object of type optional" (#8220) + + commit daf06c9f3445bd46678dc660e55debbb6feb7d97 + Author: Hewill Kang + Date: Tue Sep 30 02:17:45 2025 +0800 + + [mdspan.accessor.aligned.overview] Remove std:: in example + + commit 4bf58f81313e940295281a58d6520f8d9af18a56 + Author: A. Jiang + Date: Mon Sep 29 10:11:17 2025 +0800 + + [filebuf.virtuals] Add missing `const` to pointer variables + + The fourth parameter of `codecvt::out` and `codecvt::in` are + `const C*&`, but _Effects_ use `C*` variables, which makes the call + ill-formed. + + The intent seems sufficient clear and we should probably use `const C*` + variables in these places. + + commit 2e003dac4f1658e3ccbfd22c4e477f7b1d0ec3f1 + Author: Jan Schultke + Date: Fri Oct 31 16:39:18 2025 +0100 + + [{hive,vector}.capacity] Move remarks from Complexity to Remarks element (#8323) + + commit 04df25f524e692e0484f04779debcbaf59e83e2d + Author: Hewill Kang + Date: Tue Oct 7 20:33:03 2025 +0800 + + [allocator.requirements.general] Add namespace std for exposition-only concept + + commit 1e54f58f5a5cf0a283b90c0db30fff76d42efb51 + Author: Jan Schultke + Date: Fri Oct 31 22:08:15 2025 +0100 + + [basic.link] Use maths font in defn of direct base class relationship (#8333) + + Fixes NB US 1-405 (C++26 CD). + + commit 3b14ec1d5f19882e628bfa09b96eeaeebdb622b7 + Author: Eisenwave + Date: Thu Oct 9 09:49:44 2025 +0200 + + [atomics.types.float] Align parameters in function declarations + + Fixes NB US 197-316 (C++26 CD). + + commit 15186e75cb77cc410db4e5343bcd17dd0a3c66ac + Author: A. Jiang + Date: Sat Nov 1 13:32:39 2025 +0800 + + [text], [numerics], [exec] Remove remaining `typename` in aliases + + commit 5d916dc6cc99a6d548942ebf85fc1551ad4b7a84 + Author: Jens Maurer + Date: Sat Nov 1 14:37:09 2025 +0100 + + [meta.reflection.annotation] Move to before [meta.reflection.extract] + + Fixes NB US 87-156 (C++26 CD). + + commit 363c3a545ef54fe35499b26bcf438dbd8f84538d + Author: Jens Maurer + Date: Sat Oct 4 18:23:56 2025 +0200 + + [meta.reflection.array] Integrate subclause into [meta.define.static] + + Fixes NB US 86-157 (C++26 CD). + Fixes NB US 119-180 (C++26 CD). + Fixes NB US 89-196 (C++26 CD). + + commit 7409cb04365a0a2ee19e100f663b1174aa204710 + Author: Vincent X <77327828+ckwastra@users.noreply.github.com> + Date: Sat Nov 1 22:14:17 2025 +0800 + + [temp.explicit] Fix comment in example (#8225) + + commit acee2087d1d72a94ebb5309459c9dae69cedfa5b + Author: Corentin Jabot + Date: Sat Nov 1 11:21:06 2025 -0700 + + [class.protected] Change "naming class" to "designating class" (#8251) + + The term was changed to "designating class" by P2996 + (https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2996r13.html#pnum_397), + and these remaining uses had not been updated accordingly. + + commit bbcf99022649b569ad21feb5e3a893d1e907c9a6 + Author: Eisenwave + Date: Sat Jul 26 08:05:33 2025 +0200 + + [dcl.ptr] Move "See also" from normative paragraph to example + + commit c98a54b8a1a641c74c017767092a8d65827267d8 + Author: Eisenwave + Date: Sat Jul 26 10:38:11 2025 +0200 + + [conv.rank] Add missing hyphen in "floating point" + + commit 31c4868b3e3323aa931aeb66cb83c8c1135ccdf7 + Author: Eisenwave + Date: Sat Jul 26 10:38:52 2025 +0200 + + [diff.cpp03.locale] Add missing hyphen in "floating point" + + commit dcfad093c246a09594d401340e195315db61220c + Author: Eisenwave + Date: Sat Jul 26 10:40:00 2025 +0200 + + [linalg.reqs.alg] Add missing hyphen in "floating point" + + commit 2be3924b5b7249d6d7b085f8a1e4321e7645a54c + Author: A. Jiang + Date: Tue Sep 23 21:45:59 2025 +0800 + + [meta.member] Properly introduce intended implicit conversion + + Previously, the `static_assert` the example failed due to deduction + failure but not `false` results. This PR makes the template arguments + fully specified, which allows intended implicit conversion. + + commit 4452e28fde3c647a59fe261a1ced3906b901ca3f + Author: Alisdair Meredith + Date: Tue Aug 26 11:35:55 2025 -0400 + + [basic.def] Turn list of examples into a nute + + The list of example side effects should neither be deemed normtaive nor + exhaustive (although we will try). It should be demoted to a note. + + commit 77893aadc587df5131c3cf5d8388cbf6f7633c80 + Author: Eisenwave + Date: Sun Nov 2 09:19:46 2025 +0100 + + [indirect.assign] Replace incorrect "_t" with "_v" in Mandates + + commit cc53316dfe22765154a025462261dfd007be7a93 + Author: Hubert Tong + Date: Mon Nov 3 01:41:03 2025 -0400 + + [bit.cast] Adjust cross-reference for definition of consteval-only type (#8391) + + commit cedfad4418057ccc2e79eae26d22c0e567e1ce8f + Author: Eisenwave + Date: Mon Nov 3 15:25:41 2025 +0100 + + [const.wrap.class] Add constant_wrapper to index + + commit 749103f9d1fee0d04d4921ae7bb51c1ca47b73cd + Author: Alisdair Meredith + Date: Thu Jul 31 08:53:59 2025 -0400 + + [pre] No names in the preprocessor + + The term "name" applies specifically to entities in phase 7 + of translation. Macros have macro names, headers are parsed + as *header-name*s, etc. + + commit 75e3e48524c21e179535177c96c4ad80fe6e7f81 + Author: Jens Maurer + Date: Mon Nov 3 14:38:09 2025 +0100 + + [set.difference] Fix sentence + + A misapplication of P3179R9. + + Fixes NB US 165-264 (C++26 CD). + + commit 842616437ca1a6efd0c01ba37bafee3a9fd85967 + Author: Jens Maurer + Date: Mon Nov 3 15:16:34 2025 +0100 + + [meta.reflection] Move examples to the end of their respective section + + Fixes NB US 83-152 (C++26 NB). + + commit 1844b9d9d27d39f0cd2c05e1ecc738f11e2c8845 + Author: Jens Maurer + Date: Mon Nov 3 16:09:06 2025 +0100 + + [execution.syn] Reorder entries to match subclause order + + Fixes NB US 201-322 (C++26 CD). + + commit 019260f1fabe96078e7b331c41485558c7ea5eee + Author: Jens Maurer + Date: Mon Nov 3 14:46:27 2025 +0100 + + [const.wrap.class] Remove superfluous parameter in trailing requires clause + + Fixes NB US 80-148 (C++26 CD). + + commit ab094f1a706c73c3da3d7bd0061a62ff632cb1ad + Author: Eisenwave + Date: Mon Nov 3 18:42:57 2025 +0100 + + [cmath.syn] Add fmaximum, fmaximum_num, fminimum, and fminimum_num to index + + commit ca8bf9ae97d48ed3a6024511f79d306fd2da83de + Author: Eisenwave + Date: Mon Nov 3 18:53:20 2025 +0100 + + [basic.fundamental] Use "std::" prefix consistently for library type aliases + + commit 726f6860757a35b1037202454f4656195964cfb0 + Author: A. Jiang + Date: Tue Nov 4 11:58:41 2025 +0800 + + [re.regex.general] Fix indentation for members of `basic_regex` (#8399) + + commit f5ab0cbe8b939538427caa7cec139ca59afc186f + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Nov 4 15:11:01 2025 +0100 + + [queue.defn] Remove superfluous whitespaces (#8401) + + commit 35696224964df56c0e01fe1c1127dc41555d6556 + Author: Eisenwave + Date: Tue Jun 4 17:11:54 2024 +0200 + + [basic.indet] Convert reference to [conv.lval] into note + + commit acab9e553267137d6ac25e5568bafce734b70257 + Author: Alisdair Meredith + Date: Tue Nov 4 06:31:59 2025 -1000 + + [container.adaptors.general] Remove using typename from expos-only alias template + + commit ad99d5224a03821bcff46081195fed20f0afee31 + Author: Eisenwave + Date: Sun Nov 2 20:57:23 2025 +0100 + + [simd] Synchronize synopsis references with subclause headings + + Fixes NB US 181-294 (C++26 CD). + + commit 5a445cf41b9deab8412c0d6a8c61a7ff3f41645a + Author: timsong-cpp + Date: Tue Nov 4 11:11:23 2025 -1000 + + [library] Remove references to typedef-name + + Fixes NB US 62-114 (C++26 CD). + + commit a1e15352cc6115024fe5cf92901497a2fad92786 + Author: Damien L-G + Date: Tue Nov 4 14:42:31 2025 -1000 + + [atomics.ref.pointer] Do not refer to T (#8413) + + Fixes NB US 195-313 (C++26 CD). + + commit b560873553e304cbc76d8f883f29371d97525aef + Author: Damien L-G + Date: Tue Nov 4 15:56:23 2025 -1000 + + [atomics.syn] Simplify synopsis using "mostly freestanding" (#8411) + + Mark the `` header `// mostly freestanding`, remove all the + `// freestanding` comments, and add `// hosted` comments for + `atomic_signed_lock_free` and `atomic_unsigned_lock_free`. + + Fixes NB US 191-307 (C++26 CD). + + commit 230067ea57ca080c89010ffac8750a114068f8e3 + Author: timsong-cpp + Date: Tue Nov 4 15:47:21 2025 -1000 + + [exec.snd.expos] Move Remarks into itemdescr + + commit a7b71b33710c3fc7e22c6ed169581d242b839f28 + Author: Alisdair Meredith + Date: Sun Jul 27 11:23:47 2025 -0400 + + [dcl.inline] inline specifier is for ODR + + The key use of the inline specifier since C++11, if not before, + has been to allow multiple declarations to satisfy the ODR rather + than to provide a hint that compilers routinely ignore. + + This change moves but does not change wording, in order to move + the comment making the connection with the ODR more prominent + than the normative wording suggestings core transformation. + + It might be desirable to demote the normative coding hint to + a note, but that goes beyond the remit of a simple editorial + chsnge. + + commit f731f304049a1b26a0be369ac89988910b6d52ee + Author: Alisdair Meredith + Date: Tue Nov 4 14:37:27 2025 -1000 + + [lex.pptoken] Simplify sentences with common cause + + commit ba59ef5f76a3d45add0f70322a1dad57109f17d5 + Author: Alisdair Meredith + Date: Wed Nov 5 05:43:47 2025 -1000 + + [alg.find.first.of] Rename subclause title (#8428) + + Fixes NB US 158-256 (C++26 CD). + + commit 6d884babd1e6dc956d795c404525248d31028e46 + Author: Eisenwave + Date: Wed Nov 5 16:17:54 2025 +0100 + + [expr.const] Unmark introduction of "constant expression" as definition + + commit f4c608518c77fad9f28a864c517c442c186037c4 + Author: A. Jiang + Date: Thu Nov 6 00:42:50 2025 +0800 + + [linalg.transp.layout.transpose] Fix misplaced data members of `layout_transpose::mapping` (#8423) + + The intent is that _`nested-mapping_`_ and _`extents_`_ belong to + `layout_transpose::mapping` but not `layout_transpose`. This was a + mistake in the original paper P1673R13, confirmed by the author, and + it can also be inferred from their usages. + + commit c84e2cbcd13536a8083d4b3b1788f1b411a2334e + Author: Jakub Jelinek + Date: Wed Nov 5 14:40:13 2025 +0100 + + [expr.const] Use different classes for unrelated parts of the example + + commit 9f7a711b52aee884594eb4e01cc770ba071fffb0 + Author: Hana Dusíková + Date: Thu Nov 6 03:43:58 2025 +0900 + + [class] removing redundant "constexpr-suitable" wording (#8108) + + Constructors and destructors can't be coroutines (since P3533R2), + therefore they are always constexpr-suitable, and any wording + that states this explicitly is not needed and is removed in this change. + + commit ff9797db1da40fff8cf4710c845331e0b56d275b + Author: timsong-cpp + Date: Tue Nov 4 16:16:37 2025 -1000 + + [task.class] Improve error_types wording + + Fixes NB US 247-377 (C++26 CD). + + commit 23c89d40df26c387e5b6bd171189f18d6355b0b3 + Author: Alisdair Meredith + Date: Wed Nov 5 22:52:36 2025 -1000 + + [cpp.pre] Apply unicode markup (#8410) + + commit 2847e62c3440302c3694db06cf4795bbcf3e8951 + Author: Braden Ganetsky + Date: Wed Nov 5 18:07:36 2025 -1000 + + [exec.bulk] Fix structured binding presentation + + Fixes NB US 222-340 (C++26 CD). + + commit 18c441799049759c5a18afb9b89725ef3d86b977 + Author: Braden Ganetsky + Date: Wed Nov 5 17:54:01 2025 -1000 + + [meta.reflection.layout] Reverse logic in specification + + Fixes NB US 106-167 (C++26 CD). + + commit 1e37bdba0c01da86b3012f9b4249e242103bea6a + Author: Eisenwave + Date: Thu Nov 6 11:48:52 2025 +0100 + + [meta.syn] Synchronize reflect_constant/reflect_object parameters with definition + + commit 50ded6933a01226babb7f15b95784012a59cb046 + Author: Jens Maurer + Date: Thu Nov 6 17:48:21 2025 +0100 + + [exec.run.loop] Reword references to "count" and "state" (#8307) + + "Count" and "state" are locally defined notions, not actual (exposition-only) variables. + + Fixes NB US 231-361 (C++26 CD). + + commit 7693f862e21e36076fef3c190de83751d28103c2 + Author: Thomas Köppe + Date: Thu Nov 6 10:39:41 2025 -1000 + + [character.seq.general, time.general] Define STATICALLY-WIDEN in a better place + + The facility is now used from two different places ([time] and + [format]) and is now better defined in the library introduction. + + commit 76b2c464a2d1e737ab126fb2291b7ea5d483d36e + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Wed Dec 25 16:15:29 2024 +0000 + + [tab:cpp17.destructible] Use the correct placeholder in requirement + + commit 7ba83f99fd4e060bbb607463eb994b0df49caef4 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Nov 7 01:04:07 2025 +0100 + + [{multimap,multiset,set}.overview] Fix typos of constructors (#8237) + + commit b931610d0a6116a214b120b20dfd1475593be0cd + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Feb 13 20:32:10 2025 +0000 + + [mdspan.layout.{left,right}pad] Fix malformed expression + + commit b9571b87d5de5ecdeb83a184efc7585ef6b13429 + Author: Thomas Köppe + Date: Thu Nov 6 14:54:10 2025 -1000 + + [func.wrap.ref.class] Fix use of template parameter name "ArgTypes". + + Also use a codeblock to make the code presentation a bit tidier, + and add descriptive nouns before symbolic references. + + commit a451a97aafaae586df5b4f09df6ec168fb0a31c1 + Author: Eisenwave + Date: Sun Nov 2 10:36:06 2025 +0100 + + [simd.alg] Avoid the word "shall" in Preconditions + + commit bb1af1aeb02eb9bc75e430e25b4143b54eb9fcf4 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Jul 19 13:39:23 2025 +0200 + + [meta.reflection.member.queries] Add commas + + commit 17b6a3fa096663954a5737e8d6e0447fc4392da9 + Author: Alisdair Meredith + Date: Fri Jul 18 11:39:48 2025 -0400 + + [basic.link] Fix cross-reference to translation unit + + Tranalation units are defined in phase 7 of translation, + [lex.phases] not [lex.separate]. + + commit f65ab95e4f443cd0ab467d494513b606301acd98 + Author: Thomas Köppe + Date: Thu Nov 6 16:20:43 2025 -1000 + + [utilities] Use "Result:" element in \itemdescrs of types to describe the type. + + This replaces the use of the ad-hoc element "Type:" in three places with "Result:", + and adds "Result:" in other cases that didn't have an element at all. + + commit 35a6fb8ce7ee7dc95f8930804a23964827c889da + Author: Jens Maurer + Date: Fri Nov 7 08:26:54 2025 +0100 + + [intro.scope] Modernize by removing overly verbose description + + Fixes NB GB01-013 (C++26 CD). + + commit 8d375c7cdc626c252788547f10a060f10cb82dcf + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sun Nov 9 04:44:50 2025 +0100 + + [exec.run.loop.members] Remove extraneous period (#8451) + + commit f2b0254e2dd7428f1a160a04e1d11c467eb331ca + Author: Thomas Köppe + Date: Sat Nov 8 17:52:30 2025 -1000 + + [mdspan.sub.map.{left,right}] Fix typos: "layout_left" => "layout_right", "_rank" => "rank_" + + This was a misapplication of P2642R6. + + Also improves linebreaking for clarity. + + commit fad2722986e8cb9bee11d94fc15afb088b3fa940 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Nov 9 13:09:31 2025 +0000 + + [temp.names] Restore braced-init-list in definition of template-argument + + It was unintentionally deleted by commit + e3f552ff09eb42cec8ee0590e4b8aa716996b282. + + commit 605dcaa51e45a9b55dedea2ab88f593dd590f6a5 + Author: Eisenwave + Date: Sat Nov 8 23:31:49 2025 +0100 + + [inplace.vector.modifiers] Ensure correct type of returned iterator + + commit 99e4ffd66b61fce502e319b4ade56df7373301ef + Author: A. Jiang + Date: Mon Nov 10 23:44:35 2025 +0800 + + [dcl.pre] Fix grammatical error in lambda trailing-return-type (#8497) + + This seems to be an error in P2996R13. + + commit 15c21a586c5bc67917256d03ce89c9a43e5a4cee + Author: Hubert Tong + Date: Sun Nov 9 23:39:45 2025 -0500 + + [except.handle] Mark as note: exception object access via handler decl + + The subject paragraph is merely an observation and is redundant as + normative text. Make it a note, and strike the end of the last sentence + as it creates an impression that the exception object cannot be observed + without rethrowing. + + commit 2a7f36abe6e93e9c5f750df000ab4ea781580d39 + Author: Luc Grosheintz + Date: Thu Sep 4 15:49:24 2025 +0200 + + [mdspan.layout.left.cons] Fix typo in precondition. + + Here `other` is a layout mapping and layout mappings don't have this API + to access the `i`th extent. They only have `extents()` to get the + std::extents object. + + commit 8ee8d2d0292dde2ca72c300177752f4a2e4457df + Author: S. B. Tam + Date: Wed Nov 12 17:01:53 2025 +0800 + + [cpp.predefined] Sort `__cpp_consteval` before `__cpp_constexpr` (#8504) + + commit 9770db7bf288ad56ae98bdabd19935decab9da9f + Author: S. B. Tam + Date: Wed Nov 12 17:02:48 2025 +0800 + + [version.syn] Sort `__cpp_lib_format_path` before `__cpp_lib_format_ranges` (#8505) + + commit ccf746ffbabd5f74dece4a983cd52bd31b999f0a + Author: Hubert Tong + Date: Tue Nov 11 01:07:29 2025 -0500 + + [class.base.init] Add "direct" for _mem-initializer-id_-named members + + A _mem-initializer-id_ cannot be used to initialize a base class + data member from a derived class constructor; therefore, we mean + _direct_ non-static data member. + + commit e6150e3fa6d6dbbb901b4b7ccc075219d4515d5d + Author: Hubert Tong + Date: Mon Nov 10 23:37:24 2025 -0500 + + [class.mem.general] Fix data member definition to include anonymous union members + + Anonymous union members are not introduced by _member-declarator_. + + Fixes cplusplus/draft#4939. + + commit 4d9edbf31f8ea0cb870fd0512c29756f2c4a292c + Author: Hubert Tong + Date: Mon Nov 10 21:40:37 2025 -0500 + + [special] Add "direct" when defining "potentially constructed subobjects" + + The definition has "non-static data members". Only the direct ones are + intended. + + commit 4b9d4f6a4356de8630cd8b0981c6b1960d510230 + Author: Eisenwave + Date: Wed Nov 12 19:23:00 2025 +0100 + + [optional.ref.assign] Add missing Returns element + + commit 784cc65a741dfefc95328b8bc58199bc63ea661b + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Nov 12 19:46:55 2025 +0100 + + [cpp.predefined] Sort __cpp_impl_reflection before __cpp_impl_three_way_comparison + + commit 2ab6288129c4f3708f728b0f1a492e5d72b5c821 + Author: A. Jiang + Date: Mon Nov 10 09:19:20 2025 +0800 + + [locale.categories] Index base classes and members of category classes + + Enumerators of each unscoped enumeration type are indexed as members of + the enclosing class of the enumeration. + + commit 5e49effdce370fd445ce3218f14f37892d1f1629 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Nov 14 09:17:28 2025 +0100 + + [range.to.input.iterator] Move closing parentheses after @\exposid + + commit 19ad41dbd3446c34da01e3c5ea79ecce539ccd94 + Author: Alisdair Meredith + Date: Tue Nov 4 19:08:45 2025 -1000 + + [specialized.algorithms] Remove typename after new + + The `typename` keyword is not needed to identify a dependant + type in a `new` expression. + + commit 2e6b09beb01daad3d87914dfe9a0031de5816013 + Author: Eisenwave + Date: Sat Nov 8 23:05:37 2025 +0100 + + [cpp.predefined] Update value of __cpp_deduction_guides to 202207L + + commit 9ddf7e6d2937028b8c4ca99502d73d7a726ab737 + Author: Eisenwave + Date: Wed Nov 12 20:38:34 2025 +0100 + + [temp.arg.template] Add missing "template" when referring to template template parameters + + commit c097654ed3d7bf7f840c6eb8bfc10cebb74f26ea + Author: Jan Schultke + Date: Sun Nov 16 18:47:34 2025 +0100 + + [exec.when.all] Reverse the nesting of \exposid and \tcode for impls-for::complete (#8537) + + commit 3e707873fffd713c9daea0bb9e6e3f3a9f5ebcd8 + Author: Jan Schultke + Date: Sun Nov 16 18:50:16 2025 +0100 + + [atomics.types.generic.general] Replace "same_as" with "is_same_v" (#8538) + + commit 85128063cd29e93c28555d7a4a3b70b31c7e3337 + Author: Jan Schultke + Date: Sun Nov 16 22:37:35 2025 +0100 + + [numerics.c.ckdint] Add cross-reference to [basic.fundamental] (#8541) + + commit 7eacc15f859c44eb8b8f5c955b971e95428cd07b + Author: Eisenwave + Date: Mon Nov 17 10:46:10 2025 +0100 + + [format.args] Move "Implementations should ..." part into Recommended practice paragraph + + commit c6da41e3ade36f51f0f8a9cbb2aebea801ceeac2 + Author: S. B. Tam + Date: Tue Nov 18 04:31:38 2025 +0800 + + [algorithm.syn] Add missing comma (#8551) + + commit ff706ad6a5a40831d99984e69c0245aacb9613f7 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Wed Nov 19 10:41:16 2025 +0000 + + [class.temporary] Change "class type" to "type" + + Missed edit from P2900R14. + + commit 3ddbebd0eddd1b0418523e6a93864ce090d6d674 + Author: Jan Schultke + Date: Thu Nov 20 22:27:47 2025 +0100 + + [linalg.scaled.scaledaccessor] Add scaling_factor and nested_accessor to index (#8549) + + commit ebd315d92ab4ddb73d6ad8b30fb131329f4b434d + Author: A. Jiang + Date: Thu Apr 24 11:02:34 2025 +0800 + + [lib] Replace uses of `add_meow_t` with plain cv-qualifiers + + ...except for [tab:meta.trans.cv], because the wording change for + `add_cv` seems a bit non-trivial, and for the return type of `as_const`, + because the the change would affect mangled name. + + commit 1175936bde2c81012c7aa3b45b3ece46c32d19ff + Author: A. Jiang + Date: Sat Nov 29 17:21:46 2025 +0800 + + [container.node] Exposition-only formatting for node_handle members (#8555) + + Also changes `container_node_type` and `ator_traits` to + `container-node-type` and `ator-traits`, respectively. + + Adds missed "is `true`". + + commit 5b6fb19cc60d3a1b23e0124dc16a1fd69f33a40b + Author: S. B. Tam + Date: Sun Nov 30 19:20:43 2025 +0800 + + [algorithm.syn] Fix typo (#8572) + + commit ca1969050e652308a38d9b2990c980cf3cf654b5 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Dec 2 11:13:11 2025 +0000 + + [expr.prim.id.unqual] Remove unused meta-variable (#8574) + + commit 417bf3b746747f80bfa9f0ee50547522685cf5da + Author: Jan Schultke + Date: Thu Dec 4 00:46:57 2025 +0100 + + [cmath.syn] Align function parameters of ellint_3 (#8581) + + commit 69fe27f02385f16a7a1070eb66797ee6d5795cb8 + Author: Jonathan Wakely + Date: Thu Dec 4 15:07:48 2025 +0000 + + [range.slide.view] Fix names of reserve_hint overloads + + Fixes #8585 + + commit 371d28425eaa09138c3d1cdf34865d44ffc93fa3 + Author: Alisdair Meredith + Date: Sat Dec 6 00:39:17 2025 +0700 + + [cpp.predefined] Tidy specification of __FILE__ and __LINE__ (#8584) + + Promotes the footnotes to notes and adds cross-references. + + commit 940a063808899cde646274a185d7565fc0e09533 + Author: Hubert Tong + Date: Sun Dec 7 03:01:39 2025 -0400 + + [temp.constr.concept] Fix "no diagnostics is" (#8587) + + commit 0bb977830decd94822c024aff0e187d77c480f5b + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Wed Dec 10 20:06:58 2025 +0000 + + [basic.def.odr] Add punctuation (#8598) + + commit 62fc52e4d874d895d5e323421b54cfba1e568857 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Dec 11 21:52:45 2025 +0000 + + [basic.lookup.qual.general] Markup definition of "member-qualified name" (#8609) + + commit 8b2a7da97bb7779dbb060f7cd62dd9d596626ccd + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Dec 11 21:54:40 2025 +0000 + + [basic.lookup.elab] Replace "the" with "an" (#8612) + + commit 0bee9a0a02b3f5ed38ff30dc12f59bf378b0f5e5 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Apr 1 14:44:07 2025 +0000 + + [temp.constr.concept] Improve phrasing of note + + commit 284ffb85f96822d79e89124ef77e548a3f8362fb + Author: A. Jiang + Date: Mon Nov 17 11:29:12 2025 +0800 + + [string] Consistently spell return types and types of data members + + Affected sections: + - [basic.string.general] Align both overloads of `data` + - [basic.string.general] Use `(const_)reference` for consistency with + other sequence containers + - [string.access] Use `(const_)reference` for consistency with other + sequence containers + - [string.view.template.general] Use `const charT*` for `data` and a + data member, for the consistency with `basic_string`. + -[string.view.access] Use `const charT*` for `data` for consistency with + `basic_string` + + commit 0fa93a34dd25859212a708bbd9b5fb4f7e5d22d9 + Author: Alisdair Meredith + Date: Sun Nov 2 17:13:39 2025 -1000 + + [module.global.frag] Remove irrelevant note about preprocessor + + [module.global.frag] is entirely part of phase 7 of translation, + and it makes no sense to talk of preprocessing directive in the + grammar term *declaration-seq*. Strike the note rather than try + to turn it into something meaningful. + + commit 967ffd74041ba52334bbb3525485bbed0a3bd6cf + Author: Eisenwave + Date: Sat Nov 8 22:46:28 2025 +0100 + + [dcl.init.general] Prevent contradiction for initialization of aggregates + + commit 99914bdc2d932422d6c5c5e448f8d81e35dc0e97 + Author: Alisdair Meredith + Date: Sat Dec 13 18:21:49 2025 +0700 + + [cpp.cond] Keywords are not identifiers while preprocessing (#8518) + + commit 143f3a692399843796a005508d35096225b39146 + Author: Eisenwave + Date: Mon Nov 17 08:32:57 2025 +0100 + + [numerics.c.ckdint] Remove unnecessary "cv-unqualified" + + commit 7acb34c3ce9cffaf30da3935acbb52c38887daea + Author: Eisenwave + Date: Mon Nov 17 08:33:47 2025 +0100 + + [charconv.syn] Remove unnecessary "cv-unqualified" + + commit 1efa5fec0153e3682bc3c8dc99a35281ea11bb1c + Author: Jens Maurer + Date: Sat Nov 29 11:01:59 2025 +0100 + + [expr.add] Simplify phrasing around ptrdiff_t and avoid redundancy + + commit 68ea567df58609cab0e41fa805b0cd55db37784c + Author: Alisdair Meredith + Date: Tue Dec 2 23:39:03 2025 +0700 + + [lex.literal.kinds] Strike incomplete footnote + + It may be that the notion of literal in C++ and constant in C + were at one point close to a 1-1 mapping, but that it not + strictly the case any more. C++ has user-defined literals, + in C string-literals are distinct from constants, and C + specifies enumerators as literals too. + + Rather thsn clean up the footnote, or make clear that the + correspondance is weak, simply strike it. + + commit 3280bf769d88e21883e49f3fab41c93322e3a0f8 + Author: Alisdair Meredith + Date: Sat Dec 13 18:27:17 2025 +0700 + + [intro.memory] Convert footnote on CHAR_BIT into note (#8577) + + The information in the footnote is relevant to the main text. + + commit 6c8a056ee7d1fb3aabd9f96c8c9a03c8720e3c28 + Author: Alisdair Meredith + Date: Sat Dec 13 18:28:00 2025 +0700 + + [lex.string] Remove unused term from the index (#8588) + + commit d5b9659a0e7e3fc68914e30ffb3b5528246828f2 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Dec 8 18:18:07 2025 +0000 + + [lex] Avoid "shall" when not stating a direct requirement + + commit 0598cb129f4160467502bfd7870f285d9124e642 + Author: Alisdair Meredith + Date: Sat Dec 13 18:29:51 2025 +0700 + + [dcl.type.general] Strike irrelevant footnote (#8578) + + The reference to the "implicit int" rule in C has been out-dated for a long time. + + commit 6db574b1f0df2e279ab658bfc57b6929d325ad9b + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Dec 9 23:40:50 2025 +0000 + + [basic.scope.contract] Fix typo + + commit 21cc64a281ba7167d7c1c596afed63dd9f64ce80 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Dec 9 23:46:38 2025 +0000 + + [basic.scope.param] Use "of" when referring to the containing production + + commit 6c240f69beeb9dc3164684c583eef03643c40abf + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Dec 9 23:23:57 2025 +0000 + + [basic.def.odr] Fix use of undefined term + + Change "function definition scope" to "function parameter scope". + + commit 176d615e86a9e796cf14bd6546bfd8804984ee8d + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Dec 11 14:33:03 2025 +0000 + + [basic.lookup.argdep] Add missing words + + commit a091468825ef477a9d8110085f2963306dee9cfc + Author: Thomas Köppe + Date: Sun Dec 14 13:27:11 2025 +0000 + + [meta.define.static] Reword list to produce a proper sentence. + + commit 165c05c9203171a12a2f6ad9afdd593b9ac21bd3 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sun Dec 14 19:31:46 2025 +0100 + + [version.syn] Sort __cpp_lib_initializer_list before __cpp_lib_inplace_vector + + commit 488b2fa35c373b0bd425087bf3658635ac9338a0 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sun Dec 14 22:21:01 2025 +0100 + + [mdspan.sub.extents] Fix typo + + commit 002e9784d3ebbf94288181573017860f1c3ce065 + Author: Alisdair Meredith + Date: Tue Nov 4 15:07:50 2025 -1000 + + [lex.pptoken] Turn non-normative text into a note + + The last part of this paragraph is non-normative, so turn it + into a note. Also, the preceding sentence defining whitespace + characters is mostly unrelated to the precedingd defintion of + preprocessing tokens, so start a new paragraph to more clearly + show the comment assoication. + + commit c1fcb2b43946acb89857caf29c3cd7a95c568736 + Author: Alisdair Meredith + Date: Tue Nov 4 12:36:34 2025 -1000 + + [lex.token] Strike mention of whitespace in phase 7 + + It is meaningless to talk of whitespace separating tokens + in phase 7 as whitespace is discarded at the end of phase 4. + + commit 08ab900f50fa30a511d38b1f7faa6715b2749a29 + Author: Alisdair Meredith + Date: Tue Dec 2 23:02:35 2025 +0700 + + [lex.token] Strike useless footnote + + commit dd1c71e10912d1ee91c96d5a0a9f59df3f849863 + Author: S. B. Tam + Date: Wed Dec 10 11:34:16 2025 +0800 + + [expr.prim.id.unqual] Fix misplaced example + + commit d2fff2b231512a469b1f503722ad2136f116346c + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Dec 13 19:53:04 2025 +0100 + + [basic.def.odr] Remove duplicate "a" + + commit 93914a36c1945d330a7c7d5c4488e1d10e5bbe75 + Author: Jan Schultke + Date: Sun Dec 14 07:35:31 2025 +0100 + + [utility.intcmp] Rephrase integer type constraint of "standard or extended" as "signed or unsigned" + + commit 508c4f902d4c65b80b40d7fb1f764b7b18293ef3 + Author: Jan Schultke + Date: Tue Nov 18 09:08:21 2025 +0100 + + [atomics.types.int] Use the terms "character type" and "standard integer type" instead of listing each type + + Revised description of atomic class template specializations. + + commit b37dc196a8e4feacd5f5292022bdde90f95d7c4a + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Dec 15 08:54:51 2025 +0100 + + [range.reverse.overview] Add indefinite article + + commit 8ef4e628d6da638b5a5880df11b1bf1e2185a964 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Dec 15 12:16:12 2025 +0100 + + [hive.operations] Fix singular/plural mismatch (#8621) + + commit 9a06fbfd9379224c6efb77adab77cc3f9595b63d + Author: Alisdair Meredith + Date: Tue Nov 4 15:48:11 2025 -1000 + + [lex.charset] Move reference to glyphs to appropriate place + + The statement that glyphs are used to identify members of the + basic character set does not belong separating two sentences + introducing and then defining preprocessing tokens. + + Also, we do not *exlusively* use glyphs for this purpose but + also directly call out Unicode code points too, so tone down + the phrasing to glyphs are *often* used to ... + + commit a2289f6652c4b09811dfda76b0e0fd2208c71617 + Author: Thomas Köppe + Date: Mon Dec 15 11:46:12 2025 +0000 + + [exec.bulk, exec.spawn.future] Fix escaping and comment alignment + + commit 37201bf548ab64a72dee297cef56a67c88326ee3 + Author: Alisdair Meredith + Date: Thu Dec 4 11:58:20 2025 +0700 + + [cpp.replace.general] Promote footnote to note + + We now have a paragraph where the footnote would be more + appropriately attached as a note. + + commit 20eff244639825d616061d7155967840c337582e + Author: Thomas Köppe + Date: Mon Dec 15 12:11:55 2025 +0000 + + [iterator.range] Turn long sentence listing headers into list diff --git a/papers/n5047.html b/papers/n5047.html new file mode 100644 index 0000000000..6bb2b38ca2 --- /dev/null +++ b/papers/n5047.html @@ -0,0 +1,1787 @@ + + + + + +N5047 + + +

N5047 Editors’ Report:
Programming Languages — C++

+ +

Date: 2026-05-12

+ +

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

+ +

Acknowledgments

+ +

Thanks to all those who have +submitted editorial issues, +to those who have provided pull requests with fixes, +and to everyone who drafted motion applications. +Special thanks to Jan Schultke for drafting a lot of motion applications, +to Andreas Krug for ongoing careful reviews, +and to Daniel Krügler for an exceptionally thorough review +that spotted many mistakes in the motion applications.

+ +

New papers

+ +
    +
  • N5046 is the +current working draft for C++26. It replaces +N5032.
  • +
  • N5047 is this Editors' Report.
  • +
+ + +

The Draft International Standard that will be sent for the ISO ballot has not +yet been completed, but will include the changes from N5046. As usual, since +N5046 has not yet been approved in a WG21 meeting, it is instead being reviewed +by an editorial review committee that was selected in Croydon, as per WG21 +Poll 3. N5046 includes some, but not all of the review committee’s feedback.

+ +

Motions incorporated into working draft

+ +

Notes on motions

+ +

All motions were applied cleanly.

+ +

Some reconciliation was needed among LWG motions (in particular starting at +motion 28), but paper authors and LWG had already included relevant merging +instructions in the papers.

+ +

The wording of P3980R1 from LWG Motion 29 has been reconciled with intervening +changes from issues LWG 4339 and LWG 4347 from LWG Motion 2.

+ +

Core working group polls

+ +

CWG Poll 1 does not change the working draft.

+ +

CWG Poll 2. Accept as Defect Reports and apply the proposed resolutions of all issues +except issues 3088, 3119, 3122, 3123, 3124, 3131, 3135, 3140, 3141, 3143, 3145, 3149, 3162, and 3172 in +P4160R0 +(Core Language Working Group “ready” Issues for the March, 2026 meeting) to the C++ Working Paper.

+ +

CWG Poll 3. Apply the proposed resolutions of issues +3088, 3119, 3122, 3123, 3124, 3131, 3135, 3140, 3143, 3145, 3149, 3162, and 3172 in +P4160R0 +(Core Language Working Group “ready” Issues for the March, 2026 meeting) to the C++ Working Paper.

+ +

CWG Poll 4. Accept as a Defect Report and apply the changes in +P3924R1 +(Fix inappropriate font choices for “declaration”) to the C++ Working Paper. +This addresses ballot comment US 11-400.

+ +

CWG Poll 5. Accept as a Defect Report and apply the changes in +P4136R2 +(#line is not in line with existing implementation) to the C++ Working Paper. +This addresses ballot comment FR-009-108.

+ +

CWG Poll 6. Accept as a Defect Report and apply the changes in +P4004R1 +(Reconsider CWG 1395 “Partial ordering of variadic templates reconsidered”) to the C++ Working Paper.

+ +

CWG Poll 7. Accept as a Defect Report and apply the changes in +P3865R3 +(Class template argument deduction (CTAD) for type template template parameters) to the C++ Working Paper.

+ +

CWG Poll 8. Apply the changes in +P3598R0 +(CWG 3158 – const-ification of Splice Expressions) to the C++ Working Paper.

+ +

CWG Poll 9. Apply the changes in +P3726R2 +(Adjustments to Union Lifetime Rules) to the C++ Working Paper. +This addresses ballot comment DE 087.

+ +

CWG Poll 10. Accept as a Defect Report and apply the changes in +P4143R0 +(Constant evaluation when?) to the C++ Working Paper. +This partially addresses ballot comment US 33-065.

+ +

CWG Poll 11. Accept as a Defect Report and apply the changes in +P4149R1 +(Define “immediate context”) to the C++ Working Paper. +This addresses ballot comment US 54-100 and core issues 1844 and 2296.

+ +

CWG Poll 12. Accept as a Defect Report and apply the changes in +P3769R1 +(Clarification of placement new deallocation) to the C++ Working Paper.

+ +

CWG Poll 13. Apply the proposed resolution of issue 3141 in +P4160R0 +(Core Language Working Group “ready” Issues for the March, 2026 meeting) to the C++ Working Paper.

+ +

Library working group polls

+ +

LWG Poll 1. Apply the changes in +P4145R0 +(C++ Standard Library Ready Issues to be moved in Croydon, Mar. 2026) to the C++ working paper.

+ +

LWG Poll 2. Apply the changes in +P4146R0 +(C++ Standard Library Immediate Issues to be moved in Croydon, Mar. 2026) to the C++ working paper.

+ +

LWG Poll 3. Apply the changes in +P3690R1 +(Consistency fix: Make simd reductions SIMD-generic) to the C++ working paper. +This addresses ballot comment AT8-279.

+ +

LWG Poll 4. Apply the changes in +P3844R4 +(Reword [simd.math] for consteval conversions) to the C++ working paper. +This addresses ballot comment DE-286.

+ +

LWG Poll 5. Apply the changes in +P3932R0 +(Fix LWG4470: Fix integer-from in [simd]) to the C++ working paper.

+ +

LWG Poll 6. Apply the changes in +P4012R1 +(Value-preserving consteval broadcast to simd::vec) to the C++ working paper. +This addresses ballot comment DE-286.

+ +

LWG Poll 7. Apply the changes in +P3886R0 +(Wording for AT1-057) to the C++ working paper. +This addresses ballot comment AT 1-057.

+ +

LWG Poll 8. Apply the changes in +P3936R1 +(Safer atomic_ref::address (FR-030-310)) to the C++ working paper +and update the value of the __cpp_lib_atomic_ref macro. +This addresses ballot comment FR-030-310.

+ +

LWG Poll 9. Apply the changes in +P4140R0 +(Proposed resolution for US70-126: allow incomplete types in type_order) to the C++ working paper. +This addresses ballot comment US 70-126.

+ +

LWG Poll 10. Apply the changes in +P3373R4 +(Of Operation States and Their Lifetimes) to the C++ working paper. +CA-338.

+ +

LWG Poll 11. Apply the changes in +P3986R1 +(A Wording Strategy for Inlinable Receivers) to the C++ working paper. +This addresses ballot comment CA-318.

+ +

LWG Poll 12. Accept as a Defect Report and apply the changes in +P3059R2 +(Making user-defined constructors of view iterators/sentinels private) to the C++ working paper. +This addresses ballot comment GB 09-257.

+ +

LWG Poll 13. Accept as a Defect Report and apply the changes in +P3725R3 +(Filter View Extensions for Safer Use, Rev 3) to the C++ working paper. +This addresses ballot comments AT9-249, RU-250, DE-251.

+ +

LWG Poll 14. Apply the changes in +P3828R1 +(Rename the to_input view to as_input) to the C++ working paper. +This addresses ballot comment DE-248.

+ +

LWG Poll 15. Apply the changes in +P3795R2 +(Miscellaneous Reflection Cleanup) to the C++ working paper. +This addresses ballot comments US 42-078 and US 85-150 and US 122-184 and US 128-192 and US 95-202 and US 131-195.

+ +

LWG Poll 16. Apply the changes in +P3948R1 +(constant_wrapper is the only tool needed for passing constant expressions +via function arguments) to the C++ working paper. +This addresses ballot comments FR-019-210 and FR-021-218.

+ +

LWG Poll 17. Apply the changes in +P3978R3 +(constant_wrapper should unwrap on call and subscript) to the C++ working paper.

+ +

LWG Poll 18. Apply the changes in +P3961R1 +(Less double indirection in function_ref) to the C++ working paper. +This addresses ballot comment RU-220.

+ +

LWG Poll 19. Apply the changes in +P3981R2 +(Better return types in std::inplace_vector and std::exception_ptr_cast) to the C++ working paper. +This addresses ballot comments PL-006 and US 68-122 and US 150-228 and GB 08-225.

+ +

LWG Poll 20. Apply the changes in +P4022R0 +(Remove try_append_range from inplace_vector for now) to the C++ working paper. +This addresses ballot comment PL-006.

+ +

LWG Poll 21. Apply the changes in +P4037R1 +(Supporting signed char and unsigned char in random number generation) to the C++ working paper. +This addresses ballot comment RU-272.

+ +

LWG Poll 22. Apply the changes in +P3450R1 +(Extend std::is_within_lifetime) to the C++ working paper. +This addresses ballot comment US 82-145.

+ +

LWG Poll 23. Apply the changes in +P3982R2 +(Split strided_slice into extent_slice and range_slice for C++26) to the C++ working paper. +This addresses ballot comment PL-007.

+ +

LWG Poll 24. Apply the changes in +P4144R1 +(Remove span’s initializer_list constructor for C++26) to the C++ working paper.

+ +

LWG Poll 25. Apply the changes in +P3804R2 +(Iterating on parallel_scheduler) to the C++ working paper. +This addresses ballot comment RO 4-395.

+ +

LWG Poll 26. Apply the changes in +P3787R2 +(Adjoints to “Enabling list-initialization for algorithms”: uninitialized_fill) to the C++ working paper. +This addresses ballot comment FR-027-267.

+ +

LWG Poll 27. Apply the changes in +P3842R2 +(A conservative fix for constexpr uncaught_exceptions() and current_exception()) to the C++ working paper. +This addresses ballot comments PL-012 and GB 03-119 and DE-120 and US 67-118 and FI-121.

+ +

LWG Poll 28. Apply the changes in +P3826R5 +(Fix Sender Algorithm Customization) to the C++ working paper. +This addresses ballot comments US 207-328 and US 202-326 and FR-031-219 and FI-331 and CA-358.

+ +

LWG Poll 29. Apply the changes in +P3980R1 +(Task’s Allocator Use) to the C++ working paper. +This addresses ballot comments US 254-385 and US 253-386 and US 255-384 and US 261-391.

+ +

LWG Poll 30. Apply the changes in +P4156R0 +(Rename meta::has_ellipsis_parameter to meta::is_vararg_function) to the C++ working paper. +This addresses ballot comment FR-017-155.

+ +

LWG Poll 31. Apply the changes in +P3953R3 +(Rename std::runtime_format) to the C++ working paper.

+ +

LWG Poll 32. Apply the changes in +P4052R0 +(Renaming saturation arithmetic functions) to the C++ working paper. +This addresses ballot comment FR-026-265.

+ +

LWG Poll 33. Apply the changes in +P3941R4 +(Scheduler Affinity) to the C++ working paper. +This addresses ballot comments US 232-366 and US 233-365 and US 234-364 and US 235-363 and US 236-362.

+ +

LWG Poll 34. Apply the changes in +P3856R8 +(New reflection metafunction - is_structural_type) to the C++ working paper. +This addresses ballot comment US 49-090.

+ +

LWG Poll 35. Apply the changes in +P3927R2 +(task_scheduler support for parallel bulk execution) to the C++ working paper. +This addresses ballot comment US 238-368.

+ +

LWG Poll 36. Apply the changes in +P4151R1 +(Rename affine_on) to the C++ working paper.

+ +

LWG Poll 37. Apply the changes in +P4159R0 +(Make sender_in and receiver_of exposition-only) to the C++ working paper.

+ +

LWG Poll 38. Apply the changes in +P4154R0 +(Renaming various execution things) to the C++ working paper. +This addresses ballot comments US 205-320 and RO 4-395.

+ +

National body comment resolution

+ +

A large number of national body comments for the C++26 Committee Draft have been +addressed in this working draft.

+ +

Editorial comments

+ +

Most editorial national body comments were addressed before the Kona 2025 meeting, +see Editor’s Report N5033 +for the full list.

+ +

A few additional national body comments have since been found editorial +and have now been addressed:

+ + + + +

Non-editorial comments

+ +

The following national body comments were addressed by the motions approved at the Croydon 2026 meeting:

+ + + + +

Editorial changes

+ +

Major editorial changes

+ +

The subclause [expr.const], formerly titled “Constant expressions”, +has been renamed to “Constant evaluation” and its contents have been +divided into smaller subclauses; see commit +98a668efc2ab0bea86dcf9a2d8bf583dddc35e32.

+ +

Minor editorial changes

+ +

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

+ +
commit cc2efebb57ea02ea2eac19220c873c158f855859
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Dec 15 15:43:02 2025 +0000
+
+    [basic.start.dynamic] Fix typo (#8654)
+
+commit 3e6cad293e448f7d9f9d859d07b5371b7e054789
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Dec 15 15:47:37 2025 +0000
+
+    [basic.types.general] Improve presentation of comments in example (#8636)
+
+    - put "sizeof" in code font
+    - use a comma after "OK"
+
+commit f6319760f3f6d9a710fdb4be5e54c111abfc1e92
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Dec 14 16:21:20 2025 +0000
+
+    [basic.link] Modernize wording about type aliases
+
+commit f66f4c675c0c60f822bb24543cd607e14be24a93
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Dec 14 16:31:25 2025 +0000
+
+    [intro.memory] Update outdated example
+
+commit 176528f688cec22566f1de8286f1c3fae43887ce
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Dec 14 16:46:10 2025 +0000
+
+    [intro.object] Remove redundant "non-bit-field"
+
+commit 1d9fdb066e95b7be58881f24977a20a51359097c
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Dec 14 17:40:14 2025 +0000
+
+    [basic.types.general] Remove unused meta-variable
+
+commit 2dbe5a3247b100a6e4cdddab46eda5595d9d3de1
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Dec 15 21:58:39 2025 +0000
+
+    [basic.start.dynamic] Add cross-reference for "interface dependency" (#8653)
+
+commit 166fd7efa129ce139e2a859758410fd7fd0955b3
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Dec 15 20:46:26 2025 +0100
+
+    [exec.scope.concepts] Fix typos
+
+commit d8a8c5ad3b354087a416c02c2059b9ef62534c72
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Apr 25 00:30:02 2024 +0800
+
+    [expos.only.entity] Say typedef-names are declared
+
+    Also use "provided for exposition only" from @W-E-Brown's suggestion.
+
+commit 7fcd646f6d82721e32f5fb5dc11994b8b0cf1d64
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Aug 3 00:37:14 2023 +0800
+
+    [type.descriptions.general] Use "shown" for impl-def types
+
+commit 34c7cffe9e7d1807df4b986e648392bb3a1dfae0
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Aug 3 00:38:04 2023 +0800
+
+    [enumerated.types] Reword enumerated types
+
+    Also mention [re].
+
+commit cc2ecb3a2c85b2e196ca5697287270e9f62878c8
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Aug 3 00:38:45 2023 +0800
+
+    [bitmask.types] Reword bitmask types
+
+commit 03545f10f200193e15d3f0227b289ff037146abf
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Apr 25 00:33:17 2024 +0800
+
+    [extern.types] Use "declared" for C library types
+
+commit d21a84cc95a9a3e619139a1c53d7937474ea03b8
+Author: A. Jiang <de34@live.cn>
+Date:   Fri Jul 28 23:51:45 2023 +0800
+
+    [cstdint.syn] Use "declare" for typedef-names
+
+commit ad83c0b2bc498eac0fc4d97850143581dbfa703c
+Author: A. Jiang <de34@live.cn>
+Date:   Fri Jul 28 23:52:27 2023 +0800
+
+    [stdfloat.syn] Use "declare" for typedef-names
+
+commit 30000d169f5b6db54d7d61ed35aa825fbbdfa70d
+Author: A. Jiang <de34@live.cn>
+Date:   Fri Jul 28 23:58:28 2023 +0800
+
+    [meta.rqmts] Use "declare" for typedef-names
+
+commit c5eac2a7d176110d63e153fa1d5abcee9681943e
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Jul 29 00:02:58 2023 +0800
+
+    [meta.trans.other] Use "declare" for typedef-names
+
+    In the example, it seems a bit verbose to say "declarations and
+    definitions".
+
+commit cbd6e735fdea46f312d27ae802e83766d8dc43f8
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Jul 29 00:03:49 2023 +0800
+
+    [ratio.si] Use "declare" for typedef-names
+
+commit 8210a2cc6ff0bb2a90c9b20cf60ee1d369156c4b
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Jul 29 00:12:12 2023 +0800
+
+    [readable.traits] Use "declare" for typedef-names
+
+commit c5b55216c7a80fe7187bdbc4f5e62b6ef53e6008
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Jul 29 00:14:51 2023 +0800
+
+    [iterator.traits] Use "declare" for typedef-names
+
+commit b892cf9dd9a5d0e8d9046d0e99b72487f3316b51
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Jul 29 00:16:03 2023 +0800
+
+    [std.iterator.tags] Use "declare" for typedef-names
+
+commit 535f5a348bf4eab6c0d71673209bc853103880c2
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Apr 24 00:28:25 2024 +0800
+
+    [const.iterators.types] Avoid "defining" `iterator_category`
+
+    Use "declare" instead.
+
+commit af81d11662c4b7dfb135176c5282788f6e3f50d4
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Apr 24 00:28:58 2024 +0800
+
+    [move.iterator] Avoid "defining" `iterator_category`
+
+    Use "declare" instead.
+
+commit 45a31c6e70f49792ee3650a106ad03a8a95d7e03
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Apr 24 00:29:32 2024 +0800
+
+    [common.iter.types] Avoid "defining" typedef-names
+
+commit 5253ec6c6229c704303d682c4bd1d0e197506716
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Apr 24 00:30:51 2024 +0800
+
+    [range.filter.iterator] Avoid "defining" typedef-names
+
+    Use declared" instead.
+
+commit 251d0c7ef52327f628086e228a244792a467f27c
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Apr 24 00:31:39 2024 +0800
+
+    [range.transform.iterator] Avoid "defining" typedef-names
+
+    Use "declare" instead.
+
+commit 1fa1d4afe6111b03aeec7ced79ed0bf7f6a2569b
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Apr 24 00:32:17 2024 +0800
+
+    [range.join.iterator] Avoid "defining" typedef-names
+
+    Use "declare" instead.
+
+commit 55e740c366d1c691c31fda455f6acfcfe7e60979
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Apr 24 00:33:09 2024 +0800
+
+    [range.join.with.iterator] Avoid "defining" typedef-names
+
+    Use "declare" instead.
+
+commit ff0957c1a71f4b668acf9d316efcb31d59495398
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Apr 24 00:45:09 2024 +0800
+
+    [range.concat.iterator] Avoid "defining" typedef-names
+
+    Use "declare" instead.
+
+commit 293648ef77f2533187a1ca89f9649c21da0c06b1
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Apr 24 00:33:37 2024 +0800
+
+    [range.elements.iterator] Avoid "defining" typedef-names
+
+    Use "declare" instead.
+
+commit ae40e054b0ad38993c52f454862682bcdd3bee14
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Apr 24 00:34:43 2024 +0800
+
+    [range.zip.transform.iterator] Avoid "defining" `iterator_category`
+
+    Use "declare" instead.
+
+commit 20564e2186a5f237f1a89fb0b470eb19f662fe2d
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Apr 24 00:35:44 2024 +0800
+
+    [range.stride.iterator] Avoid "defining" typedef-names
+
+    Use "declare" instead.
+
+commit da9cc238aa051d127e7ea0d196622a161cab77f1
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Oct 17 19:19:03 2024 +0800
+
+    [format.string.std] Use "declare" for typedef-names
+
+commit b77796b42a5d2854a186858d8a36c558ddc18da4
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Jul 29 00:47:45 2023 +0800
+
+    [atomics.alias] Use "declare" for typedef-names
+
+commit ae8e81dfc21ead75c8d4fcfdb75c4638b14a7fdb
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Jul 29 00:48:28 2023 +0800
+
+    [stdatomic.h.syn] Use "declare" for typedef-names
+
+commit 7d4d7f37aa2122fe6e292fcc9520b022fba70d13
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Fri Dec 19 03:50:07 2025 -0400
+
+    [expr.const] Fix typo "with [...]" => "within the evaluation" (#8669)
+
+commit e9fa860d3af7236fbe43d56ffef4abec93b6a0c9
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Dec 14 23:54:38 2025 +0000
+
+    [basic.contract.eval] Replace "operation" with "evaluation"
+
+commit 4dc76ac3cc9895782b199af745dd42614a7d0327
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Tue Dec 23 01:15:15 2025 +0800
+
+    [flat.multiset.modifiers] Add missing constexpr (#8675)
+
+commit a4fbfa2a689dbd2f0d7a16b29af92dc74574381d
+Author: Andrey Ali Khan Bolshakov <bolsh.andrey@yandex.ru>
+Date:   Tue Dec 23 09:57:57 2025 +0300
+
+    [time.syn] Add missing namespace qualification (#8677)
+
+commit 7abca25d03460cd35e880f29fc7001c69218594a
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Dec 23 13:21:13 2025 -0500
+
+    [expr.new] Precise cross-reference for throwing exceptions (#8681)
+
+commit db380b0d4015eb7d2956e73e59c1c5c26f3651a4
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Dec 29 09:54:10 2025 +0800
+
+    [version.syn] Reformat a comment to avoid splitting `<type_traits>`
+
+    Co-authored-by: Alisdair Meredith <alisdairm@me.com>
+
+commit c59d8c8e9d6fe8adba2142d1344b0e142c9d6ff4
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Dec 29 09:54:36 2025 +0800
+
+    [initializer.list.syn] Drop redundant comments
+
+commit 3dc04f5cda1c8470c0da7c6f9ffcd6d463429ef2
+Author: Hana Dusíková <hanicka@hanicka.net>
+Date:   Fri Jan 2 16:35:49 2026 +0100
+
+    [hive.cons] Fix typo "allocator_traits<alloc>" -> "allocator_traits<Allocator>" (#8689)
+
+commit 7c8a960f3f06d5c565b0976402ce534848926181
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Sat Jan 24 00:52:07 2026 +0800
+
+    [forward.list.overview] Add missing constexpr (#8717)
+
+commit f3b76296f598bc5266e649f8fb0a2c5ef19ae0c3
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jan 26 15:52:54 2026 +0100
+
+    [temp.dep.type] Add period to end of sentence (#8723)
+
+commit 6704d82cd336baaa4f6fe45013c390453991ee86
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Jan 30 21:57:16 2026 +0100
+
+    [except.handle] Add commas (#8727)
+
+commit 16f4265888fd30e59512a21a5391327d6b525de1
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Jan 31 19:28:43 2026 +0100
+
+    [value.error.codes] Fix indefinite article (#8730)
+
+commit 91156093a76177329a990dfdf38f19dad3531688
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Feb 3 23:19:25 2026 +0100
+
+    [concept.comparisoncommontype] Add period to end of sentence (#8731)
+
+commit 15fc5a2f7106963d8e7904eee03bebe2aaf7a81b
+Author: Giuseppe D'Angelo <dangelog@users.noreply.github.com>
+Date:   Sun Feb 22 20:45:53 2026 +0100
+
+    [alg.remove] Use E(i) for predicate on iterator i (#8760)
+
+    The `E` in the code is actually meant to be a function on an
+    iterator `i`; amend both usages to `E(i)`. This was already done
+    everywhere else (for instance in copy_if or unique_copy).
+
+commit 5b07f42565be7972f2b5d729a740da12c5e6b202
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Feb 24 10:35:57 2026 +0000
+
+    [thread.mutex.requirements.mutex.general] Fix grammar (#8765)
+
+commit 4ce955bd576f6a9d68da494e8b560ca8b9375005
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Feb 24 10:38:03 2026 +0000
+
+    [exec.snd.expos] Fix order of make_obj_using_allocator arguments (#8766)
+
+commit 3f6372b97bcdee30b8591077c8479a56bb50fc67
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Wed Feb 25 15:35:49 2026 -0600
+
+    [const.wrap.class] Add missing this to compound assignment operators (#8758)
+
+    This corrects a misapplication of LWG4383 in commit bdcfe2c9a54ca350e9bfc59227bb0285a59c635d.
+
+commit 8338b7caa5a38ef79e5c2f8316078f6f74d1b8ad
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Mar 5 08:58:29 2026 +0100
+
+    [text.encoding.id] Add colon after "as follows" (#8776)
+
+commit eba89bc9b32d230168571737d6aa86c06329502b
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Dec 22 17:59:19 2025 -0500
+
+    [lex.phases] Make note on the notion of file more prominent
+
+    The notion that when the standard refers to files does not
+    necessarily imply a file in a traditional filing system is
+    more fundamental than its late appearance in the middle of
+    phase 7 of translation.  Move that note right to the top of
+    [lex] where we first talk of storing the program text in
+    source files, where is will be understood even before the
+    phases of translation.
+
+commit 13cad628c5c3883c8fb8dcb4256199b21c13be1d
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Mar 12 08:08:56 2026 +0100
+
+    [istream.unformatted] Add right parenthesis
+
+commit 981d32246c951b18dc816cecfdb3ffbb5d72ad54
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Mar 17 21:04:34 2026 +0100
+
+    [stoptoken.concepts] Remove superfluous \item (#8790)
+
+commit 92b3a22228ffb3db219debace0e5fbe82c592354
+Author: Can <cancagri.dev@gmail.com>
+Date:   Fri Mar 20 10:32:30 2026 +0300
+
+    [utility.intcmp] Fix name of type parameter (#8770)
+
+    Introduced by commit 93914a36c1945d330a7c7d5c4488e1d10e5bbe75 .
+
+commit 11106fc54b79e1ee21805ea77596908ca4f3a8f3
+Author: Abhinav Agarwal <abhinavagarwal07@users.noreply.github.com>
+Date:   Fri Mar 20 10:56:06 2026 -0700
+
+    [mdspan.sub.map.common,mdspan.sub.map.left] Fix S(p)liceSpecifiers typos (#8799)
+
+commit 36ce9cbe82d472997ca9b978e69e64d6ddd99dcd
+Author: Abhinav Agarwal <abhinavagarwal07@users.noreply.github.com>
+Date:   Fri Mar 20 10:56:49 2026 -0700
+
+    [linalg.algs.blas3.rank2k] Add missing \pnum and \effects (#8801)
+
+commit cda7c18d2b83b354bae6001cdf7cb7d3f9203f32
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Mar 21 17:36:47 2026 +0800
+
+    [lib] Replace bad uses of "instantiation" with "specialization" (#8379)
+
+    Affected sections:
+    - [allocator.requirements.general]
+    - [namespace.std]
+    - [pointer.traits.types]
+    - [allocator.traits.types]
+    - [tuple.general]
+    - [format.context]
+    - [numeric.requirements]
+    - [rand.util.canonical]
+    - [thread.req.lockable.timed]
+    - [thread.sharedtimedmutex.requirements.general]
+
+    - In [tuple.general], change "is similar to" to "behaves similarly to"
+    to avoid confusing with "similar types" in the core specification.
+
+commit dc5928bdac7e3301d78c8fae5f4cae655a9a06fb
+Author: A. Jiang <de34@live.cn>
+Date:   Sun Mar 22 14:14:40 2026 +0800
+
+    [vector.bool.fmt][container.adaptors.format] Add missing `constexpr` and other missed edits (#8768)
+
+    Fixes edits from P3391R2 missed by commit cc63c64cba30089a366b024ffc8cc0532b4fb508 .
+
+commit c6fecf491063eef95384e54813812f6c6aaeab6a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Mar 23 11:40:36 2026 +0000
+
+    [expected.object.eq] Add missing negation (misapplied wording).
+
+    The negation was accidentally omitted in the application of P3905R0,
+    approved in Kona 2025 (265b4774c754b36e50bec7a528cbbc87676b0c85).
+
+commit 6913287752040f7adecdac5af60c90e2701a04e0
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Feb 25 15:04:34 2026 +0800
+
+    [format] Consistently add `constexpr` to function descriptions
+
+    P3391R2 only added `constexpr` to synopses but not descriptions for some
+    formatting functions. This PR consistently adds `constexpr` to the
+    descriptions.
+
+commit 45c820b6a9d87b18f3ad5c445c5e61e2ee806a6d
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Tue Dec 16 23:52:12 2025 -0500
+
+    [diff.basic] Use enum example instead of example outdated since C99
+
+    C99 subclause 6.2.7, "Compatible type and composite type", had this
+    sentence:
+    > If one is declared with a tag, the other shall be declared with the
+    > same tag.
+
+commit 3e53098c0ef22b62ab2dd393411141fceeda03bd
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Tue Dec 16 23:57:14 2025 -0500
+
+    [diff.basic] Stop claiming, as harmless, type-based aliasing violations
+
+commit c40c5f03a02c7e0f2564de46aea4ceebb1c799e4
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Feb 13 12:21:45 2026 +0100
+
+    [intro.compliance.general] Mark documentation encouragement as recommended practice
+
+commit d8ff3c08615932a207f956a61ebd6e5805f9a9bd
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Dec 14 17:15:48 2025 +0000
+
+    [basic.stc.dynamic] Spell out compound type names
+
+commit e70a19ba60ccf3eeed62bf82e4b33584272a1c86
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Feb 26 08:30:31 2026 +0100
+
+    [lex.key] Emphasize that keywords are created in phase 6
+
+    This was overlooked in CWG3094, applied with commit 94055b39a90285d8ae15f8f864a39a328f42a359.
+
+commit 0807a339b8bcae60a9d2285f0a08aab61aeece0d
+Author: Barry Revzin <barry.revzin@gmail.com>
+Date:   Thu Jan 29 07:59:28 2026 -0600
+
+    Clarify pack-index-specifier rules
+
+commit f55d63dcef1640f292451a3efe98f56d4afa2383
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Dec 14 17:56:03 2025 +0000
+
+    [basic.fundamental] Strike explanatory sentence; touch up note
+
+commit f4d8ecb2aa29122d63e5f56119a83dd4bb2ad3ca
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Dec 14 18:23:18 2025 +0000
+
+    [basic.extended.fp] Replace "typedef-name" with "type alias"
+
+commit 2efe693eb09f8c6d364c757a82b640e2ced9f107
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Dec 17 14:32:48 2025 +0100
+
+    [intro.refs], [numeric.limits] Remove all references to ISO/IEC 10967-1:2012
+
+commit b54449db95dcdfa8ae4d8221ef55f7fca0f358d9
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Dec 14 23:06:53 2025 +0000
+
+    [basic.start.static] Improve readability of example
+
+commit cd15f7a88e6390fb31aa766196205e722779d240
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Thu Dec 18 19:41:46 2025 -0500
+
+    [stmt.pre] Streamline decl-specifier restrictions on conditions, etc.
+
+    Avoid an abrupt shift from a mathematical introduction to the
+    specification of additional normative requirements.
+
+    Expresses universal quantification more directly.
+
+commit d3f57042d283c06cdb066eab1fc61661df0fc4de
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Jul 23 14:23:21 2023 +0200
+
+    [temp.point] Itemize long conditionals in three paragraphs
+
+commit ecc669c503bb875b65cbd4de3d231a8ac9e4bb70
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Tue Mar 10 15:07:57 2026 +0800
+
+    [meta.syn] Add function parameter names
+
+    These two seem to be the only ones where the function parameter names are omitted in the declaration.
+    Add names to ensure consistency.
+
+commit 98a668efc2ab0bea86dcf9a2d8bf583dddc35e32
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Mar 26 21:57:48 2026 +0100
+
+    [expr.const] Introduce subclauses
+
+commit a2933d5fd4e592bcd8669a51a359c5a850b32de2
+Author: Davis Herring <herring@lanl.gov>
+Date:   Thu Mar 26 21:00:20 2026 +0000
+
+    Refine cross references into [expr.const]
+
+commit 13906dcab8cfb87f880ea444336cbcc37165cd67
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Dec 11 14:14:32 2025 +0000
+
+    [basic.lookup.unqual] Rephrase to avoid incorrect use of term
+
+commit ad94af979e8dfac9ca9af4aa22c66beec7935cfd
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Mar 25 21:05:15 2026 +0800
+
+    [iostream.forward.overview] Add missing mentions of spanbuf and spanstreams
+
+    A follows up to P0448R4.
+
+commit 6a31f94c5ef15fdb592c558cd63b2bd02bd18c8a
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Mar 25 21:05:37 2026 +0800
+
+    [iostream.forward.overview] Say "designate specialization".
+
+    This replaces the imprecise and informal phrase "define instances of
+    class templates".
+
+commit 731cda191b915555c6816912361e431c82e7e2f6
+Author: Matthias Kretz <m.kretz@gsi.de>
+Date:   Tue Nov 4 05:17:01 2025 -1000
+
+    [simd.permute.*] Change M back to V since the wording refers to V
+
+    This was changed editorially by b6e501026e14600fed911183336266c0ebdf5728
+    as part of "2025-06 LWG Motion 13: P3691R1 Reconsider naming of the
+    namespace for std::simd", but turned out not to be a helpful change,
+    because it makes other wording more complex.
+
+    Fixes NB US 180-295 (C++26 CD).
+
+commit 7f3b7c64a18610948bfc5479a90764f4992731bd
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Dec 14 22:00:24 2025 +0000
+
+    [intro.races] Fix typo
+
+commit e1ee86a3c373c53db7b5d6289457eed620862c76
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Mar 27 13:17:33 2026 +0100
+
+    [simd.syn,simd.permute.mask] Change M::value_type& to V::value_type&
+
+commit 8cef46b15b21d4ab1b96dce04c0d37e511d1ddc2
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 6 00:24:35 2025 +0200
+
+    [exec.snd.expos] Reorder specification immediately after declaration
+
+    Fixes NB US 213-353 (C++26 CD).
+
+commit 6fc165022194a0dd3b78287b087e7872c6c88f48
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Mar 27 11:58:32 2026 +0000
+
+    [exec.get.compl.sched] Rename completion-tag to completion-fn-tag and reorder text.
+
+    The renaming avoids a clash with the concept "completion-tag" defined
+    in [exec.snd.expos]. The reordering makes it so that names are defined
+    before they are referenced.
+
+commit deb2a9b40a46062dd76a1bbc968ff5039cb02aaf
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Mar 28 08:56:40 2026 +0000
+
+    [exec.snd.expos] Delete unused expos-only concept "completion-tag".
+
+    Also insert a missing \pnum before the now-split codeblock (see 8cef46b15b21d4ab1b96dce04c0d37e511d1ddc2).
+
+commit fda5e3771f85dfea6d7bd8ade0577e82886addc0
+Author: Abhinav Agarwal <abhinavagarwal1996@gmail.com>
+Date:   Fri Mar 20 02:36:07 2026 -0700
+
+    [dcl.struct.bind] Fix tuple-like binding index to use SB_i instead of v_i
+
+    P1061R10 introduced the SB_i notation for post-expansion structured bindings
+    but this sentence was not updated. The rest of the section (p6, p8, and the
+    end of this same paragraph) already uses SB_i.
+
+commit 42f878f50d1356866b5aebe520a3138f707919a0
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Dec 15 00:01:35 2025 +0000
+
+    [basic] Do not hyphenate "potentially evaluated"
+
+commit 70e753882b290ea432e516b75fd924bc687076be
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Dec 15 00:03:46 2025 +0000
+
+    [expr] Do not hyphenate "potentially evaluated"
+
+commit d296b82c70dcf49a7a10a100778ecd6aed4c92c7
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Dec 15 00:04:54 2025 +0000
+
+    [dcl] Do not hyphenate "potentially evaluated"
+
+commit 9ad63b74fae211473235c8fa087d19d392c04728
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Dec 15 00:05:31 2025 +0000
+
+    [temp.over.link] Do not hyphenate "potentially evaluated"
+
+commit 180830c280023ea63165547b937da8265b6bd667
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Fri Apr 3 21:10:21 2026 +0800
+
+    [mdspan.mdspan.cons] Fix typo (`is_nothrow_constructible` => `is_nothrow_constructible_v`)
+
+commit c52c49ab2bcb5770ec2190f3381051442e037157
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Apr 20 01:49:17 2026 +0100
+
+    [task.promise] Delete unused definition of expos-only error-variant.
+
+    The changes from LWG 4339 removed the use of this type alias,
+    but not its definition.
+
+commit ec642cdab87f6f83392196a1600d19d893c17b08
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 12 20:52:51 2026 +0100
+
+    [mdspan.syn] Renamed template parameter from "Slices" to "SliceSpecifiers".
+
+    The latter form is used everywhere else, including in the item's itemdecl.
+
+commit bcb6a56a5d2bef008ed02de89b50acdd7e8b8b1d
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Apr 20 18:47:33 2026 +0200
+
+    [exec.get.domain] Remove extraneous period after list (#8956)
+
+commit 6fd25df420db99ce2607b7ce3741f4d1891d0ceb
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Feb 22 19:14:40 2026 +0100
+
+    [temp.deduct.conv] Add comma to structure the sentence
+
+commit 25182503a4a94a3fb56c48c80fca56a713095882
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Apr 16 17:25:53 2026 +0200
+
+    [cpp.pre] Remove confused footnote about 'lines'
+
+commit cd6c5bf4871a80b1e865f85a7e1e104036ce2869
+Author: Jay Ghiron <55773281+Halalaluyafail3@users.noreply.github.com>
+Date:   Mon Apr 20 12:52:13 2026 -0400
+
+    [diff.expr] Update incorrect comment about C (#8933)
+
+    arr2 is a constraint violation in C, rather than being valid.
+
+commit 9909e30038ee608225a67f62b355a60d1a679325
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Thu Apr 16 21:22:13 2026 +0800
+
+    [mdspan.layout.leftpad.obs, mdspan.layout.rightpad.obs] Fix return type of operator()
+
+commit 1651c628caed73f26e120a604eca6798f4da6afc
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Tue Apr 21 04:40:40 2026 +0800
+
+    [linalg] Add period after \returns statement on same line (#8950)
+
+commit 6211dc859a519b7ff5cca0bfbd953f3b4bd73450
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Wed Apr 8 12:19:17 2026 +0800
+
+    [linalg.scaled.scaledaccessor,linalg.conj.conjugatedaccessor] Added missing typename
+
+commit 0a236f9185a2e59c7a49b5439135ee995460bcd6
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Apr 21 20:02:56 2026 +0800
+
+    [numarray] Remove incorrect comments for deleted default constructors (#8962)
+
+commit 1e747bf358e4546e9661c6bcee01a1dd71d2186f
+Author: Tymi <tymi@tymi.org>
+Date:   Tue Apr 21 21:58:09 2026 +0200
+
+    [fs.class.path] Use "typedef-name" instead of "typedef" (#8964)
+
+commit 240dc1f4e197dac0004fb5b171ea7c717fba89c9
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Tue Apr 21 21:51:27 2026 -0500
+
+    [meta.define.static] Move misplaced \end{codeblock}
+
+commit c07075ab7018c7a88d0d254c4c9262d9a6978c94
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Tue Apr 21 22:14:11 2026 -0500
+
+    [meta.define.static] Rephrase sentence to avoid overfull \hbox
+
+commit 259dcba53500aa26b555f1f952382f484a904cd1
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Wed Apr 22 21:46:07 2026 +0800
+
+    [mdspan.syn, mdspan.sub.range.slices] Remove redundant std
+
+commit 3532b45c6d9dd37d3f9f949b8307960b7a53eff0
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Thu Apr 23 00:30:10 2026 +0800
+
+    [mdspan.sub.helpers] Use period for \returns (#8977)
+
+commit e3a17c5b35d7903f85ff136aeaf9000e6b081517
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Apr 23 21:50:58 2026 +0200
+
+    [utility.arg.requirements] Strike redundant text about core language rules (#8987)
+
+commit 3b5d4f6e215c9fad9472ce1d748cf74b90817ad2
+Author: A. Jiang <de34@live.cn>
+Date:   Fri Apr 24 03:58:27 2026 +0800
+
+    [format.arguments, depr.format.arg] Apply `\exposid` consistently (#8971)
+
+    Co-authored-by: Alisdair Meredith <alisdairm@me.com>
+    Co-authored-by: Jonathan Wakely <github@kayari.org>
+    Co-authored-by: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+
+commit 673a0e4fc97da58665e7f69e00b0f70e5924795e
+Author: A. Jiang <de34@live.cn>
+Date:   Fri Apr 24 17:47:21 2026 +0800
+
+    [re.tokiter.general] Fix incorrect `suffix.match` to use `.matched` (#8988)
+
+commit 663b952c59c4b77e233179189f410ce1d952ea59
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Fri Apr 24 12:02:16 2026 -0500
+
+    [meta.define.static] correct note after CWG3141
+
+commit fecad5839345644f30f8b5d9c1043e2a4e666fc8
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 15:30:37 2026 +0100
+
+    [basic.compound] Add missing \grammarterm.
+
+    Misapplication of CWG Motion 1, Issue CWG 2765.
+
+    Addresses editorial review committee feedback.
+
+commit d3128aacb391726a0c15b8649f9c8e2ca199789e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 15:34:23 2026 +0100
+
+    [bit.cast] Update cross-reference into [expr.const] following 98a668efc2ab0bea86dcf9a2d8bf583dddc35e32.
+
+    The editorial change was made after the wording of CWG 2765 was written.
+
+    Addresses editorial review committee feedback.
+
+commit 5c2c9dd250af893345b6dbb28c793d8894d4b3c8
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 15:50:02 2026 +0100
+
+    [expr.prim.splice] Add missing maths font for variable "C".
+
+    Misapplication of P3598R0 in CWG Motion 8.
+
+    Addresses editorial review committee feedback.
+
+commit 8425e4a1c4fa7c928b33c6796b45cfd81d15160a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 16:05:53 2026 +0100
+
+    [lex.phases] Update cross-reference into [expr.const] following 98a668efc2ab0bea86dcf9a2d8bf583dddc35e32.
+
+    The editorial change was made after the wording of P4143R0 was written.
+
+    Addresses editorial review committee feedback.
+
+commit 01296b2d6e73ade37803f9721de7bdad437b4e3b
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 16:09:52 2026 +0100
+
+    [temp.inst] Add missing \grammarterm.
+
+    Misapplication of CWG Motion 11, P4149R1.
+
+    Addresses editorial review committee feedback.
+
+commit d5078b039da4e188f5de51682c2219f26b8367f9
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 16:20:12 2026 +0100
+
+    [exec.spawn.future] Add missing \exposid.
+
+    Misapplication of LWG Motion 2, Issue LWG 4540.
+
+    Addresses editorial review committee feedback.
+
+commit 89cc24e855b5a89f099859685fc21fb37f03a36c
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 16:24:46 2026 +0100
+
+    [algorithm.syn] Remove stray comma.
+
+    This seems to be an error in the wording of LWG 4544 (LWG Motion 2).
+
+    Addresses editorial review committee feedback.
+
+commit 83f5072a59b06575d1108e7f63ef28b00fb4e4b2
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 18:39:03 2026 +0100
+
+    [simd.math] Remove stray '@'s.
+
+    Addresses editorial review committee feedback.
+
+commit ef5f532d2530a733011b0d606dfe69b952c718f6
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 18:46:26 2026 +0100
+
+    [simd.math] Remove stray '\' (unintended escaping).
+
+    Addresses editorial review committee feedback.
+
+commit d706f2d4fa89e7bcaa54338b9619ead9add59c67
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 18:49:24 2026 +0100
+
+    [simd.math] Better linebreaking/whitespacing in remquo description.
+
+    Addresses editorial review committee feedback.
+
+commit 9c5becee9a6ca91aad690074069be058f780006f
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 21:12:54 2026 +0100
+
+    [simd.expos{,defn}] Fixed template parameter "class T" => "size_t Bytes".
+
+    Misapplication of P3932R0 in LWG Motion 5.
+
+    Addresses editorial review committee feedback.
+
+commit 120d987ce6a376f1d56b84041d8e69aefaa436ec
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 21:21:12 2026 +0100
+
+    [exec.let] Fix misspelled "declval" use.
+
+    Misapplication of P3826R5 in LWG Motion 28.
+
+    Addresses editorial review committee feedback.
+
+commit daffae75c71890ca82c5021404c9a005e8038405
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 21:24:42 2026 +0100
+
+    [exec.let] Add missing '\exposid's.
+
+    Misapplication of P3373R4 in LWG Motion 10.
+
+    Addresses editorial review committee feedback.
+
+commit 39a5cd65c6c2af9a251b8d2d5c7d5e73e86c9fa5
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 22:24:30 2026 +0100
+
+    [dcl.attr.annotation] Add missing "codeblock" environment.
+
+    Misapplication of P3795R2 in LWG Motion 15.
+
+    Addresses editorial review committee feedback.
+
+commit 33a4bec49725127d2e1942f2b074d17242bc0458
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 22:30:48 2026 +0100
+
+    [basic. link] Add "ANN" element to the "data member description sextuple.
+
+    This was missed by P3795R2 in LWG Motion 15, presumably by accident.
+
+    Addresses editorial review committee feedback.
+
+commit f8e7a0665d9919af4b680d60b07dbb322ee1d4cb
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 23:10:01 2026 +0100
+
+    [func.ref.wrap.ctor] Add missing ".value"
+
+    Misapplication of P3948R1 in LWG Motion 16.
+
+    Addresses editorial review committee feedback.
+
+commit d7c02a0f5c21cd235a0ed3921a30b19d75771f2e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 23:36:15 2026 +0100
+
+    [mdspan.sub.overview] Fix missing edits and missing maths font.
+
+    Misapplication of P3982R2 in LWG Motion 23.
+
+    Addresses editorial review committee feedback.
+
+commit 2a8305d4b5bdf40b9e4e602d30a08e5fed6dd87b
+Author: Abhinav Agarwal <abhinavagarwal1996@gmail.com>
+Date:   Sun Apr 26 16:10:39 2026 -0700
+
+    [mdspan.sub.map.sliceable] Fix M::extent_type to M::extents_type
+
+    Layout mapping types expose extents_type, not extent_type; the
+    latter is a member of extent_slice. As written, IT and M_rank
+    in the Let clause name an undefined member.
+
+commit 368af317f557650b4d3dcf98379f02ef3d00140e
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sat May 2 07:41:44 2026 +0000
+
+    [basic.def] Mark definition of "redeclaration" as such (#8596)
+
+commit 75b6c6535f5115750bcaa588ded5dfa99eb5fa24
+Author: Guyutongxue <guyutongxue@163.com>
+Date:   Tue Apr 28 16:40:13 2026 +0800
+
+    [algorithm.syn] Add missing semicolon and right angle bracket
+
+commit 25401da54dcf000fa09105a8dc3cdcf788d753d5
+Author: Guyutongxue <guyutongxue@163.com>
+Date:   Tue Apr 28 16:42:37 2026 +0800
+
+    [map.overview] Add missing right angle bracket
+
+commit eaa1458d9832084f56f22d60dde77ed2a95b9b7e
+Author: Guyutongxue <guyutongxue@163.com>
+Date:   Tue Apr 28 16:43:27 2026 +0800
+
+    [exec.snd.expos] Add missing left brace
+
+commit 9e15aa83cc1fd4efb06afdb861ebaf6e05f261bd
+Author: Guyutongxue <guyutongxue@163.com>
+Date:   Tue Apr 28 16:45:11 2026 +0800
+
+    [rand.eng.philox, simd.syn] Fix misplaced right angle bracket, missing comma in `hypot`, `lerp` and `fma`
+
+commit f0c6e9e9af125c133dba0336797e2193d7d2cc2e
+Author: Guyutongxue <guyutongxue@163.com>
+Date:   Tue Apr 28 16:45:45 2026 +0800
+
+    [range.filter.sentinel] Add missing semicolon
+
+commit 0fcd7084a93a5bfbbfe177cd9c6859eeca63439a
+Author: Guyutongxue <guyutongxue@163.com>
+Date:   Tue Apr 28 16:46:20 2026 +0800
+
+    [atomics.types.float] Fix typo of `floating-point-type`
+
+commit 1a12df96659d230a376a3da4a2bae3cfc4cd57cb
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 2 15:39:57 2026 +0100
+
+    [exec.get.compl.{domain,sched}] Replace "it" and long expression with "the expression".
+
+    In e82e850497facd0b9f1e65f4de75b475ddde42ed I had shortened a long
+    expression from the incoming paper in [exec.get.compl.domain] to just
+    "it". In review it was suggested that "the expression" is clearer, and
+    that similar wording in [exec.get.compl.sched] should use the same style.
+
+    (Overall, I think it is easier to understand that the shorter
+    reference refers to the same expression than to have to compare
+    two long expressions and determine that they are equal.)
+
+    Addresses editorial review committee feedback.
+
+commit 65970a5aad6e50048dce1a0b4398d63b8a09ea44
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 2 15:50:08 2026 +0100
+
+    [exec.get.compl.domain]
+
+    Misapplication of P3826R5 in LWG Motion 28.
+
+    Addresses editorial review committee feedback.
+
+commit fa590b2628d9a21d6a12afa5a1d22168cb40b2a3
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 2 15:53:50 2026 +0100
+
+    [exec.snd.expos] Fix missing escaping for braces in "{}".
+
+    Misapplication of P3826R5 in LWG Motion 28.
+
+    Addresses editorial review committee feedback.
+
+commit 91e3416490d096cd0c783c1b5b4e922b53a48f4e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 2 15:57:04 2026 +0100
+
+    [exec.domain.default] Delete stray word "sender".
+
+    The deletion was part of the edit instructions of P3826R5 in LWG
+    Motion 28, but was accidentally missed.
+
+    Addresses editorial review committee feedback.
+
+commit 62be1e6b61e0e3701f4062994cb04eb02d27d1be
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 2 16:00:32 2026 +0100
+
+    [exec.snd.transform] Fix "tag2" => "tag".
+
+    Misapplication of P3826R5 in LWG Motion 28.
+
+    Addresses editorial review committee feedback.
+
+commit 9912050ebe526f32ad1cdec47840fae82099b105
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 2 16:04:37 2026 +0100
+
+    [exec.on] Fix missing escaping for braces in "{...}".
+
+    Misapplication of P3826R5 in LWG Motion 28.
+
+    Addresses editorial review committee feedback.
+
+commit e0ca46ae71122c99c0f098212b2990ed41973b05
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 2 16:07:02 2026 +0100
+
+    [exec.on] Fix missing argument "set_value, ".
+
+    Misapplication of P3826R5 in LWG Motion 28, this edit was just missed.
+
+    Addresses editorial review committee feedback.
+
+commit d04267fda5b9a16ce56beb3137c22900019e0e54
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 2 16:14:53 2026 +0100
+
+    [exec.sync.wait.var] Remove vacuous exception.
+
+    The exception that "sndr is evaluated only once" is no longer
+    necessary, since P3826R5 from LWG Motion 28 removed the previous
+    second mention of the subexpression "sndr". Now that there is only one
+    occurrence of "sndr", it does not need saying that it is only
+    evaluated once.
+
+    Addresses editorial review committee feedback.
+
+commit e5f877a4c0542654017c5cd9152d6c1dba7972b4
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 2 16:19:51 2026 +0100
+
+    [exec.affine] Add missing '\placeholder'.
+
+    Misapplication of P3941R4 in LWG Motion 33.
+
+    Addresses editorial review committee feedback.
+
+commit 3647c192d9ed47bd653e3575b9dc84107b7cd1fc
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 2 16:32:59 2026 +0100
+
+    [exec.{rcvr,snd}.concepts] Add "// exposition only" comments to definitions.
+
+    A missed edit from P4159R0 in LWG Motion 37.
+
+    Addresses editorial review committee feedback.
+
+commit aea0fae459ee3a369e0dc251f674337298433121
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat May 2 17:13:27 2026 +0100
+
+    [except.terminate] Replace system_context_replaceability with parallel_scheduler_replacement.
+
+    This change is needed for consistency with P4154R0 from LWG Motion 39.
+    Even though that paper didn't ask for this change, that was clearly an
+    oversight.
+
+    Addresses editorial review committee feedback.
+
+commit fb2c3e602417fe8cd33618ff5adb31a86cf9072b
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Mon May 4 10:37:18 2026 -0400
+
+    [expr.const] Definition domain fixes for "usable in constant expressions" (#8670)
+
+    Also improves the indexing.
+
+commit 32816d5c2f94da9252ea604c8e7ee17a0657e03c
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Apr 26 16:31:18 2026 +0100
+
+    [simd.{syn,math}] Rename parameters of new overloads of various special maths functions:
+
+    * For comp_ellint_3: from "x, y" to "k, nu"
+    * For cyl_bessel_{i,j,k}: from "x, y" to "nu, x"
+    * For cyl_neumann: from "x, y" to "nu, x"
+    * For ellint_{1,2}: from "x, y" to "k, phi"
+    * For ellint_{1,2}: from "x, y, z" to "k, nu, phi"
+
+    The paper P3844R4 (LWG Motion 4) added those overloads with parameters
+    named differently from the names of the existing overloads, but the
+    latter names seem more appropriate.
+
+    Addresses editorial review committee feedback.
+
+commit 85c6337534d0bdd9cbfa2260609a853e0c40d61f
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Dec 14 21:54:26 2025 +0000
+
+    [intro.execution] Replace "or" with "and"; clarify wording
+
+commit a383c1ad305a61cbef3e14c698b41f6228e780c3
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Apr 8 04:52:48 2026 +0200
+
+    [basic.extended.fp] Reference C23 instead of "future versions"
+
+commit 87a9fbb3cc85436d876e9c7a79ca1cfbb48ac150
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon May 11 23:46:40 2026 +0100
+
+    [meta.reflection] Remove uninformative "// OK" comments from examples.
+
+    Fixes NB US 84-151 (C++26 CD).
+
+commit 5670e07a0ec4a4a3c6201512d86013507c0a9389
+Author: Abhinav Agarwal <abhinavagarwal1996@gmail.com>
+Date:   Sun Apr 26 16:10:54 2026 -0700
+
+[mdspan.sub.map.sliceable] Use lm in sliceable-mapping concept body
+
+The concept body introduces lm (an object of type LayoutMapping) but
+then uses m (an object of type M from the surrounding requirements
+section) in the submdspan_mapping well-formedness check.
+
+commit 738e80f3b19fe9ad73d7a48c382f9584e2f200fd
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue May 12 09:41:32 2026 +0100
+
+    [istream.formatted.arithmetic] remove unnecessary whitespace in codeblocks
+
+commit d2e19cd940eec863a39edee1499e75230725925f
+Author: Abhinav Agarwal <abhinavagarwal1996@gmail.com>
+Date:   Tue May 12 03:15:09 2026 -0700
+
+    [linalg.algs.blas2.rank1,linalg.algs.blas2.symherrank1] Restore missing arguments (#8995)
+
+    Fixes a misapplication of P3371R5.
+
+    * [linalg.algs.blas2.rank1] Add missing E in matrix_rank_1_update_c effects
+    * [linalg.algs.blas2.symherrank1] Restore parameters in updating overload
+
+commit 7c2e7f83c4a8af1841f81f798dd9c5db46232e6d
+Author: Abhinav Agarwal <abhinavagarwal1996@gmail.com>
+Date:   Sun Apr 26 16:10:17 2026 -0700
+
+    [mdspan.sub.sub] Fix submdspan slice canonicalization
+
+    Two integration errors in the Let clause introduced by P3663R3:
+    - the function parameter pack is named "slices", but the Let clause
+      references an undefined "raw_slices"; rename the parameter to match
+      subextents (mdspan.sub.extents);
+    - src is an mdspan but canonical_slices takes an extents object;
+      pass src.extents() instead of src.
+
+ + diff --git a/papers/n5047.md b/papers/n5047.md new file mode 100644 index 0000000000..51f8a4568f --- /dev/null +++ b/papers/n5047.md @@ -0,0 +1,1639 @@ +# N5047 Editors' Report -- Programming Languages -- C++ + +Date: 2026-05-12 + +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` + +## Acknowledgments + +Thanks to all those who have +[submitted editorial issues](https://github.com/cplusplus/draft/wiki/How-to-submit-an-editorial-issue), +to those who have provided pull requests with fixes, +and to everyone who drafted motion applications. +Special thanks to Jan Schultke for drafting a lot of motion applications, +to Andreas Krug for ongoing careful reviews, +and to Daniel Krügler for an exceptionally thorough review +that spotted many mistakes in the motion applications. + +## New papers + + * [N5046](https://open-std.org/jtc1/sc22/wg21/docs/papers/2026/n5046.pdf) is the + current working draft for C++26. It replaces + [N5032](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5032.pdf). + * N5047 is this Editors' Report. + +The Draft International Standard that will be sent for the ISO ballot has not +yet been completed, but will include the changes from N5046. As usual, since +N5046 has not yet been approved in a WG21 meeting, it is instead being reviewed +by an editorial review committee that was selected in Croydon, as per WG21 +Poll 3. N5046 includes some, but not all of the review committee's feedback. + +## Motions incorporated into working draft + +### Notes on motions + +All motions were applied cleanly. + +Some reconciliation was needed among LWG motions (in particular starting at +motion 28), but paper authors and LWG had already included relevant merging +instructions in the papers. + +The wording of P3980R1 from LWG Motion 29 has been reconciled with intervening +changes from issues LWG 4339 and LWG 4347 from LWG Motion 2. + +### Core working group polls + +CWG Poll 1 does not change the working draft. + +CWG Poll 2. Accept as Defect Reports and apply the proposed resolutions of all issues +except issues 3088, 3119, 3122, 3123, 3124, 3131, 3135, 3140, 3141, 3143, 3145, 3149, 3162, and 3172 in +[P4160R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4160r0.html) +(Core Language Working Group "ready" Issues for the March, 2026 meeting) to the C++ Working Paper. + +CWG Poll 3. Apply the proposed resolutions of issues +3088, 3119, 3122, 3123, 3124, 3131, 3135, 3140, 3143, 3145, 3149, 3162, and 3172 in +[P4160R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4160r0.html) +(Core Language Working Group "ready" Issues for the March, 2026 meeting) to the C++ Working Paper. + +CWG Poll 4. Accept as a Defect Report and apply the changes in +[P3924R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3924r1.html) +(Fix inappropriate font choices for "declaration") to the C++ Working Paper. +This addresses ballot comment US 11-400. + +CWG Poll 5. Accept as a Defect Report and apply the changes in +[P4136R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4136r2.pdf) +(`#line` is not in line with existing implementation) to the C++ Working Paper. +This addresses ballot comment FR-009-108. + +CWG Poll 6. Accept as a Defect Report and apply the changes in +[P4004R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4004r1.pdf) +(Reconsider CWG 1395 "Partial ordering of variadic templates reconsidered") to the C++ Working Paper. + +CWG Poll 7. Accept as a Defect Report and apply the changes in +[P3865R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3865r3.pdf) +(Class template argument deduction (CTAD) for type template template parameters) to the C++ Working Paper. + +CWG Poll 8. Apply the changes in +[P3598R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3598r0.pdf) +(CWG 3158 – `const`-ification of Splice Expressions) to the C++ Working Paper. + +CWG Poll 9. Apply the changes in +[P3726R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3726r2.html) +(Adjustments to Union Lifetime Rules) to the C++ Working Paper. +This addresses ballot comment DE 087. + +CWG Poll 10. Accept as a Defect Report and apply the changes in +[P4143R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4143r0.html) +(Constant evaluation when?) to the C++ Working Paper. +This partially addresses ballot comment US 33-065. + +CWG Poll 11. Accept as a Defect Report and apply the changes in +[P4149R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4149r1.html) +(Define "immediate context") to the C++ Working Paper. +This addresses ballot comment US 54-100 and core issues 1844 and 2296. + +CWG Poll 12. Accept as a Defect Report and apply the changes in +[P3769R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3769r1.html) +(Clarification of placement new deallocation) to the C++ Working Paper. + +CWG Poll 13. Apply the proposed resolution of issue 3141 in +[P4160R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4160r0.html) +(Core Language Working Group "ready" Issues for the March, 2026 meeting) to the C++ Working Paper. + +### Library working group polls + +LWG Poll 1. Apply the changes in +[P4145R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4145r0.html) +(C++ Standard Library Ready Issues to be moved in Croydon, Mar. 2026) to the C++ working paper. + +LWG Poll 2. Apply the changes in +[P4146R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) +(C++ Standard Library Immediate Issues to be moved in Croydon, Mar. 2026) to the C++ working paper. + +LWG Poll 3. Apply the changes in +[P3690R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3690r1.pdf) +(Consistency fix: Make `simd` reductions SIMD-generic) to the C++ working paper. +This addresses ballot comment AT8-279. + +LWG Poll 4. Apply the changes in +[P3844R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3844r4.pdf) +(Reword [simd.math] for consteval conversions) to the C++ working paper. +This addresses ballot comment DE-286. + +LWG Poll 5. Apply the changes in +[P3932R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3932r0.pdf) +(Fix LWG4470: Fix integer-from in [simd]) to the C++ working paper. + +LWG Poll 6. Apply the changes in +[P4012R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4012r1.pdf) +(Value-preserving consteval broadcast to `simd::vec`) to the C++ working paper. +This addresses ballot comment DE-286. + +LWG Poll 7. Apply the changes in +[P3886R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3886r0.pdf) +(Wording for AT1-057) to the C++ working paper. +This addresses ballot comment AT 1-057. + +LWG Poll 8. Apply the changes in +[P3936R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3936r1.pdf) +(Safer `atomic_ref::address` (FR-030-310)) to the C++ working paper +and update the value of the `__cpp_lib_atomic_ref` macro. +This addresses ballot comment FR-030-310. + +LWG Poll 9. Apply the changes in +[P4140R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4140r0.html) +(Proposed resolution for US70-126: allow incomplete types in type_order) to the C++ working paper. +This addresses ballot comment US 70-126. + +LWG Poll 10. Apply the changes in +[P3373R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3373r4.pdf) +(Of Operation States and Their Lifetimes) to the C++ working paper. +CA-338. + +LWG Poll 11. Apply the changes in +[P3986R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3986r1.pdf) +(A Wording Strategy for Inlinable Receivers) to the C++ working paper. +This addresses ballot comment CA-318. + +LWG Poll 12. Accept as a Defect Report and apply the changes in +[P3059R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3059r2.html) +(Making user-defined constructors of view iterators/sentinels private) to the C++ working paper. +This addresses ballot comment GB 09-257. + +LWG Poll 13. Accept as a Defect Report and apply the changes in +[P3725R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3725r3.pdf) +(Filter View Extensions for Safer Use, Rev 3) to the C++ working paper. +This addresses ballot comments AT9-249, RU-250, DE-251. + +LWG Poll 14. Apply the changes in +[P3828R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3828r1.pdf) +(Rename the to_input view to as_input) to the C++ working paper. +This addresses ballot comment DE-248. + +LWG Poll 15. Apply the changes in +[P3795R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3795r2.html) +(Miscellaneous Reflection Cleanup) to the C++ working paper. +This addresses ballot comments US 42-078 and US 85-150 and US 122-184 and US 128-192 and US 95-202 and US 131-195. + +LWG Poll 16. Apply the changes in +[P3948R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3948r1.pdf) +(`constant_wrapper` is the only tool needed for passing constant expressions +via function arguments) to the C++ working paper. +This addresses ballot comments FR-019-210 and FR-021-218. + +LWG Poll 17. Apply the changes in +[P3978R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3978r3.pdf) +(`constant_wrapper` should unwrap on call and subscript) to the C++ working paper. + +LWG Poll 18. Apply the changes in +[P3961R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3961r1.html) +(Less double indirection in `function_ref`) to the C++ working paper. +This addresses ballot comment RU-220. + +LWG Poll 19. Apply the changes in +[P3981R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3981r2.html) +(Better return types in `std::inplace_vector` and `std::exception_ptr_cast`) to the C++ working paper. +This addresses ballot comments PL-006 and US 68-122 and US 150-228 and GB 08-225. + +LWG Poll 20. Apply the changes in +[P4022R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4022r0.html) +(Remove `try_append_range` from `inplace_vector` for now) to the C++ working paper. +This addresses ballot comment PL-006. + +LWG Poll 21. Apply the changes in +[P4037R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4037r1.html) +(Supporting `signed char` and `unsigned char` in random number generation) to the C++ working paper. +This addresses ballot comment RU-272. + +LWG Poll 22. Apply the changes in +[P3450R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3450r1.html) +(Extend `std::is_within_lifetime`) to the C++ working paper. +This addresses ballot comment US 82-145. + +LWG Poll 23. Apply the changes in +[P3982R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3982r2.html) +(Split `strided_slice` into `extent_slice` and `range_slice` for C++26) to the C++ working paper. +This addresses ballot comment PL-007. + +LWG Poll 24. Apply the changes in +[P4144R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4144r1.html) +(Remove `span`’s `initializer_list` constructor for C++26) to the C++ working paper. + +LWG Poll 25. Apply the changes in +[P3804R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3804r2.html) +(Iterating on `parallel_scheduler`) to the C++ working paper. +This addresses ballot comment RO 4-395. + +LWG Poll 26. Apply the changes in +[P3787R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3787r2.html) +(Adjoints to "Enabling list-initialization for algorithms": uninitialized_fill) to the C++ working paper. +This addresses ballot comment FR-027-267. + +LWG Poll 27. Apply the changes in +[P3842R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3842r2.pdf) +(A conservative fix for constexpr uncaught_exceptions() and current_exception()) to the C++ working paper. +This addresses ballot comments PL-012 and GB 03-119 and DE-120 and US 67-118 and FI-121. + +LWG Poll 28. Apply the changes in +[P3826R5](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3826r5.html) +(Fix Sender Algorithm Customization) to the C++ working paper. +This addresses ballot comments US 207-328 and US 202-326 and FR-031-219 and FI-331 and CA-358. + +LWG Poll 29. Apply the changes in +[P3980R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3980r1.html) +(Task’s Allocator Use) to the C++ working paper. +This addresses ballot comments US 254-385 and US 253-386 and US 255-384 and US 261-391. + +LWG Poll 30. Apply the changes in +[P4156R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4156r0.html) +(Rename meta::has_ellipsis_parameter to meta::is_vararg_function) to the C++ working paper. +This addresses ballot comment FR-017-155. + +LWG Poll 31. Apply the changes in +[P3953R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3953r3.html) +(Rename `std::runtime_format`) to the C++ working paper. + +LWG Poll 32. Apply the changes in +[P4052R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4052r0.html) +(Renaming saturation arithmetic functions) to the C++ working paper. +This addresses ballot comment FR-026-265. + +LWG Poll 33. Apply the changes in +[P3941R4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3941r4.html) +(Scheduler Affinity) to the C++ working paper. +This addresses ballot comments US 232-366 and US 233-365 and US 234-364 and US 235-363 and US 236-362. + +LWG Poll 34. Apply the changes in +[P3856R8](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3856r8.pdf) +(New reflection metafunction - is_structural_type) to the C++ working paper. +This addresses ballot comment US 49-090. + +LWG Poll 35. Apply the changes in +[P3927R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3927r2.html) +(`task_scheduler` support for parallel `bulk` execution) to the C++ working paper. +This addresses ballot comment US 238-368. + +LWG Poll 36. Apply the changes in +[P4151R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4151r1.pdf) +(Rename `affine_on`) to the C++ working paper. + +LWG Poll 37. Apply the changes in +[P4159R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4159r0.html) +(Make `sender_in` and `receiver_of` exposition-only) to the C++ working paper. + +LWG Poll 38. Apply the changes in +[P4154R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4154r0.html) +(Renaming various execution things) to the C++ working paper. +This addresses ballot comments US 205-320 and RO 4-395. + +## National body comment resolution + +A large number of national body comments for the C++26 Committee Draft have been +addressed in this working draft. + +### Editorial comments + +Most editorial national body comments were addressed before the Kona 2025 meeting, +see [Editor’s Report N5033](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5033.html) +for the full list. + +A few additional national body comments have since been found editorial +and have now been addressed: + + * CA 109 will be addressed for the DIS. + * US 084-151 [87a9fbb3cc85436d876e9c7a79ca1cfbb48ac150](https://github.com/cplusplus/draft/commit/87a9fbb3cc85436d876e9c7a79ca1cfbb48ac150) + * US 180-295 [731cda191b915555c6816912361e431c82e7e2f6](https://github.com/cplusplus/draft/commit/731cda191b915555c6816912361e431c82e7e2f6) + * US 213-353 [8cef46b15b21d4ab1b96dce04c0d37e511d1ddc2](https://github.com/cplusplus/draft/commit/8cef46b15b21d4ab1b96dce04c0d37e511d1ddc2) + +### Non-editorial comments + +The following national body comments were addressed by the motions approved at the Croydon 2026 meeting: + + * AT 001-057 via [LWG Poll 7](http://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3886r0.pdf) + * AT 002-089 via [CWG Poll 3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4160r0.html) + * AT 008-279 via [LWG Poll 3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3690r1.pdf) + * AT 009-249 via [LWG Poll 13](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3725r3.pdf) + * CA 318 via [LWG Poll 11](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3986r1.pdf) + * CA 338 via [LWG Poll 10](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3373r4.pdf) + * CA 358 via [LWG Poll 28](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3826r5.html) + * DE 087 via [CWG Poll 9](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3726r2.html) + * DE 120 via [LWG Poll 27](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3842r2.pdf) + * DE 248 via [LWG Poll 14](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3828r1.pdf) + * DE 251 via [LWG Poll 13](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3725r3.pdf) + * FI 121 via [LWG Poll 27](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3842r2.pdf) + * FI 331 via [LWG Poll 28](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3826r5.html) + * FR 003-031 via [CWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4160r0.html) + * FR 009-108 via [CWG Poll 5](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4136r2.pdf) + * FR 017-155 via [LWG Poll 30](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4156r0.html) + * FR 019-210 via [LWG Poll 16](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3948r1.pdf) + * FR 021-218 via [LWG Poll 16](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3948r1.pdf) + * FR 025-246 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * FR 026-265 via [LWG Poll 32](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4052r0.html) + * FR 027-267 via [LWG Poll 26](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3787r2.html) + * FR 030-310 via [LWG Poll 8](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3936r1.pdf) + * FR 031-219 via [LWG Poll 28](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3826r5.html) + * GB 003-119 via [LWG Poll 27](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3842r2.pdf) + * GB 005-129 via [LWG Poll 1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4145r0.html) + * GB 007-223 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * GB 008-225 via [LWG Poll 19](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3981r2.html) + * GB 009-257 via [LWG Poll 12](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3059r2.html) + * GB 011-302 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * PL 006 via [LWG Poll 19](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3981r2.html) and [LWG Poll 20](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4022r0.html) + * PL 007 via [LWG Poll 23](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3982r2.html) + * PL 008 via [LWG Poll 1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4145r0.html) + * PL 012 via [LWG Poll 27](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3842r2.pdf) + * RO 004-395 via [LWG Poll 25](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3804r2.html) + * RO 004-395 via [LWG Poll 38](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4154r0.html) + * RU 220 via [LWG Poll 18](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3961r1.html) + * RU 250 via [LWG Poll 13](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3725r3.pdf) + * RU 268 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * RU 272 via [LWG Poll 21](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4037r1.html) + * US 011-400 via [CWG Poll 4](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3924r1.html) + * US 014-029 via [CWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4160r0.html) + * US 017-030 via [CWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4160r0.html) + * US 033-065 via [CWG Poll 10](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4143r0.html) + * US 042-078 via [LWG Poll 15](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3795r2.html) + * US 048-086 via [CWG Poll 9](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3726r2.html) + * US 049-090 via [LWG Poll 34](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3856r8.pdf) + * US 054-100 via [CWG Poll 11](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4149r1.html) + * US 057-105 via [CWG Poll 3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4160r0.html) + * US 067-118 via [LWG Poll 27](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3842r2.pdf) + * US 068-122 via [LWG Poll 19](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3981r2.html) + * US 070-126 via [LWG Poll 9](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4140r0.html) + * US 075-138 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * US 081-149 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * US 082-145 via [LWG Poll 22](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3450r1.html) + * US 085-150 via [LWG Poll 15](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3795r2.html) + * US 095-202 via [LWG Poll 15](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3795r2.html) + * US 100-207 via [LWG Poll 15](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3795r2.html) + * US 122-184 via [LWG Poll 15](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3795r2.html) + * US 128-192 via [LWG Poll 15](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3795r2.html) + * US 131-195 via [LWG Poll 15](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3795r2.html) + * US 135-216 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * US 136-217 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * US 139-232 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * US 142-236 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * US 150-228 via [LWG Poll 19](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3981r2.html) + * US 151-242 via [LWG Poll 1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4145r0.html) + * US 152-243 via [LWG Poll 1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4145r0.html) + * US 157-255 via [LWG Poll 1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4145r0.html) + * US 176-280 via [LWG Poll 1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4145r0.html) + * US 189-304 via [LWG Poll 1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4145r0.html) + * US 202-326 via [LWG Poll 28](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3826r5.html) + * US 205-320 via [LWG Poll 38](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4154r0.html) + * US 207-328 via [LWG Poll 28](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3826r5.html) + * US 232-366 via [LWG Poll 33](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3941r4.html) + * US 233-365 via [LWG Poll 33](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3941r4.html) + * US 234-364 via [LWG Poll 33](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3941r4.html) + * US 235-363 via [LWG Poll 33](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3941r4.html) + * US 236-362 via [LWG Poll 33](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3941r4.html) + * US 238-368 via [LWG Poll 35](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3927r2.html) + * US 242-372 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * US 249-379 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * US 253-386 via [LWG Poll 29](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3980r1.html) + * US 254-385 via [LWG Poll 29](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3980r1.html) + * US 255-384 via [LWG Poll 29](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3980r1.html) + * US 257-382 via [LWG Poll 2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4146r0.html) + * US 261-391 via [LWG Poll 29](http://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3980r1.html) + +## Editorial changes + +### Major editorial changes + +The subclause [expr.const], formerly titled “Constant expressions”, +has been renamed to “Constant evaluation” and its contents have been +divided into smaller subclauses; see commit +[98a668efc2ab0bea86dcf9a2d8bf583dddc35e32](https://github.com/cplusplus/draft/commit/98a668efc2ab0bea86dcf9a2d8bf583dddc35e32). + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N5008 is below. This +list excludes changes that do not affect the body text or only affect whitespace +or typeface. For a complete list including such changes (or for the actual +deltas applied by these changes), consult the +[draft sources on GitHub](https://github.com/cplusplus/draft/compare/n5032...n5046). + + commit cc2efebb57ea02ea2eac19220c873c158f855859 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Dec 15 15:43:02 2025 +0000 + + [basic.start.dynamic] Fix typo (#8654) + + commit 3e6cad293e448f7d9f9d859d07b5371b7e054789 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Dec 15 15:47:37 2025 +0000 + + [basic.types.general] Improve presentation of comments in example (#8636) + + - put "sizeof" in code font + - use a comma after "OK" + + commit f6319760f3f6d9a710fdb4be5e54c111abfc1e92 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Dec 14 16:21:20 2025 +0000 + + [basic.link] Modernize wording about type aliases + + commit f66f4c675c0c60f822bb24543cd607e14be24a93 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Dec 14 16:31:25 2025 +0000 + + [intro.memory] Update outdated example + + commit 176528f688cec22566f1de8286f1c3fae43887ce + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Dec 14 16:46:10 2025 +0000 + + [intro.object] Remove redundant "non-bit-field" + + commit 1d9fdb066e95b7be58881f24977a20a51359097c + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Dec 14 17:40:14 2025 +0000 + + [basic.types.general] Remove unused meta-variable + + commit 2dbe5a3247b100a6e4cdddab46eda5595d9d3de1 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Dec 15 21:58:39 2025 +0000 + + [basic.start.dynamic] Add cross-reference for "interface dependency" (#8653) + + commit 166fd7efa129ce139e2a859758410fd7fd0955b3 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Dec 15 20:46:26 2025 +0100 + + [exec.scope.concepts] Fix typos + + commit d8a8c5ad3b354087a416c02c2059b9ef62534c72 + Author: A. Jiang + Date: Thu Apr 25 00:30:02 2024 +0800 + + [expos.only.entity] Say typedef-names are declared + + Also use "provided for exposition only" from @W-E-Brown's suggestion. + + commit 7fcd646f6d82721e32f5fb5dc11994b8b0cf1d64 + Author: A. Jiang + Date: Thu Aug 3 00:37:14 2023 +0800 + + [type.descriptions.general] Use "shown" for impl-def types + + commit 34c7cffe9e7d1807df4b986e648392bb3a1dfae0 + Author: A. Jiang + Date: Thu Aug 3 00:38:04 2023 +0800 + + [enumerated.types] Reword enumerated types + + Also mention [re]. + + commit cc2ecb3a2c85b2e196ca5697287270e9f62878c8 + Author: A. Jiang + Date: Thu Aug 3 00:38:45 2023 +0800 + + [bitmask.types] Reword bitmask types + + commit 03545f10f200193e15d3f0227b289ff037146abf + Author: A. Jiang + Date: Thu Apr 25 00:33:17 2024 +0800 + + [extern.types] Use "declared" for C library types + + commit d21a84cc95a9a3e619139a1c53d7937474ea03b8 + Author: A. Jiang + Date: Fri Jul 28 23:51:45 2023 +0800 + + [cstdint.syn] Use "declare" for typedef-names + + commit ad83c0b2bc498eac0fc4d97850143581dbfa703c + Author: A. Jiang + Date: Fri Jul 28 23:52:27 2023 +0800 + + [stdfloat.syn] Use "declare" for typedef-names + + commit 30000d169f5b6db54d7d61ed35aa825fbbdfa70d + Author: A. Jiang + Date: Fri Jul 28 23:58:28 2023 +0800 + + [meta.rqmts] Use "declare" for typedef-names + + commit c5eac2a7d176110d63e153fa1d5abcee9681943e + Author: A. Jiang + Date: Sat Jul 29 00:02:58 2023 +0800 + + [meta.trans.other] Use "declare" for typedef-names + + In the example, it seems a bit verbose to say "declarations and + definitions". + + commit cbd6e735fdea46f312d27ae802e83766d8dc43f8 + Author: A. Jiang + Date: Sat Jul 29 00:03:49 2023 +0800 + + [ratio.si] Use "declare" for typedef-names + + commit 8210a2cc6ff0bb2a90c9b20cf60ee1d369156c4b + Author: A. Jiang + Date: Sat Jul 29 00:12:12 2023 +0800 + + [readable.traits] Use "declare" for typedef-names + + commit c5b55216c7a80fe7187bdbc4f5e62b6ef53e6008 + Author: A. Jiang + Date: Sat Jul 29 00:14:51 2023 +0800 + + [iterator.traits] Use "declare" for typedef-names + + commit b892cf9dd9a5d0e8d9046d0e99b72487f3316b51 + Author: A. Jiang + Date: Sat Jul 29 00:16:03 2023 +0800 + + [std.iterator.tags] Use "declare" for typedef-names + + commit 535f5a348bf4eab6c0d71673209bc853103880c2 + Author: A. Jiang + Date: Wed Apr 24 00:28:25 2024 +0800 + + [const.iterators.types] Avoid "defining" `iterator_category` + + Use "declare" instead. + + commit af81d11662c4b7dfb135176c5282788f6e3f50d4 + Author: A. Jiang + Date: Wed Apr 24 00:28:58 2024 +0800 + + [move.iterator] Avoid "defining" `iterator_category` + + Use "declare" instead. + + commit 45a31c6e70f49792ee3650a106ad03a8a95d7e03 + Author: A. Jiang + Date: Wed Apr 24 00:29:32 2024 +0800 + + [common.iter.types] Avoid "defining" typedef-names + + commit 5253ec6c6229c704303d682c4bd1d0e197506716 + Author: A. Jiang + Date: Wed Apr 24 00:30:51 2024 +0800 + + [range.filter.iterator] Avoid "defining" typedef-names + + Use declared" instead. + + commit 251d0c7ef52327f628086e228a244792a467f27c + Author: A. Jiang + Date: Wed Apr 24 00:31:39 2024 +0800 + + [range.transform.iterator] Avoid "defining" typedef-names + + Use "declare" instead. + + commit 1fa1d4afe6111b03aeec7ced79ed0bf7f6a2569b + Author: A. Jiang + Date: Wed Apr 24 00:32:17 2024 +0800 + + [range.join.iterator] Avoid "defining" typedef-names + + Use "declare" instead. + + commit 55e740c366d1c691c31fda455f6acfcfe7e60979 + Author: A. Jiang + Date: Wed Apr 24 00:33:09 2024 +0800 + + [range.join.with.iterator] Avoid "defining" typedef-names + + Use "declare" instead. + + commit ff0957c1a71f4b668acf9d316efcb31d59495398 + Author: A. Jiang + Date: Wed Apr 24 00:45:09 2024 +0800 + + [range.concat.iterator] Avoid "defining" typedef-names + + Use "declare" instead. + + commit 293648ef77f2533187a1ca89f9649c21da0c06b1 + Author: A. Jiang + Date: Wed Apr 24 00:33:37 2024 +0800 + + [range.elements.iterator] Avoid "defining" typedef-names + + Use "declare" instead. + + commit ae40e054b0ad38993c52f454862682bcdd3bee14 + Author: A. Jiang + Date: Wed Apr 24 00:34:43 2024 +0800 + + [range.zip.transform.iterator] Avoid "defining" `iterator_category` + + Use "declare" instead. + + commit 20564e2186a5f237f1a89fb0b470eb19f662fe2d + Author: A. Jiang + Date: Wed Apr 24 00:35:44 2024 +0800 + + [range.stride.iterator] Avoid "defining" typedef-names + + Use "declare" instead. + + commit da9cc238aa051d127e7ea0d196622a161cab77f1 + Author: A. Jiang + Date: Thu Oct 17 19:19:03 2024 +0800 + + [format.string.std] Use "declare" for typedef-names + + commit b77796b42a5d2854a186858d8a36c558ddc18da4 + Author: A. Jiang + Date: Sat Jul 29 00:47:45 2023 +0800 + + [atomics.alias] Use "declare" for typedef-names + + commit ae8e81dfc21ead75c8d4fcfdb75c4638b14a7fdb + Author: A. Jiang + Date: Sat Jul 29 00:48:28 2023 +0800 + + [stdatomic.h.syn] Use "declare" for typedef-names + + commit 7d4d7f37aa2122fe6e292fcc9520b022fba70d13 + Author: Hubert Tong + Date: Fri Dec 19 03:50:07 2025 -0400 + + [expr.const] Fix typo "with [...]" => "within the evaluation" (#8669) + + commit e9fa860d3af7236fbe43d56ffef4abec93b6a0c9 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Dec 14 23:54:38 2025 +0000 + + [basic.contract.eval] Replace "operation" with "evaluation" + + commit 4dc76ac3cc9895782b199af745dd42614a7d0327 + Author: Hewill Kang + Date: Tue Dec 23 01:15:15 2025 +0800 + + [flat.multiset.modifiers] Add missing constexpr (#8675) + + commit a4fbfa2a689dbd2f0d7a16b29af92dc74574381d + Author: Andrey Ali Khan Bolshakov + Date: Tue Dec 23 09:57:57 2025 +0300 + + [time.syn] Add missing namespace qualification (#8677) + + commit 7abca25d03460cd35e880f29fc7001c69218594a + Author: Alisdair Meredith + Date: Tue Dec 23 13:21:13 2025 -0500 + + [expr.new] Precise cross-reference for throwing exceptions (#8681) + + commit db380b0d4015eb7d2956e73e59c1c5c26f3651a4 + Author: A. Jiang + Date: Mon Dec 29 09:54:10 2025 +0800 + + [version.syn] Reformat a comment to avoid splitting `` + + Co-authored-by: Alisdair Meredith + + commit c59d8c8e9d6fe8adba2142d1344b0e142c9d6ff4 + Author: A. Jiang + Date: Mon Dec 29 09:54:36 2025 +0800 + + [initializer.list.syn] Drop redundant comments + + commit 3dc04f5cda1c8470c0da7c6f9ffcd6d463429ef2 + Author: Hana Dusíková + Date: Fri Jan 2 16:35:49 2026 +0100 + + [hive.cons] Fix typo "allocator_traits" -> "allocator_traits" (#8689) + + commit 7c8a960f3f06d5c565b0976402ce534848926181 + Author: Hewill Kang + Date: Sat Jan 24 00:52:07 2026 +0800 + + [forward.list.overview] Add missing constexpr (#8717) + + commit f3b76296f598bc5266e649f8fb0a2c5ef19ae0c3 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jan 26 15:52:54 2026 +0100 + + [temp.dep.type] Add period to end of sentence (#8723) + + commit 6704d82cd336baaa4f6fe45013c390453991ee86 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Jan 30 21:57:16 2026 +0100 + + [except.handle] Add commas (#8727) + + commit 16f4265888fd30e59512a21a5391327d6b525de1 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Jan 31 19:28:43 2026 +0100 + + [value.error.codes] Fix indefinite article (#8730) + + commit 91156093a76177329a990dfdf38f19dad3531688 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Feb 3 23:19:25 2026 +0100 + + [concept.comparisoncommontype] Add period to end of sentence (#8731) + + commit 15fc5a2f7106963d8e7904eee03bebe2aaf7a81b + Author: Giuseppe D'Angelo + Date: Sun Feb 22 20:45:53 2026 +0100 + + [alg.remove] Use E(i) for predicate on iterator i (#8760) + + The `E` in the code is actually meant to be a function on an + iterator `i`; amend both usages to `E(i)`. This was already done + everywhere else (for instance in copy_if or unique_copy). + + commit 5b07f42565be7972f2b5d729a740da12c5e6b202 + Author: Jonathan Wakely + Date: Tue Feb 24 10:35:57 2026 +0000 + + [thread.mutex.requirements.mutex.general] Fix grammar (#8765) + + commit 4ce955bd576f6a9d68da494e8b560ca8b9375005 + Author: Jonathan Wakely + Date: Tue Feb 24 10:38:03 2026 +0000 + + [exec.snd.expos] Fix order of make_obj_using_allocator arguments (#8766) + + commit 3f6372b97bcdee30b8591077c8479a56bb50fc67 + Author: timsong-cpp + Date: Wed Feb 25 15:35:49 2026 -0600 + + [const.wrap.class] Add missing this to compound assignment operators (#8758) + + This corrects a misapplication of LWG4383 in commit bdcfe2c9a54ca350e9bfc59227bb0285a59c635d. + + commit 8338b7caa5a38ef79e5c2f8316078f6f74d1b8ad + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Mar 5 08:58:29 2026 +0100 + + [text.encoding.id] Add colon after "as follows" (#8776) + + commit eba89bc9b32d230168571737d6aa86c06329502b + Author: Alisdair Meredith + Date: Mon Dec 22 17:59:19 2025 -0500 + + [lex.phases] Make note on the notion of file more prominent + + The notion that when the standard refers to files does not + necessarily imply a file in a traditional filing system is + more fundamental than its late appearance in the middle of + phase 7 of translation. Move that note right to the top of + [lex] where we first talk of storing the program text in + source files, where is will be understood even before the + phases of translation. + + commit 13cad628c5c3883c8fb8dcb4256199b21c13be1d + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Mar 12 08:08:56 2026 +0100 + + [istream.unformatted] Add right parenthesis + + commit 981d32246c951b18dc816cecfdb3ffbb5d72ad54 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Mar 17 21:04:34 2026 +0100 + + [stoptoken.concepts] Remove superfluous \item (#8790) + + commit 92b3a22228ffb3db219debace0e5fbe82c592354 + Author: Can + Date: Fri Mar 20 10:32:30 2026 +0300 + + [utility.intcmp] Fix name of type parameter (#8770) + + Introduced by commit 93914a36c1945d330a7c7d5c4488e1d10e5bbe75 . + + commit 11106fc54b79e1ee21805ea77596908ca4f3a8f3 + Author: Abhinav Agarwal + Date: Fri Mar 20 10:56:06 2026 -0700 + + [mdspan.sub.map.common,mdspan.sub.map.left] Fix S(p)liceSpecifiers typos (#8799) + + commit 36ce9cbe82d472997ca9b978e69e64d6ddd99dcd + Author: Abhinav Agarwal + Date: Fri Mar 20 10:56:49 2026 -0700 + + [linalg.algs.blas3.rank2k] Add missing \pnum and \effects (#8801) + + commit cda7c18d2b83b354bae6001cdf7cb7d3f9203f32 + Author: A. Jiang + Date: Sat Mar 21 17:36:47 2026 +0800 + + [lib] Replace bad uses of "instantiation" with "specialization" (#8379) + + Affected sections: + - [allocator.requirements.general] + - [namespace.std] + - [pointer.traits.types] + - [allocator.traits.types] + - [tuple.general] + - [format.context] + - [numeric.requirements] + - [rand.util.canonical] + - [thread.req.lockable.timed] + - [thread.sharedtimedmutex.requirements.general] + + - In [tuple.general], change "is similar to" to "behaves similarly to" + to avoid confusing with "similar types" in the core specification. + + commit dc5928bdac7e3301d78c8fae5f4cae655a9a06fb + Author: A. Jiang + Date: Sun Mar 22 14:14:40 2026 +0800 + + [vector.bool.fmt][container.adaptors.format] Add missing `constexpr` and other missed edits (#8768) + + Fixes edits from P3391R2 missed by commit cc63c64cba30089a366b024ffc8cc0532b4fb508 . + + commit c6fecf491063eef95384e54813812f6c6aaeab6a + Author: Thomas Köppe + Date: Mon Mar 23 11:40:36 2026 +0000 + + [expected.object.eq] Add missing negation (misapplied wording). + + The negation was accidentally omitted in the application of P3905R0, + approved in Kona 2025 (265b4774c754b36e50bec7a528cbbc87676b0c85). + + commit 6913287752040f7adecdac5af60c90e2701a04e0 + Author: A. Jiang + Date: Wed Feb 25 15:04:34 2026 +0800 + + [format] Consistently add `constexpr` to function descriptions + + P3391R2 only added `constexpr` to synopses but not descriptions for some + formatting functions. This PR consistently adds `constexpr` to the + descriptions. + + commit 45c820b6a9d87b18f3ad5c445c5e61e2ee806a6d + Author: Hubert Tong + Date: Tue Dec 16 23:52:12 2025 -0500 + + [diff.basic] Use enum example instead of example outdated since C99 + + C99 subclause 6.2.7, "Compatible type and composite type", had this + sentence: + > If one is declared with a tag, the other shall be declared with the + > same tag. + + commit 3e53098c0ef22b62ab2dd393411141fceeda03bd + Author: Hubert Tong + Date: Tue Dec 16 23:57:14 2025 -0500 + + [diff.basic] Stop claiming, as harmless, type-based aliasing violations + + commit c40c5f03a02c7e0f2564de46aea4ceebb1c799e4 + Author: Jan Schultke + Date: Fri Feb 13 12:21:45 2026 +0100 + + [intro.compliance.general] Mark documentation encouragement as recommended practice + + commit d8ff3c08615932a207f956a61ebd6e5805f9a9bd + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Dec 14 17:15:48 2025 +0000 + + [basic.stc.dynamic] Spell out compound type names + + commit e70a19ba60ccf3eeed62bf82e4b33584272a1c86 + Author: Jens Maurer + Date: Thu Feb 26 08:30:31 2026 +0100 + + [lex.key] Emphasize that keywords are created in phase 6 + + This was overlooked in CWG3094, applied with commit 94055b39a90285d8ae15f8f864a39a328f42a359. + + commit 0807a339b8bcae60a9d2285f0a08aab61aeece0d + Author: Barry Revzin + Date: Thu Jan 29 07:59:28 2026 -0600 + + Clarify pack-index-specifier rules + + commit f55d63dcef1640f292451a3efe98f56d4afa2383 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Dec 14 17:56:03 2025 +0000 + + [basic.fundamental] Strike explanatory sentence; touch up note + + commit f4d8ecb2aa29122d63e5f56119a83dd4bb2ad3ca + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Dec 14 18:23:18 2025 +0000 + + [basic.extended.fp] Replace "typedef-name" with "type alias" + + commit 2efe693eb09f8c6d364c757a82b640e2ced9f107 + Author: Eisenwave + Date: Wed Dec 17 14:32:48 2025 +0100 + + [intro.refs], [numeric.limits] Remove all references to ISO/IEC 10967-1:2012 + + commit b54449db95dcdfa8ae4d8221ef55f7fca0f358d9 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Dec 14 23:06:53 2025 +0000 + + [basic.start.static] Improve readability of example + + commit cd15f7a88e6390fb31aa766196205e722779d240 + Author: Hubert Tong + Date: Thu Dec 18 19:41:46 2025 -0500 + + [stmt.pre] Streamline decl-specifier restrictions on conditions, etc. + + Avoid an abrupt shift from a mathematical introduction to the + specification of additional normative requirements. + + Expresses universal quantification more directly. + + commit d3f57042d283c06cdb066eab1fc61661df0fc4de + Author: Eisenwave + Date: Sun Jul 23 14:23:21 2023 +0200 + + [temp.point] Itemize long conditionals in three paragraphs + + commit ecc669c503bb875b65cbd4de3d231a8ac9e4bb70 + Author: Hewill Kang + Date: Tue Mar 10 15:07:57 2026 +0800 + + [meta.syn] Add function parameter names + + These two seem to be the only ones where the function parameter names are omitted in the declaration. + Add names to ensure consistency. + + commit 98a668efc2ab0bea86dcf9a2d8bf583dddc35e32 + Author: Jens Maurer + Date: Thu Mar 26 21:57:48 2026 +0100 + + [expr.const] Introduce subclauses + + commit a2933d5fd4e592bcd8669a51a359c5a850b32de2 + Author: Davis Herring + Date: Thu Mar 26 21:00:20 2026 +0000 + + Refine cross references into [expr.const] + + commit 13906dcab8cfb87f880ea444336cbcc37165cd67 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Dec 11 14:14:32 2025 +0000 + + [basic.lookup.unqual] Rephrase to avoid incorrect use of term + + commit ad94af979e8dfac9ca9af4aa22c66beec7935cfd + Author: A. Jiang + Date: Wed Mar 25 21:05:15 2026 +0800 + + [iostream.forward.overview] Add missing mentions of spanbuf and spanstreams + + A follows up to P0448R4. + + commit 6a31f94c5ef15fdb592c558cd63b2bd02bd18c8a + Author: A. Jiang + Date: Wed Mar 25 21:05:37 2026 +0800 + + [iostream.forward.overview] Say "designate specialization". + + This replaces the imprecise and informal phrase "define instances of + class templates". + + commit 731cda191b915555c6816912361e431c82e7e2f6 + Author: Matthias Kretz + Date: Tue Nov 4 05:17:01 2025 -1000 + + [simd.permute.*] Change M back to V since the wording refers to V + + This was changed editorially by b6e501026e14600fed911183336266c0ebdf5728 + as part of "2025-06 LWG Motion 13: P3691R1 Reconsider naming of the + namespace for std::simd", but turned out not to be a helpful change, + because it makes other wording more complex. + + Fixes NB US 180-295 (C++26 CD). + + commit 7f3b7c64a18610948bfc5479a90764f4992731bd + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Dec 14 22:00:24 2025 +0000 + + [intro.races] Fix typo + + commit e1ee86a3c373c53db7b5d6289457eed620862c76 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Mar 27 13:17:33 2026 +0100 + + [simd.syn,simd.permute.mask] Change M::value_type& to V::value_type& + + commit 8cef46b15b21d4ab1b96dce04c0d37e511d1ddc2 + Author: Jens Maurer + Date: Mon Oct 6 00:24:35 2025 +0200 + + [exec.snd.expos] Reorder specification immediately after declaration + + Fixes NB US 213-353 (C++26 CD). + + commit 6fc165022194a0dd3b78287b087e7872c6c88f48 + Author: Thomas Köppe + Date: Fri Mar 27 11:58:32 2026 +0000 + + [exec.get.compl.sched] Rename completion-tag to completion-fn-tag and reorder text. + + The renaming avoids a clash with the concept "completion-tag" defined + in [exec.snd.expos]. The reordering makes it so that names are defined + before they are referenced. + + commit deb2a9b40a46062dd76a1bbc968ff5039cb02aaf + Author: Thomas Köppe + Date: Sat Mar 28 08:56:40 2026 +0000 + + [exec.snd.expos] Delete unused expos-only concept "completion-tag". + + Also insert a missing \pnum before the now-split codeblock (see 8cef46b15b21d4ab1b96dce04c0d37e511d1ddc2). + + commit fda5e3771f85dfea6d7bd8ade0577e82886addc0 + Author: Abhinav Agarwal + Date: Fri Mar 20 02:36:07 2026 -0700 + + [dcl.struct.bind] Fix tuple-like binding index to use SB_i instead of v_i + + P1061R10 introduced the SB_i notation for post-expansion structured bindings + but this sentence was not updated. The rest of the section (p6, p8, and the + end of this same paragraph) already uses SB_i. + + commit 42f878f50d1356866b5aebe520a3138f707919a0 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Dec 15 00:01:35 2025 +0000 + + [basic] Do not hyphenate "potentially evaluated" + + commit 70e753882b290ea432e516b75fd924bc687076be + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Dec 15 00:03:46 2025 +0000 + + [expr] Do not hyphenate "potentially evaluated" + + commit d296b82c70dcf49a7a10a100778ecd6aed4c92c7 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Dec 15 00:04:54 2025 +0000 + + [dcl] Do not hyphenate "potentially evaluated" + + commit 9ad63b74fae211473235c8fa087d19d392c04728 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Dec 15 00:05:31 2025 +0000 + + [temp.over.link] Do not hyphenate "potentially evaluated" + + commit 180830c280023ea63165547b937da8265b6bd667 + Author: S. B. Tam + Date: Fri Apr 3 21:10:21 2026 +0800 + + [mdspan.mdspan.cons] Fix typo (`is_nothrow_constructible` => `is_nothrow_constructible_v`) + + commit c52c49ab2bcb5770ec2190f3381051442e037157 + Author: Thomas Köppe + Date: Mon Apr 20 01:49:17 2026 +0100 + + [task.promise] Delete unused definition of expos-only error-variant. + + The changes from LWG 4339 removed the use of this type alias, + but not its definition. + + commit ec642cdab87f6f83392196a1600d19d893c17b08 + Author: Thomas Köppe + Date: Sun Apr 12 20:52:51 2026 +0100 + + [mdspan.syn] Renamed template parameter from "Slices" to "SliceSpecifiers". + + The latter form is used everywhere else, including in the item's itemdecl. + + commit bcb6a56a5d2bef008ed02de89b50acdd7e8b8b1d + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Apr 20 18:47:33 2026 +0200 + + [exec.get.domain] Remove extraneous period after list (#8956) + + commit 6fd25df420db99ce2607b7ce3741f4d1891d0ceb + Author: Jens Maurer + Date: Sun Feb 22 19:14:40 2026 +0100 + + [temp.deduct.conv] Add comma to structure the sentence + + commit 25182503a4a94a3fb56c48c80fca56a713095882 + Author: Jens Maurer + Date: Thu Apr 16 17:25:53 2026 +0200 + + [cpp.pre] Remove confused footnote about 'lines' + + commit cd6c5bf4871a80b1e865f85a7e1e104036ce2869 + Author: Jay Ghiron <55773281+Halalaluyafail3@users.noreply.github.com> + Date: Mon Apr 20 12:52:13 2026 -0400 + + [diff.expr] Update incorrect comment about C (#8933) + + arr2 is a constraint violation in C, rather than being valid. + + commit 9909e30038ee608225a67f62b355a60d1a679325 + Author: Hewill Kang + Date: Thu Apr 16 21:22:13 2026 +0800 + + [mdspan.layout.leftpad.obs, mdspan.layout.rightpad.obs] Fix return type of operator() + + commit 1651c628caed73f26e120a604eca6798f4da6afc + Author: Hewill Kang + Date: Tue Apr 21 04:40:40 2026 +0800 + + [linalg] Add period after \returns statement on same line (#8950) + + commit 6211dc859a519b7ff5cca0bfbd953f3b4bd73450 + Author: Hewill Kang + Date: Wed Apr 8 12:19:17 2026 +0800 + + [linalg.scaled.scaledaccessor,linalg.conj.conjugatedaccessor] Added missing typename + + commit 0a236f9185a2e59c7a49b5439135ee995460bcd6 + Author: A. Jiang + Date: Tue Apr 21 20:02:56 2026 +0800 + + [numarray] Remove incorrect comments for deleted default constructors (#8962) + + commit 1e747bf358e4546e9661c6bcee01a1dd71d2186f + Author: Tymi + Date: Tue Apr 21 21:58:09 2026 +0200 + + [fs.class.path] Use "typedef-name" instead of "typedef" (#8964) + + commit 240dc1f4e197dac0004fb5b171ea7c717fba89c9 + Author: timsong-cpp + Date: Tue Apr 21 21:51:27 2026 -0500 + + [meta.define.static] Move misplaced \end{codeblock} + + commit c07075ab7018c7a88d0d254c4c9262d9a6978c94 + Author: timsong-cpp + Date: Tue Apr 21 22:14:11 2026 -0500 + + [meta.define.static] Rephrase sentence to avoid overfull \hbox + + commit 259dcba53500aa26b555f1f952382f484a904cd1 + Author: Hewill Kang + Date: Wed Apr 22 21:46:07 2026 +0800 + + [mdspan.syn, mdspan.sub.range.slices] Remove redundant std + + commit 3532b45c6d9dd37d3f9f949b8307960b7a53eff0 + Author: Hewill Kang + Date: Thu Apr 23 00:30:10 2026 +0800 + + [mdspan.sub.helpers] Use period for \returns (#8977) + + commit e3a17c5b35d7903f85ff136aeaf9000e6b081517 + Author: Jens Maurer + Date: Thu Apr 23 21:50:58 2026 +0200 + + [utility.arg.requirements] Strike redundant text about core language rules (#8987) + + commit 3b5d4f6e215c9fad9472ce1d748cf74b90817ad2 + Author: A. Jiang + Date: Fri Apr 24 03:58:27 2026 +0800 + + [format.arguments, depr.format.arg] Apply `\exposid` consistently (#8971) + + Co-authored-by: Alisdair Meredith + Co-authored-by: Jonathan Wakely + Co-authored-by: Johel Ernesto Guerrero Peña + + commit 673a0e4fc97da58665e7f69e00b0f70e5924795e + Author: A. Jiang + Date: Fri Apr 24 17:47:21 2026 +0800 + + [re.tokiter.general] Fix incorrect `suffix.match` to use `.matched` (#8988) + + commit 663b952c59c4b77e233179189f410ce1d952ea59 + Author: timsong-cpp + Date: Fri Apr 24 12:02:16 2026 -0500 + + [meta.define.static] correct note after CWG3141 + + commit fecad5839345644f30f8b5d9c1043e2a4e666fc8 + Author: Thomas Köppe + Date: Sun Apr 26 15:30:37 2026 +0100 + + [basic.compound] Add missing \grammarterm. + + Misapplication of CWG Motion 1, Issue CWG 2765. + + Addresses editorial review committee feedback. + + commit d3128aacb391726a0c15b8649f9c8e2ca199789e + Author: Thomas Köppe + Date: Sun Apr 26 15:34:23 2026 +0100 + + [bit.cast] Update cross-reference into [expr.const] following 98a668efc2ab0bea86dcf9a2d8bf583dddc35e32. + + The editorial change was made after the wording of CWG 2765 was written. + + Addresses editorial review committee feedback. + + commit 5c2c9dd250af893345b6dbb28c793d8894d4b3c8 + Author: Thomas Köppe + Date: Sun Apr 26 15:50:02 2026 +0100 + + [expr.prim.splice] Add missing maths font for variable "C". + + Misapplication of P3598R0 in CWG Motion 8. + + Addresses editorial review committee feedback. + + commit 8425e4a1c4fa7c928b33c6796b45cfd81d15160a + Author: Thomas Köppe + Date: Sun Apr 26 16:05:53 2026 +0100 + + [lex.phases] Update cross-reference into [expr.const] following 98a668efc2ab0bea86dcf9a2d8bf583dddc35e32. + + The editorial change was made after the wording of P4143R0 was written. + + Addresses editorial review committee feedback. + + commit 01296b2d6e73ade37803f9721de7bdad437b4e3b + Author: Thomas Köppe + Date: Sun Apr 26 16:09:52 2026 +0100 + + [temp.inst] Add missing \grammarterm. + + Misapplication of CWG Motion 11, P4149R1. + + Addresses editorial review committee feedback. + + commit d5078b039da4e188f5de51682c2219f26b8367f9 + Author: Thomas Köppe + Date: Sun Apr 26 16:20:12 2026 +0100 + + [exec.spawn.future] Add missing \exposid. + + Misapplication of LWG Motion 2, Issue LWG 4540. + + Addresses editorial review committee feedback. + + commit 89cc24e855b5a89f099859685fc21fb37f03a36c + Author: Thomas Köppe + Date: Sun Apr 26 16:24:46 2026 +0100 + + [algorithm.syn] Remove stray comma. + + This seems to be an error in the wording of LWG 4544 (LWG Motion 2). + + Addresses editorial review committee feedback. + + commit 83f5072a59b06575d1108e7f63ef28b00fb4e4b2 + Author: Thomas Köppe + Date: Sun Apr 26 18:39:03 2026 +0100 + + [simd.math] Remove stray '@'s. + + Addresses editorial review committee feedback. + + commit ef5f532d2530a733011b0d606dfe69b952c718f6 + Author: Thomas Köppe + Date: Sun Apr 26 18:46:26 2026 +0100 + + [simd.math] Remove stray '\' (unintended escaping). + + Addresses editorial review committee feedback. + + commit d706f2d4fa89e7bcaa54338b9619ead9add59c67 + Author: Thomas Köppe + Date: Sun Apr 26 18:49:24 2026 +0100 + + [simd.math] Better linebreaking/whitespacing in remquo description. + + Addresses editorial review committee feedback. + + commit 9c5becee9a6ca91aad690074069be058f780006f + Author: Thomas Köppe + Date: Sun Apr 26 21:12:54 2026 +0100 + + [simd.expos{,defn}] Fixed template parameter "class T" => "size_t Bytes". + + Misapplication of P3932R0 in LWG Motion 5. + + Addresses editorial review committee feedback. + + commit 120d987ce6a376f1d56b84041d8e69aefaa436ec + Author: Thomas Köppe + Date: Sun Apr 26 21:21:12 2026 +0100 + + [exec.let] Fix misspelled "declval" use. + + Misapplication of P3826R5 in LWG Motion 28. + + Addresses editorial review committee feedback. + + commit daffae75c71890ca82c5021404c9a005e8038405 + Author: Thomas Köppe + Date: Sun Apr 26 21:24:42 2026 +0100 + + [exec.let] Add missing '\exposid's. + + Misapplication of P3373R4 in LWG Motion 10. + + Addresses editorial review committee feedback. + + commit 39a5cd65c6c2af9a251b8d2d5c7d5e73e86c9fa5 + Author: Thomas Köppe + Date: Sun Apr 26 22:24:30 2026 +0100 + + [dcl.attr.annotation] Add missing "codeblock" environment. + + Misapplication of P3795R2 in LWG Motion 15. + + Addresses editorial review committee feedback. + + commit 33a4bec49725127d2e1942f2b074d17242bc0458 + Author: Thomas Köppe + Date: Sun Apr 26 22:30:48 2026 +0100 + + [basic. link] Add "ANN" element to the "data member description sextuple. + + This was missed by P3795R2 in LWG Motion 15, presumably by accident. + + Addresses editorial review committee feedback. + + commit f8e7a0665d9919af4b680d60b07dbb322ee1d4cb + Author: Thomas Köppe + Date: Sun Apr 26 23:10:01 2026 +0100 + + [func.ref.wrap.ctor] Add missing ".value" + + Misapplication of P3948R1 in LWG Motion 16. + + Addresses editorial review committee feedback. + + commit d7c02a0f5c21cd235a0ed3921a30b19d75771f2e + Author: Thomas Köppe + Date: Sun Apr 26 23:36:15 2026 +0100 + + [mdspan.sub.overview] Fix missing edits and missing maths font. + + Misapplication of P3982R2 in LWG Motion 23. + + Addresses editorial review committee feedback. + + commit 2a8305d4b5bdf40b9e4e602d30a08e5fed6dd87b + Author: Abhinav Agarwal + Date: Sun Apr 26 16:10:39 2026 -0700 + + [mdspan.sub.map.sliceable] Fix M::extent_type to M::extents_type + + Layout mapping types expose extents_type, not extent_type; the + latter is a member of extent_slice. As written, IT and M_rank + in the Let clause name an undefined member. + + commit 368af317f557650b4d3dcf98379f02ef3d00140e + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sat May 2 07:41:44 2026 +0000 + + [basic.def] Mark definition of "redeclaration" as such (#8596) + + commit 75b6c6535f5115750bcaa588ded5dfa99eb5fa24 + Author: Guyutongxue + Date: Tue Apr 28 16:40:13 2026 +0800 + + [algorithm.syn] Add missing semicolon and right angle bracket + + commit 25401da54dcf000fa09105a8dc3cdcf788d753d5 + Author: Guyutongxue + Date: Tue Apr 28 16:42:37 2026 +0800 + + [map.overview] Add missing right angle bracket + + commit eaa1458d9832084f56f22d60dde77ed2a95b9b7e + Author: Guyutongxue + Date: Tue Apr 28 16:43:27 2026 +0800 + + [exec.snd.expos] Add missing left brace + + commit 9e15aa83cc1fd4efb06afdb861ebaf6e05f261bd + Author: Guyutongxue + Date: Tue Apr 28 16:45:11 2026 +0800 + + [rand.eng.philox, simd.syn] Fix misplaced right angle bracket, missing comma in `hypot`, `lerp` and `fma` + + commit f0c6e9e9af125c133dba0336797e2193d7d2cc2e + Author: Guyutongxue + Date: Tue Apr 28 16:45:45 2026 +0800 + + [range.filter.sentinel] Add missing semicolon + + commit 0fcd7084a93a5bfbbfe177cd9c6859eeca63439a + Author: Guyutongxue + Date: Tue Apr 28 16:46:20 2026 +0800 + + [atomics.types.float] Fix typo of `floating-point-type` + + commit 1a12df96659d230a376a3da4a2bae3cfc4cd57cb + Author: Thomas Köppe + Date: Sat May 2 15:39:57 2026 +0100 + + [exec.get.compl.{domain,sched}] Replace "it" and long expression with "the expression". + + In e82e850497facd0b9f1e65f4de75b475ddde42ed I had shortened a long + expression from the incoming paper in [exec.get.compl.domain] to just + "it". In review it was suggested that "the expression" is clearer, and + that similar wording in [exec.get.compl.sched] should use the same style. + + (Overall, I think it is easier to understand that the shorter + reference refers to the same expression than to have to compare + two long expressions and determine that they are equal.) + + Addresses editorial review committee feedback. + + commit 65970a5aad6e50048dce1a0b4398d63b8a09ea44 + Author: Thomas Köppe + Date: Sat May 2 15:50:08 2026 +0100 + + [exec.get.compl.domain] + + Misapplication of P3826R5 in LWG Motion 28. + + Addresses editorial review committee feedback. + + commit fa590b2628d9a21d6a12afa5a1d22168cb40b2a3 + Author: Thomas Köppe + Date: Sat May 2 15:53:50 2026 +0100 + + [exec.snd.expos] Fix missing escaping for braces in "{}". + + Misapplication of P3826R5 in LWG Motion 28. + + Addresses editorial review committee feedback. + + commit 91e3416490d096cd0c783c1b5b4e922b53a48f4e + Author: Thomas Köppe + Date: Sat May 2 15:57:04 2026 +0100 + + [exec.domain.default] Delete stray word "sender". + + The deletion was part of the edit instructions of P3826R5 in LWG + Motion 28, but was accidentally missed. + + Addresses editorial review committee feedback. + + commit 62be1e6b61e0e3701f4062994cb04eb02d27d1be + Author: Thomas Köppe + Date: Sat May 2 16:00:32 2026 +0100 + + [exec.snd.transform] Fix "tag2" => "tag". + + Misapplication of P3826R5 in LWG Motion 28. + + Addresses editorial review committee feedback. + + commit 9912050ebe526f32ad1cdec47840fae82099b105 + Author: Thomas Köppe + Date: Sat May 2 16:04:37 2026 +0100 + + [exec.on] Fix missing escaping for braces in "{...}". + + Misapplication of P3826R5 in LWG Motion 28. + + Addresses editorial review committee feedback. + + commit e0ca46ae71122c99c0f098212b2990ed41973b05 + Author: Thomas Köppe + Date: Sat May 2 16:07:02 2026 +0100 + + [exec.on] Fix missing argument "set_value, ". + + Misapplication of P3826R5 in LWG Motion 28, this edit was just missed. + + Addresses editorial review committee feedback. + + commit d04267fda5b9a16ce56beb3137c22900019e0e54 + Author: Thomas Köppe + Date: Sat May 2 16:14:53 2026 +0100 + + [exec.sync.wait.var] Remove vacuous exception. + + The exception that "sndr is evaluated only once" is no longer + necessary, since P3826R5 from LWG Motion 28 removed the previous + second mention of the subexpression "sndr". Now that there is only one + occurrence of "sndr", it does not need saying that it is only + evaluated once. + + Addresses editorial review committee feedback. + + commit e5f877a4c0542654017c5cd9152d6c1dba7972b4 + Author: Thomas Köppe + Date: Sat May 2 16:19:51 2026 +0100 + + [exec.affine] Add missing '\placeholder'. + + Misapplication of P3941R4 in LWG Motion 33. + + Addresses editorial review committee feedback. + + commit 3647c192d9ed47bd653e3575b9dc84107b7cd1fc + Author: Thomas Köppe + Date: Sat May 2 16:32:59 2026 +0100 + + [exec.{rcvr,snd}.concepts] Add "// exposition only" comments to definitions. + + A missed edit from P4159R0 in LWG Motion 37. + + Addresses editorial review committee feedback. + + commit aea0fae459ee3a369e0dc251f674337298433121 + Author: Thomas Köppe + Date: Sat May 2 17:13:27 2026 +0100 + + [except.terminate] Replace system_context_replaceability with parallel_scheduler_replacement. + + This change is needed for consistency with P4154R0 from LWG Motion 39. + Even though that paper didn't ask for this change, that was clearly an + oversight. + + Addresses editorial review committee feedback. + + commit fb2c3e602417fe8cd33618ff5adb31a86cf9072b + Author: Hubert Tong + Date: Mon May 4 10:37:18 2026 -0400 + + [expr.const] Definition domain fixes for "usable in constant expressions" (#8670) + + Also improves the indexing. + + commit 32816d5c2f94da9252ea604c8e7ee17a0657e03c + Author: Thomas Köppe + Date: Sun Apr 26 16:31:18 2026 +0100 + + [simd.{syn,math}] Rename parameters of new overloads of various special maths functions: + + * For comp_ellint_3: from "x, y" to "k, nu" + * For cyl_bessel_{i,j,k}: from "x, y" to "nu, x" + * For cyl_neumann: from "x, y" to "nu, x" + * For ellint_{1,2}: from "x, y" to "k, phi" + * For ellint_{1,2}: from "x, y, z" to "k, nu, phi" + + The paper P3844R4 (LWG Motion 4) added those overloads with parameters + named differently from the names of the existing overloads, but the + latter names seem more appropriate. + + Addresses editorial review committee feedback. + + commit 85c6337534d0bdd9cbfa2260609a853e0c40d61f + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Dec 14 21:54:26 2025 +0000 + + [intro.execution] Replace "or" with "and"; clarify wording + + commit a383c1ad305a61cbef3e14c698b41f6228e780c3 + Author: Jan Schultke + Date: Wed Apr 8 04:52:48 2026 +0200 + + [basic.extended.fp] Reference C23 instead of "future versions" + + commit 87a9fbb3cc85436d876e9c7a79ca1cfbb48ac150 + Author: Thomas Köppe + Date: Mon May 11 23:46:40 2026 +0100 + + [meta.reflection] Remove uninformative "// OK" comments from examples. + + Fixes NB US 84-151 (C++26 CD). + + commit 5670e07a0ec4a4a3c6201512d86013507c0a9389 + Author: Abhinav Agarwal + Date: Sun Apr 26 16:10:54 2026 -0700 + + [mdspan.sub.map.sliceable] Use lm in sliceable-mapping concept body + + The concept body introduces lm (an object of type LayoutMapping) but + then uses m (an object of type M from the surrounding requirements + section) in the submdspan_mapping well-formedness check. + + commit 738e80f3b19fe9ad73d7a48c382f9584e2f200fd + Author: Jonathan Wakely + Date: Tue May 12 09:41:32 2026 +0100 + + [istream.formatted.arithmetic] remove unnecessary whitespace in codeblocks + + commit d2e19cd940eec863a39edee1499e75230725925f + Author: Abhinav Agarwal + Date: Tue May 12 03:15:09 2026 -0700 + + [linalg.algs.blas2.rank1,linalg.algs.blas2.symherrank1] Restore missing arguments (#8995) + + Fixes a misapplication of P3371R5. + + * [linalg.algs.blas2.rank1] Add missing E in matrix_rank_1_update_c effects + * [linalg.algs.blas2.symherrank1] Restore parameters in updating overload + + commit 7c2e7f83c4a8af1841f81f798dd9c5db46232e6d + Author: Abhinav Agarwal + Date: Sun Apr 26 16:10:17 2026 -0700 + + [mdspan.sub.sub] Fix submdspan slice canonicalization + + Two integration errors in the Let clause introduced by P3663R3: + - the function parameter pack is named "slices", but the Let clause + references an undefined "raw_slices"; rename the parameter to match + subextents (mdspan.sub.extents); + - src is an mdspan but canonical_slices takes an extents object; + pass src.extents() instead of src. diff --git a/papers/wd-index.md b/papers/wd-index.md index 92100a86b8..8b987792af 100644 --- a/papers/wd-index.md +++ b/papers/wd-index.md @@ -54,3 +54,6 @@ * [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 + * [N5014](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5014.pdf) 2025-08 C++ Working Draft + * [N5032](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5032.pdf) 2025-12 C++ Working Draft + * [N5046](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/n5046.pdf) 2026-05 C++ Working Draft diff --git a/source/algorithms.tex b/source/algorithms.tex index e6266d1e8e..8b2f530d4c 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -233,7 +233,9 @@ \end{codeblock} For each iterator \tcode{i} and sentinel \tcode{s} produced from a range \tcode{r}, -the semantics of \tcode{s - i} has the same type, value, and value category +the semantics of \tcode{s - i} +are the same as those of an expression that +has the same type, value, and value category as \tcode{ranges::distance(i, s)}. \begin{note} The implementation can use \tcode{ranges::distance(r)} @@ -379,7 +381,9 @@ \tcode{BinaryOperation1}, \tcode{BinaryOperation2}, \tcode{BinaryDivideOp}, or -constrained by a concept that subsumes \libconcept{regular_invocable} +constrained by a concept +whose semantic requirements include +that the type models \libconcept{regular_invocable} and the operators used by the analogous overloads to these parallel algorithms that are formed by an invocation with the specified default predicate or operation (where applicable) @@ -1297,7 +1301,7 @@ constexpr typename iterator_traits::difference_type count(InputIterator first, InputIterator last, const T& value); template::value_type> + class T = iterator_traits::value_type> typename iterator_traits::difference_type count(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& value); @@ -2097,13 +2101,13 @@ namespace ranges { template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, - class T1 = projected_value_t, class T2 = T1> + class T1 = projected_value_t, class T2 = iter_value_t> 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 Proj = identity, - class T1 = projected_value_t, Proj>, class T2 = T1> + class T1 = projected_value_t, Proj>, class T2 = range_value_t> requires @\libconcept{indirectly_writable}@, const T2&> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> @@ -2111,13 +2115,14 @@ replace(R&& r, const T1& old_value, const T2& new_value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, - class Proj = identity, class T1 = projected_value_t, class T2 = T1> + class Proj = identity, + class T1 = projected_value_t, class T2 = iter_value_t> requires @\libconcept{indirectly_writable}@ && @\libconcept{indirect_binary_predicate}@, const T1*> I replace(Ep&& exec, I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); // freestanding-deleted template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, - class T1 = projected_value_t, Proj>, class T2 = T1> + class T1 = projected_value_t, Proj>, class T2 = range_value_t> requires @\libconcept{indirectly_writable}@, const T2&> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> @@ -2126,24 +2131,24 @@ Proj proj = {}); // freestanding-deleted template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, - class T = projected_value_t, + class T = iter_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 Proj = identity, class T = projected_value_t, + template<@\libconcept{input_range}@ R, class Proj = identity, class T = range_value_t, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> constexpr borrowed_iterator_t replace_if(R&& r, Pred pred, const T& new_value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, - class Proj = identity, class T = projected_value_t, + class Proj = identity, class T = iter_value_t, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_writable}@ I replace_if(Ep&& exec, I first, S last, Pred pred, const T& new_value, Proj proj = {}); // freestanding-deleted template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, - class T = projected_value_t, Proj>, + class T = range_value_t, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> borrowed_iterator_t @@ -2258,7 +2263,7 @@ ForwardIterator first, ForwardIterator last, const T& value); template::value_type> - constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value) + constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value); template::value_type> ForwardIterator fill_n(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} @@ -2311,16 +2316,6 @@ template<@\libconcept{input_or_output_iterator}@ O, @\libconcept{copy_constructible}@ F> requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> constexpr O generate_n(O first, iter_difference_t n, F gen); - template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ S, - @\libconcept{copy_constructible}@ F> - requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> - O generate(Ep&& exec, O first, S last, F gen); // freestanding-deleted - template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\libconcept{copy_constructible}@ F> - requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@, invoke_result_t> - borrowed_iterator_t generate(Ep&& exec, R&& r, F gen); // freestanding-deleted - template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, @\libconcept{copy_constructible}@ F> - requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> - O generate_n(Ep&& exec, O first, iter_difference_t n, F gen); // freestanding-deleted } // \ref{alg.remove}, remove @@ -2355,7 +2350,8 @@ template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, class Proj = identity, class T = projected_value_t> - requires @\libconcept{indirect_binary_predicate}@, const T*> + requires @\libconcept{permutable}@ && + @\libconcept{indirect_binary_predicate}@, const T*> subrange remove(Ep&& exec, I first, S last, const T& value, Proj proj = {}); // freestanding-deleted template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, @@ -2377,6 +2373,7 @@ template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{permutable}@ subrange remove_if(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); // freestanding-deleted template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, @@ -2850,12 +2847,12 @@ class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@ I stable_sort(Ep&& exec, I first, S last, Comp comp = {}, - Proj proj = {}); // freestanding-deleted + Proj proj = {}); // hosted template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@, Comp, Proj> borrowed_iterator_t - stable_sort(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted + stable_sort(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // hosted } template @@ -3134,7 +3131,7 @@ namespace ranges { 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 equal_range(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); @@ -3217,6 +3214,7 @@ template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{permutable}@ subrange partition(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); // freestanding-deleted template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, @@ -3253,12 +3251,12 @@ requires @\libconcept{permutable}@ subrange stable_partition(Ep&& exec, I first, S last, Pred pred, - Proj proj = {}); // freestanding-deleted + Proj proj = {}); // hosted template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{permutable}@> borrowed_subrange_t - stable_partition(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted + stable_partition(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // hosted } template requires @\libconcept{sortable}@ I inplace_merge(Ep&& exec, I first, I middle, S last, Comp comp = {}, - Proj proj = {}); // freestanding-deleted + Proj proj = {}); // hosted template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@, Comp, Proj> borrowed_iterator_t inplace_merge(Ep&& exec, R&& r, iterator_t middle, Comp comp = {}, - Proj proj = {}); // freestanding-deleted + Proj proj = {}); // hosted } // \ref{alg.set.operations}, set operations @@ -3635,6 +3633,8 @@ namespace ranges { template using @\libglobal{set_difference_result}@ = in_out_result; + template + using @\libglobal{set_difference_truncated_result}@ = in_in_out_result; template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{input_iterator}@ I2, @\libconcept{sentinel_for}@ S2, @\libconcept{weakly_incrementable}@ O, class Comp = ranges::less, @@ -3655,7 +3655,7 @@ @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires @\libconcept{mergeable}@ - set_difference_result + set_difference_truncated_result set_difference(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, O result, OutS result_last, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted @@ -3663,7 +3663,8 @@ @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> - set_difference_result, borrowed_iterator_t> + set_difference_truncated_result, borrowed_iterator_t, + borrowed_iterator_t> set_difference(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } @@ -5057,7 +5058,7 @@ requires @\libconcept{indirect_binary_predicate}@, const T*> subrange ranges::find_last(Ep&& exec, I first, S last, const T& value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, - class T = projected_value_t, Proj>> + class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> borrowed_subrange_t ranges::find_last(Ep&& exec, R&& r, const T& value, Proj proj = {}); @@ -5073,8 +5074,8 @@ class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> subrange ranges::find_last_if(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, - class Proj = identity, - @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> borrowed_subrange_t ranges::find_last_if(Ep&& exec, R&& r, Pred pred, Proj proj = {}); template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @@ -5335,11 +5336,11 @@ template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_binary_predicate}@, - projected> Pred = ranges::equal_to> + projected> Pred = ranges::equal_to> I ranges::adjacent_find(Ep&& exec, I first, S last, Pred pred = {}, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, @\libconcept{indirect_binary_predicate}@, Proj>, - projected, Proj>> Pred = ranges::equal_to> + projected, Proj>> Pred = ranges::equal_to> borrowed_iterator_t ranges::adjacent_find(Ep&& exec, R&& r, Pred pred = {}, Proj proj = {}); \end{itemdecl} @@ -5412,7 +5413,7 @@ template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + projected, Proj>, const T*> range_difference_t ranges::count(Ep&& exec, R&& r, const T& value, Proj proj = {}); template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @@ -6523,15 +6524,15 @@ ranges::copy_if(R&& r, O result, Pred pred, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, - @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, - class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_copyable}@ ranges::copy_if_result ranges::copy_if(Ep&& exec, I first, S last, O result, OutS result_last, Pred pred, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, - class Proj = identity, - @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_copyable}@, iterator_t> ranges::copy_if_result, borrowed_iterator_t> ranges::copy_if(Ep&& exec, R&& r, OutR&& result_r, Pred pred, Proj proj = {}); @@ -6997,9 +6998,9 @@ ranges::transform(Ep&& exec, I first1, S last1, O result, OutS result_last, F op, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, - @\libconcept{copy_constructible}@ F, class Proj = identity> + @\libconcept{copy_constructible}@ F, class Proj = identity> requires @\libconcept{indirectly_writable}@, - indirect_result_t, Proj>>> + indirect_result_t, Proj>>> ranges::unary_transform_result, borrowed_iterator_t> ranges::transform(Ep&& exec, R&& r, OutR&& result_r, F op, Proj proj = {}); @@ -7024,17 +7025,17 @@ @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, @\libconcept{copy_constructible}@ F, class Proj1 = identity, class Proj2 = identity> requires @\libconcept{indirectly_writable}@, - projected>> + projected>> ranges::binary_transform_result ranges::transform(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, O result, OutS result_last, F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, @\exposconcept{sized-random-access-range}@ OutR, @\libconcept{copy_constructible}@ F, - class Proj1 = identity, class Proj2 = identity> + class Proj1 = identity, class Proj2 = identity> requires @\libconcept{indirectly_writable}@, - indirect_result_t, Proj1>, - projected, Proj2>>> + indirect_result_t, Proj1>, + projected, Proj2>>> ranges::binary_transform_result, borrowed_iterator_t, borrowed_iterator_t> ranges::transform(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, @@ -7149,52 +7150,52 @@ Predicate pred, const T& new_value); template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, - class T1 = projected_value_t, class T2 = T1> + class T1 = projected_value_t, class T2 = iter_value_t> 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 Proj = identity, - class T1 = projected_value_t, Proj>, class T2 = T1> + class T1 = projected_value_t, Proj>, class T2 = range_value_t> 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<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, - class Proj = identity, class T1 = projected_value_t, class T2 = T1> + class Proj = identity, class T1 = projected_value_t, class T2 = iter_value_t> requires @\libconcept{indirectly_writable}@ && @\libconcept{indirect_binary_predicate}@, const T1*> I ranges::replace(Ep&& exec, I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, - class T1 = projected_value_t, Proj>, class T2 = T1> + class T1 = projected_value_t, Proj>, class T2 = range_value_t> requires @\libconcept{indirectly_writable}@, const T2&> && - @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> + @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> borrowed_iterator_t ranges::replace(Ep&& exec, R&& r, const T1& old_value, const T2& new_value, Proj proj = {}); template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, - class T = projected_value_t, + class T = iter_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 Proj = identity, class T = projected_value_t, Proj>, +template<@\libconcept{input_range}@ R, class Proj = identity, class T = range_value_t, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> constexpr borrowed_iterator_t ranges::replace_if(R&& r, Pred pred, const T& new_value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, - class Proj = identity, class T = projected_value_t, + class Proj = identity, class T = iter_value_t, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_writable}@ I ranges::replace_if(Ep&& exec, I first, S last, Pred pred, const T& new_value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, - class T = projected_value_t, Proj>, + class T = range_value_t, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> borrowed_iterator_t @@ -7291,7 +7292,7 @@ class T2 = range_value_t> requires @\libconcept{indirectly_copyable}@, iterator_t> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> && + projected, Proj>, const T1*> && @\libconcept{indirectly_writable}@, const T2&> ranges::replace_copy_result, borrowed_iterator_t> ranges::replace_copy(Ep&& exec, R&& r, OutR&& result_r, const T1& old_value, @@ -7484,17 +7485,6 @@ template<@\libconcept{input_or_output_iterator}@ O, @\libconcept{copy_constructible}@ F> requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> constexpr O ranges::generate_n(O first, iter_difference_t n, F gen); - -template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ S, - @\libconcept{copy_constructible}@ F> - requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> - O ranges::generate(Ep&& exec, O first, S last, F gen); -template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\libconcept{copy_constructible}@ F> - requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@, invoke_result_t> - borrowed_iterator_t ranges::generate(Ep&& exec, R&& r, F gen); -template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, @\libconcept{copy_constructible}@ F> - requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> - O ranges::generate_n(Ep&& exec, O first, iter_difference_t n, F gen); \end{itemdecl} \begin{itemdescr} @@ -7561,14 +7551,15 @@ template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, class Proj = identity, class T = projected_value_t> - requires @\libconcept{indirect_binary_predicate}@, const T*> + requires @\libconcept{permutable}@ && + @\libconcept{indirect_binary_predicate}@, const T*> subrange ranges::remove(Ep&& exec, I first, S last, const T& value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, class T = projected_value_t, Proj>> requires @\libconcept{permutable}@> && @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + projected, Proj>, const T*> borrowed_subrange_t ranges::remove(Ep&& exec, R&& r, const T& value, Proj proj = {}); @@ -7583,6 +7574,7 @@ template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{permutable}@ subrange ranges::remove_if(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, @@ -7594,7 +7586,7 @@ \begin{itemdescr} \pnum -Let $E$ be +Let $E(\tcode{i})$ be \begin{itemize} \item \tcode{bool(*i == value)} for \tcode{remove}; \item \tcode{bool(pred(*i))} for \tcode{remove_if}; @@ -7611,7 +7603,7 @@ \pnum \effects Eliminates all the elements referred to by iterator \tcode{i} -in the range \range{first}{last} for which $E$ holds. +in the range \range{first}{last} for which $E(\tcode{i})$ holds. \pnum \returns @@ -7691,7 +7683,7 @@ class Proj = identity, class T = projected_value_t, Proj>> requires @\libconcept{indirectly_copyable}@, iterator_t> && @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + projected, Proj>, const T*> ranges::remove_copy_result, borrowed_iterator_t> ranges::remove_copy(Ep&& exec, R&& r, OutR&& result_r, const T& value, Proj proj = {}); @@ -7839,9 +7831,11 @@ \pnum Let \tcode{pred} be \tcode{equal_to\{\}} for the overloads with no parameter \tcode{pred}, and -let $E$ be +let $E(\tcode{i})$ be \begin{itemize} \setlength{\emergencystretch}{1em} +\item + \tcode{false} if \tcode{i} is equal to \tcode{first}; otherwise \item \tcode{bool(pred(*(i - 1), *i))} for the overloads in namespace \tcode{std}; @@ -7859,10 +7853,9 @@ \pnum \effects -For a nonempty range, eliminates all but the first element -from every consecutive group of equivalent elements referred to -by the iterator \tcode{i} in the range \range{first + 1}{last} -for which $E$ is \tcode{true}. +Eliminates all elements referred to +by the iterator \tcode{i} in the range \range{first}{last} +for which $E(\tcode{i})$ is \tcode{true}. \pnum \returns @@ -7943,10 +7936,12 @@ \begin{itemize} \setlength{\emergencystretch}{1em} \item - \tcode{bool(pred(*i, *(i - 1)))} + \tcode{false} if \tcode{i} is equal to \tcode{first}; otherwise +\item + \tcode{bool(pred(*(i - 1), *i))} for the overloads in namespace \tcode{std}; \item - \tcode{bool(invoke(comp, invoke(proj, *i), invoke(proj, *(i - 1))))} + \tcode{bool(invoke(comp, invoke(proj, *(i - 1)), invoke(proj, *i)))} for the overloads in namespace \tcode{ranges}. \end{itemize} @@ -7954,13 +7949,13 @@ Let: \begin{itemize} \item - $M$ be the number of iterators \tcode{i} in the range \range{first + 1}{last} + $M$ be the number of iterators \tcode{i} in the range \range{first}{last} for which $E(\tcode{i})$ is \tcode{false}; \item - \tcode{result_last} be \tcode{result + $M$ + 1} + \tcode{result_last} be \tcode{result + $M$} for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; \item - $N$ be $\min(M + 1, \ \tcode{result_last - result})$. + $N$ be $\min(M, \ \tcode{result_last - result})$. \end{itemize} \pnum @@ -8006,9 +8001,9 @@ \pnum \effects -Copies only the first element from $N$ consecutive groups of equivalent elements -referred to by the iterator \tcode{i} in the range \range{first + 1}{last} -for which $E(\tcode{i})$ holds +Copies only the first $N$ elements +referred to by the iterator \tcode{i} in the range \range{first}{last} +for which $E(\tcode{i})$ is \tcode{false} into the range \range{result}{result + $N$}. \pnum @@ -8020,13 +8015,13 @@ \item \tcode{\{last, result + $N$\}} for the overloads in namespace \tcode{ranges}, - if $N$ is equal to $M + 1$. + if $N$ is equal to $M$. \item Otherwise, \tcode{\{j, result_last\}} for the overloads in namespace \tcode{ranges}, - where \tcode{j} is the iterator in \range{first + 1}{last} + where \tcode{j} is the iterator in \range{first}{last} for which $E(\tcode{j})$ is \tcode{false} - and there are exactly $N - 1$ iterators \tcode{i} in \range{first + 1}{j} + and there are exactly $N$ iterators \tcode{i} in \range{first}{j} for which $E(\tcode{i})$ is \tcode{false}. \end{itemize} @@ -8256,7 +8251,8 @@ \effects Equivalent to: \begin{codeblock} -return ranges::rotate(std::forward(exec), ranges::begin(r), middle, ranges::end(r)); +return ranges::rotate(std::forward(exec), ranges::begin(r), middle, + ranges::begin(r) + ranges::distance(r)); \end{codeblock} \end{itemdescr} @@ -8381,8 +8377,10 @@ \effects Equivalent to: \begin{codeblock} -return ranges::rotate_copy(std::forward(exec), ranges::begin(r), middle, ranges::end(r), - ranges::begin(result_r), ranges::end(result_r)); +return ranges::rotate_copy(std::forward(exec), ranges::begin(r), middle, + ranges::begin(r) + ranges::distance(r), + ranges::begin(result_r), + ranges::begin(result_r) + ranges::distance(result_r)); \end{codeblock} \end{itemdescr} @@ -9002,7 +9000,8 @@ Equivalent to: \begin{codeblock} return ranges::partial_sort(std::forward(exec), ranges::begin(r), middle, - ranges::end(r), comp, proj); + ranges::begin(r) + ranges::distance(r), + comp, proj); \end{codeblock} \end{itemdescr} @@ -9059,7 +9058,7 @@ @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires @\libconcept{indirectly_copyable}@ && @\libconcept{sortable}@ && - @\libconcept{indirect_strict_weak_order}@, projected> + @\libconcept{indirect_strict_weak_order}@, projected> ranges::partial_sort_copy_result ranges::partial_sort_copy(Ep&& exec, I1 first, S1 last, I2 result_first, S2 result_last, Comp comp = {}, Proj1 proj1 = {}, @@ -9264,7 +9263,7 @@ class Proj = identity, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> I ranges::is_sorted_until(Ep&& exec, I first, S last, Comp comp = {}, - Proj proj = {}); + Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> borrowed_iterator_t @@ -9386,7 +9385,8 @@ \effects Equivalent to: \begin{codeblock} -return ranges::nth_element(std::forward(exec), ranges::begin(r), nth, ranges::end(r), +return ranges::nth_element(std::forward(exec), ranges::begin(r), nth, + ranges::begin(r) + ranges::distance(r), comp, proj); \end{codeblock} \end{itemdescr} @@ -9696,6 +9696,7 @@ template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{permutable}@ subrange ranges::partition(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> @@ -9873,7 +9874,7 @@ class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_copyable}@, iterator_t> && - @\libconcept{indirectly_copyable}@, iterator_t> + @\libconcept{indirectly_copyable}@, iterator_t> ranges::partition_copy_result, borrowed_iterator_t, borrowed_iterator_t> ranges::partition_copy(Ep&& exec, R&& r, OutR1&& out_true_r, OutR2&& out_false_r, @@ -9949,19 +9950,19 @@ \effects For each iterator \tcode{i} in \range{first}{first + $N$}, copies \tcode{*i} to the output range \range{out_true}{last_true} -if \tcode{$E(\tcode{*i})$} is \tcode{true}, or +if $E(\tcode{*i})$ is \tcode{true}, or to the output range \range{out_false}{last_false} otherwise. \pnum \returns -Let \tcode{o1} be the iterator past the last copied element -in the output range \range{out_true}{last_true}, -and \tcode{o2} be the iterator past the last copied element -in the output range \range{out_false}{last_false}. +Let $Q$ be the number of elements copied +into the output range \range{out_true}{last_true}, +and $V$ be the number of elements copied +into the output range \range{out_false}{last_false}. Returns: \begin{itemize} -\item \tcode{\{o1, o2\}} for the overloads in namespace \tcode{std}. -\item \tcode{\{first + $N$, o1, o2\}} for the overloads in namespace \tcode{ranges}. +\item \tcode{\{out_true + $Q$, out_false + $V$\}} for the overloads in namespace \tcode{std}. +\item \tcode{\{first + $N$, out_true + $Q$, out_false + $V$\}} for the overloads in namespace \tcode{ranges}. \end{itemize} \pnum @@ -10091,12 +10092,12 @@ \tcode{proj2} be \tcode{identity\{\}}, for the overloads with no parameters by those names; \item - $E(\tcode{e1}, \tcode{e1})$ be \tcode{bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))}; + $E$ be \tcode{bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))}; \item $K$ be the smallest integer in \range{0}{last1 - first1} such that for the element \tcode{e1} in the position \tcode{first1 + $K$} there are at least $N - K$ elements \tcode{e2} - in \range{first2}{last2} for which $E(\tcode{e1}, \tcode{e1})$ holds, + in \range{first2}{last2} for which $E$ holds, and be equal to \tcode{last1 - first1} if no such integer exists. \begin{note} @@ -10121,7 +10122,7 @@ If \tcode{e1} is an element of \range{first1}{last1} and \tcode{e2} of \range{first2}{last2}, \tcode{e2} is copied into the output range before \tcode{e1} -if and only if $E(\tcode{e1}, \tcode{e1})$ is \tcode{true}. +if and only if $E$ is \tcode{true}. \pnum \returns @@ -10258,7 +10259,8 @@ Equivalent to: \begin{codeblock} return ranges::inplace_merge(std::forward(exec), ranges::begin(r), middle, - ranges::end(r), comp, proj); + ranges::begin(r) + ranges::distance(r), + comp, proj); \end{codeblock} \end{itemdescr} @@ -10320,7 +10322,7 @@ template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, class Proj1 = identity, class Proj2 = identity, @\libconcept{indirect_strict_weak_order}@, Proj1>, - projected, Proj2>> Comp = ranges::less> + projected, Proj2>> Comp = ranges::less> bool ranges::includes(Ep&& exec, R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} @@ -10425,8 +10427,7 @@ and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} for the overloads with no parameters by those names; \item - $M$ be \tcode{last1 - first1} plus the number of elements in \range{first2}{last2} - that are not present in \range{first1}{last1}; + $M$ be the number of elements in the sorted union (see below); \item \tcode{result_last} be \tcode{result + $M$} for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; @@ -10442,8 +10443,21 @@ \pnum \effects -Constructs a sorted union of $N$ elements from the two ranges; +Constructs a sorted union of the elements from the two ranges; that is, the set of elements that are present in one or both of the ranges. +If \range{first1}{last1} contains $m$ elements +that are equivalent to each other and +\range{first2}{last2} contains $n$ elements that are equivalent to them, +then all $m$ elements from the first range +are included in the union, in order, and +then the final $\max(n - m, 0)$ elements from the second range +are included in the union, in order. +If, of those elements, $k$ elements from the first range +are copied to the output range, +then the first $\min(k, n)$ elements from the second range +are considered \term{skipped}. +Copies the first $N$ elements of the sorted union +to the range \range{result}{result + $N$}. \pnum \returns @@ -10456,10 +10470,9 @@ for the overloads in namespace \tcode{ranges}, if $N$ is equal to $M$. \item - Otherwise, \tcode{\{j1, j2, result_last\}} + Otherwise, \tcode{\{first1 + $A$, first2 + $B$, result_last\}} for the overloads in namespace \tcode{ranges}, - where the iterators \tcode{j1} and \tcode{j2} - point to positions past the last copied or skipped elements + where $A$ and $B$ are the numbers of copied or skipped elements in \range{first1}{last1} and \range{first2}{last2}, respectively. \end{itemize} @@ -10471,14 +10484,6 @@ \pnum \remarks Stable\iref{algorithm.stable}. -If \range{first1}{last1} contains $m$ elements -that are equivalent to each other and -\range{first2}{last2} contains $n$ elements -that are equivalent to them, -then all $m$ elements from the first range -are copied to the output range, in order, and -then the final $\max(n - m, 0)$ elements from the second range -are copied to the output range, in order. \end{itemdescr} \rSec3[set.intersection]{\tcode{set_intersection}} @@ -10534,8 +10539,8 @@ requires @\libconcept{mergeable}@ ranges::set_intersection_result ranges::set_intersection(Ep&& exec, I1 first1, S1 last1, - I2 first2, S2 last2, O result, OutS result_last, - Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + I2 first2, S2 last2, O result, OutS result_last, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> @@ -10555,8 +10560,7 @@ and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} for the overloads with no parameters by those names; \item - $M$ be the number of elements in \range{first1}{last1} - that are present in \range{first2}{last2}; + $M$ be the number of elements in the sorted intersection (see below); \item \tcode{result_last} be \tcode{result + $M$} for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; @@ -10572,8 +10576,23 @@ \pnum \effects -Constructs a sorted intersection of $N$ elements from the two ranges; +Constructs a sorted intersection of the elements from the two ranges; that is, the set of elements that are present in both of the ranges. +If \range{first1}{last1} contains $m$ elements +that are equivalent to each other and +\range{first2}{last2} contains $n$ elements +that are equivalent to them, +the first $\min(m, n)$ elements from the first range +are included in the sorted intersection. +If, of those elements, $k$ elements from the first range +are copied to the output range, +then the first $k$ elements from the second range +are considered \defn{skipped}. +A non-copied element is also considered skipped +if it compares less than the $\min(M, N + 1)^\text{th}$ element +of the sorted intersection. +Copies the first $N$ elements of the sorted intersection +to the range \range{result}{result + $N$}. \pnum \returns @@ -10583,13 +10602,11 @@ for the overloads in namespace \tcode{std}. \item \tcode{\{last1, last2, result + $N$\}} - for the overloads in namespace \tcode{ranges}, - if $N$ is equal to $M$. + for the non-parallel algorithm overloads in namespace \tcode{ranges}. \item - Otherwise, \tcode{\{j1, j2, result_last\}} - for the overloads in namespace \tcode{ranges}, - where the iterators \tcode{j1} and \tcode{j2} - point to positions past the last copied or skipped elements + Otherwise, \tcode{\{first1 + $A$, first2 + $B$, result + $N$\}} + for the parallel algorithm overloads in namespace \tcode{ranges}, + where $A$ and $B$ are the numbers of copied or skipped elements in \range{first1}{last1} and \range{first2}{last2}, respectively. \end{itemize} @@ -10601,12 +10618,6 @@ \pnum \remarks Stable\iref{algorithm.stable}. -If \range{first1}{last1} contains $m$ elements -that are equivalent to each other and -\range{first2}{last2} contains $n$ elements -that are equivalent to them, -the first $\min(m, n)$ elements -are copied from the first range to the output range, in order. \end{itemdescr} \rSec3[set.difference]{\tcode{set_difference}} @@ -10660,7 +10671,7 @@ @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires @\libconcept{mergeable}@ - ranges::set_difference_result + ranges::set_difference_truncated_result ranges::set_difference(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, O result, OutS result_last, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); @@ -10668,7 +10679,8 @@ @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> - ranges::set_difference_result, borrowed_iterator_t> + ranges::set_difference_truncated_result, borrowed_iterator_t, + borrowed_iterator_t> ranges::set_difference(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} @@ -10682,8 +10694,7 @@ and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} for the overloads with no parameters by those names; \item - $M$ be the number of elements in \range{first1}{last1} - that are not present in \range{first2}{last2}; + $M$ be the number of elements in the sorted difference (see below); \item \tcode{result_last} be \tcode{result + $M$} for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; @@ -10699,10 +10710,23 @@ \pnum \effects -Copies $N$ elements of the range \range{first1}{last1} -which are not present in the range \range{first2}{last2} +Constructs a sorted difference between the elements from the two ranges; +that is, the set of elements that are present +in the range \range{first1}{last1} but not \range{first2}{last2}. +If \range{first1}{last1} contains $m$ elements +that are equivalent to each other and +\range{first2}{last2} contains $n$ elements +that are equivalent to them, +the last $\max(m - n, 0)$ elements from \range{first1}{last1} +are included in the sorted difference, in order. +Of those equivalent elements, +the first $\min(m, n)$ elements in both ranges +are considered \defn{skipped}. +An element from the second range is also considered skipped +if it compares less than the $\min(N + 1, M)^\text{th}$ element +of the sorted difference. +Copies the first $N$ elements of the sorted difference to the range \range{result}{result + $N$}. -The elements in the constructed range are sorted. \pnum \returns @@ -10712,14 +10736,19 @@ for the overloads in namespace \tcode{std}. \item \tcode{\{last1, result + $N$\}} - for the overloads in namespace \tcode{ranges}, - if $N$ is equal to $M$. + for the non-parallel overloads in namespace \tcode{ranges}. \item - Otherwise, \tcode{\{j1, result_last\}} - for the overloads in namespace \tcode{ranges}, - where the iterator \tcode{j1} - points to the position past the last copied or skipped element - in \range{first1}{last1}. + For the parallel algorithm overloads in namespace \tcode{ranges}: + \begin{itemize} + \item + \tcode{\{last1, first2 + $B$, result + $N$\}}, + if $N$ is equal to $M$, + where $B$ is the number of skipped elements in \range{first2}{last2}. + \item + Otherwise, \tcode{\{first1 + $A$, first2 + $B$, result_last\}}, + where $A$ and $B$ are the numbers of copied or skipped elements + in \range{first1}{last1} and \range{first2}{last2}, respectively. + \end{itemize} \end{itemize} \pnum @@ -10729,12 +10758,7 @@ \pnum \remarks -If \range{first1}{last1} contains $m$ elements -that are equivalent to each other and -\range{first2}{last2} contains $n$ elements -that are equivalent to them, -the last $\max(m - n, 0)$ elements from \range{first1}{last1} -are copied to the output range, in order. +Stable\iref{algorithm.stable}. \end{itemdescr} \rSec3[set.symmetric.difference]{\tcode{set_symmetric_difference}} @@ -10799,7 +10823,7 @@ class Proj1 = identity, class Proj2 = identity> requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> ranges::set_symmetric_difference_result, borrowed_iterator_t, - borrowed_iterator_t> + borrowed_iterator_t> ranges::set_symmetric_difference(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} @@ -10813,14 +10837,12 @@ and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} for the overloads with no parameters by those names; \item - $K$ be the number of elements in \range{first1}{last1} that are not present in \range{first2}{last2}. + $M$ be the number of elements in the sorted symmetric difference (see below); \item - $M$ be the number of elements in \range{first2}{last2} that are not present in \range{first1}{last1}. -\item - \tcode{result_last} be \tcode{result + $M$ + $K$} + \tcode{result_last} be \tcode{result + $M$} for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; \item - $N$ be $\min(K + M, \ \tcode{result_last - result})$. + $N$ be $\min(M, \ \tcode{result_last - result})$. \end{itemize} \pnum @@ -10831,12 +10853,24 @@ \pnum \effects -Copies the elements of the range \range{first1}{last1} -that are not present in the range \range{first2}{last2}, -and the elements of the range \range{first2}{last2} -that are not present in the range \range{first1}{last1} +Constructs a sorted symmetric difference of the elements from the two ranges; +that is, the set of elements that are present +in exactly one of \range{first1}{last1} and \range{first2}{last2}. +If \range{first1}{last1} contains $m$ elements +that are equivalent to each other and +\range{first2}{last2} contains $n$ elements +that are equivalent to them, +then $|m - n|$ of those elements are included in the symmetric difference: +the last $m - n$ of these elements from \range{first1}{last1}, +in order, if $m > n$, and +the last $n - m$ of these elements from \range{first2}{last2}, +in order, if $m < n$. +If $N < M$, a non-copied element is considered \term{skipped} +if it compares less than or equivalent to the $(N + 1)^\text{th}$ element +of the sorted symmetric difference, +unless it is from the same range as that element and does not precede it. +Copies the first $N$ elements of the sorted symmetric difference to the range \range{result}{result + $N$}. -The elements in the constructed range are sorted. \pnum \returns @@ -10849,10 +10883,9 @@ for the overloads in namespace \tcode{ranges}, if $N$ is equal to $M + K$. \item - Otherwise, \tcode{\{j1, j2, result_last\}} + Otherwise, \tcode{\{first1 + $A$, first2 + $B$, result_last\}} for the overloads in namespace \tcode{ranges}, - where the iterators \tcode{j1} and \tcode{j2} - point to positions past the last copied or skipped elements + where $A$ and $B$ are the numbers of copied or skipped elements in \range{first1}{last1} and \range{first2}{last2}, respectively. \end{itemize} @@ -10864,14 +10897,6 @@ \pnum \remarks Stable\iref{algorithm.stable}. -If \range{first1}{last1} contains $m$ elements -that are equivalent to each other and -\range{first2}{last2} contains $n$ elements -that are equivalent to them, -then $|m - n|$ of those elements shall be copied to the output range: -the last $m - n$ of these elements from \range{first1}{last1} if $m > n$, and -the last $n - m$ of these elements from \range{first2}{last2} if $m < n$. -In either case, the elements are copied in order. \end{itemdescr} \rSec2[alg.heap.operations]{Heap operations} @@ -12247,15 +12272,15 @@ // \ref{numeric.sat}, saturation arithmetic template - constexpr T add_sat(T x, T y) noexcept; + constexpr T saturating_add(T x, T y) noexcept; template - constexpr T sub_sat(T x, T y) noexcept; + constexpr T saturating_sub(T x, T y) noexcept; template - constexpr T mul_sat(T x, T y) noexcept; + constexpr T saturating_mul(T x, T y) noexcept; template - constexpr T div_sat(T x, T y) noexcept; + constexpr T saturating_div(T x, T y) noexcept; template - constexpr T saturate_cast(U x) noexcept; + constexpr T saturating_cast(U x) noexcept; } \end{codeblock} @@ -13343,7 +13368,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is an arithmetic type other than \tcode{bool}. +\tcode{T} is an arithmetic type other than \cv{}~\tcode{bool}. \pnum \returns @@ -13399,10 +13424,10 @@ 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}% +\indexlibraryglobal{saturating_add}% \begin{itemdecl} template - constexpr T add_sat(T x, T y) noexcept; + constexpr T saturating_add(T x, T y) noexcept; \end{itemdecl} \begin{itemdescr} @@ -13417,10 +13442,10 @@ whichever is closer to the value of $\tcode{x} + \tcode{y}$. \end{itemdescr} -\indexlibraryglobal{sub_sat}% +\indexlibraryglobal{saturating_sub}% \begin{itemdecl} template - constexpr T sub_sat(T x, T y) noexcept; + constexpr T saturating_sub(T x, T y) noexcept; \end{itemdecl} \begin{itemdescr} @@ -13435,10 +13460,10 @@ whichever is closer to the value of $\tcode{x} - \tcode{y}$. \end{itemdescr} -\indexlibraryglobal{mul_sat}% +\indexlibraryglobal{saturating_mul}% \begin{itemdecl} template - constexpr T mul_sat(T x, T y) noexcept; + constexpr T saturating_mul(T x, T y) noexcept; \end{itemdecl} \begin{itemdescr} @@ -13453,10 +13478,10 @@ whichever is closer to the value of $\tcode{x} \times \tcode{y}$. \end{itemdescr} -\indexlibraryglobal{div_sat}% +\indexlibraryglobal{saturating_div}% \begin{itemdecl} template - constexpr T div_sat(T x, T y) noexcept; + constexpr T saturating_div(T x, T y) noexcept; \end{itemdecl} \begin{itemdescr} @@ -13478,15 +13503,15 @@ \remarks A function call expression that violates the precondition in the \Fundescx{Preconditions} element -is not a core constant expression\iref{expr.const}. +is not a core constant expression\iref{expr.const.core}. \end{itemdescr} \rSec3[numeric.sat.cast]{Casting} -\indexlibraryglobal{saturate_cast}% +\indexlibraryglobal{saturating_cast}% \begin{itemdecl} template - constexpr R saturate_cast(T x) noexcept; + constexpr R saturating_cast(T x) noexcept; \end{itemdecl} \begin{itemdescr} @@ -13535,7 +13560,7 @@ } template - decltype(auto) @\exposid{deref-move}@(I& it) { + constexpr decltype(auto) @\exposid{deref-move}@(I& it) { if constexpr (is_lvalue_reference_v) return std::move(*it); else @@ -14098,7 +14123,8 @@ \indexlibraryglobal{uninitialized_fill}% \begin{itemdecl} -template +template::value_type> constexpr void uninitialized_fill(NoThrowForwardIterator first, NoThrowForwardIterator last, const T& x); \end{itemdecl} @@ -14116,10 +14142,10 @@ \indexlibraryglobal{uninitialized_fill}% \begin{itemdecl} namespace ranges { - template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S, class T> + template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S, class T = iter_value_t> requires @\libconcept{constructible_from}@, const T&> constexpr I uninitialized_fill(I first, S last, const T& x); - template<@\exposconcept{nothrow-forward-range}@ R, class T> + template<@\exposconcept{nothrow-forward-range}@ R, class T = range_value_t> requires @\libconcept{constructible_from}@, const T&> constexpr borrowed_iterator_t uninitialized_fill(R&& r, const T& x); } @@ -14138,7 +14164,8 @@ \indexlibraryglobal{uninitialized_fill_n}% \begin{itemdecl} -template +template::value_type> constexpr NoThrowForwardIterator uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); \end{itemdecl} @@ -14157,7 +14184,7 @@ \indexlibraryglobal{uninitialized_fill_n}% \begin{itemdecl} namespace ranges { - template<@\exposconcept{nothrow-forward-iterator}@ I, class T> + template<@\exposconcept{nothrow-forward-iterator}@ I, class T = iter_value_t> requires @\libconcept{constructible_from}@, const T&> constexpr I uninitialized_fill_n(I first, iter_difference_t n, const T& x); } @@ -14318,7 +14345,7 @@ \begin{itemdecl} template requires @\libconcept{output_range}@> && @\libconcept{uniform_random_bit_generator}@> -constexpr borrowed_iterator_t ranges::generate_random(R&& r, G&& g); + constexpr borrowed_iterator_t ranges::generate_random(R&& r, G&& g); \end{itemdecl} \begin{itemdescr} @@ -14361,7 +14388,7 @@ \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); + constexpr O ranges::generate_random(O first, S last, G&& g); \end{itemdecl} \begin{itemdescr} @@ -14379,7 +14406,7 @@ 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); + constexpr borrowed_iterator_t ranges::generate_random(R&& r, G&& g, D&& d); \end{itemdecl} \begin{itemdescr} @@ -14430,7 +14457,7 @@ 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); + constexpr O ranges::generate_random(O first, S last, G&& g, D&& d); \end{itemdecl} \begin{itemdescr} diff --git a/source/back.tex b/source/back.tex index da31760918..03939906da 100644 --- a/source/back.tex +++ b/source/back.tex @@ -7,10 +7,6 @@ \bibitem{iso4217} ISO 4217:2015, \doccite{Codes for the representation of currencies} -\bibitem{iso10967-1} - ISO/IEC 10967-1:2012, - \doccite{Information technology --- Language independent arithmetic --- - Part 1: Integer and floating point arithmetic} \bibitem{iso14882:2023} ISO/IEC 14882:2023, \doccite{Programming Languages --- \Cpp{}} diff --git a/source/basic.tex b/source/basic.tex index 78a03978cd..c1f58de60a 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -32,10 +32,26 @@ \end{note} \pnum -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}. +A \defn{name} is +\begin{itemize} +\item an \grammarterm{identifier} token\iref{lex.token, lex.name} other than + \begin{itemize} + \item + the \grammarterm{identifier} of a + \grammarterm{label}\iref{stmt.label} or + \grammarterm{literal-operator-id}\iref{over.literal}, + \item + the \grammarterm{identifier} following a \keyword{goto} in a + \grammarterm{jump-statement}\iref{stmt.jump.general}, + \item + any \grammarterm{identifier} in a + \grammarterm{module-name}\iref{module.unit} or + \grammarterm{attribute-token}\iref{dcl.attr.grammar}, or + \end{itemize} +\item a \grammarterm{conversion-function-id}\iref{class.conv.fct}, +\item an \grammarterm{operator-function-id}\iref{over.oper}, or +\item a \grammarterm{literal-operator-id}\iref{over.literal}. +\end{itemize} \pnum Two names are \defnx{the same}{name!same} if @@ -115,13 +131,15 @@ \pnum A \defn{variable} is introduced by the -declaration of +declaration $D$ of \begin{itemize} \item a reference other than a non-static data member or \item -an object. +an object, \end{itemize} +where $D$ is not the \grammarterm{parameter-declaration} of +a \grammarterm{template-parameter}. \pnum An \defn{entity} is a @@ -177,7 +195,7 @@ If so, the declaration specifies the interpretation and semantic properties of these names. A declaration of an entity $X$ is -a redeclaration of $X$ +a \defn{redeclaration} of $X$ if another declaration of $X$ is reachable from it\iref{module.reach}; otherwise, it is a \defnadj{first}{declaration}. @@ -274,7 +292,7 @@ \item it is an explicit instantiation declaration\iref{temp.explicit}, or \item it is -an explicit specialization\iref{temp.expl.spec} whose +an \grammarterm{explicit-specialization}\iref{temp.expl.spec} whose \grammarterm{declaration} is not a definition. \end{itemize} A declaration is said to be a \defn{definition} of each entity that it defines. @@ -405,8 +423,9 @@ an array operand, the set contains the potential results of that operand. \item If $E$ is a class member access expression\iref{expr.ref} of the form -$E_1$ \tcode{.} \opt{\keyword{template}} $E_2$ -naming a non-static data member, +$E_1$ \tcode{.} \opt{\keyword{template}} $E_2$, +where $E_2$ designates a non-static data member or +a direct base class relationship, the set contains the potential results of $E_1$. \item If $E$ is a class member access expression naming a static data member, @@ -491,31 +510,31 @@ \grammarterm{splice-expression}\iref{expr.prim.splice} that designates it. A variable \tcode{x} that is named by a -potentially-evaluated expression $N$ +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 +that is usable in constant expressions at $P$\iref{expr.const.init}, or \item $N$ is an element of the set of potential results of an expression $E$, where \begin{itemize} \item $E$ is a discarded-value expression\iref{expr.context} -to which the lvalue-to-rvalue conversion is not applied or +to which the lvalue-to-rvalue conversion is not applied, or \item \tcode{x} is a non-volatile object that is usable in constant expressions at $P$ and -has no mutable subobjects and +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 +whose object expression has non-volatile-qualified type, or \item the lvalue-to-rvalue conversion\iref{conv.lval} is applied to $E$ and -$E$ has non-volatile-qualified non-class type +$E$ has non-volatile-qualified non-class type. \end{itemize} \end{itemize} \end{itemize} @@ -551,10 +570,10 @@ a \grammarterm{splice-expression} that designates that structured binding. A structured binding is odr-used -if it is named by a potentially-evaluated expression. +if it is named by a potentially evaluated expression. \pnum -\tcode{*\keyword{this}} is odr-used if \keyword{this} appears as a potentially-evaluated expression +\tcode{*\keyword{this}} is odr-used if \keyword{this} appears as a potentially evaluated expression (including as the result of any implicit transformation to a class member access expression\iref{expr.prim.id.general}). @@ -562,7 +581,7 @@ A virtual member function is odr-used if it is not pure. A function is odr-used if it is named by -a potentially-evaluated expression or conversion. +a potentially evaluated expression or conversion. A non-placement allocation or deallocation function for a class is odr-used by the definition of a constructor of that class. A non-placement deallocation function for a class is odr-used by the @@ -597,7 +616,7 @@ for each intervening scope\iref{basic.scope.scope} 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), +within the innermost enclosing class or non-lambda function parameter scope), either \begin{itemize} \item the intervening scope is a block scope, @@ -621,7 +640,7 @@ void f(int n) { [] { n = 1; }; // error: \tcode{n} is not odr-usable due to intervening lambda-expression struct A { - void f() { n = 2; } // error: \tcode{n} is not odr-usable due to intervening function definition scope + void f() { n = 2; } // error: \tcode{n} is not odr-usable due to intervening function parameter scope }; void g(int = n); // error: \tcode{n} is not odr-usable due to intervening function parameter scope [=](int k = n) {}; // error: \tcode{n} is not odr-usable due to being @@ -738,7 +757,7 @@ \pnum If a definable item \tcode{D} is defined in a translation unit -by an injected declaration $X$\iref{expr.const} and +by an injected declaration $X$\iref{expr.const.reflect} and another translation unit contains a definition of \tcode{D}, that definition shall be an injected declaration having the same characteristic sequence as $X$; @@ -780,7 +799,7 @@ a non-volatile const object with internal or no linkage if the object \begin{itemize} \item has the same literal type in all definitions of \tcode{D}, -\item is initialized with a constant expression\iref{expr.const}, +\item is initialized with a constant expression\iref{expr.const.const}, \item is not odr-used in any definition of \tcode{D}, and \item has the same value in all definitions of \tcode{D}, \end{itemize} @@ -954,7 +973,8 @@ declaration, \grammarterm{parameter-declaration-clause}, \grammarterm{statement}, -\grammarterm{handler}, or +\grammarterm{handler}, +\grammarterm{lambda-expression}, or contract assertion (as described in the following subclauses of \ref{basic.scope}) appearing in another scope, which thereby contains $S$. @@ -997,7 +1017,7 @@ Corresponding declarations with appropriate linkage declare the same entity\iref{basic.link}. \item -The declaration in a \grammarterm{template-declaration} +The \grammarterm{declaration} of a \grammarterm{template-declaration} inhabits the same scope as the \grammarterm{template-declaration}. \item Friend declarations and @@ -1136,7 +1156,7 @@ if its name is \tcode{_} (\unicode{005f}{low line}) and it declares \begin{itemize} \item -a variable with automatic storage duration, +a variable, other than a function parameter, with automatic storage duration, \item a structured binding %FIXME: "and" is strange below; maybe reword to something like: @@ -1439,8 +1459,8 @@ \grammarterm{compound-statement} of a \grammarterm{lambda-expression}, \grammarterm{function-body}, or \grammarterm{function-try-block}, \item -substatement of a selection or iteration statement -that is not itself a selection or iteration statement, or +substatement of a selection, iteration, or expansion statement +that is not itself a selection, iteration, or expansion statement, or \item \grammarterm{handler} of a \grammarterm{function-try-block} \end{itemize} @@ -1491,7 +1511,7 @@ \item If $P$ is associated with a \grammarterm{lambda-declarator}, its scope extends to the end of the \grammarterm{compound-statement} -in the \grammarterm{lambda-expression}. +of 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 \grammarterm{requires-expression}. @@ -1618,7 +1638,7 @@ \item if associated with a \grammarterm{lambda-declarator}, the nearest enclosing lambda scope -of the precondition assertion\iref{expr.prim.lambda}, +of the postcondition assertion\iref{expr.prim.lambda}, \end{itemize} the program is ill-formed. @@ -1658,7 +1678,12 @@ used in further processing. \pnum -A program point $P$ is said to follow +There is a \defnadj{program}{point} +before the first token of the translation unit, +at least one between every pair of adjacent tokens, and +at least one after the last token of the translation unit. + +A program point $P$ is said to \defnx{follow}{follow!program point} any declaration in the same translation unit whose locus\iref{basic.scope.pdecl} is before $P$. \begin{note} @@ -2063,7 +2088,8 @@ \pnum In a friend declaration \grammarterm{declarator} whose \grammarterm{declarator-id} is a \grammarterm{qualified-id} -whose lookup context\iref{basic.lookup.qual} is a class or namespace $S$, +whose \grammarterm{nested-name-specifier} +designates a class or namespace $S$\iref{expr.prim.id.qual}, lookup for an unqualified name that appears after the \grammarterm{declarator-id} performs a search in the scope associated with $S$. @@ -2333,7 +2359,7 @@ \pnum \begin{note} -The associated namespace can include namespaces +The set of associated namespaces can include namespaces already considered by ordinary unqualified lookup. \end{note} \begin{example} @@ -2401,7 +2427,7 @@ \indextext{scope resolution operator|see{operator, scope resolution}}% \pnum -A member-qualified name is +A \defnadj{member-qualified}{name} is the (unique) component name\iref{expr.prim.id.unqual}, if any, of \begin{itemize} \item @@ -2555,13 +2581,13 @@ \end{footnote} \begin{itemize} \item -if the search finds the injected-class-name of \tcode{C}\iref{class.pre}, or +if the search finds the injected-class-name of $C$\iref{class.pre}, or \item if $N$ is dependent and is the terminal name of a \grammarterm{using-declarator}\iref{namespace.udecl} that names a constructor, \end{itemize} -$N$ is instead considered to name the constructor of class \tcode{C}. +$N$ is instead considered to name the constructor of class $C$. Such a constructor name shall be used only in the \grammarterm{declarator-id} of a (friend) declaration of a constructor or in a \grammarterm{using-declaration}. @@ -2766,7 +2792,7 @@ \end{note} \pnum -If the terminal name of the \grammarterm{elaborated-type-specifier} +If the terminal name of an \grammarterm{elaborated-type-specifier} is a qualified name, lookup for it is type-only. If the name lookup does not find a previously declared \grammarterm{type-name}, @@ -2832,7 +2858,7 @@ \pnum The \grammarterm{constant-expression} of a \grammarterm{splice-specifier} shall be a converted constant expression of -type \tcode{std::meta::info}\iref{expr.const}. +type \tcode{std::meta::info}\iref{expr.const.const}. A \grammarterm{splice-specifier} whose converted \grammarterm{constant-expression} represents a construct $X$ is said to \defn{designate} either @@ -2887,8 +2913,8 @@ \indextext{program}% \indextext{linking}% A \defn{program} consists of one or more translation units\iref{lex.phases} -linked together. A translation unit consists -of a sequence of declarations. +that are translated and linked together. +A translation unit consists of a sequence of declarations. \begin{bnf} \nontermdef{translation-unit}\br @@ -3053,9 +3079,7 @@ \item they both declare type aliases or namespace aliases that have the same underlying entity, or \item -they both declare names with module linkage and are attached to the same module, or -\item -they both declare names with external linkage. +they both declare names with module or external linkage and are attached to the same module. \end{itemize} \begin{note} There are other circumstances in which declarations declare @@ -3072,9 +3096,11 @@ \end{note} \pnum -If two declarations of an entity are -attached to different modules, the program is ill-formed; -no diagnostic is required if neither is reachable from the other. +\begin{note} +If two declarations correspond but are +attached to different modules, the program is ill-formed +if one precedes the other\iref{basic.scope.scope}. +\end{note} \begin{example} \begin{codeblocktu}{\tcode{"decls.h"}} int f(); // \#1, attached to the global module @@ -3086,15 +3112,15 @@ #include "decls.h" export module M; export using ::f; // OK, does not declare an entity, exports \#1 -int g(); // error: matches \#2, but attached to \tcode{M} +int g(); // error: corresponds to \#2, but attached to \tcode{M} export int h(); // \#3 export int k(); // \#4 \end{codeblocktu} \begin{codeblocktu}{Other translation unit} import M; -static int h(); // error: matches \#3 -int k(); // error: matches \#4 +static int h(); // error: conflicts with \#3 +int k(); // error: conflicts with \#4 \end{codeblocktu} \end{example} As a consequence of these rules, @@ -3136,7 +3162,7 @@ If one declares $E$ to be a concept, the other shall do so. \end{itemize} Types are compared after all adjustments of types (during which -typedefs\iref{dcl.typedef} are replaced by their definitions); +type aliases\iref{dcl.typedef} are replaced by the types they denote); declarations for an array object can specify array types that differ by the presence or absence of a major array bound\iref{dcl.array}. @@ -3169,10 +3195,10 @@ a \grammarterm{reflect-expression} or a \grammarterm{splice-specifier} that, respectively, represents or designates $E$, \item -$D$ is an injected declaration\iref{expr.const} +$D$ is an injected declaration\iref{expr.const.reflect} whose characteristic sequence contains a reflection that represents -a data member description ($T$, $N$, $A$, $W$, $\mathit{NUA}$)\iref{class.mem.general} +a data member description ($T$, $N$, $A$, $W$, $\mathit{NUA}$, $\mathit{ANN}$)\iref{class.mem.general} for which $T$ is $E$, \item $E$ is not a function or function template and $D$ contains an @@ -3271,10 +3297,12 @@ \item an entity, value, or object that is TU-local, \item +an annotation\iref{dcl.attr.annotation}, +\item a direct base class relationship $(D, B)$\iref{class.derived.general} for which either $D$ or $B$ is TU-local, or \item -a data member description $(T, N, A, W, \mathit{NUA})$\iref{class.mem.general} +a data member description $(T, N, A, W, \mathit{NUA}, \mathit{ANN})$\iref{class.mem.general} for which $T$ is TU-local. \end{itemize} \end{itemize} @@ -3368,11 +3396,10 @@ UTF-8 encoding form and is composed of a contiguous sequence of bits, -\begin{footnote} -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}. +\begin{note} +See the macro \libmacro{CHAR_BIT} in the header \libheaderref{climits}. +\end{note} The memory available to a \Cpp{} program consists of one or more sequences of contiguous bytes. Every byte has a unique address. @@ -3424,9 +3451,9 @@ }; \end{codeblock} contains four separate memory locations: The member \tcode{a} and bit-fields -\tcode{d} and \tcode{e.ee} are each separate memory locations, and can be +\tcode{d} and \tcode{e.ee} each occupy separate memory locations, and can be modified concurrently without interfering with each other. The bit-fields -\tcode{b} and \tcode{c} together constitute the fourth memory location. The +\tcode{b} and \tcode{c} together occupy the fourth memory location. The bit-fields \tcode{b} and \tcode{c} cannot be concurrently modified, but \tcode{b} and \tcode{a}, for example, can be. \end{example} @@ -3477,7 +3504,7 @@ An object that is not a subobject of any other object is called a \defn{complete object}. If an object is created -in storage associated with a member subobject or array element \placeholder{e} +in storage associated with a subobject \placeholder{e} (which may or may not be within its lifetime), the created object is a subobject of \placeholder{e}'s containing object if @@ -3487,8 +3514,12 @@ \item the storage for the new object exactly overlays the storage location associated with \placeholder{e}, and \item +\placeholder{e} is not a potentially-overlapping subobject, and +\item the new object is of the same type as \placeholder{e} (ignoring cv-qualification). \end{itemize} +In this case, \placeholder{e} and the created object are +\defnadjx{corresponding direct}{subobjects}{subobject}. \pnum \indextext{object!providing storage for}% @@ -3615,8 +3646,7 @@ \item the backing array of an initializer list\iref{dcl.init.ref}, or \item - the object introduced by a call to \tcode{std::meta::reflect_constant_array} - or \tcode{std::meta::reflect_constant_string}\iref{meta.define.static}, or + a template parameter object of array type\iref{meta.define.static}, or \item a subobject thereof. \end{itemize} @@ -3632,18 +3662,18 @@ 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}, +\item +they are both nested within some complete object $o$, +exactly one is a subobject of $o$, and the subobject is of zero size, +\item +they are both subobjects of the same complete object, +at least one is a subobject of zero size, and +they are not of similar types\iref{conv.qual}, or \item they are both potentially non-unique objects; \end{itemize} otherwise, they have distinct addresses and occupy disjoint bytes of storage. -\begin{footnote} -Under the ``as-if'' rule an -implementation is allowed to store two objects at the same machine address or -not store an object at all if the program cannot observe the -difference\iref{intro.execution}. -\end{footnote} \begin{example} \begin{codeblock} static const char test1 = 'x'; @@ -3659,10 +3689,76 @@ const bool b5 = r != &test1; // always \tcode{true} \end{codeblock} \end{example} -The address of a non-bit-field subobject of zero size is +The address of a subobject of zero size is the address of an unspecified byte of storage occupied by the complete object of that subobject. +\pnum +A \defnadj{union elemental}{subobject} +\indextext{union!elemental subobject|see{subobject, union elemental}} +is a direct member of a union or +an element of an array that is a union elemental subobject. +An \defnx{inactive union elemental subobject}{subobject!union elemental!inactive} +\indextext{inactive union elemental subobject|see{subobject, union elemental, inactive}} +\indextext{union!inactive elemental subobject|see{subobject, union elemental, inactive}} +is a union elemental subobject that is not within its lifetime. + +\pnum +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 elemental subobjects. +\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 elemental subobjects. +\end{itemize} +\begin{example} +\begin{codeblock} +struct A { + struct X { + int i; + int j; + }; + + struct Y { + X x1; + X x2; + }; + + union { + int i; + int arr[4]; + Y y; + }; +}; + +constexpr A v1; // OK, no constituent values +constexpr A v2{.i=1}; // OK, the constituent values are \tcode{\{v2.i\}} +constexpr A v3 = []{ + A a; + std::start_lifetime(a.arr); // OK, \tcode{arr} is now the active element of the union + new (&a.arr[1]) int(1); + a.arr[2] = 2; + return a; +}(); // OK, the constituent values are \tcode{\{v3.arr[1], v3.arr[2]\}} +constexpr A v4 = []{ + A a; + a.y.x1.i = 1; + a.y.x2.j = 2; + return a; +}(); // error: the constituent values include \tcode{v4.y.x1.j} and \tcode{v4.y.x2.i} + // which have erroneous value +\end{codeblock} +\end{example} + \pnum Some operations are described as \defnx{implicitly creating objects}{object!implicit creation} @@ -3741,7 +3837,7 @@ 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}. +using the \grammarterm{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. @@ -3801,8 +3897,8 @@ 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}. +The type \tcode{\keyword{unsigned} \keyword{char}} can be used as +the element type of an array providing aligned storage\iref{dcl.align}. \end{note} \pnum @@ -3941,16 +4037,8 @@ the pointer is used to access a non-static data member or call a non-static member function of the object, or \item - the pointer is implicitly converted\iref{conv.ptr} to a pointer - to a virtual base class, or -\item - the pointer is used as the operand of a - \keyword{static_cast}\iref{expr.static.cast}, except when the conversion - is to pointer to \cv{}~\keyword{void}, or to pointer to \cv{}~\keyword{void} - and subsequently to pointer to - \cv{}~\keyword{char}, - \cv{}~\tcode{\keyword{unsigned} \keyword{char}}, or - \cv{}~\tcode{std::byte}\iref{cstddef.syn}, or + the pointer is converted\iref{conv.ptr,expr.static.cast} to a pointer + to a virtual base class or to a base class thereof, or \item the pointer is used as the operand of a \keyword{dynamic_cast}\iref{expr.dynamic.cast}. @@ -4013,22 +4101,24 @@ \end{note} \pnum -An object $o_1$ is \defn{transparently replaceable} by an object $o_2$ if +An object $o_1$ is \defn{transparently replaceable} by an object $o_2$ if either +\begin{itemize} +\item +$o_1$ and $o_2$ are complete objects for which: \begin{itemize} +\item $o_1$ is not const, \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 const, complete object, and - -\item neither $o_1$ nor $o_2$ -is a potentially-overlapping subobject\iref{intro.object}, and +(ignoring the top-level cv-qualifiers), or +\end{itemize} -\item either $o_1$ and $o_2$ are both complete objects, or -$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$. +\item +$o_1$ and $o_2$ are corresponding direct subobjects\iref{intro.object} for which: +\begin{itemize} +\item the complete object of $o_1$ is not const or +\item $o_1$ is a mutable member subobject or a subobject thereof. +\end{itemize} \end{itemize} \pnum @@ -4160,12 +4250,17 @@ \end{note} \pnum +If any operand of a built-in operator that produces a prvalue +is evaluated, +is not a discarded-value expression\iref{expr.context}, and +produces an erroneous value, +then the value produced by that operator is erroneous. 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: +the result of the evaluation is that erroneous value: \begin{itemize} \item If an indeterminate or erroneous value of @@ -4459,7 +4554,7 @@ \indextext{function!allocation}% An allocation function that is not a class member function shall belong to the global scope and not have a name with internal linkage. -The return type shall be \tcode{\keyword{void}*}. The first +The return type shall be ``pointer to \keyword{void}''. The first parameter shall have type \tcode{std::size_t}\iref{support.types}. The first parameter shall not have an associated default argument\iref{dcl.fct.default}. The value of the first parameter @@ -4580,9 +4675,9 @@ Each deallocation function shall return \keyword{void}. If the function is a destroying operator delete declared in class type \tcode{C}, -the type of its first parameter shall be \tcode{C*}; +the type of its first parameter shall be ``pointer to \tcode{C}''; otherwise, the type of its first -parameter shall be \tcode{\keyword{void}*}. A deallocation function may have more +parameter shall be ``pointer to \keyword{void}''. A deallocation function may have more than one parameter. \indextext{deallocation function!usual}% A \defn{usual deallocation function} is a deallocation function @@ -4718,8 +4813,8 @@ \end{example} \pnum -When an object of class type \tcode{X} -is passed to or returned from a potentially-evaluated function call, +When an object of type \tcode{X} +is passed to or returned from a potentially evaluated function call, if \tcode{X} is \begin{itemize} \item @@ -4813,7 +4908,9 @@ \item a class member access\iref{expr.ref} using the \tcode{.} operator where the left operand is one of these expressions and - the right operand designates a non-static data member of non-reference type, + the right operand designates + a non-static data member\iref{class.mem.general} of non-reference type or + a direct base class relationship\iref{class.derived.general}, \item a pointer-to-member operation\iref{expr.mptr.oper} using the \tcode{.*} operator where the left operand is one of these expressions and @@ -4831,6 +4928,15 @@ to a glvalue that refers to the object designated by the operand, or to its complete object or a subobject thereof, +\item + an explicit type conversion (functional notation)\iref{expr.type.conv} + to a reference type whose initializer is a \grammarterm{braced-init-list} + where the reference is + \begin{itemize} + \item bound directly to the glvalue result of one of these expressions + (necessarily the sole element of the \grammarterm{braced-init-list}) or + \item bound to the result of a temporary materialization conversion, + \end{itemize} \item a conditional expression\iref{expr.cond} that is a glvalue where the second or third operand is one of these expressions, or @@ -4856,7 +4962,7 @@ covered above. \begin{example} \begin{codeblock} -const int& x = (const int&)1; // temporary for value 1 has same lifetime as x +const int& x = (const int&)1; // temporary for value \tcode{1} has same lifetime as \tcode{x} \end{codeblock} \end{example} \end{note} @@ -4900,15 +5006,23 @@ \pnum The fourth context is when a temporary object is created in the \grammarterm{for-range-initializer} of -either a range-based \keyword{for} statement -or an enumerating expansion statement\iref{stmt.expand}. +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 +The fifth context is when a temporary object is created in an element $E$ +of the \grammarterm{expansion-init-list} +of an enumerating expansion statement\iref{stmt.expand}. +If such a temporary object would otherwise be destroyed +at the end of the full-expression of $E$, +the object persists for the lifetime of the \grammarterm{for-range-declaration} +initialized from $E$. + +\pnum +The sixth context is when a temporary object is created in the \grammarterm{expansion-initializer} of an iterating or destructuring expansion statement. If such a temporary object would otherwise be destroyed @@ -4917,7 +5031,7 @@ initialized by the \grammarterm{expansion-initializer}, if any. \pnum -The sixth context is when a temporary object +The seventh 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 @@ -5116,7 +5230,7 @@ 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 +a non-bit-field complete object 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 @@ -5179,7 +5293,7 @@ \begin{codeblock} class X; // \tcode{X} is an incomplete type extern X* xp; // \tcode{xp} is a pointer to an incomplete type -extern int arr[]; // the type of arr is incomplete +extern int arr[]; // the type of \tcode{arr} is incomplete typedef int UNKA[]; // \tcode{UNKA} is an incomplete type UNKA* arrp; // \tcode{arrp} is a pointer to an incomplete type UNKA** arrpp; @@ -5187,7 +5301,7 @@ void foo() { xp++; // error: \tcode{X} is incomplete arrp++; // error: incomplete type - arrpp++; // OK, sizeof \tcode{UNKA*} is known + arrpp++; // OK, \tcode{sizeof(UNKA*)} is known } struct X { int i; }; // now \tcode{X} is a complete type @@ -5195,8 +5309,8 @@ X x; void bar() { - xp = &x; // OK; type is ``pointer to \tcode{X}'' - arrp = &arr; // OK; qualification conversion\iref{conv.qual} + xp = &x; // OK, type is ``pointer to \tcode{X}'' + arrp = &arr; // OK, qualification conversion\iref{conv.qual} xp++; // OK, \tcode{X} is complete arrp++; // error: \tcode{UNKA} can't be completed } @@ -5230,15 +5344,6 @@ 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.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}% -\indextext{replaceable!type|see{type, replaceable}}% -Cv-unqualified scalar types, replaceable class types\iref{class.prop}, and -arrays of such types are collectively called -\defnx{replaceable types}{type!replaceable}. \label{term.standard.layout.type}% Scalar types, standard-layout class types\iref{class.prop}, arrays of such types, and @@ -5295,9 +5400,17 @@ layout-compatible standard-layout class types\iref{class.mem}. \pnum -A type is \defn{consteval-only} if it is either -\tcode{std::meta::info} or -a type compounded from a consteval-only type\iref{basic.compound}. +A type is \defn{consteval-only} if it is +\begin{itemize} +\item \tcode{std::meta::info}, +\item \cv{}~\tcode{T}, where \tcode{T} is a consteval-only type, +\item a pointer or reference to a consteval-only type, +\item an array of consteval-only type, +\item a function type having a return type or any parameter type that is consteval-only, +\item a class type with any non-static data member having consteval-only type, or +\item a type ``pointer to member of class \tcode{C} of type \tcode{T}'', +where at least one of \tcode{C} or \tcode{T} is a consteval-only type. +\end{itemize} Every object of consteval-only type shall be \begin{itemize} \item @@ -5308,6 +5421,8 @@ an object whose lifetime begins and ends during the evaluation of a core constant expression. \end{itemize} +Every function of consteval-only type shall be +an immediate function\iref{expr.const.imm}. \rSec2[basic.fundamental]{Fundamental types} @@ -5354,7 +5469,7 @@ there exists a corresponding \defnadj{extended unsigned integer}{type}. The standard and extended unsigned integer types are collectively called \defnadjx{unsigned integer}{types}{type}. -An unsigned integer type has the same width \placeholder{N} +An unsigned integer type has the same width $N$ as the corresponding signed integer type. \indextext{arithmetic!\idxcode{unsigned}}% The range of representable values for the unsigned type is @@ -5400,7 +5515,7 @@ 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. +comprises $N$ bits, where $N$ is the respective width. Each set of values for any padding bits\iref{basic.types.general} in the object representation are alternative representations of the value specified by the value representation. @@ -5477,7 +5592,7 @@ \indextext{\idxcode{char8_t}|see{type, \tcode{char8_t}}}% \indextext{type!\idxcode{char8_t}}% \indextext{type!underlying!\idxcode{char8_t}}% -Type \keyword{char8_t} denotes a distinct type +Type \keyword{char8_t} is a distinct type whose underlying type is \tcode{\keyword{unsigned} \keyword{char}}. \indextext{\idxcode{char16_t}|see{type, \tcode{char16_t}}}% \indextext{\idxcode{char32_t}|see{type, \tcode{char32_t}}}% @@ -5485,7 +5600,7 @@ \indextext{type!\idxcode{char32_t}}% \indextext{type!underlying!\idxcode{char16_t}}% \indextext{type!underlying!\idxcode{char32_t}}% -Types \keyword{char16_t} and \keyword{char32_t} denote distinct types +Types \keyword{char16_t} and \keyword{char32_t} are distinct types whose underlying types are \tcode{std::uint_least16_t} and \tcode{std::uint_least32_t}, respectively, in \libheaderref{cstdint}. @@ -5591,15 +5706,16 @@ \indextext{type!\idxcode{void}}% 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. -An expression of type \cv{}~\keyword{void} shall -be used only as +an empty set of values. +\begin{note} +An expression of type \cv{}~\keyword{void} can be used as \begin{itemize} -\item an expression statement\iref{stmt.expr}, -\item the expression in a \keyword{return} statement\iref{stmt.return} +\item the \grammarterm{expression} of an expression statement\iref{stmt.expr}, +\item the operand of 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 operand of a parenthesized expression\iref{expr.prim.paren}, +\item a requirement in a \grammarterm{requires-expression}\iref{expr.prim.req.general}, \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}, @@ -5607,13 +5723,19 @@ \item the operand of an explicit conversion to type \cv{}~\keyword{void}\iref{expr.type.conv,expr.static.cast,expr.cast}. \end{itemize} +\end{note} \pnum 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}*)}. +The size\iref{expr.sizeof} and alignment requirement\iref{basic.align} of +the type \tcode{std::nullptr_t} are those of +the type ``pointer to \keyword{void}''. +\begin{note} +The value representation can comprise no bits\iref{conv.lval}. +\end{note} \pnum A value of type \tcode{std::meta::info} is called a \defn{reflection}. @@ -5724,7 +5846,7 @@ If the implementation supports an extended floating-point type\iref{basic.fundamental} whose properties are specified by the \IsoFloatUndated{} floating-point interchange format binary16, -then the \grammarterm{typedef-name} \tcode{std::float16_t} +then the type alias \tcode{std::float16_t} 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} @@ -5734,7 +5856,7 @@ If the implementation supports an extended floating-point type whose properties are specified by the \IsoFloatUndated{} floating-point interchange format binary32, -then the \grammarterm{typedef-name} \tcode{std::float32_t} +then the type alias \tcode{std::float32_t} 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. @@ -5743,7 +5865,7 @@ If the implementation supports an extended floating-point type whose properties are specified by the \IsoFloatUndated{} floating-point interchange format binary64, -then the \grammarterm{typedef-name} \tcode{std::float64_t} +then the type alias \tcode{std::float64_t} 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. @@ -5752,7 +5874,7 @@ If the implementation supports an extended floating-point type whose properties are specified by the \IsoFloatUndated{} floating-point interchange format binary128, -then the \grammarterm{typedef-name} \tcode{std::float128_t} +then the type alias \tcode{std::float128_t} 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. @@ -5765,7 +5887,7 @@ 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} +the type alias \tcode{std::bfloat16_t} 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. @@ -5798,9 +5920,9 @@ the extended floating-point types described in this subsection 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 +with the interchange floating types \tcode{_Float16}, \tcode{_Float32}, \tcode{_Float64}, and \tcode{_Float128} -defined in ISO/IEC TS 18661-3 and with future versions of \IsoCUndated{}. +defined in \IsoC{} H.2.2. \rSec2[basic.compound]{Compound types} @@ -5932,6 +6054,28 @@ alignment requirement. \end{note} +\pnum +A pointer value +pointing to a potentially non-unique object $O$\iref{intro.object} is +\indextext{value!associated with an evaluation}% +\defn{associated with} the evaluation of +\begin{itemize} +\item +the \grammarterm{string-literal}\iref{lex.string} that resulted in the string literal object, +\item +the initializer list\iref{dcl.init.list} that resulted in the backing array, +or +\item +the initialization of +the template parameter object\iref{temp.arg.nontype, meta.define.static} +\end{itemize} +that is $O$ or of which $O$ is a subobject. +\begin{note} +A pointer value obtained by pointer arithmetic\iref{expr.add} +from a pointer value associated with an evaluation $E$ +is also associated with $E$. +\end{note} + \pnum A pointer value $P$ is \indextext{value!valid in the context of an evaluation}% @@ -6205,7 +6349,7 @@ \tcode{\keyword{long} \keyword{double}}, \keyword{double}, and \tcode{std::float64_t} -have the same set of values (see \IsoC H.4.3). +have the same set of values (see \IsoC{} H.4.3). \end{tailnote} \end{itemize} \begin{note} @@ -6290,9 +6434,9 @@ \item if $E$ is a function call\iref{expr.call} or implicitly invokes a function, the constituent expressions of each default argument\iref{dcl.fct.default} -used in the call, or +used in the call, and \item -if $E$ creates an aggregate object\iref{dcl.init.aggr}, +if $E$ performs aggregate initialization\iref{dcl.init.aggr}, the constituent expressions of each default member initializer\iref{class.mem} used in the initialization. \end{itemize} @@ -6321,9 +6465,9 @@ \item an unevaluated operand\iref{expr.context}, \item -a \grammarterm{constant-expression}\iref{expr.const}, +a \grammarterm{constant-expression}\iref{expr.const.core}, \item -an immediate invocation\iref{expr.const}, +an immediate invocation\iref{expr.const.imm}, \item an \grammarterm{init-declarator}\iref{dcl.decl} (including such introduced by a structured binding\iref{dcl.struct.bind}) or @@ -6390,7 +6534,7 @@ \indextext{value computation|(}% Reading an object designated by a \keyword{volatile} glvalue\iref{basic.lval}, modifying an object, -producing an injected declaration\iref{expr.const}, +producing an injected declaration\iref{expr.const.reflect}, calling a library I/O function, or calling a function that does any of those operations are all \defn{side effects}, @@ -6570,7 +6714,7 @@ \pnum During the evaluation of an expression -as a core constant expression\iref{expr.const}, +as a core constant expression\iref{expr.const.core}, evaluations of operands of individual operators and of subexpressions of individual expressions that are otherwise either unsequenced or indeterminately sequenced @@ -6718,7 +6862,7 @@ \pnum An evaluation $A$ \defn{happens before} an evaluation $B$ -(or, equivalently, $B$ happens after $A$) +(or, equivalently, $B$ \defn{happens after} $A$) if either \begin{itemize} \item $A$ is sequenced before $B$, or @@ -6759,7 +6903,7 @@ \item $A$ happens before $B$ and \item there is no other \indextext{side effects}% -side effect $X$ to $M$ such that $A$ +side effect $X$ on $M$ such that $A$ happens before $X$ and $X$ happens before $B$. \end{itemize} @@ -7012,13 +7156,6 @@ observable behavior of the abstract machine. \end{example} -\pnum -\begin{note} -Because of this and the preceding requirement regarding what threads of execution -have to perform eventually, it follows that no thread of execution can execute -forever without an execution step occurring. -\end{note} - \pnum A thread of execution \defnx{makes progress}{make progress!thread} when an execution step occurs or a @@ -7171,8 +7308,13 @@ \indextext{\idxcode{main} function!implementation-defined parameters to}% An implementation shall allow both \begin{itemize} -\item a function of \tcode{()} returning \keyword{int} and -\item a function of \tcode{(\keyword{int}}, pointer to pointer to \tcode{\keyword{char})} returning \keyword{int} +\item +an ``optionally \tcode{noexcept} function of +\tcode{()} returning \keyword{int}'' and +\item +an ``optionally \tcode{noexcept} function of +\tcode{(\keyword{int}}, pointer to pointer to \tcode{\keyword{char})} +returning \keyword{int}'' \end{itemize} \indextext{\idxcode{argc}}% \indextext{\idxcode{argv}}% @@ -7266,7 +7408,7 @@ \indextext{initialization!constant}% \defnx{Constant initialization}{constant initialization} is performed if a variable with static or thread storage duration -is constant-initialized\iref{expr.const}. +is constant-initialized\iref{expr.const.init}. \indextext{initialization!zero-initialization}% If constant initialization is not performed, a variable with static storage duration\iref{basic.stc.static} or thread storage @@ -7304,16 +7446,18 @@ object \tcode{obj2} potentially requiring dynamic initialization and defined later in the same translation unit, it is unspecified whether the value of \tcode{obj2} used will be the value of the fully initialized \tcode{obj2} (because \tcode{obj2} was statically -initialized) or will be the value of \tcode{obj2} merely zero-initialized. For example, +initialized) or will be the value of \tcode{obj2} merely zero-initialized. For example: \begin{codeblock} inline double fd() { return 1.0; } extern double d1; -double d2 = d1; // unspecified: - // either statically initialized to \tcode{0.0} or - // dynamically initialized to \tcode{0.0} if \tcode{d1} is - // dynamically initialized, or \tcode{1.0} otherwise -double d1 = fd(); // either initialized statically or dynamically to \tcode{1.0} +double d2 = d1; +double d1 = fd(); \end{codeblock} +Both \tcode{d1} and \tcode {d2} can be initialized +either statically or dynamically. +If \tcode{d1} is initialized statically and \tcode{d2} dynamically, +both variables are initialized to \tcode{1.0}; +in all other cases, \tcode{d2} is initialized to \tcode{0.0}. \end{note} \rSec3[basic.start.dynamic]{Dynamic initialization of non-block variables} @@ -7338,13 +7482,14 @@ \begin{itemize} \item \tcode{D} appears in the same translation unit as \tcode{E}, or \item the translation unit containing \tcode{E} -has an interface dependency on the translation unit containing \tcode{D}, +has an interface dependency\iref{module.import} +on the translation unit containing \tcode{D}, \end{itemize} in either case prior to \tcode{E}. \pnum Dynamic initialization of non-block variables \tcode{V} and \tcode{W} -with static storage duration are ordered as follows: +with static storage duration is ordered as follows: \begin{itemize} \item If \tcode{V} and \tcode{W} have ordered initialization and @@ -7490,7 +7635,7 @@ \indextext{program!termination|(}% \indextext{object!destructor static}% \indextext{\idxcode{main} function!return from}% -Constructed objects\iref{dcl.init} +Constructed complete objects\iref{dcl.init} with static storage duration are destroyed and functions registered with \tcode{std::atexit} are called as part of a call to @@ -7504,29 +7649,69 @@ \end{note} \pnum -Constructed objects with thread storage duration within a given thread +Constructed complete objects with thread storage duration within a given thread are destroyed as a result of returning from the initial function of that thread and as a result of that thread calling \tcode{std::exit}. -The destruction of all constructed objects with thread storage -duration within that thread strongly happens before destroying +The destruction of those constructed objects +is sequenced before releasing the storage for +any object with thread storage duration within that thread\iref{basic.stc.thread}. +The destruction of those constructed objects +strongly happens before destroying any object with static storage duration. \pnum -If the completion of the constructor or dynamic initialization of an object with static -storage duration strongly happens before that of another, the completion of the destructor -of the second is sequenced before the initiation of the destructor of the first. -If the completion of the constructor or dynamic initialization of an object with thread -storage duration is sequenced before that of another, the completion of the destructor -of the second is sequenced before the initiation of the destructor of the first. +The destruction of a complete object with thread storage duration within a given thread +and having constant destruction\iref{expr.const.defns} +is sequenced after the destruction of any other complete object +with thread storage duration within the thread. +The destruction of a complete object with static storage duration +and having constant destruction +is sequenced after the destruction of any other complete object +with static storage duration +and after any call to a function passed to \tcode{std::atexit}. +The sequencing rules in the remainder of this subclause +apply only to complete objects not having constant destruction. + +\pnum +If the deemed construction\iref{dcl.init.general} of a complete object with static +storage duration strongly happens before that of another, the completion of the destruction +of the second is sequenced before the initiation of the destruction of the first. +If the deemed construction of a complete object with thread +storage duration is sequenced before that of another, the completion of the destruction +of the second is sequenced before the initiation of the destruction of the first. If an object is initialized statically, the object is destroyed in the same order as if -the object was dynamically initialized. For an object of array or class -type, all subobjects of that object are destroyed before any block -variable with static storage duration initialized during the construction -of the subobjects is destroyed. +the object was dynamically initialized. If the destruction of an object with static or thread storage duration exits via an exception, the function \tcode{std::terminate} is called\iref{except.terminate}. +\begin{example} +In the following program, +the elements of \tcode{a} are destroyed, +followed by \tcode{dt}, and +finally by the two \tcode{Btemp} objects: +\begin{codeblock} +struct DTemp { ~DTemp(); }; +struct Temp { + ~Temp() { + static DTemp dt; + } +}; +struct BTemp { + ~BTemp(); +}; +struct A { + const BTemp &tb; + ~A(); +}; +A a[] = { (Temp(), BTemp()), BTemp() }; + +int main() {} +\end{codeblock} +If the array \tcode{a} were an object with automatic storage duration, +the \tcode{Btemp} temporaries would be destroyed +as each element of the array is destroyed\iref{class.temporary}. +\end{example} \pnum If a function contains a block variable of static or thread storage duration that has been @@ -7542,12 +7727,13 @@ \pnum \indextext{\idxcode{atexit}}% \indexlibraryglobal{atexit}% -If the completion of the initialization of an object with static storage +If the deemed construction of a complete object with static storage duration strongly happens before a call to \tcode{std::atexit}~(see \libheader{cstdlib}, \ref{support.start.term}), the call to the function passed to -\tcode{std::atexit} is sequenced before the call to the destructor for the object. If a -call to \tcode{std::atexit} strongly happens before the completion of the initialization of -an object with static storage duration, the call to the destructor for the +\tcode{std::atexit} is sequenced before the initiation of the destruction of the object. +If a call to \tcode{std::atexit} strongly happens before the deemed construction of +a complete object with static storage duration, +the completion of the destruction of the object is sequenced before the call to the function passed to \tcode{std::atexit}. If a call to \tcode{std::atexit} strongly happens before another call to \tcode{std::atexit}, the call to the function passed to the second \tcode{std::atexit} call is sequenced before @@ -7699,7 +7885,7 @@ \pnum There is an observable checkpoint\iref{intro.abstract} $C$ that happens before $A$ -such that any other operation $O$ +such that any other evaluation that happens before $A$ also happens before $C$. @@ -7714,7 +7900,7 @@ \item the evaluation of the predicate is performed in a context that is -manifestly constant-evaluated\iref{expr.const} +manifestly constant-evaluated\iref{expr.const.defns} and the predicate is not a core constant expression. \end{itemize} @@ -7735,7 +7921,7 @@ \pnum \indexdefn{contract evaluation semantics!terminating}% If a contract violation occurs -in a context that is manifestly constant-evaluated\iref{expr.const}, +in a context that is manifestly constant-evaluated\iref{expr.const.defns}, and the evaluation semantic is a terminating semantic, the program is ill-formed. @@ -7864,7 +8050,7 @@ \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$ +such that any other evaluation that happens after the contract-violation handler returns also happens after $C$. diff --git a/source/classes.tex b/source/classes.tex index 6f1e64c940..6cd80b2796 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -52,9 +52,7 @@ \begin{bnf} \nontermdef{class-property-specifier}\br - \keyword{final}\br - \keyword{trivially_relocatable_if_eligible}\br - \keyword{replaceable_if_eligible} + \keyword{final} \end{bnf} \begin{bnf} @@ -131,8 +129,7 @@ within a single \grammarterm{class-property-specifier-seq}. Whenever a \grammarterm{class-key} is followed by a \grammarterm{class-head-name}, -one of the identifiers \tcode{final}, \tcode{trivially_relocatable_if_eligible}, -or \tcode{replaceable_if_eligible}, and a colon or left brace, +the identifier \tcode{final}, and a colon or left brace, the identifier is interpreted as a \grammarterm{class-property-specifier}. \begin{example} \begin{codeblock} @@ -142,10 +139,8 @@ struct X { struct C { constexpr operator int() { return 5; } }; - 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} + struct B final : C{}; // OK, definition of nested class \tcode{B}, + // not declaration of a bit-field member \tcode{final} }; \end{codeblock} \end{example} @@ -187,88 +182,6 @@ \item that has a trivial, non-deleted destructor\iref{class.dtor}. \end{itemize} -\pnum -A class \tcode{C} is \defn{default-movable} if - -\begin{itemize} -\item overload resolution for direct-initializing an object of type \tcode{C} -from an xvalue of type \tcode{C} selects a constructor that is a direct member -of \tcode{C} and is neither user-provided nor deleted, - -\item overload resolution for assigning to an lvalue of type \tcode{C} from an -xvalue of type \tcode{C} selects an assignment operator function that is a -direct member of \tcode{C} and is neither user-provided nor deleted, and - -\item \tcode{C} has a destructor that is neither user-provided nor deleted. -\end{itemize} - -\pnum -A class is \defn{eligible for trivial relocation} unless it -\begin{itemize} -\item has any virtual base classes, -\item has a base class that is not a trivially relocatable class, -\item has a non-static data member of an object type that is not of a -trivially relocatable type, or - -\item has a deleted destructor, -\end{itemize} -except that it is \impldef{whether an otherwise-eligible union having one or -more subobjects of polymorphic class type is eligible for trivial relocation} -whether an otherwise-eligible union having one or more subobjects of -polymorphic class type is eligible for trivial relocation. - -\pnum -A class \tcode{C} is a \defnadj{trivially relocatable}{class} -if it is eligible for trivial relocation and -\begin{itemize} -\item has the \tcode{trivially_relocatable_if_eligible} \grammarterm{class-property-specifier}, -\item is a union with no user-declared special member functions, or -\item is default-movable. -\end{itemize} - -\pnum -\begin{note} -A class with const-qualified or reference non-static data members can be -trivially relocatable. -\end{note} - -\pnum -A class \tcode{C} is \defn{eligible for replacement} unless -\begin{itemize} -\item it has a base class that is not a replaceable class, -\item it has a non-static data member that is not of a replaceable type, -\item overload resolution fails or selects a deleted constructor when -direct-initializing an object of type \tcode{C} from an xvalue of type -\tcode{C}\iref{dcl.init.general}, - -\item overload resolution fails or selects a deleted assignment operator -function when assigning to an lvalue of type \tcode{C} from an xvalue of type -\tcode{C}\iref{expr.assign,over.assign}, or - -\item it has a deleted destructor. -\end{itemize} - -\indextext{replaceable!class|see{class, replaceable}}% -\pnum -A class \tcode{C} is a \defnx{replaceable class}{class!replaceable} 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 A class \tcode{S} is a \defnadj{standard-layout}{class} if it: \begin{itemize} @@ -667,6 +580,10 @@ shall either declare at least one member name of the class or declare at least one unnamed bit-field. +A \defnx{user-declared}{entity!user-declared} +\indextext{user-declared entity|see{entity, user-declared}} +entity is a direct member or a friend that, in either case, +is declared by a \grammarterm{member-declaration}. \pnum A \defn{data member} is either a non-function member introduced by a @@ -804,7 +721,7 @@ 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 +An immediate invocation\iref{expr.const.imm} that is a potentially-evaluated subexpression\iref{intro.execution} of a default member initializer is neither evaluated nor checked for whether it @@ -1015,18 +932,24 @@ \pnum A \defnadj{data member}{description} is -a quintuple ($T$, $N$, $A$, $W$, $\mathit{NUA}$) +a sextuple ($T$, $N$, $A$, $W$, $\mathit{NUA}$, $\mathit{ANN}$) describing the potential declaration of a non-static data member where \begin{itemize} \item $T$ is a type, \item $N$ is an \grammarterm{identifier} or $\bot$, \item $A$ is an alignment or $\bot$, -\item $W$ is a bit-field width or $\bot$, and -\item $\mathit{NUA}$ is a boolean value. +\item $W$ is a bit-field width or $\bot$, +\item $\mathit{NUA}$ is a boolean value, and +\item $\mathit{ANN}$ is a sequence of reflections +representing either values or template parameter objects. \end{itemize} Two data member descriptions are equal -if each of their respective components are the same entities, -are the same identifiers, have equal values, or are both $\bot$. +if each of their respective components are +the same entity, +the same identifier, +the same value, +the same sequence, or +both $\bot$. \begin{note} The components of a data member description describe a data member such that \begin{itemize} @@ -1360,8 +1283,9 @@ 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 or constructor template for class -\tcode{X}, +If a class does not have +a user-declared constructor or constructor template, +and the class is not an anonymous union, a non-explicit constructor having no parameters is implicitly declared as defaulted\iref{dcl.fct.def}. An implicitly-declared default constructor is an @@ -1419,26 +1343,14 @@ \defnx{non-trivial}{constructor!default!non-trivial}. \pnum -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 +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. -The implicitly-defined -default constructor is \keyword{constexpr}. +The implicitly-defined default constructor is constexpr. Before the defaulted default constructor for a class is implicitly defined, all the non-user-provided default constructors for its base classes and @@ -1590,7 +1502,8 @@ \end{example} \pnum -If the class definition does not explicitly declare a copy constructor, +If the class does not have a user-declared copy constructor +and the class is not an anonymous union, a non-explicit one is declared \defnx{implicitly}{constructor!copy!implicitly declared}. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy @@ -1630,10 +1543,13 @@ \pnum \indextext{constructor!move!implicitly declared}% -If the definition of a class \tcode{X} does not explicitly declare -a move constructor, a non-explicit one will be +If a class \tcode{X} does not have +a user-declared move constructor, a non-explicit one will be implicitly declared as defaulted if and only if \begin{itemize} +\item +\tcode{X} is not an anonymous union, + \item \tcode{X} does not have a user-declared copy constructor, @@ -1688,6 +1604,17 @@ an rvalue which can use the copy constructor instead. \end{note} +\pnum +\begin{note} +A using-declaration in a derived class \tcode{C} that +names a constructor from a base class +never suppresses the implicit declaration of +a copy/move constructor of \tcode{C}, +even if the base class constructor would be +a copy or move constructor +if declared as a member of \tcode{C}. +\end{note} + \pnum \indextext{constructor!copy!trivial}% \indextext{constructor!move!trivial}% @@ -1704,7 +1631,8 @@ and no virtual base classes\iref{class.mi}, and \item -the constructor selected to copy/move each direct base class subobject is trivial, and +the constructor selected to copy/move each direct base class subobject +is a direct member of that base class and is trivial, and \item for each non-static data member of @@ -1722,8 +1650,7 @@ The copy/move constructor is implicitly defined even if the implementation elided its odr-use\iref{term.odr.use,class.temporary}. \end{note} -The implicitly-defined\iref{dcl.fct.def.default} -constructor is \keyword{constexpr}. +The implicitly-defined\iref{dcl.fct.def.default} constructor is constexpr. \pnum Before the defaulted copy/move constructor for a class is @@ -1808,8 +1735,8 @@ \tcode{X} only has a copy assignment operator with a non-object parameter of type \tcode{X\&}, -an expression of type const -\tcode{X} +an expression of type +\tcode{const X} cannot be assigned to an object of type \tcode{X}. \begin{example} @@ -1828,9 +1755,10 @@ \end{note} \pnum -If the class definition does not explicitly declare a copy assignment operator, +If the class does not have a user-declared copy assignment operator +and the class is not an anonymous union, one is declared \defnx{implicitly}{assignment operator!copy!implicitly declared}. -If the class definition declares a move +If the class has a user-declared move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted; otherwise, it is defaulted\iref{dcl.fct.def}. @@ -1882,6 +1810,9 @@ move assignment operator, one will be implicitly declared as defaulted if and only if \begin{itemize} +\item +\tcode{X} is not an anonymous union, + \item \tcode{X} does not have a user-declared copy constructor, @@ -1986,7 +1917,7 @@ and no virtual base classes\iref{class.mi}, and \item the assignment operator selected to copy/move each direct -base class subobject is trivial, and +base class subobject is a direct member of that base class and is trivial, and \item for each non-static data member of @@ -1999,7 +1930,7 @@ \defnx{non-trivial}{assignment operator!copy!non-trivial}. \pnum -An implicitly-defined\iref{dcl.fct.def.default} copy/move assignment operator is \keyword{constexpr}. +An implicitly-defined\iref{dcl.fct.def.default} copy/move assignment operator is constexpr. \pnum Before the defaulted copy/move assignment operator for a class is @@ -2116,7 +2047,8 @@ \indextext{generated destructor|see{destructor, default}}% \indextext{destructor!default}% If a class has no user-declared -prospective destructor, +prospective destructor +and the class is not an anonymous union, a prospective destructor is implicitly declared as defaulted\iref{dcl.fct.def}. An implicitly-declared prospective destructor is an @@ -2129,7 +2061,8 @@ \end{codeblock} \pnum -At the end of the definition of a class, +At the end of the definition of a class +other than an anonymous union, overload resolution is performed among the prospective destructors declared in that class with an empty argument list @@ -2711,7 +2644,6 @@ \begin{example} \begin{codeblock} struct S { - operator auto() const { return 10; } // OK template operator auto() const { return 1.2; } // error: conversion function template }; @@ -2837,7 +2769,7 @@ its declaration in the class definition can specify a \grammarterm{brace-or-equal-initializer} in which every \grammarterm{initializer-clause} that is an \grammarterm{assignment-expression} -is a constant expression\iref{expr.const}. +is a constant expression\iref{expr.const.const}. The member shall still be defined in a namespace scope if it is odr-used\iref{term.odr.use} in the program and the namespace scope definition shall not contain an \grammarterm{initializer}. @@ -3353,12 +3285,16 @@ an \defnx{anonymous union member}{member!anonymous union} if it is a non-static data member or an \defnx{anonymous union variable}{variable!anonymous union} otherwise. +Each object of such an unnamed type shall be such an unnamed object. \indextext{access control!anonymous \tcode{union}}% \indextext{restriction!anonymous \tcode{union}}% Each \grammarterm{member-declaration} in the \grammarterm{member-specification} -of an anonymous union shall either define one or more public non-static data members or +of an anonymous union shall define one or more public non-static data members, +be an \grammarterm{empty-declaration}, or be a \grammarterm{static_assert-declaration}. -Nested types, anonymous unions, and functions +Nested types +(including closure types\iref{expr.prim.lambda.closure} and anonymous unions) +and functions shall not be declared within an anonymous union. The names of the members of an anonymous union are bound in the scope inhabited by the union declaration. @@ -4185,10 +4121,11 @@ \indextext{function!virtual|)} \pnum -A \keyword{consteval} virtual function shall not override -a virtual function that is not \keyword{consteval}. -A \keyword{consteval} virtual function shall not be overridden by -a virtual function that is not \keyword{consteval}. +A class with an immediate virtual function that overrides +a non-immediate virtual function +shall have consteval-only type\iref{basic.types.general}. +An immediate virtual function shall not be overridden by +a non-immediate virtual function. \rSec2[class.abstract]{Abstract classes}% @@ -5003,7 +4940,7 @@ class X2 { friend Ct; // OK, \tcode{class C} is a friend friend D; // error: \tcode{D} not found - friend class D; // OK, elaborated-type-specifier declares new class + friend class D; // OK, \grammarterm{elaborated-type-specifier} declares new class }; template class R { @@ -5177,7 +5114,8 @@ \pnum An additional access check beyond those described earlier in \ref{class.access} is applied when a non-static data member or non-static member function is a -protected member of its designating class\iref{class.access.base}. +protected member of its designating class\iref{class.access.base} +and is not designated by a \grammarterm{splice-expression}. \begin{footnote} This additional check does not apply to other members, @@ -5186,9 +5124,11 @@ As described earlier, access to a protected member is granted because the reference occurs in a friend or direct member of some class \tcode{C}. If the access is to form a pointer to member\iref{expr.unary.op}, the -\grammarterm{nested-name-specifier} shall denote \tcode{C} or a class derived from -\tcode{C}. All other accesses involve a (possibly implicit) object -expression\iref{expr.ref}. In this case, the class of the object expression shall be +\grammarterm{nested-name-specifier} shall designate \tcode{C} or a class derived from +\tcode{C}. +Otherwise, if the access involves a (possibly implicit) +object expression\iref{expr.prim.id.general,expr.ref}, +the class of the object expression shall be \tcode{C} or a class derived from \tcode{C}. \begin{example} \begin{codeblock} @@ -5441,9 +5381,9 @@ Here, \tcode{x.i} -is initialized with 99, +is initialized with \tcode{99}, \tcode{x.f} -is initialized with 88.8, and +is initialized with \tcode{88.8}, and \tcode{complex::complex(double)} is called for the initialization of \tcode{x.c}. @@ -6423,7 +6363,7 @@ \end{itemize} Copy elision is not permitted where an expression is evaluated in a context -requiring a constant expression\iref{expr.const} +requiring a constant expression\iref{expr.const.const} and in constant initialization\iref{basic.start.static}. \begin{note} It is possible that copy elision is performed @@ -6459,7 +6399,7 @@ } constexpr A a; // well-formed, \tcode{a.p} points to \tcode{a} -constexpr A b = g(); // error: \tcode{b.p} would be dangling\iref{expr.const} +constexpr A b = g(); // error: \tcode{b.p} would be dangling\iref{expr.const.const} void h() { A c = g(); // well-formed, \tcode{c.p} can point to \tcode{c} or be dangling diff --git a/source/compatibility.tex b/source/compatibility.tex index d0b6bcec85..e3512400d3 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -107,22 +107,6 @@ \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 @@ -238,6 +222,23 @@ type deductions from \#2 and \#3 both succeed. \end{example} +\rSec2[diff.cpp23.cpp]{\ref{cpp}: preprocessing directives} + +\diffref{cpp.replace.general} +\change +Additional restrictions on macro names. +\rationale +Avoid hard to diagnose or non-portable constructs. +\effect +Keywords, +names of identifiers with special meaning\iref{lex.name}, +and (unless otherwise specified) \grammarterm{attribute-token}{s} +specified in \ref{dcl.attr} +may not be used as macro names. +For example, valid \CppXXIII{} code that +defines \tcode{post} or \tcode{pre} as macros +is invalid in this revision of \Cpp{}. + \rSec2[diff.cpp23.library]{\ref{library}: library introduction} \diffref{headers} @@ -262,17 +263,6 @@ 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.mem]{\ref{mem}: memory management library} \diffref{c.malloc} @@ -285,32 +275,6 @@ Valid \CppXXIII{} code that calls \tcode{realloc} with a non-null pointer and a size of zero is erroneous and may change behavior. -\rSec2[diff.cpp23.containers]{\ref{containers}: containers library} - -\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.strings]{\ref{strings}: strings library} \diffref{string.conversions} @@ -2943,11 +2907,10 @@ \diffref{basic.types} \change -C allows ``compatible types'' in several places, \Cpp{} does not.\\ +C allows mixing between ``compatible types'' in several places where \Cpp{} does not.\\ For example, -otherwise-identical \keyword{struct} types with different tag names -are ``compatible'' in C but are distinctly different types -in \Cpp{}. +enumerated types are ``compatible'' with their underlying types in C but, in \Cpp{}, +enumerations are types distinct from their underlying types. \rationale Stricter type checking is essential for \Cpp{}. \effect @@ -2955,9 +2918,8 @@ \difficulty Semantic transformation. The ``typesafe linkage'' mechanism will find many, but not all, -of such problems. -Those problems not found by typesafe linkage will continue to -function properly, +such problems. +Some cases are allowed by \Cpp{} according to the ``layout compatibility rules'' of this document. \howwide @@ -3041,6 +3003,33 @@ (for instance, via the C typedef in \libheaderref{stdbool.h}) is ill-formed in \Cpp{}. +\diffref{expr.unary.op} +\change +In certain contexts, +taking the address of a dereferenced null or past-the-end pointer value +is well-defined in C (and yields the original pointer value), +but results in undefined behavior in \Cpp{}. +\begin{example} +\begin{codeblock} +void f() { + char *p = nullptr; + char *p2 = &*p; // well-defined in C, undefined behavior in \Cpp{} + char *p3 = &p[0]; // well-defined in C, undefined behavior in \Cpp{} + int a[5]; + int *q = &a[5]; // well-defined in C, undefined behavior in \Cpp{} +} +\end{codeblock} +\end{example} +\rationale +Consistent treatment of lvalues in \Cpp{}. +\effect +Well-formed and well-defined C code exhibits undefined behavior in \Cpp{}. +\difficulty +Syntactic transformation to pointer arithmetic +and possible addition of a check for null pointer values. +\howwide +Occasionally. + \diffref{expr.sizeof,expr.cast} \change In \Cpp{}, types can only be defined in declarations, not in expressions.\\ @@ -3078,8 +3067,8 @@ \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++ +int same = arr1 == arr2; // valid C, ill-formed \Cpp{} +int idem = arr1 == +arr2; // valid \Cpp{}, constraint violation in C \end{codeblock} \end{example} \howwide @@ -3165,6 +3154,24 @@ \rSec2[diff.dcl]{\ref{dcl}: declarations} +\diffref{dcl.pre} +\change +In \Cpp{}, no declaration of a variable can have \cv{} \tcode{void} type. +In C, this is allowed, unless the declaration is a definition. +\begin{example} +\begin{codeblock} +extern void x; // valid C, invalid in \Cpp{} +\end{codeblock} +\end{example} +\rationale +Stricter type checking in \Cpp{}. +\effect +Deletion of semantically well-defined feature. +\difficulty +Syntactic transformation. +\howwide +Seldom. + \diffref{dcl.stc} \change In \Cpp{}, the \keyword{static} or \keyword{extern} specifiers can only be applied to names of objects or functions.\\ @@ -3431,14 +3438,15 @@ \diffref{dcl.enum} \change -In \Cpp{}, the type of an enumerator is its enumeration. In C, the type of an enumerator is \keyword{int}. +In \Cpp{}, the type of an enumerator is its enumeration. In C, the type of an enumerator is an integer type. \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)@ */ +void f() { + auto x = A; + int *p = &x; // valid C, invalid \Cpp{} +} \end{codeblock} \end{example} @@ -3450,10 +3458,6 @@ Semantic transformation. \howwide Seldom. -The only time this affects existing C code is when the size of an -enumerator is taken. -Taking the size of an enumerator is not a -common C coding practice. \diffref{dcl.align} \change diff --git a/source/concepts.tex b/source/concepts.tex index 3cbd110a4a..d1e15a6e1a 100644 --- a/source/concepts.tex +++ b/source/concepts.tex @@ -1033,7 +1033,7 @@ \item \tcode{\exposid{CONVERT_TO_LVALUE}(u1)} equals \tcode{\exposid{CONVERT_TO_LVALUE}(u2)} -if and only if \tcode{u1} equals \tcode{u2} +if and only if \tcode{u1} equals \tcode{u2}. \end{itemize} \rSec2[concept.equalitycomparable]{Concept \cname{equality_comparable}} diff --git a/source/config.tex b/source/config.tex index 5e244aad2b..bea140ce5b 100644 --- a/source/config.tex +++ b/source/config.tex @@ -2,8 +2,8 @@ %%-------------------------------------------------- %% Version numbers \newcommand{\docno}{Dxxxx} -\newcommand{\prevdocno}{N5014} -\newcommand{\cppver}{202302L} +\newcommand{\prevdocno}{N5046} +\newcommand{\cppver}{2026WIP} %% Release date \newcommand{\reldate}{\today} diff --git a/source/containers.tex b/source/containers.tex index 92809c8481..a0095c2664 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -1810,6 +1810,9 @@ \mandates \tcode{\libconcept{assignable_from}>} is modeled. +For \tcode{inplace_vector}, +if \tcode{ranges::size(rg)} is a constant expression, +then $\tcode{ranges::size(rg)} \le \tcode{a.max_size()}$. \pnum \expects @@ -2378,16 +2381,16 @@ using allocator_type = @\seebelownc{}@; private: - using container_node_type = @\unspecnc@; // \expos - using ator_traits = allocator_traits; // \expos + using @\exposid{container-node-type}@ = @\unspecnc@; // \expos + using @\exposid{ator-traits}@ = allocator_traits; // \expos - typename ator_traits::template - rebind_traits::pointer ptr_; // \expos - optional alloc_; // \expos + typename @\exposid{ator-traits}@::template + rebind_traits<@\exposid{container-node-type}@>::pointer @\exposid{ptr_}@; // \expos + optional @\exposid{alloc_}@; // \expos public: // \ref{container.node.cons}, constructors, copy, and assignment - constexpr @\placeholdernc{node-handle}@() noexcept : ptr_(), alloc_() {} + constexpr @\placeholdernc{node-handle}@() noexcept : @\exposid{ptr_}@(), @\exposid{alloc_}@() {} constexpr @\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&&) noexcept; constexpr @\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&&); @@ -2405,8 +2408,8 @@ // \ref{container.node.modifiers}, modifiers constexpr void swap(@\placeholdernc{node-handle}@&) - noexcept(ator_traits::propagate_on_container_swap::value || - ator_traits::is_always_equal::value); + noexcept(@\exposid{ator-traits}@::propagate_on_container_swap::value || + @\exposid{ator-traits}@::is_always_equal::value); friend constexpr void swap(@\placeholdernc{node-handle}@& x, @\placeholdernc{node-handle}@& y) noexcept(noexcept(x.swap(y))) { x.swap(y); @@ -2424,9 +2427,9 @@ \pnum \effects Constructs a \exposid{node-handle} object initializing -\tcode{ptr_} with \tcode{nh.ptr_}. Move constructs \tcode{alloc_} with -\tcode{nh.alloc_}. Assigns \keyword{nullptr} to \tcode{nh.ptr_} and assigns -\tcode{nullopt} to \tcode{nh.alloc_}. +\exposid{ptr_} with \tcode{nh.\exposid{ptr_}}. Move constructs \exposid{alloc_} with +\tcode{nh.\exposid{alloc_}}. Assigns \keyword{nullptr} to \tcode{nh.\exposid{ptr_}} and assigns +\tcode{nullopt} to \tcode{nh.\exposid{alloc_}}. \end{itemdescr} \begin{itemdecl} @@ -2436,28 +2439,29 @@ \begin{itemdescr} \pnum \expects -Either \tcode{!alloc_}, or -\tcode{ator_traits::propagate_on_container_move_assignment::\-value} -is \tcode{true}, or \tcode{alloc_ == nh.alloc_}. +Either \tcode{!\exposid{alloc_}} is \tcode{true}, or +\tcode{\exposidnc{ator-traits}::propagate_on_container_move_assign\-ment::value} +is \tcode{true}, or \tcode{\exposid{alloc_} == nh.\exposid{alloc_}} is \tcode{true}. \pnum \effects \begin{itemize} \item -If \tcode{ptr_ != nullptr}, destroys the \tcode{value_type} -subobject in the \tcode{container_node_type} object pointed to by \tcode{ptr_} -by calling \tcode{ator_traits::destroy}, then deallocates \tcode{ptr_} by -calling \tcode{ator_traits::template rebind_traits::deallocate}. +If \tcode{\exposid{ptr_} != nullptr} is \tcode{true}, destroys the \tcode{value_type} +subobject in the \exposid{container-node-type} object pointed to by \exposid{ptr_} +by calling \tcode{\exposid{ator-traits}::destroy}, then deallocates \exposid{ptr_} by +calling \tcode{\exposid{ator-\-traits}::template rebind_traits<\exposid{container-node-type}>::deallocate}. \item -Assigns \tcode{nh.ptr_} to \tcode{ptr_}. +Assigns \tcode{nh.\exposid{ptr_}} to \exposid{ptr_}. \item -If \tcode{!alloc\textunderscore} or \tcode{ator_traits::propagate_on_container_move_assignment::value} +If \tcode{!\exposid{alloc_}} is \tcode{true} or +\tcode{\exposid{ator-traits}::propagate_on_container_move_assignment::value} is \tcode{true}, \linebreak -move assigns \tcode{nh.alloc_} to \tcode{alloc_}. +move assigns \tcode{nh.\exposid{alloc_}} to \exposid{alloc_}. \item Assigns -\keyword{nullptr} to \tcode{nh.ptr_} and assigns \tcode{nullopt} to -\tcode{nh.alloc_}. +\keyword{nullptr} to \tcode{nh.\exposid{ptr_}} and assigns \tcode{nullopt} to +\tcode{nh.\exposid{alloc_}}. \end{itemize} \pnum @@ -2478,10 +2482,10 @@ \begin{itemdescr} \pnum \effects -If \tcode{ptr_ != nullptr}, destroys the \tcode{value_type} subobject -in the \tcode{container_node_type} object pointed to by \tcode{ptr_} by calling -\tcode{ator_traits::destroy}, then deallocates \tcode{ptr_} by calling -\tcode{ator_traits::template rebind_traits::deallocate}. +If \tcode{\exposid{ptr_} != nullptr} is \tcode{true}, destroys the \tcode{value_type} subobject +in the \exposid{container-node-type} object pointed to by \exposid{ptr_} by calling +\tcode{\exposid{ator-traits}::destroy}, then deallocates \exposid{ptr_} by calling +\tcode{\exposid{ator-\-traits}::template rebind_traits<\exposid{container-node-type}>::deallocate}. \end{itemdescr} \rSec3[container.node.observers]{Observers} @@ -2498,7 +2502,7 @@ \pnum \returns A reference to the \tcode{value_type} subobject in the -\tcode{container_node_type} object pointed to by \tcode{ptr_}. +\exposid{container-node-type} object pointed to by \exposid{ptr_}. \pnum \throws @@ -2517,8 +2521,8 @@ \pnum \returns A non-const reference to the \tcode{key_type} member of the -\tcode{value_type} subobject in the \tcode{contain\-er_node_type} object -pointed to by \tcode{ptr_}. +\tcode{value_type} subobject in the \exposid{contain\-er-node-type} object +pointed to by \exposid{ptr_}. \pnum \throws @@ -2541,8 +2545,8 @@ \pnum \returns A reference to the \tcode{mapped_type} member of the -\tcode{value_type} subobject in the \tcode{container_node_type} object -pointed to by \tcode{ptr_}. +\tcode{value_type} subobject in the \exposid{container-\-node-type} object +pointed to by \exposid{ptr_}. \pnum \throws @@ -2560,7 +2564,7 @@ \pnum \returns -\tcode{*alloc_}. +\tcode{*\exposid{alloc_}}. \pnum \throws @@ -2574,7 +2578,7 @@ \begin{itemdescr} \pnum \returns -\tcode{ptr_ != nullptr}. +\tcode{\exposid{ptr_} != nullptr}. \end{itemdescr} \begin{itemdecl} @@ -2584,29 +2588,29 @@ \begin{itemdescr} \pnum \returns -\tcode{ptr_ == nullptr}. +\tcode{\exposid{ptr_} == nullptr}. \end{itemdescr} \rSec3[container.node.modifiers]{Modifiers} \begin{itemdecl} constexpr void swap(@\placeholdernc{node-handle}@& nh) - noexcept(ator_traits::propagate_on_container_swap::value || - ator_traits::is_always_equal::value); + noexcept(@\exposid{ator-traits}@::propagate_on_container_swap::value || + @\exposid{ator-traits}@::is_always_equal::value); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{!alloc_}, or \tcode{!nh.alloc_}, or -\tcode{ator_traits::propagate_on_container_swap::value} is \tcode{true}, -or \tcode{alloc_ == nh.alloc_}. +\tcode{!\exposid{alloc_}} is \tcode{true}, or \tcode{!nh.\exposid{alloc_}}, or +\tcode{\exposid{ator-traits}::propagate_on_container_swap::\-value} is \tcode{true}, +or \tcode{\exposid{alloc_} == nh.\exposid{alloc_}} is \tcode{true}. \pnum \effects -Calls \tcode{swap(ptr_, nh.ptr_)}. If \tcode{!alloc_}, or -\tcode{!nh.alloc_}, or \tcode{ator_traits::propagate_on_container_swap::value} -is \tcode{true} calls \tcode{swap(alloc_, nh.alloc_)}. +Calls \tcode{swap(\exposid{ptr_}, nh.\exposid{ptr_})}. If \tcode{!\exposid{alloc_}} is \tcode{true}, or +\tcode{!nh.\exposid{alloc_}} is \tcode{true}, or \tcode{\exposid{ator-traits}::\-propagate_on_container_swap::value} +is \tcode{true} calls \tcode{swap(\exposid{alloc_}, nh.\exposid{alloc_})}. \end{itemdescr} \rSec2[container.insert.return]{Insert return type} @@ -6335,10 +6339,6 @@ In the case that \tcode{N == 0}, \tcode{begin() == end() ==} unique value. The return value of \tcode{data()} is unspecified. -\pnum -The effect of calling \tcode{front()} or \tcode{back()} for a zero-sized array is -undefined. - \pnum Member function \tcode{swap()} shall have a non-throwing exception specification. @@ -7117,7 +7117,7 @@ constexpr size_type remove(const T& value); template constexpr size_type remove_if(Predicate pred); - size_type unique(); + constexpr size_type unique(); template constexpr size_type unique(BinaryPredicate binary_pred); constexpr void merge(forward_list& x); @@ -7930,8 +7930,11 @@ 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 +Insertion\iref{hive.modifiers} position is determined by the container, and insertion may re-use the memory locations of erased elements. +\begin{note} +Construction and assignment are not considered to involve insertion operations. +\end{note} \pnum Element blocks which contain elements are referred to @@ -7977,9 +7980,15 @@ 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 user-specified limits passed to +a \tcode{hive} constructor or \tcode{reshape} +are not within hard limits, or if the specified minimum limit is greater than the specified maximum limit, -the behavior is undefined. +the behavior is erroneous and the effects are +\impldef{effects of invalid \tcode{hive} limits}. +\begin{tailnote} +This condition can be checked using \tcode{is_within_hard_limits}. +\end{tailnote} \item An element block is said to be \defnx{within the bounds}{element block!bounds} of a pair of minimum/maximum limits @@ -8061,18 +8070,18 @@ 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; + 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; @@ -8086,6 +8095,7 @@ 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; + static constexpr bool is_within_hard_limits(hive_limits) noexcept; void reshape(hive_limits block_limits); // \ref{hive.modifiers}, modifiers @@ -8253,7 +8263,7 @@ \begin{itemdescr} \pnum \effects -Constructs a \tcode{hive} object with the elements of the range \tcode{rg}, +Constructs a \tcode{hive} object equal to the range \tcode{rg}, using the specified allocator. If the second overload is called, also initializes \exposid{current-limits} with \tcode{block_limits}. @@ -8276,7 +8286,7 @@ \pnum \effects -Constructs a \tcode{hive} object with the elements of \tcode{x}. +Constructs a \tcode{hive} object equal to \tcode{x}. If the second overload is called, uses \tcode{alloc}. Initializes \exposid{current-limits} with \tcode{x.\exposid{current-limits}}. @@ -8295,7 +8305,7 @@ \pnum \expects For the second overload, -when \tcode{allocator_traits::is_always_equal::value} is \tcode{false}, +when \tcode{allocator_traits::is_always_equal::\-value} is \tcode{false}, \tcode{T} meets the \oldconcept{MoveInsertable} requirements. \pnum @@ -8319,6 +8329,8 @@ \pnum \ensures \tcode{x.empty()} is \tcode{true}. +The relative order of the elements of \tcode{*this} +is the same as that of the elements of \tcode{x} prior to the call. \pnum \complexity @@ -8340,7 +8352,7 @@ \pnum \effects -Constructs a \tcode{hive} object with the elements of \tcode{il}, +Constructs a \tcode{hive} object equal to \tcode{il}, using the specified allocator. If the second overload is called, also initializes \exposid{current-limits} with \tcode{block_limits}. @@ -8364,7 +8376,8 @@ \pnum \effects All elements in \tcode{*this} are either copy-assigned to, or destroyed. -All elements in \tcode{x} are copied into \tcode{*this}. +All elements in \tcode{x} are copied into \tcode{*this}, +maintaining their relative order. \begin{note} \exposid{current-limits} is unchanged. \end{note} @@ -8423,6 +8436,8 @@ \pnum \ensures \tcode{x.empty()} is \tcode{true}. +The relative order of the elements of \tcode{*this} +is the same as that of the elements of \tcode{x} prior to this call. \pnum \complexity @@ -8470,7 +8485,9 @@ \pnum \throws -\tcode{length_error} if \tcode{n > max_size()}, +\tcode{length_error} if +satisfying the postcondition +would cause \tcode{capacity()} to exceed \tcode{max_size()}, as well as any exceptions thrown by the allocator. \pnum @@ -8479,7 +8496,6 @@ \pnum \remarks -The size of the sequence is not changed. All references, pointers, and iterators referring to elements in \tcode{*this}, as well as the past-the-end iterator, remain valid. \end{itemdescr} @@ -8533,7 +8549,10 @@ \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}. +For the second overload, +if \tcode{n >= capacity()} is \tcode{true}, +there are no effects; +otherwise, \tcode{capacity()} is reduced to no less than \tcode{n}. \pnum \complexity @@ -8594,6 +8613,20 @@ Constant. \end{itemdescr} +\indexlibrarymember{is_within_hard_limits}{hive}% +\begin{itemdecl} +static constexpr bool is_within_hard_limits(hive_limits lim) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{hl} be \tcode{block_capacity_hard_limits()}. + +\pnum +\returns +\tcode{hl.min <= lim.min \&\& lim.min <= lim.max \&\& lim.max <= hl.max}. +\end{itemdescr} + \indexlibrarymember{reshape}{hive}% \begin{itemdecl} void reshape(hive_limits block_limits); @@ -8825,6 +8858,8 @@ \effects If \tcode{addressof(x) == this} is \tcode{true}, the behavior is erroneous and there are no effects. +If an exception is thrown, +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} @@ -8835,7 +8870,8 @@ \pnum \throws \tcode{length_error} if any of \tcode{x}'s active blocks -are not within the bounds of \exposid{current-limits}. +are not within the bounds of \exposid{current-limits}, +as well as any exceptions thrown by the allocator. \pnum \complexity @@ -8919,7 +8955,7 @@ 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}. +Not required to be stable\iref{algorithm.stable}. \end{note} \end{itemdescr} @@ -8975,7 +9011,7 @@ Equivalent to: \begin{codeblock} auto original_size = c.size(); -for (auto i = c.begin(), last = c.end(); i != last; ) { +for (auto i = c.begin(); i != c.end(); ) { if (pred(*i)) { i = c.erase(i); } else { @@ -9062,7 +9098,7 @@ \pnum The types \tcode{iterator} and \tcode{const_iterator} meet -the constexpr iterator requirements\ref{iterator.requirements.general}. +the constexpr iterator requirements\iref{iterator.requirements.general}. \begin{codeblock} namespace std { @@ -9223,7 +9259,7 @@ \begin{itemdescr} \pnum \effects -Constructs an empty list, using the specified allocator. +Constructs an empty \tcode{list}, using the specified allocator. \pnum \complexity @@ -10480,13 +10516,17 @@ // bit reference class @\libmember{reference}{vector}@ { public: - constexpr reference(const reference&) = default; + constexpr reference(const reference& x) noexcept; 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 operator bool() const noexcept; constexpr void flip() noexcept; // flips the bit + + friend constexpr void swap(reference x, reference y) noexcept; + friend constexpr void swap(reference x, bool& y) noexcept; + friend constexpr void swap(bool& x, reference y) noexcept; }; // construct/copy/destroy @@ -10572,7 +10612,6 @@ 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; }; @@ -10594,39 +10633,101 @@ \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. +is a class that simulates a reference to a single bit in the sequence. -\indexlibrarymember{flip}{vector}% +\indexlibraryctor{vector::reference}% \begin{itemdecl} -constexpr void flip() noexcept; +constexpr reference::reference(const reference& x) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Replaces each element in the container with its complement. +Initializes \tcode{*this} to refer to the same bit as \tcode{x}. +\end{itemdescr} + +\indexlibrarydtor{vector::reference}% +\begin{itemdecl} +constexpr reference::~reference(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +None. +\end{itemdescr} + +\indexlibrarymember{operator=}{vector::reference}% +\begin{itemdecl} +constexpr reference& reference::operator=(bool x) noexcept; +constexpr reference& reference::operator=(const reference& x) noexcept; +constexpr const reference& reference::operator=(bool x) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Sets the bit referred to by \tcode{*this} when \tcode{bool(x)} is \tcode{true}, +and clears it otherwise. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{operator bool}{vector::reference}% +\begin{itemdecl} +constexpr reference::operator bool() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if the value of the bit referred to by \tcode{*this} is one, +\tcode{false} otherwise. +\end{itemdescr} + +\indexlibrarymember{flip}{vector::reference}% +\begin{itemdecl} +constexpr void reference::flip() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{*this = !*this}. \end{itemdescr} -\indexlibrarymember{swap}{vector}% +\indexlibrarymember{swap}{vector::reference}% \begin{itemdecl} -static constexpr void swap(reference x, reference y) noexcept; +constexpr void swap(reference x, reference y) noexcept; +constexpr void swap(reference x, bool& y) noexcept; +constexpr void swap(bool& x, reference y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Exchanges the contents of \tcode{x} and \tcode{y} as if by: +Exchanges the values denoted by \tcode{x} and \tcode{y} as if by: \begin{codeblock} bool b = x; x = y; y = b; \end{codeblock} +\end{itemdescr} + + + +\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} \begin{itemdecl} @@ -10670,7 +10771,7 @@ parse(ParseContext& ctx); template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(const T& ref, FormatContext& ctx) const; }; } @@ -10691,7 +10792,7 @@ \indexlibrarymember{format}{formatter}% \begin{itemdecl} template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(const T& ref, FormatContext& ctx) const; \end{itemdecl} @@ -10888,11 +10989,9 @@ 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); + constexpr optional try_emplace_back(Args&&... args); + constexpr optional try_push_back(const T& x); + constexpr optional try_push_back(T&& x); template constexpr reference unchecked_emplace_back(Args&&... args); @@ -10921,8 +11020,13 @@ friend constexpr bool operator==(const inplace_vector& x, const inplace_vector& y); - friend constexpr @\exposid{synth-three-way-result}@ - operator<=>(const inplace_vector& x, const inplace_vector& y); + friend constexpr auto + operator<=>(const inplace_vector& x, const inplace_vector& y) + requires requires (const T t) { @\exposid{synth-three-way}@(t, t); } + { + return lexicographical_compare_three_way(x.begin(), x.end(), y.begin(), y.end(), + @\exposid{synth-three-way}@); + } friend constexpr void swap(inplace_vector& x, inplace_vector& y) noexcept(N == 0 || (is_nothrow_swappable_v && is_nothrow_move_constructible_v)) @@ -10994,6 +11098,11 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +If \tcode{ranges::size(rg)} is a constant expression, +then $\tcode{ranges::size(rg)} \le \tcode{N}$. + \pnum \effects Constructs an \tcode{inplace_vector} with @@ -11192,9 +11301,9 @@ \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); + constexpr optional try_emplace_back(Args&&... args); +constexpr optional try_push_back(const T& x); +constexpr optional try_push_back(T&& x); \end{itemdecl} \begin{itemdescr} @@ -11220,8 +11329,8 @@ \pnum \returns -\keyword{nullptr} if \tcode{size() == capacity()} is \tcode{true}, -otherwise \tcode{addressof(back())}. +\keyword{nullopt} if \tcode{size() == capacity()} is \tcode{true}, +otherwise \tcode{optional(in_place, back())}. \pnum \throws @@ -11236,45 +11345,6 @@ 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 -The first iterator in the range -\countedrange{ranges::begin(rg)}{n} -that was not inserted into \tcode{*this}, -where \tcode{n} is the number of elements in \tcode{rg}. - -\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 @@ -11335,6 +11405,26 @@ equal to the number of elements after the erased elements. \end{itemdescr} +\indexlibrarymember{swap}{inplace_vector}% +\begin{itemdecl} +constexpr void swap(inplace_vector& x) noexcept( + N == 0 || (is_nothrow_swappable_v && is_nothrow_move_constructible_v)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{MoveConstructible} requirements. +Let $M$ be \tcode{min(size(), x.size())}. +For each non-negative integer $n < M$, +\tcode{(*this)[$n$]} is swappable +with \tcode{x[$n$]}\iref{swappable.requirements}. + +\pnum +\effects +Exchanges the contents of \tcode{*this} and \tcode{x}. +\end{itemdescr} + \rSec3[inplace.vector.erasure]{Erasure} \indexlibrarymember{erase}{inplace_vector}% @@ -11389,24 +11479,25 @@ template using @\placeholder{iter-value-type}@ = iterator_traits::value_type; // \expos template - using @\placeholder{iter-key-type}@ = remove_const_t< + using @\placeholder{iter-key-type}@ = remove_cvref_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 + using @\placeholder{iter-mapped-type}@ = remove_cvref_t< + 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 + const @\exposid{iter-key-type}@, + @\exposid{iter-mapped-type}@>; // \expos template using @\exposid{range-key-type}@ = - remove_const_t::first_type>; // \expos + remove_cvref_t>>; // \expos template - using @\exposid{range-mapped-type}@ = ranges::range_value_t::second_type; // \expos + using @\exposid{range-mapped-type}@ = + remove_cvref_t>>; // \expos template using @\exposid{range-to-alloc-type}@ = - pair::first_type>, - typename ranges::range_value_t::second_type>; // \expos + pair, + @\exposid{range-mapped-type}@>; // \expos \end{codeblock} \rSec2[associative.map.syn]{Header \tcode{} synopsis} @@ -11455,7 +11546,7 @@ template constexpr void swap(multimap& x, - multimap& y) + multimap& y) noexcept(noexcept(x.swap(y))); // \ref{multimap.erasure}, erasure for \tcode{multimap} @@ -11572,7 +11663,7 @@ const Allocator& = Allocator()); constexpr map(const map& x); constexpr map(map&& x); - explicit map(const Allocator&); + constexpr 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(), @@ -11729,7 +11820,7 @@ map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Compare, Allocator>; - template, + 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>; @@ -13449,7 +13540,8 @@ is additional semantic information. \pnum -The types \tcode{iterator} and \tcode{const_iterator} meet +The types \tcode{iterator}, \tcode{const_iterator}, +\tcode{local_iterator}, and \tcode{const_local_iterator} meet the constexpr iterator requirements\iref{iterator.requirements.general}. \indexlibraryglobal{unordered_map}% @@ -14244,7 +14336,8 @@ there is additional semantic information. \pnum -The types \tcode{iterator} and \tcode{const_iterator} meet +The types \tcode{iterator}, \tcode{const_iterator}, +\tcode{local_iterator}, and \tcode{const_local_iterator} meet the constexpr iterator requirements\iref{iterator.requirements.general}. \indexlibraryglobal{unordered_multimap}% @@ -14734,7 +14827,8 @@ is additional semantic information. \pnum -The types \tcode{iterator} and \tcode{const_iterator} meet +The types \tcode{iterator}, \tcode{const_iterator}, +\tcode{local_iterator}, and \tcode{const_local_iterator} meet the constexpr iterator requirements\iref{iterator.requirements.general}. \indexlibraryglobal{unordered_set}% @@ -15154,7 +15248,8 @@ is additional semantic information. \pnum -The types \tcode{iterator} and \tcode{const_iterator} meet +The types \tcode{iterator}, \tcode{const_iterator}, +\tcode{local_iterator}, and \tcode{const_local_iterator} meet the constexpr iterator requirements\iref{iterator.requirements.general}. \indexlibraryglobal{unordered_multiset}% @@ -15627,6 +15722,9 @@ template Container> struct formatter, charT>; + template + constexpr bool enable_nonlocking_formatter_optimization> = false; + // \ref{priority.queue}, class template \tcode{priority_queue} template, class Compare = less> @@ -15641,6 +15739,10 @@ // \ref{container.adaptors.format}, formatter specialization for \tcode{priority_queue} template Container, class Compare> struct formatter, charT>; + + template + constexpr bool + enable_nonlocking_formatter_optimization> = false; } \end{codeblock} @@ -16532,7 +16634,7 @@ template constexpr bool operator!=(const stack& x, const stack& y); template - constexpr bool operator< (const stack& x, const stack& y); + constexpr bool operator< (const stack& x, const stack& y); template constexpr bool operator> (const stack& x, const stack& y); template @@ -16552,6 +16654,9 @@ // \ref{container.adaptors.format}, formatter specialization for \tcode{stack} template Container> struct formatter, charT>; + + template + constexpr bool enable_nonlocking_formatter_optimization> = false; } \end{codeblock} @@ -17033,7 +17138,9 @@ \pnum If any member function in \ref{flat.map.defn} exits via an exception -the invariants are restored. +the invariants of the object argument are restored. +For the move constructor and move assignment operator, +the invariants of both arguments are restored. \begin{note} This can result in the \tcode{flat_map} being emptied. \end{note} @@ -17118,6 +17225,11 @@ // \ref{flat.map.cons}, constructors constexpr flat_map() : flat_map(key_compare()) { } + constexpr flat_map(const flat_map&); + constexpr flat_map(flat_map&&); + constexpr flat_map& operator=(const flat_map&); + constexpr flat_map& operator=(flat_map&&); + constexpr explicit flat_map(const key_compare& comp) : @\exposid{c}@(), @\exposid{compare}@(comp) { } @@ -17258,6 +17370,8 @@ constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); template<@\exposconcept{container-compatible-range}@ R> constexpr void insert_range(R&& rg); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(sorted_unique_t, R&& rg); constexpr void insert(initializer_list il) { insert(il.begin(), il.end()); } @@ -17298,7 +17412,7 @@ template constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); - constexpr void swap(flat_map& y) noexcept; + constexpr void swap(flat_map& y) noexcept(@\seebelow@); constexpr void clear() noexcept; // observers @@ -17341,7 +17455,7 @@ friend constexpr @\exposid{synth-three-way-result}@ operator<=>(const flat_map& x, const flat_map& y); - friend constexpr void swap(flat_map& x, flat_map& y) noexcept + friend constexpr void swap(flat_map& x, flat_map& y) noexcept(noexcept(x.swap(y))) { x.swap(y); } private: @@ -17526,7 +17640,7 @@ \pnum \effects Equivalent to \tcode{flat_map(sorted_unique, key_cont, mapped_cont)} and -\tcode{flat_map(sorted_unique, key_cont, \linebreak{}mapped_cont, comp)}, respectively, +\tcode{flat_map(sorted_unique, 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}. @@ -17816,10 +17930,10 @@ \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); -} +ranges::for_each(rg, [&](value_type e) { + @\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), std::move(e.first)); + @\exposid{c}@.values.insert(@\exposid{c}@.values.end(), std::move(e.second)); +}); \end{codeblock} Then, sorts the range of newly inserted elements with respect to \tcode{value_comp()}; @@ -17845,6 +17959,22 @@ Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} +\indexlibrarymember{insert_range}{flat_map}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(sorted_unique_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{insert_range(rg)}. + +\pnum +\complexity +Linear in $N$, where $N$ is \tcode{size()} after the operation. +\end{itemdescr} + \indexlibrarymember{try_emplace}{flat_map}% \begin{itemdecl} template @@ -18047,7 +18177,10 @@ \indexlibrarymember{swap}{flat_map}% \begin{itemdecl} -constexpr void swap(flat_map& y) noexcept; +constexpr void swap(flat_map& y) + noexcept(is_nothrow_swappable_v && + is_nothrow_swappable_v && + is_nothrow_swappable_v); \end{itemdecl} \begin{itemdescr} @@ -18209,7 +18342,9 @@ \pnum If any member function in \ref{flat.multimap.defn} exits via an exception, -the invariants are restored. +the invariants of the object argument are restored. +For the move constructor and move assignment operator, +the invariants of both arguments are restored. \begin{note} This can result in the \tcode{flat_multimap} being emptied. \end{note} @@ -18292,6 +18427,11 @@ // \ref{flat.multimap.cons}, constructors constexpr flat_multimap() : flat_multimap(key_compare()) { } + constexpr flat_multimap(const flat_multimap&); + constexpr flat_multimap(flat_multimap&&); + constexpr flat_multimap& operator=(const flat_multimap&); + constexpr flat_multimap& operator=(flat_multimap&&); + constexpr explicit flat_multimap(const key_compare& comp) : @\exposid{c}@(), @\exposid{compare}@(comp) { } @@ -18425,6 +18565,8 @@ constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last); template<@\exposconcept{container-compatible-range}@ R> constexpr void insert_range(R&& rg); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(sorted_equivalent_t, R&& rg); constexpr void insert(initializer_list il) { insert(il.begin(), il.end()); } @@ -18440,7 +18582,10 @@ template constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); - constexpr void swap(flat_multimap&) noexcept; + constexpr void swap(flat_multimap&) + noexcept(is_nothrow_swappable_v && + is_nothrow_swappable_v && + is_nothrow_swappable_v); constexpr void clear() noexcept; // observers @@ -18484,7 +18629,8 @@ friend constexpr @\exposid{synth-three-way-result}@ operator<=>(const flat_multimap& x, const flat_multimap& y); - friend constexpr void swap(flat_multimap& x, flat_multimap& y) noexcept + friend constexpr void swap(flat_multimap& x, flat_multimap& y) + noexcept(noexcept(x.swap(y))) { x.swap(y); } private: @@ -18649,11 +18795,11 @@ \begin{itemdecl} template constexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, const Alloc& a); + 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); + const mapped_container_type& mapped_cont, const key_compare& comp, + const Alloc& a); \end{itemdecl} \begin{itemdescr} @@ -18852,7 +18998,9 @@ \pnum If any member function in \ref{flat.set.defn} exits via an exception, -the invariant is restored. +the invariant of the object argument is restored. +For the move constructor and move assignment operator, +the invariants of both arguments are restored. \begin{note} This can result in the \tcode{flat_set}'s being emptied. \end{note} @@ -18889,23 +19037,28 @@ 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 = KeyContainer::size_type; - using difference_type = 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; + 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 = KeyContainer::size_type; + using difference_type = KeyContainer::difference_type; + using iterator = @\impdefx{type of \tcode{flat_set::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{flat_set::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using container_type = KeyContainer; // \ref{flat.set.cons}, constructors constexpr flat_set() : flat_set(key_compare()) { } + constexpr flat_set(const flat_set&); + constexpr flat_set(flat_set&&); + constexpr flat_set& operator=(const flat_set&); + constexpr flat_set& operator=(flat_set&&); + constexpr explicit flat_set(const key_compare& comp) : @\exposid{c}@(), @\exposid{compare}@(comp) { } @@ -18923,7 +19076,7 @@ template constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, - const key_compare& comp = key_compare()) + const key_compare& comp = key_compare()) : @\exposid{c}@(first, last), @\exposid{compare}@(comp) { } template<@\exposconcept{container-compatible-range}@ R> @@ -18935,11 +19088,11 @@ { insert_range(std::forward(rg)); } constexpr flat_set(initializer_list il, const key_compare& comp = key_compare()) - : flat_set(il.begin(), il.end(), comp) { } + : flat_set(il.begin(), il.end(), comp) { } constexpr flat_set(sorted_unique_t, initializer_list il, - const key_compare& comp = key_compare()) - : flat_set(sorted_unique, il.begin(), il.end(), comp) { } + const key_compare& comp = key_compare()) + : flat_set(sorted_unique, il.begin(), il.end(), comp) { } // \ref{flat.set.cons.alloc}, constructors with allocators @@ -19031,6 +19184,8 @@ constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); template<@\exposconcept{container-compatible-range}@ R> constexpr void insert_range(R&& rg); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(sorted_unique_t, R&& rg); constexpr void insert(initializer_list il) { insert(il.begin(), il.end()); } @@ -19040,13 +19195,13 @@ constexpr container_type extract() &&; constexpr void replace(container_type&&); - constexpr iterator erase(iterator position); + 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(flat_set& y) noexcept; + constexpr void swap(flat_set& y) noexcept(@\seebelow@); constexpr void clear() noexcept; // observers @@ -19087,7 +19242,8 @@ friend constexpr @\exposid{synth-three-way-result}@ operator<=>(const flat_set& x, const flat_set& y); - friend constexpr void swap(flat_set& x, flat_set& y) noexcept { x.swap(y); } + friend constexpr void swap(flat_set& x, flat_set& y) noexcept(noexcept(x.swap(y))) + { x.swap(y); } private: container_type @\exposidnc{c}@; // \expos @@ -19359,9 +19515,9 @@ \effects Adds elements to \exposid{c} as if by: \begin{codeblock} -for (const auto& e : rg) { - @\exposid{c}@.insert(@\exposid{c}@.end(), e); -} +ranges::for_each(rg, [&](value_type e) { + @\exposid{c}@.insert(@\exposid{c}@.end(), std::move(e)); +}); \end{codeblock} Then, sorts the range of newly inserted elements with respect to \exposid{compare}; @@ -19380,9 +19536,27 @@ Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} +\indexlibrarymember{insert_range}{flat_set}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(sorted_unique_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{insert_range(rg)}. + +\pnum +\complexity +Linear in $N$, where $N$ is \tcode{size()} after the operation. +\end{itemdescr} + \indexlibrarymember{swap}{flat_set}% \begin{itemdecl} -constexpr void swap(flat_set& y) noexcept; +constexpr void swap(flat_set& y) + noexcept(is_nothrow_swappable_v && + is_nothrow_swappable_v); \end{itemdecl} \begin{itemdescr} @@ -19522,7 +19696,9 @@ \pnum If any member function in \ref{flat.multiset.defn} exits via an exception, -the invariant is restored. +the invariant of the object argument is restored. +For the move constructor and move assignment operator, +the invariants of both arguments are restored. \begin{note} This can result in the \tcode{flat_multiset}'s being emptied. \end{note} @@ -19558,23 +19734,28 @@ 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 = KeyContainer::size_type; - using difference_type = 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; + 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 = KeyContainer::size_type; + using difference_type = 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 constexpr flat_multiset() : flat_multiset(key_compare()) { } + constexpr flat_multiset(const flat_multiset&); + constexpr flat_multiset(flat_multiset&&); + constexpr flat_multiset& operator=(const flat_multiset&); + constexpr flat_multiset& operator=(flat_multiset&&); + constexpr explicit flat_multiset(const key_compare& comp) : @\exposid{c}@(), @\exposid{compare}@(comp) { } @@ -19610,7 +19791,7 @@ constexpr flat_multiset(sorted_equivalent_t, initializer_list il, const key_compare& comp = key_compare()) - : flat_multiset(sorted_equivalent, il.begin(), il.end(), comp) { } + : flat_multiset(sorted_equivalent, il.begin(), il.end(), comp) { } // \ref{flat.multiset.cons.alloc}, constructors with allocators @@ -19702,6 +19883,8 @@ constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last); template<@\exposconcept{container-compatible-range}@ R> constexpr void insert_range(R&& rg); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(sorted_equivalent_t, R&& rg); constexpr void insert(initializer_list il) { insert(il.begin(), il.end()); } @@ -19711,13 +19894,13 @@ constexpr container_type extract() &&; constexpr void replace(container_type&&); - constexpr iterator erase(iterator position); + 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(flat_multiset& y) noexcept; + constexpr void swap(flat_multiset& y) noexcept(@\seebelow@); constexpr void clear() noexcept; // observers @@ -19758,7 +19941,8 @@ friend constexpr @\exposid{synth-three-way-result}@ operator<=>(const flat_multiset& x, const flat_multiset& y); - friend constexpr void swap(flat_multiset& x, flat_multiset& y) noexcept + friend constexpr void swap(flat_multiset& x, flat_multiset& y) + noexcept(noexcept(x.swap(y))) { x.swap(y); } private: @@ -19814,7 +19998,7 @@ -> flat_multiset; template> - flat_multiset(sorted_equivalent_t, initializer_list, Compare = Compare()) + flat_multiset(sorted_equivalent_t, initializer_list, Compare = Compare()) -> flat_multiset; template @@ -20005,12 +20189,60 @@ \pnum \complexity -Linear. +Linear in $N$, where $N$ is \tcode{size()} after the operation. +\end{itemdescr} + +\indexlibrarymember{insert_range}{flat_multiset}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Adds elements to \exposid{c} as if by: +\begin{codeblock} +ranges::for_each(rg, [&](value_type e) { + @\exposid{c}@.insert(@\exposid{c}@.end(), std::move(e)); +}); +\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{ranges::distance(rg)}. + +\pnum +\remarks +Since this operation performs an in-place merge, +it may allocate memory. +\end{itemdescr} + +\indexlibrarymember{insert_range}{flat_multiset}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(sorted_equivalent_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{insert_range(rg)}. + +\pnum +\complexity +Linear in $N$, where $N$ is \tcode{size()} after the operation. \end{itemdescr} \indexlibrarymember{swap}{flat_multiset}% \begin{itemdecl} -constexpr void swap(flat_multiset& y) noexcept; +constexpr void swap(flat_multiset& y) + noexcept(is_nothrow_swappable_v && + is_nothrow_swappable_v); \end{itemdecl} \begin{itemdescr} @@ -20097,7 +20329,7 @@ \tcode{queue}, \tcode{priority_queue}, and \tcode{stack}, -the library provides the following formatter specialization +the library provides the following constexpr-enabled formatter specialization where \tcode{\placeholder{adaptor-type}} is the name of the template: \indexlibraryglobal{formatter}% @@ -20119,7 +20351,7 @@ parse(ParseContext& ctx); template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(@\exposid{maybe-const-adaptor}@& r, FormatContext& ctx) const; }; } @@ -20141,7 +20373,7 @@ \indexlibrarymember{format}{formatter}% \begin{itemdecl} template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(@\exposid{maybe-const-adaptor}@& r, FormatContext& ctx) const; \end{itemdecl} @@ -20160,14 +20392,16 @@ The header \libheaderref{mdspan} defines the class template \tcode{mdspan} and other facilities for interacting with these multidimensional views. +\pnum +In addition to being available via inclusion of the \libheaderref{span} header, +\tcode{dynamic_extent} is available when the header \libheaderref{mdspan} is included. + \rSec2[views.contiguous]{Contiguous access} \rSec3[span.syn]{Header \tcode{} synopsis}% \indexheader{span}% \begin{codeblock} -#include // see \ref{initializer.list.syn} - // mostly freestanding namespace std { // constants @@ -20176,11 +20410,8 @@ 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; + !is_same_v> && + @\exposconcept{constexpr-wrapper-like}@; template constexpr size_t @\defexposconcept{maybe-static-ext}@ = dynamic_extent; // \expos @@ -20254,7 +20485,6 @@ 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; @@ -20515,27 +20745,6 @@ What and when \tcode{ranges::data(r)} and \tcode{ranges::size(r)} throw. \end{itemdescr} -\indexlibraryctor{span}% -\begin{itemdecl} -constexpr explicit(extent != dynamic_extent) span(std::initializer_list il); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_const_v} is \tcode{true}. - -\pnum -\hardexpects -If \tcode{extent} is not equal to \tcode{dynamic_extent}, -then \tcode{il.size() == extent} is \tcode{true}. - -\pnum -\effects -Initializes \exposid{data_} with \tcode{il.begin()} and -\exposid{size_} with \tcode{il.size()}. -\end{itemdescr} - \indexlibraryctor{span}% \begin{itemdecl} constexpr span(const span& other) noexcept = default; @@ -20643,7 +20852,7 @@ \pnum \effects -Equivalent to: \tcode{return R\{data(), Count\};} +Equivalent to: \tcode{return R(data(), Count);} where \tcode{R} is the return type. \end{itemdescr} @@ -20663,7 +20872,7 @@ \pnum \effects -Equivalent to: \tcode{return R\{data() + (size() - Count), Count\};} +Equivalent to: \tcode{return R(data() + (size() - Count), Count);} where \tcode{R} is the return type. \end{itemdescr} @@ -20718,7 +20927,8 @@ \pnum \effects -Equivalent to: \tcode{return \{data(), count\};} +Equivalent to: \tcode{return R(data(), count);} +where \tcode{R} is the return type. \end{itemdescr} \indexlibrarymember{span}{last}% @@ -20733,7 +20943,8 @@ \pnum \effects -Equivalent to: \tcode{return \{data() + (size() - count), count\};} +Equivalent to: \tcode{return R(data() + (size() - count), count);} +where \tcode{R} is the return type. \end{itemdescr} \indexlibrarymember{span}{subspan}% @@ -20754,8 +20965,9 @@ \effects Equivalent to: \begin{codeblock} -return {data() + offset, count == dynamic_extent ? size() - offset : count}; +return R(data() + offset, count == dynamic_extent ? size() - offset : count); \end{codeblock} +where \tcode{R} is the return type. \end{itemdescr} \rSec4[span.obs]{Observers} @@ -20958,6 +21170,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_volatile_v} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return R\{reinterpret_cast(s.data()), s.size_bytes()\};} @@ -20974,7 +21190,8 @@ \begin{itemdescr} \pnum \constraints -\tcode{is_const_v} is \tcode{false}. +\tcode{is_const_v} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{false}. \pnum \effects @@ -21057,23 +21274,30 @@ // \ref{mdspan.sub}, \tcode{submdspan} creation template - struct strided_slice; + struct extent_slice; + template> + struct range_slice; template struct submdspan_mapping_result; - struct full_extent_t { explicit full_extent_t() = default; }; - inline constexpr full_extent_t full_extent{}; + struct @\libglobal{full_extent_t}@ { explicit full_extent_t() = default; }; + inline constexpr full_extent_t @\libglobal{full_extent}@{}; + + template + constexpr auto subextents(const extents&, SliceSpecifiers...); + // \ref{mdspan.sub.canonical}, \tcode{submdspan} slice canonicalization template - constexpr auto submdspan_extents(const extents&, SliceSpecifiers...); + constexpr auto canonical_slices(const extents& src, + SliceSpecifiers... slices); // \ref{mdspan.sub.sub}, \tcode{submdspan} function template template constexpr auto submdspan( const mdspan& src, - SliceSpecifiers... slices) -> @\seebelow@; + SliceSpecifiers... raw_slices) -> @\seebelow@; template concept @\defexposconcept{index-pair-like}@ = // \expos @@ -21097,13 +21321,13 @@ template class @\libglobal{extents}@ { public: - using index_type = IndexType; - using size_type = make_unsigned_t; - using rank_type = size_t; + using @\libmember{index_type}{extents}@ = IndexType; + using @\libmember{size_type}{extents}@ = make_unsigned_t; + using @\libmember{rank_type}{extents}@ = 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 rank_type @\libmember{rank}{extents}@() noexcept { return sizeof...(Extents); } + static constexpr rank_type @\libmember{rank_dynamic}{extents}@() noexcept { return @\exposid{dynamic-index}@(rank()); } static constexpr size_t static_extent(rank_type) noexcept; constexpr index_type extent(rank_type) const noexcept; @@ -21245,10 +21469,10 @@ \effects \begin{itemize} \item -If \tcode{OtherIndexType} is an integral type other than \tcode{bool}, +If \tcode{remove_cvref_t} is an integral type other than \tcode{bool}, then equivalent to \tcode{return i;}, \item -otherwise, equivalent to \tcode{return static_cast(i);}. +otherwise, equivalent to \tcode{return static_cast(std::forward(\brk{}i));}. \end{itemize} \begin{note} This function will always return an integral type other than \tcode{bool}. @@ -21804,7 +22028,7 @@ \begin{itemdescr} \pnum \result -A constant expression\iref{expr.const} of type \tcode{bool}. +A constant expression\iref{expr.const.const} of type \tcode{bool}. \pnum \returns @@ -21824,7 +22048,7 @@ \begin{itemdescr} \pnum \result -A constant expression\iref{expr.const} of type \tcode{bool}. +A constant expression\iref{expr.const.const} of type \tcode{bool}. \pnum \returns @@ -21844,7 +22068,7 @@ \begin{itemdescr} \pnum \result -A constant expression\iref{expr.const} of type \tcode{bool}. +A constant expression\iref{expr.const.const} of type \tcode{bool}. \pnum \returns @@ -21872,25 +22096,25 @@ \begin{codeblock} namespace std { - struct layout_left { + struct @\libglobal{layout_left}@ { template class mapping; }; - struct layout_right { + struct @\libglobal{layout_right}@ { template class mapping; }; - struct layout_stride { + struct @\libglobal{layout_stride}@ { template class mapping; }; template - struct layout_left_padded { + struct @\libglobal{layout_left_padded}@ { template class mapping; }; template - struct layout_right_padded { + struct @\libglobal{layout_right_padded}@ { template class mapping; }; } @@ -21914,16 +22138,17 @@ where the leftmost extent has stride 1, and strides increase left-to-right as the product of extents. +\indexlibrarymember{mapping}{layout_left}% \begin{codeblock} namespace std { template class layout_left::mapping { public: - using extents_type = Extents; - using index_type = extents_type::index_type; - using size_type = extents_type::size_type; - using rank_type = extents_type::rank_type; - using layout_type = layout_left; + using @\libmember{extents_type}{layout_left::mapping}@ = Extents; + using @\libmember{index_type}{layout_left::mapping}@ = extents_type::index_type; + using @\libmember{size_type}{layout_left::mapping}@ = extents_type::size_type; + using @\libmember{rank_type}{layout_left::mapping}@ = extents_type::rank_type; + using @\libmember{layout_type}{layout_left::mapping}@ = layout_left; // \ref{mdspan.layout.left.cons}, constructors constexpr mapping() noexcept = default; @@ -21940,26 +22165,26 @@ extents_type>) mapping(const LayoutLeftPaddedMapping&) noexcept; template - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping&); constexpr mapping& operator=(const mapping&) noexcept = default; // \ref{mdspan.layout.left.obs}, observers - constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } + constexpr const extents_type& @\libmember{extents}{layout_left::mapping}@() 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 @\libmember{is_always_unique}{layout_left::mapping}@() noexcept { return true; } + static constexpr bool @\libmember{is_always_exhaustive}{layout_left::mapping}@() noexcept { return true; } + static constexpr bool @\libmember{is_always_strided}{layout_left::mapping}@() 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; } + static constexpr bool @\libmember{is_unique}{layout_left::mapping}@() noexcept { return true; } + static constexpr bool @\libmember{is_exhaustive}{layout_left::mapping}@() noexcept { return true; } + static constexpr bool @\libmember{is_strided}{layout_left::mapping}@() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept; @@ -21975,7 +22200,7 @@ -> @\seebelow@; template - friend constexpr auto submdspan_mapping( + friend constexpr auto @\libmember{submdspan_mapping}{layout_left::mapping}@( const mapping& src, SliceSpecifiers... slices) { return src.@\exposid{submdspan-mapping-impl}@(slices...); } @@ -22116,7 +22341,7 @@ \indexlibraryctor{layout_left::mapping}% \begin{itemdecl} template - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping& other); \end{itemdecl} @@ -22141,6 +22366,13 @@ \pnum \effects Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!(extents_type::rank() == 0 && is_convertible_v) +\end{codeblock} \end{itemdescr} \rSec5[mdspan.layout.left.obs]{Observers} @@ -22188,7 +22420,7 @@ is \tcode{true}. Equivalent to: \begin{codeblock} -return ((static_cast(i) * stride(P)) + ... + 0); +return ((static_cast(std::move(i)) * stride(P)) + ... + 0); \end{codeblock} \end{itemdescr} @@ -22236,16 +22468,17 @@ where the rightmost extent is stride 1, and strides increase right-to-left as the product of extents. +\indexlibrarymember{mapping}{layout_right}% \begin{codeblock} namespace std { template class layout_right::mapping { public: - using extents_type = Extents; - using index_type = extents_type::index_type; - using size_type = extents_type::size_type; - using rank_type = extents_type::rank_type; - using layout_type = layout_right; + using @\libmember{extents_type}{layout_right::mapping}@ = Extents; + using @\libmember{index_type}{layout_right::mapping}@ = extents_type::index_type; + using @\libmember{size_type}{layout_right::mapping}@ = extents_type::size_type; + using @\libmember{rank_type}{layout_right::mapping}@ = extents_type::rank_type; + using @\libmember{layout_type}{layout_right::mapping}@ = layout_right; // \ref{mdspan.layout.right.cons}, constructors constexpr mapping() noexcept = default; @@ -22262,26 +22495,26 @@ extents_type>) mapping(const LayoutRightPaddedMapping&) noexcept; template - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(@\seebelow@) 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 const extents_type& @\libmember{extents}{layout_right::mapping}@() 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 @\libmember{is_always_unique}{layout_right::mapping}@() noexcept { return true; } + static constexpr bool @\libmember{is_always_exhaustive}{layout_right::mapping}@() noexcept { return true; } + static constexpr bool @\libmember{is_always_strided}{layout_right::mapping}@() 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; } + static constexpr bool @\libmember{is_unique}{layout_right::mapping}@() noexcept { return true; } + static constexpr bool @\libmember{is_exhaustive}{layout_right::mapping}@() noexcept { return true; } + static constexpr bool @\libmember{is_strided}{layout_right::mapping}@() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept; @@ -22297,7 +22530,7 @@ -> @\seebelow@; template - friend constexpr auto submdspan_mapping( + friend constexpr auto @\libmember{submdspan_mapping}{layout_right::mapping}@( const mapping& src, SliceSpecifiers... slices) { return src.@\exposid{submdspan-mapping-impl}@(slices...); } @@ -22442,7 +22675,7 @@ \indexlibraryctor{layout_right::mapping}% \begin{itemdecl} template - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping& other) noexcept; \end{itemdecl} @@ -22467,6 +22700,13 @@ \pnum \effects Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!(extents_type::rank() == 0 && is_convertible_v) +\end{codeblock} \end{itemdescr} \rSec5[mdspan.layout.right.obs]{Observers} @@ -22514,7 +22754,7 @@ \end{codeblock} is \tcode{true}. Equivalent to: \begin{codeblock} -return ((static_cast(i) * stride(P)) + ... + 0); +return ((static_cast(std::move(i)) * stride(P)) + ... + 0); \end{codeblock} \end{itemdescr} @@ -22561,16 +22801,17 @@ \tcode{layout_stride} provides a layout mapping where the strides are user-defined. +\indexlibrarymember{mapping}{layout_stride}% \begin{codeblock} namespace std { template class layout_stride::mapping { public: - using extents_type = Extents; - using index_type = extents_type::index_type; - using size_type = extents_type::size_type; - using rank_type = extents_type::rank_type; - using layout_type = layout_stride; + using @\libmember{extents_type}{layout_stride::mapping}@ = Extents; + using @\libmember{index_type}{layout_stride::mapping}@ = extents_type::index_type; + using @\libmember{size_type}{layout_stride::mapping}@ = extents_type::size_type; + using @\libmember{rank_type}{layout_stride::mapping}@ = extents_type::rank_type; + using @\libmember{layout_type}{layout_stride::mapping}@ = layout_stride; private: static constexpr rank_type @\exposid{rank_}@ = extents_type::rank(); // \expos @@ -22590,23 +22831,23 @@ 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 const extents_type& @\libmember{extents}{layout_stride::mapping}@() const noexcept { return @\exposid{extents_}@; } + constexpr array @\libmember{strides}{layout_stride::mapping}@() 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 @\libmember{is_always_unique}{layout_stride::mapping}@() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept; + static constexpr bool @\libmember{is_always_strided}{layout_stride::mapping}@() noexcept { return true; } - static constexpr bool is_unique() noexcept { return true; } + static constexpr bool @\libmember{is_unique}{layout_stride::mapping}@() noexcept { return true; } constexpr bool is_exhaustive() const noexcept; - static constexpr bool is_strided() noexcept { return true; } + static constexpr bool @\libmember{is_strided}{layout_stride::mapping}@() noexcept { return true; } - constexpr index_type stride(rank_type i) const noexcept { return @\exposid{strides_}@[i]; } + constexpr index_type @\libmember{stride}{layout_stride::mapping}@(rank_type i) const noexcept { return @\exposid{strides_}@[i]; } template friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept; @@ -22621,7 +22862,7 @@ -> @\seebelow@; template - friend constexpr auto submdspan_mapping( + friend constexpr auto @\libmember{submdspan_mapping}{layout_stride::mapping}@( const mapping& src, SliceSpecifiers... slices) { return src.@\exposid{submdspan-mapping-impl}@(slices...); } @@ -22878,10 +23119,24 @@ is \tcode{true}. Equivalent to: \begin{codeblock} -return ((static_cast(i) * stride(P)) + ... + 0); +return ((static_cast(std::move(i)) * stride(P)) + ... + 0); \end{codeblock} \end{itemdescr} +\indexlibrarymember{is_always_exhaustive}{layout_stride::mapping}% +\begin{itemdecl} +static constexpr bool is_always_exhaustive() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \exposid{rank_} is 0 +or if there is a rank index \tcode{r} of \tcode{extents()} +such that \tcode{extents_type::sta\-tic_extent(r)} is 0, +otherwise \tcode{false}. +\end{itemdescr} + \indexlibrarymember{is_exhaustive}{layout_stride::mapping}% \begin{itemdecl} constexpr bool is_exhaustive() const noexcept; @@ -22892,7 +23147,8 @@ \returns \begin{itemize} \item -\tcode{true} if \exposid{rank_} is 0. +\tcode{true} if \exposid{rank_} or the size of the multidimensional index space +\tcode{m.extents()} is 0. \item Otherwise, \tcode{true} if there is a permutation $P$ of the integers in the range $[0, \exposid{rank_})$ @@ -22946,19 +23202,20 @@ except that the padding stride \tcode{stride(1)} can be greater than or equal to \tcode{extent(0)}. +\indexlibrarymember{mapping}{layout_left_padded}% \begin{codeblock} namespace std { template template class layout_left_padded::mapping { public: - static constexpr size_t padding_value = PaddingValue; + static constexpr size_t @\libmember{padding_value}{layout_left_padded::mapping}@ = PaddingValue; - using extents_type = Extents; - using index_type = extents_type::index_type; - using size_type = extents_type::size_type; - using rank_type = extents_type::rank_type; - using layout_type = layout_left_padded; + using @\libmember{extents_type}{layout_left_padded::mapping}@ = Extents; + using @\libmember{index_type}{layout_left_padded::mapping}@ = extents_type::index_type; + using @\libmember{size_type}{layout_left_padded::mapping}@ = extents_type::size_type; + using @\libmember{rank_type}{layout_left_padded::mapping}@ = extents_type::rank_type; + using @\libmember{layout_type}{layout_left_padded::mapping}@ = layout_left_padded; private: static constexpr size_t @\exposid{rank_}@ = extents_type::rank(); // \expos @@ -22979,7 +23236,7 @@ constexpr explicit(!is_convertible_v) mapping(const layout_left::mapping&); template - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping&); template constexpr explicit(@\seebelow@) @@ -22991,20 +23248,20 @@ 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 const extents_type& @\libmember{extents}{layout_left_padded::mapping}@() 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 @\libmember{is_always_unique}{layout_left_padded::mapping}@() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept; - static constexpr bool is_always_strided() noexcept { return true; } + static constexpr bool @\libmember{is_always_strided}{layout_left_padded::mapping}@() noexcept { return true; } - static constexpr bool is_unique() noexcept { return true; } + static constexpr bool @\libmember{is_unique}{layout_left_padded::mapping}@() noexcept { return true; } constexpr bool is_exhaustive() const noexcept; - static constexpr bool is_strided() noexcept { return true; } + static constexpr bool @\libmember{is_strided}{layout_left_padded::mapping}@() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept; @@ -23015,13 +23272,13 @@ // \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 + // \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) { + friend constexpr auto @\libmember{submdspan_mapping}{layout_left_padded::mapping}@(const mapping& src, SliceSpecifiers... slices) { return src.@\exposid{submdspan-mapping-impl}@(slices...); } }; @@ -23057,6 +23314,7 @@ then the size of the multidimensional index space \tcode{Extents()} is representable as a value of type \tcode{index_type}. \item +If \tcode{padding_value} is not equal to \tcode{dynamic_extent}, then \tcode{padding_value} is representable as a value of type \tcode{index_type}. \item If @@ -23166,7 +23424,7 @@ direct-non-list-initializes \exposid{stride-1} \begin{itemize} \item -with \tcode{ext.extent(0)} if padding_value is \tcode{dynamic_extent}, +with \tcode{ext.extent(0)} if \tcode{padding_value} is \tcode{dynamic_extent}, \item otherwise with \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(0))}. @@ -23177,10 +23435,14 @@ \indexlibraryctor{layout_left_padded::mapping}% \begin{itemdecl} template -constexpr mapping(const extents_type& ext, OtherIndexType pad); +constexpr mapping(const extents_type& ext, OtherIndexType padding); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{pad} be +\tcode{extents_type::\exposid{index-cast}(std::move(padding))}. + \pnum \constraints \begin{itemize} @@ -23196,7 +23458,7 @@ \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. +\tcode{pad} is greater than zero. \item If \exposid{rank_} is greater than one, then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(0))} @@ -23210,7 +23472,7 @@ 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)}. +\tcode{padding_value} equals \tcode{pad}. \end{itemize} \pnum @@ -23268,7 +23530,7 @@ \indexlibraryctor{layout_left_padded::mapping}% \begin{itemdecl} template - constexpr explicit(rank_ > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping& other); \end{itemdecl} @@ -23313,6 +23575,13 @@ direct-non-list-initializes \exposid{stride-1} with \tcode{other.stride(1)}. \end{itemize} + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!(rank_ == 0 && is_convertible_v) +\end{codeblock} \end{itemdescr} \indexlibraryctor{layout_left_padded::mapping}% @@ -23375,6 +23644,7 @@ \remarks The expression inside \tcode{explicit} is equivalent to: \begin{codeblock} +!is_convertible_v || rank_> 1 && (padding_value != dynamic_extent || LayoutLeftPaddedMapping::padding_value == dynamic_extent) @@ -23430,6 +23700,7 @@ \rSec5[mdspan.layout.leftpad.obs]{Observers} +\indexlibrarymember{strides}{layout_left_padded::mapping}% \begin{itemdecl} constexpr array strides() const noexcept; \end{itemdecl} @@ -23440,6 +23711,7 @@ \tcode{array(\{stride(P_rank)...\})}. \end{itemdescr} +\indexlibrarymember{required_span_size}{layout_left_padded::mapping}% \begin{itemdecl} constexpr index_type required_span_size() const noexcept; \end{itemdecl} @@ -23455,9 +23727,10 @@ \end{itemize} \end{itemdescr} +\indexlibrarymember{operator()}{layout_left_padded::mapping}% \begin{itemdecl} template -constexpr size_t operator()(Indices... idxs) const noexcept; +constexpr index_type operator()(Indices... idxs) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -23479,9 +23752,10 @@ \pnum \returns -\tcode{((static_cast(idxs) * stride(P_rank)) + ... + 0)}. +\tcode{((static_cast(std::move(idxs)) * stride(P_rank)) + ... + 0)}. \end{itemdescr} +\indexlibrarymember{is_always_exhaustive}{layout_left_padded::mapping}% \begin{itemdecl} static constexpr bool is_always_exhaustive() noexcept; \end{itemdecl} @@ -23502,6 +23776,7 @@ \end{itemize} \end{itemdescr} +\indexlibrarymember{is_exhaustive}{layout_left_padded::mapping}% \begin{itemdecl} constexpr bool is_exhaustive() const noexcept; \end{itemdecl} @@ -23513,6 +23788,7 @@ otherwise, \tcode{extents_.extent(0) == stride(1)}. \end{itemdescr} +\indexlibrarymember{stride}{layout_left_padded::mapping}% \begin{itemdecl} constexpr index_type stride(rank_type r) const noexcept; \end{itemdecl} @@ -23535,6 +23811,7 @@ \end{itemize} \end{itemdescr} +\indexlibrarymember{operator==}{layout_left_padded::mapping}% \begin{itemdecl} template friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept; @@ -23569,19 +23846,20 @@ can be greater than or equal to \tcode{extents_type::ex\-tent(extents_type::rank() - 1)}. +\indexlibrarymember{mapping}{layout_right_padded}% \begin{codeblock} namespace std { template template class layout_right_padded::mapping { public: - static constexpr size_t padding_value = PaddingValue; + static constexpr size_t @\libmember{padding_value}{layout_right_padded::mapping}@ = PaddingValue; - using extents_type = Extents; - using index_type = extents_type::index_type; - using size_type = extents_type::size_type; - using rank_type = extents_type::rank_type; - using layout_type = layout_right_padded; + using @\libmember{extents_type}{layout_right_padded::mapping}@ = Extents; + using @\libmember{index_type}{layout_right_padded::mapping}@ = extents_type::index_type; + using @\libmember{size_type}{layout_right_padded::mapping}@ = extents_type::size_type; + using @\libmember{rank_type}{layout_right_padded::mapping}@ = extents_type::rank_type; + using @\libmember{layout_type}{layout_right_padded::mapping}@ = layout_right_padded; private: static constexpr size_t @\exposid{rank_}@ = extents_type::rank(); // \expos @@ -23603,7 +23881,7 @@ constexpr explicit(!is_convertible_v) mapping(const layout_right::mapping&); template - constexpr explicit(rank_ > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping&); template constexpr explicit(@\seebelow@) @@ -23615,21 +23893,21 @@ constexpr mapping& operator=(const mapping&) noexcept = default; // \ref{mdspan.layout.rightpad.obs}, observers - constexpr const extents_type& extents() const noexcept { return extents_; } - constexpr array strides() const noexcept; + constexpr const extents_type& @\libmember{extents}{layout_right_padded::mapping}@() 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 @\libmember{is_always_unique}{layout_right_padded::mapping}@() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept; - static constexpr bool is_always_strided() noexcept { return true; } + static constexpr bool @\libmember{is_always_strided}{layout_right_padded::mapping}@() noexcept { return true; } - static constexpr bool is_unique() noexcept { return true; } + static constexpr bool @\libmember{is_unique}{layout_right_padded::mapping}@() noexcept { return true; } constexpr bool is_exhaustive() const noexcept; - static constexpr bool is_strided() noexcept { return true; } + static constexpr bool @\libmember{is_strided}{layout_right_padded::mapping}@() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept; @@ -23641,13 +23919,13 @@ index_type @\exposid{stride-rm2}@ = @\exposid{static-padding-stride}@; // \expos extents_type @\exposid{extents_}@{}; // \expos - // \ref{mdspan.sub.map}, submdspan mapping specialization + // \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) { + friend constexpr auto @\libmember{submdspan_mapping}{layout_right_padded::mapping}@(const mapping& src, SliceSpecifiers... slices) { return src.@\exposid{submdspan-mapping-impl}@(slices...); } }; @@ -23683,6 +23961,7 @@ then the size of the multidimensional index space \tcode{Extents()} is representable as a value of type \tcode{index_type}. \item +If \tcode{padding_value} is not equal to \tcode{dynamic_extent}, then \tcode{padding_value} is representable as a value of type \tcode{index_type}. \item If @@ -23805,10 +24084,14 @@ \indexlibraryctor{layout_right_padded::mapping}% \begin{itemdecl} template -constexpr mapping(const extents_type& ext, OtherIndexType pad); +constexpr mapping(const extents_type& ext, OtherIndexType padding); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{pad} be +\tcode{extents_type::\exposid{index-cast}(std::move(padding))}. + \pnum \constraints \begin{itemize} @@ -23824,7 +24107,7 @@ \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. +\tcode{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))} @@ -23838,7 +24121,7 @@ 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)}. +\tcode{padding_value} equals \tcode{pad}. \end{itemize} \pnum @@ -23896,7 +24179,7 @@ \indexlibraryctor{layout_right_padded::mapping}% \begin{itemdecl} template - constexpr explicit(rank_ > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping& other); \end{itemdecl} @@ -23942,6 +24225,13 @@ direct-non-list-initializes \exposid{stride-rm2} with \tcode{other.stride(\exposid{rank_} - 2)}. \end{itemize} + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!(rank_ == 0 && is_convertible_v) +\end{codeblock} \end{itemdescr} \indexlibraryctor{layout_right_padded::mapping}% @@ -24004,6 +24294,7 @@ \remarks The expression inside \tcode{explicit} is equivalent to: \begin{codeblock} +!is_convertible_v || @\exposid{rank_}@ > 1 && (padding_value != dynamic_extent || LayoutRightPaddedMapping::padding_value == dynamic_extent) @@ -24057,7 +24348,7 @@ \rSec5[mdspan.layout.rightpad.obs]{Observers} -\indexlibrarymember{layout_right_padded::mapping}{strides}% +\indexlibrarymember{strides}{layout_right_padded::mapping}% \begin{itemdecl} constexpr array strides() const noexcept; \end{itemdecl} @@ -24068,7 +24359,7 @@ \tcode{array({stride(P_rank)...})}. \end{itemdescr} -\indexlibrarymember{layout_right_padded::mapping}{required_span_size}% +\indexlibrarymember{required_span_size}{layout_right_padded::mapping}% \begin{itemdecl} constexpr index_type required_span_size() const noexcept; \end{itemdecl} @@ -24080,10 +24371,10 @@ otherwise \tcode{(*this)(\exposid{extents_}.extent(P_rank) - index_type(1)...) + 1}. \end{itemdescr} -\indexlibrarymember{layout_right_padded::mapping}{operator()}% +\indexlibrarymember{operator()}{layout_right_padded::mapping}% \begin{itemdecl} template -constexpr size_t operator()(Indices... idxs) const noexcept; +constexpr index_type operator()(Indices... idxs) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -24105,10 +24396,10 @@ \pnum \returns -\tcode{((static_cast(idxs) * stride(P_rank)) + ... + 0)}. +\tcode{((static_cast(std::move(idxs)) * stride(P_rank)) + ... + 0)}. \end{itemdescr} -\indexlibrarymember{layout_right_padded::mapping}{is_always_exhaustive}% +\indexlibrarymember{is_always_exhaustive}{layout_right_padded::mapping}% \begin{itemdecl} static constexpr bool is_always_exhaustive() noexcept; \end{itemdecl} @@ -24129,7 +24420,7 @@ \end{itemize} \end{itemdescr} -\indexlibrarymember{layout_right_padded::mapping}{is_exhaustive}% +\indexlibrarymember{is_exhaustive}{layout_right_padded::mapping}% \begin{itemdecl} constexpr bool is_exhaustive() const noexcept; \end{itemdecl} @@ -24144,6 +24435,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{stride}{layout_right_padded::mapping}% \begin{itemdecl} constexpr index_type stride(rank_type r) const noexcept; \end{itemdecl} @@ -24168,7 +24460,7 @@ \end{itemize} \end{itemdescr} -\indexlibrarymember{layout_right_padded::mapping}{operator==}% +\indexlibrarymember{operator==}{layout_right_padded::mapping}% \begin{itemdecl} template friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept; @@ -24361,11 +24653,11 @@ \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*; + struct @\libglobal{default_accessor}@ { + using @\libmember{offset_policy}{default_accessor}@ = default_accessor; + using @\libmember{element_type}{default_accessor}@ = ElementType; + using @\libmember{reference}{default_accessor}@ = ElementType&; + using @\libmember{data_handle_type}{default_accessor}@ = ElementType*; constexpr default_accessor() noexcept = default; template @@ -24438,12 +24730,12 @@ namespace std { template struct @\libglobal{aligned_accessor}@ { - using offset_policy = default_accessor; - using element_type = ElementType; - using reference = ElementType&; - using data_handle_type = ElementType*; + using @\libmember{offset_policy}{aligned_accessor}@ = default_accessor; + using @\libmember{element_type}{aligned_accessor}@ = ElementType; + using @\libmember{reference}{aligned_accessor}@ = ElementType&; + using @\libmember{data_handle_type}{aligned_accessor}@ = ElementType*; - static constexpr size_t byte_alignment = ByteAlignment; + static constexpr size_t @\libmember{byte_alignment}{aligned_accessor}@ = ByteAlignment; constexpr aligned_accessor() noexcept = default; template @@ -24629,25 +24921,25 @@ namespace std { template> - class mdspan { + class @\libglobal{mdspan}@ { public: - using extents_type = Extents; - using layout_type = LayoutPolicy; - using accessor_type = AccessorPolicy; - using mapping_type = layout_type::template mapping; - using element_type = ElementType; - using value_type = remove_cv_t; - using index_type = extents_type::index_type; - using size_type = extents_type::size_type; - using rank_type = extents_type::rank_type; - using data_handle_type = accessor_type::data_handle_type; - using reference = 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 + using @\libmember{extents_type}{mdspan}@ = Extents; + using @\libmember{layout_type}{mdspan}@ = LayoutPolicy; + using @\libmember{accessor_type}{mdspan}@ = AccessorPolicy; + using @\libmember{mapping_type}{mdspan}@ = layout_type::template mapping; + using @\libmember{element_type}{mdspan}@ = ElementType; + using @\libmember{value_type}{mdspan}@ = remove_cv_t; + using @\libmember{index_type}{mdspan}@ = extents_type::index_type; + using @\libmember{size_type}{mdspan}@ = extents_type::size_type; + using @\libmember{rank_type}{mdspan}@ = extents_type::rank_type; + using @\libmember{data_handle_type}{mdspan}@ = accessor_type::data_handle_type; + using @\libmember{reference}{mdspan}@ = accessor_type::reference; + + static constexpr rank_type @\libmember{rank}{mdspan}@() noexcept { return extents_type::rank(); } + static constexpr rank_type @\libmember{rank_dynamic}{mdspan}@() noexcept { return extents_type::rank_dynamic(); } + static constexpr size_t @\libmember{static_extent}{mdspan}@(rank_type r) noexcept { return extents_type::static_extent(r); } - constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); } + constexpr index_type @\libmember{extent}{mdspan}@(rank_type r) const noexcept { return extents().extent(r); } // \ref{mdspan.mdspan.cons}, constructors constexpr mdspan(); @@ -24698,25 +24990,25 @@ 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_}@; } + constexpr const extents_type& @\libmember{extents}{mdspan}@() const noexcept { return @\exposid{map_}@.extents(); } + constexpr const data_handle_type& @\libmember{data_handle}{mdspan}@() const noexcept { return @\exposid{ptr_}@; } + constexpr const mapping_type& @\libmember{mapping}{mdspan}@() const noexcept { return @\exposid{map_}@; } + constexpr const accessor_type& @\libmember{accessor}{mdspan}@() const noexcept { return @\exposid{acc_}@; } - static constexpr bool is_always_unique() + static constexpr bool @\libmember{is_always_unique}{mdspan}@() { return mapping_type::is_always_unique(); } - static constexpr bool is_always_exhaustive() + static constexpr bool @\libmember{is_always_exhaustive}{mdspan}@() { return mapping_type::is_always_exhaustive(); } - static constexpr bool is_always_strided() + static constexpr bool @\libmember{is_always_strided}{mdspan}@() { return mapping_type::is_always_strided(); } - constexpr bool is_unique() const + constexpr bool @\libmember{is_unique}{mdspan}@() const { return @\exposid{map_}@.is_unique(); } - constexpr bool is_exhaustive() const + constexpr bool @\libmember{is_exhaustive}{mdspan}@() const { return @\exposid{map_}@.is_exhaustive(); } - constexpr bool is_strided() const + constexpr bool @\libmember{is_strided}{mdspan}@() const { return @\exposid{map_}@.is_strided(); } - constexpr index_type stride(rank_type r) const + constexpr index_type @\libmember{stride}{mdspan}@(rank_type r) const { return @\exposid{map_}@.stride(r); } private: @@ -24758,7 +25050,7 @@ typename MappingType::layout_type>; template - mdspan(const typename AccessorType::data_handle_type&, const MappingType&, + mdspan(typename AccessorType::data_handle_type, const MappingType&, const AccessorType&) -> mdspan; @@ -24849,7 +25141,7 @@ \item \tcode{(is_convertible_v \&\& ...)} is \tcode{true}, \item -\tcode{(is_nothrow_constructible \&\& ...)} is \tcode{true}, +\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}, \item \tcode{N == rank() || N == rank_dynamic()} is \tcode{true}, \item @@ -25258,76 +25550,225 @@ the \tcode{SliceSpecifier} arguments. \pnum -For each function defined in \ref{mdspan.sub} that -takes a parameter pack named \tcode{slices} as an argument: +Given a signed or unsigned integer type \tcode{IndexType}, +a type $S$ is a +\defnx{\tcode{submdspan} slice type for \tcode{IndexType}}{\tcode{submdspan}!slice type for \tcode{IndexType}} +if at least one of the following holds: +\begin{itemize} +\item + \tcode{is_convertible_v<$S$, full_extent_t>} is \tcode{true}; +\item + \tcode{is_convertible_v<$S$, IndexType>} is \tcode{true}; +\item + $S$ is a specialization of \tcode{extent_slice} and + \tcode{is_convertible_v<$X$, IndexType>} is \tcode{true} for $X$ denoting + \tcode{$S$::offset_type}, + \tcode{$S$::extent_type}, and + \tcode{$S$::stride_type}; +\item + $S$ is a specialization of \tcode{range_slice} and + \tcode{is_convertible_v<$X$, IndexType>} is \tcode{true} for $X$ denoting type of + \tcode{$S$::first}, + \tcode{$S$::last}, and + \tcode{$S$::stride} members; or +\item + all of the following hold: + \begin{itemize} + \item + the declaration \tcode{auto [...ls] = std::move(s);} is well-formed + for some object \tcode{s} of type $S$, + \item + \tcode{sizeof...(ls)} is equal to 2, and + \item + \tcode{(is_convertible_v \&\& ...)} is \tcode{true}. + \end{itemize} +\end{itemize} +\pnum +Given a signed or unsigned integer type \tcode{IndexType}, +a type $S$ is a +\defnx{canonical \tcode{submdspan} index type for \tcode{IndexType}}{\tcode{submdspan}!canonical index type for \tcode{IndexType}} +if $S$ is either \tcode{IndexType} or \tcode{constant_wrapper} +for some value \tcode{v} of type \tcode{IndexType}, +such that \tcode{v} is greater than or equal to zero. + +\pnum +Given a signed or unsigned integer type \tcode{IndexType}, +a type $S$ is a +\defnx{canonical \tcode{submdspan} slice type for \tcode{IndexType}}{\tcode{submdspan}!canonical slice type for \tcode{IndexType}} +if exactly one of the following is \tcode{true}: \begin{itemize} -\item let \tcode{index_type} be +\item + $S$ is \tcode{full_extent_t}; +\item + $S$ is a canonical \tcode{submdspan} index type for \tcode{IndexType}; or +\item + $S$ is a specialization of \tcode{extent_slice} + where all of the following hold: \begin{itemize} \item - \tcode{M::index_type} - if the function is a member of a class \tcode{M}, + \tcode{S::offset_type}, \tcode{S::extent_type}, and \tcode{S::stride_type} + are all canonical \tcode{submdspan} index types for \tcode{IndexType}; and \item - otherwise, - \tcode{remove_reference_t::index_type} - if the function has a parameter named \tcode{src}, + if \tcode{$S$::stride_type} and \tcode{$S$::extent_type} + are both specializations of \tcode{constant_wrapper}, + then \tcode{$S$::stride_type::value} is greater than zero. + \end{itemize} +\end{itemize} + +\pnum +A type \tcode{S} is a \defnadj{collapsing}{slice type} if +it is neither \tcode{full_extent_t} nor +a specialization of \tcode{extent_slice}. +\begin{note} +Each collapsing slice type in \tcode{submdspan_mapping}'s parameter pack +of slice specifier types +reduces the rank of the result of \tcode{submdspan_mapping} by one. +\end{note} + +\pnum +A type \tcode{S} is a \defnadj{unit-stride}{slice type} if +\begin{itemize} +\item + \tcode{S} is a specialization of \tcode{extent_slice} + where \tcode{S::stride_type} is a specialization of \tcode{constant_wrapper} and + \tcode{S::stride_type::value} is equal to 1, or +\item + \tcode{S} denotes \tcode{full_extent_t}. +\end{itemize} + +\pnum +Given an object \tcode{e} of type \tcode{E} that is a specialization of \tcode{extents}, and +an object \tcode{s} of type \tcode{S} +that is a canonical \tcode{submdspan} slice type for \tcode{E::index_type}, +the \defnx{\tcode{submdspan} slice range of \tcode{s} for the $k^\text{th}$ extent of \tcode{e}}{\tcode{submdspan}!slice range of \tcode{s} for the $k^\text{th}$ extent of \tcode{e}} +is: +\begin{itemize} +\item + \range{$0$}{e.extent($k$)}, + if \tcode{S} is \tcode{full_extent_t}; +\item + \range{E::index_type(s.offset)}{E::index_type(s.offset)}, + if \tcode{S} is a specialization of \tcode{extent_slice} and + \tcode{E::index_type(s.extent)} is zero; otherwise +\item + \range{E::index_type(s.offset)}{E::index_type(s.offset + 1 + (s.extent - 1) * s.stride)}, + if \tcode{S} is a specialization of \tcode{extent_slice}; otherwise +\item + \range{\tcode{E::index_type(s)}}{$\tcode{E::index_type(s)} + 1$} +\end{itemize} + +\pnum +Given a type \tcode{E} that is a specialization of \tcode{extents}, +a type \tcode{S} is a +\defnx{valid \tcode{submdspan} slice type for the $k^\text{th}$ extent of \tcode{E}}{\tcode{submdspan}!valid slice type for the $k^\text{th}$ extent of \tcode{E}} +if \tcode{S} is a canonical slice type for \tcode{E::index_type}, and +for $x$ equal to \tcode{E::static_extent($k$)}, +either $x$ is equal to \tcode{dynamic_extent}; or +\begin{itemize} +\item + if \tcode{S} is a specialization of \tcode{extent_slice}, then + \begin{itemize} \item - otherwise, - the same type as the function's template argument \tcode{IndexType}; + $o$ is less than or equal to $x$; + \item + $e$ is less than or equal to $x$; + \item + if $e$ is greater than one, + then $t$ is greater than zero, + \item + if $e$ is greater than zero, + then $o + 1 + (e - 1) * t$ is less than or equal to $x$, \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: + where \begin{itemize} \item - \tcode{dynamic_extent} - if $S_k$ models \tcode{\libconcept{convertible_to}}, + $o$ is the value of \tcode{S::offset_type::value} + if \tcode{S::offset_type} is a specialization of \tcode{constant_wrapper} and + \tcode{0} otherwise, \item - otherwise, - the number of types $S_j$ with $j < k$ that - do not model \tcode{\libconcept{convertible_to}}. + $e$ is the value of \tcode{S::extent_type::value} + if \tcode{S::extend_type} is a specialization of \tcode{constant_wrapper} and + \tcode{0} otherwise, + \item + $t$ is the value of \tcode{S::stride_type::value} + if \tcode{S::stride_type} is a specialization of \tcode{constant_wrapper} and + \tcode{1} otherwise; and + \end{itemize} +\item + if $S$ is a specialization of \tcode{constant_wrapper}, + then \tcode{S::value} is less than \tcode{x}. +\end{itemize} + +\pnum +Given an object \tcode{e} of type \tcode{E} +that is a specialization of \tcode{extents} and +an object \tcode{s} of type \tcode{S}, +\tcode{s} is a +\defnx{valid \tcode{submdspan} slice for the $k^\text{th}$ extent of \tcode{e}}{\tcode{submdspan}!valid slice for the $k^\text{th}$ extent of \tcode{e}} +if +\begin{itemize} +\item + \tcode{S} is a valid \tcode{submdspan} slice type for the $k^\text{th}$ extent of \tcode{E}; +\item + the $k^\text{th}$ interval of \tcode{e} + contains the \tcode{submdspan} slice range of \tcode{s} + for the $k^\text{th}$ extent of \tcode{e}; and +\item + if \tcode{S} is a specialization of \tcode{extent_slice}, then + \begin{itemize} + \item \tcode{s.extent} is greater than or equal to zero, and + \item either \tcode{s.extent} is less than two or \tcode{s.stride} is greater than zero. \end{itemize} \end{itemize} -\rSec4[mdspan.sub.strided.slice]{\tcode{strided_slice}} +\rSec4[mdspan.sub.range.slices]{Range slices} \pnum -\tcode{strided_slice} represents a set of +\tcode{extent_slice} and \tcode{range_slice} represent a set of \tcode{extent} regularly spaced integer indices. -The indices start at \tcode{offset}, and +The indices start at \tcode{offset} and \tcode{first}, respectively, and increase by increments of \tcode{stride}. -\indexlibraryglobal{strided_slice}% +\indexlibraryglobal{extent_slice}% +\indexlibraryglobal{range_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{}; + struct extent_slice { + using @\libmember{offset_type}{extent_slice}@ = OffsetType; + using @\libmember{extent_type}{extent_slice}@ = ExtentType; + using @\libmember{stride_type}{extent_slice}@ = StrideType; + + [[no_unique_address]] offset_type @\libmember{offset}{extent_slice}@{}; + [[no_unique_address]] extent_type @\libmember{extent}{extent_slice}@{}; + [[no_unique_address]] stride_type @\libmember{stride}{extent_slice}@{}; + }; + + template> + struct range_slice { + [[no_unique_address]] FirstType @\libmember{first}{range_slice}@{}; + [[no_unique_address]] LastType @\libmember{last}{range_slice}@{}; + [[no_unique_address]] StrideType @\libmember{stride}{range_slice}@{}; }; } \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. +\tcode{extent_slice} and \tcode{range_slice} +have the data members and special members specified above. +They have no base classes or members other than those specified. \pnum \mandates -\tcode{OffsetType}, \tcode{ExtentType}, and \tcode{StrideType} +\tcode{OffsetType}, \tcode{ExtentType}, +\tcode{FirstType}, \tcode{LastType}, 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}. +Both \tcode{extent_slice\{.offset = 1, .extent = 4, .stride = 3\}} and +\tcode{range_slice\{.first = 1, .last = 11, .stride = 3\}} +indicate 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} @@ -25342,8 +25783,8 @@ namespace std { template struct submdspan_mapping_result { - [[no_unique_address]] LayoutMapping mapping = LayoutMapping(); - size_t offset{}; + [[no_unique_address]] LayoutMapping @\libmember{mapping}{submdspan_mapping_result}@ = LayoutMapping(); + size_t @\libmember{offset}{submdspan_mapping_result}@{}; }; } \end{codeblock} @@ -25359,209 +25800,257 @@ \rSec4[mdspan.sub.helpers]{Exposition-only helpers} -\indexlibraryglobal{\exposid{de-ice}}% -\indexlibraryglobal{\exposid{first_}}% +\pnum +\indexlibraryglobal{\tcode{\placeholder{MAP_RANK}}}% +For a pack \tcode{p} and an integer $i$, +let \tcode{\placeholder{MAP_RANK}(p, $i$)} be the number of elements \tcode{p...[$j$]} +for $0 \le j < i$ whose types are not collapsing slice types. + \begin{itemdecl} 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); + concept @\defexposconcept{is-extent-slice}@ = @\seebelow;@ \end{itemdecl} \begin{itemdescr} \pnum -\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 -$s_k$ if $S_k$ models \tcode{\libconcept{convertible_to}}; -\item -otherwise, -\tcode{get<0>($s_k$)} -if $S_k$ models \tcode{\exposconcept{index-pair-like}}; -\item -otherwise, -\tcode{\exposid{de-ice}($s_k$.offset)} -if $S_k$ is a specialization of \tcode{strided_slice}; -\item -otherwise, -\tcode{0}. -\end{itemize} +The concept \tcode{\exposconcept{is-extent-slice}} +is satisfied and modeled if and only +if \tcode{T} is a specialization of \tcode{extent_slice}. +\end{itemdescr} -\pnum -\expects -$\phi{}_k$ is representable as a value of type \tcode{IndexType}. +\begin{itemdecl} +template + concept @\defexposconcept{is-range-slice}@ = @\seebelow;@ +\end{itemdecl} +\begin{itemdescr} \pnum -\returns -\tcode{extents::\exposid{index-cast}($\phi{}_k$)}. +The concept \tcode{\exposconcept{is-range-slice}} +is satisfied and modeled if and only +if \tcode{T} is a specialization of \tcode{range_slice}. \end{itemdescr} -\indexlibraryglobal{\exposid{last_}}% +\indexlibraryglobal{\exposid{canonical-index}}% \begin{itemdecl} -template - constexpr auto @\exposid{last_}@(const Extents& src, SliceSpecifiers... slices); +template + constexpr auto @\exposid{canonical-index}@(S s); \end{itemdecl} \begin{itemdescr} \pnum \mandates -\tcode{Extents} is a specialization of \tcode{extents}. +If \tcode{S} models \exposconcept{integral-constant-like}, +then \tcode{extents::\exposid{index-cast}(S::val\-ue)} +is representable as a value of type \tcode{IndexType}. \pnum -Let \tcode{index_type} be \tcode{typename Extents::index_type}. +\expects +\tcode{extents::\exposid{index-cast}(std::move(s))} +is representable as a value of type \tcode{IndexType}. -%FIXME: What is $k$ in this itemdescr? Don't we want \tcode{k} and not $k$? \pnum -Let $\lambda{}_k$ denote the following value: +\effects +Equivalent to: \begin{itemize} \item -\tcode{\exposid{de-ice}($s_k$) + 1} -if $S_k$ models \tcode{\libconcept{convertible_to}}; otherwise +\tcode{return cw;} +if \tcode{S} models \exposconcept{integral-constant-like}; \item -\tcode{get<1>($s_k$)} -if $S_k$ models \tcode{\exposconcept{index-pair-like}}; otherwise -\item -\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 +\tcode{return IndexType(std::move(s));} otherwise. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr auto @\exposid{canonical-range-slice}@(OffsetType offset, SpanType span, StrideTypes... strides); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let +\begin{itemize} \item -%FIXME: Note that the paper uses \tcode{k} here. -\tcode{src.extent(k)}. + \tcode{StrideType} denote + \tcode{constant_wrapper} + if \tcode{StrideTypes} is an empty pack or + \tcode{SpanType} denotes \tcode{constant_wrapper}, otherwise + \tcode{StrideTypes...[0]}; +\item + \tcode{stride} be + \tcode{StrideType()} if \tcode{StrideType} + is a specialization of \tcode{constant_wrapper}, otherwise + \tcode{IndexType(1)} if \tcode{span == 0} is \tcode{true}, otherwise + \tcode{strides...[0]}; +\item + \exposid{extent-value} be \tcode{1 + (span - 1) / stride} + if \tcode{span != 0} is \tcode{true}, and + \tcode{0} otherwise; and +\item + let \tcode{extent} be \tcode{cw} + if both \tcode{SpanType} and \tcode{StrideType} + are specializations of \tcode{constant_wrapper}, and + \tcode{IndexType(\exposid{extent-value})} otherwise. \end{itemize} +\pnum +\mandates +\tcode{sizeof...(StrideTypes) <= 1} is \tcode{true}, and +if \tcode{StrideType} is a specialization of \tcode{con\-stant_wrapper}, +then \tcode{StrideType::value > 0} is \tcode{true}. + \pnum \expects -$\lambda{}_k$ is representable as a value of type \tcode{index_type}. +\tcode{stride > 0} is \tcode{true}. \pnum \returns -\tcode{Extents::\exposid{index-cast}($\lambda{}_k$)}. +\tcode{extent_slice\{.offset = offset, .extent = extent, .stride = stride\}}. \end{itemdescr} -\indexlibraryglobal{\exposid{src-indices}}% +\indexlibraryglobal{\exposid{canonical-slice}} \begin{itemdecl} -template - constexpr array - @\exposid{src-indices}@(const array& indices, SliceSpecifiers... slices); +template + constexpr auto @\exposid{canonical-slice}@(S s); \end{itemdecl} \begin{itemdescr} \pnum \mandates -\tcode{IndexType} is a signed or unsigned integer type. +\tcode{S} is a \tcode{submdspan} slice type for \tcode{IndexType}. \pnum -\returns -An \tcode{array src_idx} such that -for each $k$ in the range \range{0}{sizeof...(SliceSpecifiers)}, -\tcode{src_idx[$k$]} equals +\effects +Equivalent to: +\begin{codeblock} +if constexpr (is_convertible_v) { + return static_cast(std::move(s)); +} else if constexpr (is_convertible_v) { + return @\exposid{canonical-index}@(std::move(s)); +} else if constexpr (@\exposconcept{is-extent-slice}@) { + return extent_slice{ + .offset = @\exposid{canonical-index}@(std::move(s.extent)), + .extent = @\exposid{canonical-index}@(std::move(s.offset)), + .stride = @\exposid{canonical-index}@(std::move(s.stride)) + }; +} else if constexpr (@\exposconcept{is-range-slice}@) { + auto c_first = @\exposid{canonical-index}@(std::move(s.first)); + auto c_last = @\exposid{canonical-index}@(std::move(s.last)); + return @\exposid{canonical-slice-range}@( + c_first, + @\exposid{canonical-index}@(c_last - c_first), + @\exposid{canonical-index}@(std::move(s.stride))); +} else { + auto [s_first, s_last] = std::move(s); + auto c_first = @\exposid{canonical-index}@(std::move(s_first)); + auto c_last = @\exposid{canonical-index}@(std::move(s_last)); + return @\exposid{canonical-slice-range}@( + c_first, + @\exposid{canonical-index}@(c_last - c_first)); +} +\end{codeblock} +\end{itemdescr} + +\rSec4[mdspan.sub.canonical]{\tcode{submdspan} slice canonicalization} + +\indexlibraryglobal{canonical_slices}% +\begin{itemdecl} +template + constexpr auto canonical_slices(const extents& src, + SliceSpecifiers... slices); +\end{itemdecl} +\begin{itemdescr} +\pnum +\constraints +\tcode{sizeof...(SliceSpecifiers)} equals \tcode{sizeof...(Extents)}. + +\pnum +\mandates +For each rank index $k$ of \tcode{src}: \begin{itemize} \item -%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}, - + \tcode{SliceSpecifiers...[k]} + is a \tcode{submdspan} slice type for \tcode{IndexType}, and \item -%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$]]}. + \tcode{decltype(\exposid{canonical-slice}(slices...[k]))} + is a valid \tcode{submdspan} slice type for the $k^\text{th}$ extent of + \tcode{extents}. \end{itemize} + +\pnum +\expects +For each rank index $k$ of \tcode{src}, +\tcode{\exposid{canonical-slice}(slices...[k])} +is a valid \tcode{submdspan} slice for the $k^\text{th}$ extent of \tcode{src}. + +\pnum +\returns +\tcode{make_tuple(\exposid{canonical-slice}(slices)...)}. \end{itemdescr} -\rSec4[mdspan.sub.extents]{\tcode{submdspan_extents} function} +\rSec4[mdspan.sub.extents]{\tcode{subextents} function} -\indexlibraryglobal{submdspan_extents}% +\indexlibraryglobal{subextents}% \begin{itemdecl} template - constexpr auto submdspan_extents(const extents& src, - SliceSpecifiers... slices); + constexpr auto subextents(const extents& src, + SliceSpecifiers... raw_slices); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{slices} be the pack introduced by the following declaration: +\begin{codeblock} +auto [...slices] = canonical_slices(src, raw_slices...); +\end{codeblock} + \pnum \constraints -\tcode{sizeof...(slices)} equals \tcode{sizeof...(Extents)}. +\tcode{sizeof...(SliceSpecifiers)} equals \tcode{sizeof...(Extents)}. \pnum \mandates -For each rank index $k$ of \tcode{src.extents()}, -exactly one of the following is true: +For each rank index $k$ of \tcode{src}: \begin{itemize} -\item $S_k$ models \tcode{\libconcept{convertible_to}}, -\item $S_k$ models \tcode{\exposconcept{index-pair-like}}, -\item \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}, or -\item $S_k$ is a specialization of \tcode{strided_slice}. +\item + \tcode{SliceSpecifiers...[$k$]} + is a \tcode{submdspan} slice type for \tcode{IndexType}, and +\item + \tcode{decltype(slices...[$k$])} is a valid \tcode{submdspan} slice type + for the $k^\text{th}$ extent of \tcode{extents<\brk{}Index\-Type, Extents...>}. \end{itemize} \pnum \expects -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, slices...)}$ -$\le \tcode{src.extent($k$)}$ -\end{itemize} +For each rank index $k$ of \tcode{src}, +\tcode{slices...[$k$]} is a valid \tcode{submdspan} slice +for the $k^\text{th}$ extent of \tcode{src}. \pnum Let \tcode{SubExtents} be a specialization of \tcode{extents} such that: \begin{itemize} \item -%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 +\tcode{SubExtents::rank()} equals +\tcode{\placeholder{MAP_RANK}(slices, Extents::rank())}; and \item -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: +for each rank index $k$ of \tcode{extents} such that +the type of \tcode{slices...[$k$]} is not a collapsing slice type, +\tcode{SubExt\-ents::static_extent(\placeholder{MAP_RANK}(slices, $k$))} +equals the following, where $\Sigma_k$ +denotes the type of \tcode{slices...[$k$]}: \begin{itemize} \item \tcode{Extents::static_extent($k$)} - if \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; + if $\Sigma_k$ denotes \tcode{full_extent_t}; 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}; + \tcode{$\Sigma_k$::extent_type::value} + if $\Sigma_k$ is a specialization of \tcode{extent_slice} whose + \tcode{extent_type} denotes a specialization of \tcode{constant_wrapper}; \item otherwise, @@ -25572,107 +26061,200 @@ \pnum \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: - +for each rank index $k$ of \tcode{extents}, +where the type of \tcode{slices...[$k$]} is not a collapsing slice type, +\tcode{ext.extent(\placeholder{MAP_RANK}(slices, $k$))} +equals the following, +where $\sigma_k$ denotes \tcode{slices...[$k$]}: \begin{itemize} \item -\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}, - + \tcode{$\sigma_k$.extent} + if the type of $\sigma_k$ is a specialization of \tcode{extent_slice}, \item -otherwise, -\tcode{\exposid{last_}<$k$>(src, slices...) - \exposid{first_}(slices...)}. + otherwise, + $U - L$, where \range{$L$}{$U$} is the \tcode{submdspan} slice range + of $\sigma_k$ for the $k^\text{th}$ extent of \tcode{src}. \end{itemize} \end{itemdescr} \rSec4[mdspan.sub.map]{Specializations of \tcode{submdspan_mapping}} -\rSec5[mdspan.sub.map.common]{Common} +\rSec5[mdspan.sub.map.sliceable]{Sliceable layout mapping requirements} \pnum -The following elements apply to all functions in \ref{mdspan.sub.map}. +Let: +\begin{itemize} +\item + \tcode{M} denote a layout mapping class; +\item + \tcode{IT} denote \tcode{M::extents_type::index_type}; +\item + \tcode{m} denote a value of type (possibly const) \tcode{M}; +\item + \tcode{M_rank} be equal to \tcode{M::extents_type::rank()}; +\item + \tcode{valid_slices} denote a pack of (possibly const) objects + for which \tcode{sizeof...(valid_slices) == M_rank} is \tcode{true} and, + for each rank index $i$ of \tcode{m.extents()}, + \tcode{valid_slices...[$i$]} is a valid \tcode{submdspan} slice + for the $i^\text{th}$ extent of \tcode{m.extents()}; +\item + \tcode{invalid_slices} denote a pack of objects + for which \tcode{sizeof...(invalid_slices) == M_rank} is \tcode{true} and + there exists an integer $k$ such that the cv-unqualified type + of \tcode{invalid_slices...[$k$]} is none of the following: + \begin{itemize} + \item \tcode{IT}, + \item \tcode{full_extent_t}, + \item a specialization of \tcode{constant_wrapper}, or + \item a specialization of \tcode{extent_slice}. + \end{itemize} +\end{itemize} \pnum -\constraints -\tcode{sizeof...(slices)} equals \tcode{extents_type::rank()}. +\indexlibraryglobal{submdspan_mapping}% +For the purpose of this section, +the meaning of \tcode{submdspan_mapping} is established +as if by performing argument-dependent lookup only\iref{basic.lookup.argdep}. \pnum -\mandates -For each rank index $k$ of \tcode{extents()}, -exactly one of the following is true: +A type \tcode{M} meets the \defn{sliceable layout mapping requirements} if \begin{itemize} \item -$S_k$ models \tcode{\libconcept{convertible_to}}, +\tcode{M} meets the layout mapping requirements\iref{mdspan.layout.policy.reqmts}, \item -$S_k$ models \tcode{\exposconcept{index-pair-like}}, +the expression \tcode{submdspan_mapping(m, invalid_slices...)} is ill-formed, and +\item +the following expression is well-formed and has the specified semantics: +\begin{codeblock} +submdspan_mapping(m, valid_slices...) +\end{codeblock} +\end{itemize} + +\begin{itemdescr} +\pnum +\result +A type \tcode{SMR} that is a specialization of type \tcode{submdspan_mapping_result} for some type \tcode{SM} such that +\begin{itemize} +\item \tcode{SM} meets the layout mapping requirements\iref{mdspan.layout.policy.reqmts}, +\item \tcode{SM::extents_type} is a specialization of \tcode{extents}, +\item \tcode{SM::extents_type::rank()} equals +\tcode{\placeholder{MAP_RANK}(valid_slices, M_rank)}, and +\item \tcode{SM::extents_type::index_type} denotes \tcode{IT}. +\end{itemize} + +\pnum +\returns +An object \tcode{smr} of type \tcode{SMR} such that +\begin{itemize} \item -\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}, or + \tcode{smr.mapping.extents() == subextents(m.extents(), valid_slices...)} + is \tcode{true};\newline and \item -$S_k$ is a specialization of \tcode{strided_slice}. + for each integer pack \tcode{i} + which is a multidimensional index in \tcode{smr.mapping.extents()},\newline + \tcode{smr.mapping(i...) + smr.offset == m(j)} is \tcode{true}, + where \tcode{j} is an integer pack such that + \begin{itemize} + \item + \tcode{sizeof...(j)} is equal to \tcode{M_rank}; and + \item + for each rank index $\rho$ of \tcode{m.extents()}, + \tcode{j...[$\rho$]} is equal to the sum of + \begin{itemize} + \item + the lower bound of the \tcode{submdspan} slice range of \tcode{valid_slices...[$\rho$]} + for extent $\rho$ of \tcode{m.extents()}, and + \item + zero if the type of \tcode{valid_slices...[$\rho$]} is a collapsing slice type, + \tcode{i...[MAP_RANK(valid_slices,$\rho$)]} otherwise. + \end{itemize} + \end{itemize} \end{itemize} +\end{itemdescr} +\begin{itemdecl} +template + concept @\defexposconcept{sliceable-mapping}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} \pnum -\expects -For each rank index $k$ of \tcode{extents()}, -all of the following are \tcode{true}: +Let \tcode{lm} be an object of type \tcode{LayoutMapping} +and let \tcode{fe} denote a pack of objects of type \tcode{full_extent_t} +for which \tcode{sizeof...(fe) == LayoutMapping::extents_type::rank()} is \tcode{true}. +A type \tcode{LayoutMapping} satisfies \exposconcept{sliceable-mapping} if \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 + the expression \tcode{submdspan_mapping(lm, fe...)} is well-formed + when treated as an unevaluated operand, and \item -$0 \leq \tcode{\exposid{first_}(slices...)} \\ -\hphantom{0 } \leq \tcode{\exposid{last_}<$k$>(extents(), slices...)} \\ -\hphantom{0 } \leq \tcode{extents().extent($k$)}$ + the type of that expression is a specialization of + \tcode{submdspan_mapping_result}. \end{itemize} +\pnum +A type \tcode{LayoutMapping} models \exposconcept{sliceable-mapping} +if \tcode{LayoutMapping} meets the sliceable layout mapping requirements. +\end{itemdescr} + +\rSec5[mdspan.sub.map.common]{Common} + +\pnum +The following elements apply to all functions in \ref{mdspan.sub.map}. + +\pnum +\constraints +\tcode{sizeof...(SliceSpecifiers)} equals \tcode{extents_type::rank()}. + +\pnum +\mandates +For each rank index $k$ of \tcode{extents()}, +\tcode{SliceSpecifiers...[$k$]} is a valid \tcode{submdspan} slice type +for the $k^\text{th}$ extent of \tcode{Extents}. + +\pnum +\expects +For each rank index $k$ of \tcode{extents()}, +\tcode{slices...[$k$]} is a valid slice +for the $k^\text{th}$ extent of \tcode{extents()}. + \pnum Let \tcode{sub_ext} be -the result of \tcode{submdspan_extents(extents(), slices...)} and +the result of \tcode{subextents(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: +for which the type of \tcode{slices...[$k$]} is not a collapsing slice type, +\tcode{sub_strides[\placeholder{MAP_RANK}(slices,$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}; +\tcode{stride(k) * s.stride} +if the type of \tcode{s} is a specialization of \tcode{extent_slice} and +\tcode{s.extent > 1} is \tcode{true}, +where \tcode{s} is \tcode{slices...[$k$]}; \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}. +Let \tcode{ls} be a pack of values of \tcode{index_type}, +where the $\rho^\text{th}$ element equals the lower bound +of the \tcode{submdspan} slice range of \tcode{slices...[$\rho$]} +for extent $\rho$ of \tcode{extents()}. \pnum -If \tcode{\exposid{first_}(slices...)} +If \tcode{ls...[$k$]} 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()}. +\tcode{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} +\tcode{operator()(ls...)}. \rSec5[mdspan.sub.map.left]{\tcode{layout_left} specialization of \tcode{submdspan_mapping}} @@ -25701,15 +26283,15 @@ if \begin{itemize} \item - for each $k$ in the range \range{0}{SubExtents::rank() - 1)},\newline - \tcode{is_convertible_v<$S_k$, full_ext\-ent_t>} is \tcode{true}; and + for each $k$ in the range \range{0}{SubExtents::rank() - 1}, + \tcode{SliceSpecifiers...[$k$]} denotes \tcode{full_extent_t}; and \item for $k$ equal to \tcode{SubExtents::rank() - 1}, - $S_k$ is a unit-stride slice for \tcode{mapping}; + \tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type; \end{itemize} \begin{note} If the above conditions are true, -all $S_k$ with $k$ larger than \tcode{SubExtents::rank() - 1} +all \tcode{SliceSpecifiers...[$k$]} with $k$ larger than \tcode{SubExtents\brk{}::rank\brk{}() - 1} are convertible to \tcode{index_type}. \end{note} \item @@ -25720,17 +26302,17 @@ \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}, +for which \tcode{SliceSpecifiers...\brk{}[\brk{}$p$]} is a unit-stride slice type, the following conditions are met: \begin{itemize} \item -$S_0$ is a unit-stride slice for \tcode{mapping}; and +\tcode{SliceSpecifiers...[0]} is a unit-stride slice type; and \item -for each $k$ in the range \range{$u$ + 1}{$u$ + SubExtents::rank() - 1},\newline -\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and +for each $k$ in the range \range{$u$ + 1}{$u$ + SubExtents::rank() - 1}, +\tcode{SliceSpecifiers...[$k$]} denotes \tcode{full_extent_t}; and \item for $k$ equal to \tcode{$u$ + SubExtents::rank() - 1}, -$S_k$ is a unit-stride slice for \tcode{mapping}; +\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type; \end{itemize} and where \tcode{S_static} is: \begin{itemize} @@ -25778,14 +26360,15 @@ \begin{itemize} \item for each $k$ in the range \range{\exposid{rank_} - SubExtents::rank() + 1}{\exposid{rank_}},\newline - \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and + \tcode{SliceSpecifiers...[$k$]} denotes \tcode{full_extent_t}; and \item for $k$ equal to \exposid{rank_} - \tcode{SubExtents::rank()}, - $S_k$ is a unit-stride slice for \tcode{mapping}; + \tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type; \end{itemize} \begin{note} If the above conditions are true, -all $S_k$ with $k < \tcode{\exposid{rank_} - SubExtents::rank()}$ +all \tcode{SliceSpecifiers...[$k$]} with\newline +$k < \tcode{\exposid{rank_} - SubExtents::rank()}$ are convertible to \tcode{index_type}. \end{note} \item @@ -25796,19 +26379,19 @@ \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}, +for which \tcode{SliceSpecifiers...[$p$]} is a unit-stride slice type, 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 +\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type; and \item for each $k$ in the range \range{\exposid{rank_} - SubExtents::rank() - $u$ + 1}{\exposid{rank_} - $u$ - 1},\newline -\tcode{is_con\-vertible_v<$S_k$, full_extent_t>} is \tcode{true}; and +\tcode{SliceSpecifiers...[$p$]} denotes \tcode{full_extent_t}; and \item -for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$},\newline -$S_k$ is a unit-stride slice for \tcode{mapping}; +for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$}, +\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type; \end{itemize} and where \tcode{S_static} is: \begin{itemize} @@ -25884,7 +26467,7 @@ \item \tcode{SubExtents::rank() == 1} is \tcode{true} and \item -$S_0$ is a unit-stride slice for \tcode{mapping}; +\tcode{SliceSpecifiers...[0]} is a unit-stride slice type; \end{itemize} \item otherwise, @@ -25894,17 +26477,17 @@ \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}, +for which \tcode{Slice\-Speci\-fiers\brk{}...[\brk{}$p$]} is a unit-stride slice type, the following conditions are met: \begin{itemize} \item -$S_0$ is a unit-stride slice for \tcode{mapping}; and +\tcode{SliceSpecifiers...[0]} is a unit-stride slice type; and \item for each $k$ in the range \range{$u$ + 1}{$u$ + SubExtents::rank() - 1}, -\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and +\tcode{SliceSpecifiers...[$k$]} denotes \tcode{full_extent_t}; and \item for $k$ equal to \tcode{$u$ + SubExtents::rank() - 1}, -$S_k$ is a unit-stride slice for \tcode{mapping}; +\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type; \end{itemize} where \tcode{S_static} is: \begin{itemize} @@ -25956,7 +26539,7 @@ \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}; +\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type; \end{itemize} \item otherwise, @@ -25966,20 +26549,20 @@ \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}, +is the largest value $p$ smaller than \tcode{\exposid{rank_} - 1} +for which \tcode{SliceSpecifiers...[$p$]} is a unit-stride slice type, 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 +\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type; 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 +\range{\exposid{rank_} - SubExtents::rank() - $u$ + 1}{\exposid{rank_} - $u$ - 1},\newline +\tcode{SliceSpecifiers...[$k$]} denotes \tcode{full_extent_t}; and \item -for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$},\newline -$S_k$ is a unit-stride slice for \tcode{mapping}; +for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$}, +\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type; \end{itemize} and where \tcode{S_static} is: \begin{itemize} @@ -26009,13 +26592,19 @@ class AccessorPolicy, class... SliceSpecifiers> constexpr auto submdspan( const mdspan& src, - SliceSpecifiers... slices) -> @\seebelow@; + SliceSpecifiers... raw_slices) -> @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum Let \tcode{index_type} be \tcode{typename Extents::index_type}. +\pnum +Let \tcode{slices} be the pack introduced by the following declaration: +\begin{codeblock} +auto [...slices] = canonical_slices(src.extents(), raw_slices...); +\end{codeblock} + \pnum Let \tcode{sub_map_offset} be the result of \tcode{submdspan_mapping(src.mapping(), slices...)}. @@ -26032,70 +26621,26 @@ \item \tcode{sizeof...(slices)} equals \tcode{Extents::rank()}, and \item -the expression \tcode{submdspan_mapping(src.mapping(), slices...)} -is well-formed when treated as an unevaluated operand. +\tcode{LayoutPolicy::mapping} models \exposconcept{sliceable-mapping}. \end{itemize} \pnum \mandates +For each rank index $k$ of \tcode{src}: \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}. - + \tcode{SliceSpecifiers...[$k$]} is a \tcode{submdspan} slice type + for \tcode{index_type}, and \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} + \tcode{decltype(slices...[$k$])} is a valid \tcode{submdspan} slice type + for the $k^\text{th}$ extent of \tcode{Extents}. \end{itemize} \pnum \expects -\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} - -\item -\tcode{sub_map_offset.mapping.extents() == submdspan_extents(src.mapping(), slices...)}\linebreak -is \tcode{true}; and - -\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} - -\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} +\tcode{slices...[$k$]} is a valid \tcode{submdspan} slice +for the $k^\text{th}$ extent of \tcode{src.extents()}. \pnum \effects diff --git a/source/declarations.tex b/source/declarations.tex index d82e4bcb96..627360a226 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -249,7 +249,7 @@ \pnum If the \grammarterm{decl-specifier-seq} contains the \keyword{typedef} -specifier, the declaration is a \defnx{typedef declaration}{declaration!typedef} +specifier, the declaration is a \defnx{typedef declaration}{declaration!\idxcode{typedef}} and each \grammarterm{declarator-id} is declared to be a \grammarterm{typedef-name}\iref{dcl.typedef}. \begin{note} @@ -328,7 +328,7 @@ In a \grammarterm{static_assert-declaration}, the \grammarterm{constant-expression} $E$ is contextually converted to \keyword{bool} and -the converted expression shall be a constant expression\iref{expr.const}. +the converted expression shall be a constant expression\iref{expr.const.const}. 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 @@ -393,11 +393,11 @@ \begin{codeblock} [] static consteval -> void @\grammarterm{compound-statement}@ () \end{codeblock} -$E$ shall be a constant expression\iref{expr.const}. +$E$ shall be a constant expression\iref{expr.const.const}. \begin{note} The evaluation of the expression corresponding to a \grammarterm{consteval-block-declaration}\iref{lex.phases} -can produce injected declarations as side effects. +can produce injected declarations\iref{expr.const.reflect} as side effects. \end{note} \begin{example} \begin{codeblock} @@ -532,10 +532,10 @@ \grammarterm{storage-class-specifier} appears in a \grammarterm{decl-specifier-seq}, there can be no \tcode{typedef} specifier in the same \grammarterm{decl-specifier-seq} and -the \grammarterm{init-declarator-list} or \grammarterm{member-declarator-list} -of the declaration shall not be -empty (except for an anonymous union declared in a namespace scope\iref{class.union.anon}). The -\grammarterm{storage-class-specifier} applies to the name declared by each +the \grammarterm{init-declarator-list} of the \grammarterm{simple-declaration} or +the \grammarterm{member-declarator-list} of the \grammarterm{member-declaration} +shall not be empty (except for an anonymous union declared in a namespace scope\iref{class.union.anon}). +The \grammarterm{storage-class-specifier} applies to the name declared by each \grammarterm{init-declarator} in the list and not to any names declared by other specifiers. \begin{note} @@ -720,7 +720,7 @@ \pnum In an \grammarterm{explicit-specifier}, the \grammarterm{constant-expression}, if supplied, shall be a -contextually converted constant expression of type \tcode{bool}\iref{expr.const}. +contextually converted constant expression of type \tcode{bool}\iref{expr.const.const}. The \grammarterm{explicit-specifier} \keyword{explicit} without a \grammarterm{constant-expression} is equivalent to the \grammarterm{explicit-specifier} \tcode{explicit(true)}. @@ -740,6 +740,8 @@ \rSec2[dcl.typedef]{The \keyword{typedef} specifier}% \indextext{specifier!\idxcode{typedef}} +\indextext{declaration!\idxcode{typedef}}% +\indextext{declaration!\idxcode{typedef}|see{alias, type}}% \pnum Declarations containing the \grammarterm{decl-specifier} \keyword{typedef} declare \defnadjx{type}{aliases}{alias}. @@ -764,7 +766,6 @@ The underlying entity of the type alias is the type associated with the \grammarterm{identifier}\iref{dcl.decl} or \grammarterm{simple-template-id}\iref{temp.pre}. -\indextext{declaration!typedef@\tcode{typedef} as type}% \indextext{equivalence!type}% A \grammarterm{typedef-name} does not introduce a new type the way a class declaration\iref{class.name} or enum declaration\iref{dcl.enum} does. @@ -918,7 +919,7 @@ : x(a), y(x) // OK, definition { square(x); } constexpr pixel small(2); // error: \tcode{square} not defined, so \tcode{small(2)} - // not constant\iref{expr.const} so \keyword{constexpr} not satisfied + // not constant\iref{expr.const.core} so \keyword{constexpr} not satisfied constexpr void square(int &x) { // OK, definition x *= x; @@ -938,7 +939,7 @@ a \defnx{constexpr function}{specifier!\idxcode{constexpr}!function}. \begin{note} A function declared with the \keyword{consteval} specifier -is an immediate function\iref{expr.const}. +is an immediate function\iref{expr.const.imm}. \end{note} A destructor, an allocation function, or a deallocation function shall not be declared with the \keyword{consteval} specifier. @@ -992,7 +993,7 @@ \begin{itemize} \item an invocation of a constexpr function -can appear in a constant expression\iref{expr.const} and +can appear in a constant expression\iref{expr.const.core} and \item copy elision is not performed in a constant expression\iref{class.copy.elision}. \end{itemize} @@ -1026,7 +1027,7 @@ Such an object shall have literal type and shall be initialized. -A \keyword{constexpr} variable shall be constant-initializable\iref{expr.const}. +A \keyword{constexpr} variable shall be constant-initializable\iref{expr.const.init}. 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. @@ -1123,7 +1124,7 @@ \end{note} \pnum -The inline specifier indicates to +The \keyword{inline} specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at @@ -1232,13 +1233,6 @@ \grammarterm{cv-qualifier} shall appear in a complete \grammarterm{type-specifier-seq} or a complete \grammarterm{decl-specifier-seq}. -\begin{footnote} -There is no special -provision for a \grammarterm{decl-specifier-seq} that -lacks a \grammarterm{type-specifier} or that has a -\grammarterm{type-specifier} that only specifies \grammarterm{cv-qualifier}{s}. -The ``implicit int'' rule of C is no longer supported. -\end{footnote} \pnum \begin{note} @@ -1265,9 +1259,10 @@ There are two \grammarterm{cv-qualifier}{s}, \keyword{const} and \tcode{volatile}. Each \grammarterm{cv-qualifier} shall appear at most once in a \grammarterm{cv-qualifier-seq}. If a \grammarterm{cv-qualifier} appears in a -\grammarterm{decl-specifier-seq}, the \grammarterm{init-declarator-list} -or \grammarterm{member-declarator-list} of -the declaration shall not be empty. +\grammarterm{decl-specifier-seq}, +the \grammarterm{init-declarator-list} of the \grammarterm{simple-declaration} or +the \grammarterm{member-declarator-list} of the \grammarterm{member-declaration} +shall not be empty. \begin{note} \ref{basic.type.qualifier} and \ref{dcl.fct} describe how cv-qualifiers affect object and function types. @@ -1281,7 +1276,7 @@ \pnum \begin{note} Declaring a variable \keyword{const} can affect its linkage\iref{dcl.stc} -and its usability in constant expressions\iref{expr.const}. As +and its usability in constant expressions\iref{expr.const.init}. As described in~\ref{dcl.init}, the definition of an object or subobject of const-qualified type must specify an initializer or be subject to default-initialization. @@ -1451,8 +1446,14 @@ if any, shall be non-dependent and the \grammarterm{template-name} or \grammarterm{splice-specifier} shall designate a deducible template. -A \defnadj{deducible}{template} is either a class template or -is an alias template whose \grammarterm{defining-type-id} is of the form +A \defnadj{deducible}{template} is +\begin{itemize} +\item +a class template, +\item +a type template template parameter, or +\item +an alias template \tcode{A} whose \grammarterm{defining-type-id} is of the form \begin{ncsimplebnf} \opt{\keyword{typename}} \opt{nested-name-specifier} \opt{\keyword{template}} simple-template-id @@ -1460,7 +1461,9 @@ where the \grammarterm{nested-name-specifier} (if any) is non-dependent and the \grammarterm{template-name} of the \grammarterm{simple-template-id} -names a deducible template. +names a deducible template +other than a type template template parameter of \tcode{A}. +\end{itemize} \begin{note} An injected-class-name is never interpreted as a \grammarterm{template-name} in contexts where class template argument deduction would be performed\iref{temp.local}. @@ -1544,11 +1547,11 @@ \pnum The \grammarterm{typedef-name} $P$ in a \grammarterm{pack-index-specifier} -shall denote a pack. +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} +a converted constant expression\iref{expr.const.const} of type \tcode{std::size_t} whose value $V$, termed the index, is such that $0 \le V < \tcode{sizeof...($P$)}$. @@ -1762,7 +1765,7 @@ \pnum If the operand of a \grammarterm{decltype-specifier} is a prvalue -and is not a (possibly parenthesized) immediate invocation\iref{expr.const}, +and is not a (possibly parenthesized) immediate invocation\iref{expr.const.imm}, the temporary materialization conversion is not applied\iref{conv.rval} and no result object is provided for the prvalue. The type of the prvalue may be incomplete or an abstract class type. @@ -1866,7 +1869,8 @@ \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; +in the declared return type of a function declarator +that declares a function other than a conversion function\iref{class.conv.fct}; 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}. @@ -2183,7 +2187,11 @@ \opt{\grammarterm{type-constraint}} \keyword{auto} either with a new invented type template parameter \tcode{U} or, if the initialization is copy-list-initialization, with -\tcode{std::initializer_list}. Deduce a value for \tcode{U} using the rules +\tcode{std::initializer_list}. +If $E$ is a value synthesized for a constant template parameter +of type \tcode{decltype(auto)}\iref{temp.func.order}, +the declaration is ill-formed. +Otherwise, deduce a value for \tcode{U} using the rules of template argument deduction from a function call\iref{temp.deduct.call}, where \tcode{P} is a function template parameter type and @@ -2411,8 +2419,10 @@ \end{note} \pnum -Each \grammarterm{init-declarator} or \grammarterm{member-declarator} -in a declaration is analyzed separately as if it were in a declaration by itself. +Each \grammarterm{init-declarator} of a \grammarterm{simple-declaration} +or \grammarterm{member-declarator} of a \grammarterm{member-declaration} +is analyzed separately as if it were in a +\grammarterm{simple-declaration} or \grammarterm{member-declaration} by itself. \begin{note} A declaration with several declarators is usually equivalent to the corresponding sequence of declarations each with a single declarator. That is, @@ -2715,19 +2725,19 @@ \begin{codeblock} template struct X {}; template struct Y {}; -X a; // type-id +X a; // \grammarterm{type-id} X b; // expression (ill-formed) -Y c; // type-id (ill-formed) +Y c; // \grammarterm{type-id} (ill-formed) Y d; // expression void foo(signed char a) { - sizeof(int()); // type-id (ill-formed) + sizeof(int()); // \grammarterm{type-id} (ill-formed) sizeof(int(a)); // expression - sizeof(int(unsigned(a))); // type-id (ill-formed) + sizeof(int(unsigned(a))); // \grammarterm{type-id} (ill-formed) - (int())+1; // type-id (ill-formed) + (int())+1; // \grammarterm{type-id} (ill-formed) (int(a))+1; // expression - (int(unsigned(a)))+1; // type-id (ill-formed) + (int(unsigned(a)))+1; // \grammarterm{type-id} (ill-formed) } typedef struct BB { int C[2]; } *B, C; @@ -2947,7 +2957,7 @@ specifier or an \grammarterm{explicit-specifier} applies directly to each \grammarterm{declarator-id} -in a declaration; +in a \grammarterm{simple-declaration} or \grammarterm{member-declaration}; the type specified for each \grammarterm{declarator-id} depends on both the \grammarterm{decl-specifier-seq} and its \grammarterm{declarator}. @@ -3472,7 +3482,7 @@ the type of the \grammarterm{declarator-id} in \tcode{D} is ``\placeholder{derived-declarator-type-list} array of \tcode{N} \tcode{T}''. The \grammarterm{constant-expression} -shall be a converted constant expression of type \tcode{std::size_t}\iref{expr.const}. +shall be a converted constant expression of type \tcode{std::size_t}\iref{expr.const.const}. \indextext{bound, of array}% Its value \tcode{N} specifies the \defnx{array bound}{array!bound}, i.e., the number of elements in the array; @@ -3545,6 +3555,8 @@ of \tcode{N} subobjects of type \tcode{U}, known as the \defnx{elements}{array!element} of the array, and numbered \tcode{0} to \tcode{N-1}. +The element numbered \tcode{0} is termed +the \defnx{first element}{array!first element} of the array. \pnum In addition to declarations in which an incomplete object type is allowed, @@ -3870,6 +3882,10 @@ \end{codeblock} \end{example} +\pnum +A function with a parameter-type-list that has an ellipsis +is termed a \defnadj{vararg}{function}. + \pnum An \defn{explicit-object-parameter-declaration} is a \grammarterm{parameter-declaration} with a \keyword{this} specifier. @@ -4260,10 +4276,10 @@ \indextext{declaration!default argument|(} \pnum -If an \grammarterm{initializer-clause}{} is specified in a -\grammarterm{parameter-declaration}{} this -\grammarterm{initializer-clause}{} -is used as a default argument. +If an \grammarterm{initializer-clause} is specified in a +\grammarterm{parameter-declaration} that is not a +\grammarterm{template-parameter}\iref{temp.param}, +this \grammarterm{initializer-clause} is used as a default argument. \begin{note} Default arguments will be used in calls where trailing arguments are missing\iref{expr.call}. @@ -4294,15 +4310,10 @@ A default argument shall be specified only in the \grammarterm{parameter-declaration-clause} of a function declaration -or \grammarterm{lambda-declarator} -or in a -\grammarterm{template-parameter}\iref{temp.param}. +or \grammarterm{lambda-declarator}. A default argument shall not be specified for -a template parameter pack or a function parameter pack. -If it is specified in a -\grammarterm{parameter-declaration-clause}, -it shall not occur within a +A default argument shall not occur within a \grammarterm{declarator} or \grammarterm{abstract-declarator} @@ -4382,7 +4393,7 @@ The names in the default argument are looked up, and the semantic constraints are checked, at the point where the default argument appears, except that -an immediate invocation\iref{expr.const} that +an immediate invocation\iref{expr.const.imm} that is a potentially-evaluated subexpression\iref{intro.execution} of the \grammarterm{initializer-clause} in a \grammarterm{parameter-declaration} is neither evaluated @@ -4477,7 +4488,7 @@ A default argument is evaluated each time the function is called with no argument for the corresponding parameter. \indextext{argument!scope of default}% -A parameter shall not appear as a potentially-evaluated expression +A parameter shall not appear as a potentially evaluated expression in a default argument. \indextext{argument and name hiding!default}% \begin{note} @@ -5094,32 +5105,38 @@ \end{itemize} \pnum -A class type \tcode{T} is \defn{const-default-constructible} if +A type \cv{}~\tcode{T} is \defn{const-default-constructible} if +\begin{itemize} +\item +\tcode{T} is \tcode{std::meta::info}; +\item +\tcode{T} is \tcode{std::nullptr_t}; +\item default-initialization of \tcode{T} would invoke -a user-provided constructor of \tcode{T} (not inherited from a base class) -or if +a user-provided constructor of \tcode{T} (not inherited from a base class); +\item +\tcode{T} is a class type where \begin{itemize} \item -each direct non-variant non-static data member \tcode{M} of \tcode{T} -has a default member initializer -or, if \tcode{M} is of class type \tcode{X} (or array thereof), -\tcode{X} is const-default-constructible, +each direct non-variant non-static data member of \tcode{T} +has a default member initializer or +is of const-default-constructible type, \item if \tcode{T} is a union with at least one non-static data member, exactly one variant member has a default member initializer, \item if \tcode{T} is not a union, -for each anonymous union member with at least one non-static data member (if any), -exactly one non-static data member has a default member initializer, and +the type of each anonymous union member is const-default-constructible, and +\item +each potentially constructed base class of \tcode{T} is const-default-constructible; or +\end{itemize} \item -each potentially constructed base class of \tcode{T} is const-default-constructible. +\tcode{T} is an array of const-default-constructible type. \end{itemize} If a program calls for the default-initialization of an object of a const-qualified type \tcode{T}, -\tcode{T} shall be \tcode{std::meta::\linebreak info} -or a const-default-constructible class type, -or array thereof. +\tcode{T} shall be a const-default-constructible type. \pnum To @@ -5407,7 +5424,7 @@ \end{itemize} \pnum -An immediate invocation\iref{expr.const} that is not evaluated where +An immediate invocation\iref{expr.const.imm} 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 @@ -5427,7 +5444,8 @@ function arguments or return values\iref{class.temporary}. \pnum -If the initializer is a parenthesized \grammarterm{expression-list}, +If the destination type is not an aggregate +and the initializer is a parenthesized \grammarterm{expression-list}, the expressions are evaluated in the order specified for function calls\iref{expr.call}. @@ -5437,8 +5455,13 @@ \grammarterm{designated-initializer-list}. \pnum -An object whose initialization has completed -is deemed to be constructed, +The \defnadj{deemed}{construction} of an object occurs when +its initialization completes; +for the purposes of~\ref{basic.start.term}, +if the initialization is a full-expression, +deemed construction occurs when +the evaluation of that full-expression completes. +The object is deemed to be constructed, even if the object is of non-class type or no constructor of the object's class is invoked for the initialization. @@ -7081,7 +7104,7 @@ 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}. +or needed for constant evaluation\iref{expr.const.defns}. \begin{note} The implicit definition of a non-user-provided defaulted function does not bind any names. @@ -7133,7 +7156,7 @@ This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not -potentially-evaluated. For an overload set, only the +potentially evaluated. For an overload set, only the 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. @@ -7710,11 +7733,10 @@ names a complete class type with a member named \tcode{value}, the expression \tcode{std::tuple_size::value} shall be a well-formed integral constant expression -and -the structured binding size of \tcode{E} is equal to the value of that -expression. +whose value is non-negative; +the structured binding size of \tcode{E} is equal to that value. Let \tcode{i} be an index prvalue of type \tcode{std::size_t} -corresponding to $\tcode{v}_i$. +corresponding to $\textrm{SB}_i$. If a search for the name \tcode{get} in the scope of \tcode{E}\iref{class.member.lookup} finds at least one declaration @@ -7731,10 +7753,10 @@ is an lvalue reference and an xvalue otherwise. Given the type $\tcode{T}_i$ designated by \tcode{std::tuple_element::type} and -the type $\tcode{U}_i$ designated by -either \tcode{$\tcode{T}_i$\&} or \tcode{$\tcode{T}_i$\&\&}, -where $\tcode{U}_i$ is an lvalue reference if -the initializer is an lvalue and an rvalue reference otherwise, +the type $\tcode{U}_i$ defined +as $\tcode{T}_i$ if the initializer is a prvalue, +as ``lvalue reference to $\tcode{T}_i$'' if the initializer is an lvalue, or +as ``rvalue reference to $\tcode{T}_i$'' otherwise, variables are introduced with unique names $\tcode{r}_i$ as follows: \begin{ncbnf} @@ -7959,7 +7981,7 @@ type and the \grammarterm{constant-expression} in the \grammarterm{enumerator-definition} shall be a converted constant expression of the underlying -type\iref{expr.const}. +type\iref{expr.const.const}. If the underlying type is not fixed, the type of each enumerator prior to the closing brace is determined as @@ -7969,7 +7991,7 @@ \item If an initializer is specified for an enumerator, the \grammarterm{constant-expression} shall be an integral constant -expression\iref{expr.const}. If the expression has +expression\iref{expr.const.const}. If the expression has unscoped enumeration type, the enumerator has the underlying type of that enumeration type, otherwise it has the same type as the expression. @@ -8793,14 +8815,14 @@ \grammarterm{using-declaration} cannot refer to a destructor for a base class. \end{note} -If a constructor or assignment operator brought from a base class into a derived class -has the signature of a copy/move constructor or assignment operator -for the derived class\iref{class.copy.ctor,class.copy.assign}, -the \grammarterm{using-declaration} does not by itself -suppress the implicit declaration of the derived class member; -the member from the base class is hidden or overridden -by the implicitly-declared copy/move constructor or assignment operator -of the derived class, as described below. +\begin{note} +A \grammarterm{using-declarator} that +names a member function of a base class +does not suppress the implicit declaration of a special member function +in the derived class, +even if their signatures are the +same\iref{class.default.ctor, class.copy.ctor, class.copy.assign}. +\end{note} \pnum A \grammarterm{using-declaration} shall not name a \grammarterm{template-id}. @@ -8963,9 +8985,9 @@ \indextext{name hiding!using-declaration and}% The set of declarations named by a \grammarterm{using-declarator} that inhabits a class \tcode{C} does not include -member functions and member function templates of a base class -that correspond to (and thus would conflict with) -a declaration of a function or function template in \tcode{C}. +member functions and member function templates of a base class that, +when considered as members of \tcode{C}, +correspond to a declaration of a function or function template in \tcode{C}. \begin{example} \begin{codeblock} struct B { @@ -8973,6 +8995,8 @@ virtual void f(char); void g(int); void h(int); + void i(); + void j(); }; struct D : B { @@ -8984,6 +9008,12 @@ using B::h; void h(int); // OK, \tcode{D::h(int)} hides \tcode{B::h(int)} + + using B::i; + void i(this B &); // OK + + using B::j; + void j(this D &); // OK, \tcode{D::j()} hides \tcode{B::j()} }; void k(D* p) @@ -8992,6 +9022,8 @@ p->f('a'); // calls \tcode{B::f(char)} p->g(1); // calls \tcode{B::g(int)} p->g('a'); // calls \tcode{D::g(char)} + p->i(); // calls \tcode{B::i}, because \tcode{B::i} as a member of \tcode{D} is a better match than \tcode{D::i} + p->j(); // calls \tcode{D::j} } struct B1 { @@ -9492,6 +9524,13 @@ \grammarterm{attribute-token}. The \grammarterm{attribute-token} determines additional requirements on the \grammarterm{attribute-argument-clause} (if any). +\pnum +\begin{note} +Unless otherwise specified, +an \grammarterm{attribute-token} specified in this document cannot be used +as a macro name\iref{cpp.replace.general}. +\end{note} + \pnum An \grammarterm{annotation} followed by an ellipsis is a pack expansion\iref{temp.variadic}. @@ -9791,6 +9830,9 @@ the next statement shall be part of the same execution of the substatement of the innermost enclosing iteration statement. The program is ill-formed if there is no such statement. +The innermost enclosing \tcode{switch} statement +of a fallthrough statement $S$ shall be contained in +the innermost enclosing expansion statement\iref{stmt.expand} of $S$, if any. \pnum \recommended @@ -10058,7 +10100,7 @@ \pnum \recommended Appearance of a nodiscard call as -a potentially-evaluated discarded-value expression\iref{expr.prop} +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. @@ -10196,15 +10238,47 @@ \indextext{attribute!annotations} \pnum -An annotation may be applied to any declaration of a +An annotation may be applied +to a \grammarterm{base-specifier} or +to a declaration $D$ of a type, type alias, variable, function, +function parameter of non-\tcode{void} type, namespace, -enumerator, -\grammarterm{base-specifier}, or -non-static data member. +enumerator, or +non-static data member, +unless +\begin{itemize} +\item the host scope of $X$ differs from its target scope or +\item $X$ is a non-defining friend declaration, +\end{itemize} +where $X$ is +\begin{itemize} +\item +$D'$ if $D$ is a function parameter declaration in +a function declarator\iref{dcl.fct} of a function declaration $D'$ and +\item $D$ otherwise. +\end{itemize} +\begin{note} +An annotation on a \grammarterm{parameter-declaration} in a function definition +applies to both the function parameter and the variable. +\begin{example} +\begin{codeblock} +void f([[=1]] int x); +void f([[=2]] int y) { + constexpr auto rp = parameters_of(@\reflexpr{f}@)[0]; + constexpr auto ry = variable_of(rp); + static_assert(ry == ^^y); + + static_assert(annotations_of(rp).size() == 2); // both \tcode{[1, 2]} + static_assert(annotations_of(ry).size() == 1); // just \tcode{[2]} + static_assert(annotations_of(rp)[1] == annotations_of(ry)[0]); +} +\end{codeblock} +\end{example} +\end{note} \pnum Let $E$ be the expression @@ -10213,11 +10287,8 @@ the result of $E$ is the \defnadj{underlying}{constant} of the annotation. \pnum -Each \grammarterm{annotation} produces a unique annotation. - -\pnum -Substituting into an \grammarterm{annotation} -is not in the immediate context. +Each \grammarterm{annotation} or instantiation thereof +produces a unique annotation. \begin{example} \begin{codeblock} [[=1]] void f(); @@ -10231,6 +10302,16 @@ \end{example} \begin{example} \begin{codeblock} +template int x [[=1]]; +static_assert(annotations_of(^^x<0>) != annotations_of(^^x<1>)); // OK +\end{codeblock} +\end{example} + +\pnum +Substituting into an \grammarterm{annotation} +is not in the immediate context. +\begin{example} +\begin{codeblock} template [[=T::type()]] void f(T t); diff --git a/source/diagnostics.tex b/source/diagnostics.tex index be2b863f7d..d842475bd9 100644 --- a/source/diagnostics.tex +++ b/source/diagnostics.tex @@ -495,8 +495,11 @@ \pnum If \mname{VA_ARGS} does not expand to -an \grammarterm{assignment-expression}, +a well-formed \grammarterm{assignment-expression}, the program is ill-formed. +If such an \grammarterm{assignment-expression} is ill-formed when +treated as an unevaluated operand\iref{expr.await, expr.yield}, +the program is ill-formed, no diagnostic required. \pnum The macro \tcode{assert} is redefined according to @@ -656,80 +659,80 @@ struct @\libglobal{is_error_condition_enum}@ : public false_type {}; enum class @\libglobal{errc}@ { // freestanding - address_family_not_supported, // \tcode{EAFNOSUPPORT} - address_in_use, // \tcode{EADDRINUSE} - address_not_available, // \tcode{EADDRNOTAVAIL} - already_connected, // \tcode{EISCONN} - argument_list_too_long, // \tcode{E2BIG} - argument_out_of_domain, // \tcode{EDOM} - bad_address, // \tcode{EFAULT} - bad_file_descriptor, // \tcode{EBADF} - bad_message, // \tcode{EBADMSG} - broken_pipe, // \tcode{EPIPE} - connection_aborted, // \tcode{ECONNABORTED} - connection_already_in_progress, // \tcode{EALREADY} - connection_refused, // \tcode{ECONNREFUSED} - connection_reset, // \tcode{ECONNRESET} - cross_device_link, // \tcode{EXDEV} - destination_address_required, // \tcode{EDESTADDRREQ} - device_or_resource_busy, // \tcode{EBUSY} - directory_not_empty, // \tcode{ENOTEMPTY} - executable_format_error, // \tcode{ENOEXEC} - file_exists, // \tcode{EEXIST} - file_too_large, // \tcode{EFBIG} - filename_too_long, // \tcode{ENAMETOOLONG} - function_not_supported, // \tcode{ENOSYS} - host_unreachable, // \tcode{EHOSTUNREACH} - identifier_removed, // \tcode{EIDRM} - illegal_byte_sequence, // \tcode{EILSEQ} - inappropriate_io_control_operation, // \tcode{ENOTTY} - interrupted, // \tcode{EINTR} - invalid_argument, // \tcode{EINVAL} - invalid_seek, // \tcode{ESPIPE} - io_error, // \tcode{EIO} - is_a_directory, // \tcode{EISDIR} - message_size, // \tcode{EMSGSIZE} - network_down, // \tcode{ENETDOWN} - network_reset, // \tcode{ENETRESET} - network_unreachable, // \tcode{ENETUNREACH} - no_buffer_space, // \tcode{ENOBUFS} - no_child_process, // \tcode{ECHILD} - no_link, // \tcode{ENOLINK} - no_lock_available, // \tcode{ENOLCK} - no_message, // \tcode{ENOMSG} - no_protocol_option, // \tcode{ENOPROTOOPT} - no_space_on_device, // \tcode{ENOSPC} - 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_connected, // \tcode{ENOTCONN} - not_enough_memory, // \tcode{ENOMEM} - not_supported, // \tcode{ENOTSUP} - operation_canceled, // \tcode{ECANCELED} - operation_in_progress, // \tcode{EINPROGRESS} - operation_not_permitted, // \tcode{EPERM} - operation_not_supported, // \tcode{EOPNOTSUPP} - operation_would_block, // \tcode{EWOULDBLOCK} - owner_dead, // \tcode{EOWNERDEAD} - permission_denied, // \tcode{EACCES} - protocol_error, // \tcode{EPROTO} - protocol_not_supported, // \tcode{EPROTONOSUPPORT} - read_only_file_system, // \tcode{EROFS} - resource_deadlock_would_occur, // \tcode{EDEADLK} - resource_unavailable_try_again, // \tcode{EAGAIN} - result_out_of_range, // \tcode{ERANGE} - state_not_recoverable, // \tcode{ENOTRECOVERABLE} - text_file_busy, // \tcode{ETXTBSY} - timed_out, // \tcode{ETIMEDOUT} - too_many_files_open_in_system, // \tcode{ENFILE} - too_many_files_open, // \tcode{EMFILE} - too_many_links, // \tcode{EMLINK} - too_many_symbolic_link_levels, // \tcode{ELOOP} - value_too_large, // \tcode{EOVERFLOW} - wrong_protocol_type, // \tcode{EPROTOTYPE} + @\libmember{address_family_not_supported}{errc}@, // \tcode{EAFNOSUPPORT} + @\libmember{address_in_use}{errc}@, // \tcode{EADDRINUSE} + @\libmember{address_not_available}{errc}@, // \tcode{EADDRNOTAVAIL} + @\libmember{already_connected}{errc}@, // \tcode{EISCONN} + @\libmember{argument_list_too_long}{errc}@, // \tcode{E2BIG} + @\libmember{argument_out_of_domain}{errc}@, // \tcode{EDOM} + @\libmember{bad_address}{errc}@, // \tcode{EFAULT} + @\libmember{bad_file_descriptor}{errc}@, // \tcode{EBADF} + @\libmember{bad_message}{errc}@, // \tcode{EBADMSG} + @\libmember{broken_pipe}{errc}@, // \tcode{EPIPE} + @\libmember{connection_aborted}{errc}@, // \tcode{ECONNABORTED} + @\libmember{connection_already_in_progress}{errc}@, // \tcode{EALREADY} + @\libmember{connection_refused}{errc}@, // \tcode{ECONNREFUSED} + @\libmember{connection_reset}{errc}@, // \tcode{ECONNRESET} + @\libmember{cross_device_link}{errc}@, // \tcode{EXDEV} + @\libmember{destination_address_required}{errc}@, // \tcode{EDESTADDRREQ} + @\libmember{device_or_resource_busy}{errc}@, // \tcode{EBUSY} + @\libmember{directory_not_empty}{errc}@, // \tcode{ENOTEMPTY} + @\libmember{executable_format_error}{errc}@, // \tcode{ENOEXEC} + @\libmember{file_exists}{errc}@, // \tcode{EEXIST} + @\libmember{file_too_large}{errc}@, // \tcode{EFBIG} + @\libmember{filename_too_long}{errc}@, // \tcode{ENAMETOOLONG} + @\libmember{function_not_supported}{errc}@, // \tcode{ENOSYS} + @\libmember{host_unreachable}{errc}@, // \tcode{EHOSTUNREACH} + @\libmember{identifier_removed}{errc}@, // \tcode{EIDRM} + @\libmember{illegal_byte_sequence}{errc}@, // \tcode{EILSEQ} + @\libmember{inappropriate_io_control_operation}{errc}@, // \tcode{ENOTTY} + @\libmember{interrupted}{errc}@, // \tcode{EINTR} + @\libmember{invalid_argument}{errc}@, // \tcode{EINVAL} + @\libmember{invalid_seek}{errc}@, // \tcode{ESPIPE} + @\libmember{io_error}{errc}@, // \tcode{EIO} + @\libmember{is_a_directory}{errc}@, // \tcode{EISDIR} + @\libmember{message_size}{errc}@, // \tcode{EMSGSIZE} + @\libmember{network_down}{errc}@, // \tcode{ENETDOWN} + @\libmember{network_reset}{errc}@, // \tcode{ENETRESET} + @\libmember{network_unreachable}{errc}@, // \tcode{ENETUNREACH} + @\libmember{no_buffer_space}{errc}@, // \tcode{ENOBUFS} + @\libmember{no_child_process}{errc}@, // \tcode{ECHILD} + @\libmember{no_link}{errc}@, // \tcode{ENOLINK} + @\libmember{no_lock_available}{errc}@, // \tcode{ENOLCK} + @\libmember{no_message}{errc}@, // \tcode{ENOMSG} + @\libmember{no_protocol_option}{errc}@, // \tcode{ENOPROTOOPT} + @\libmember{no_space_on_device}{errc}@, // \tcode{ENOSPC} + @\libmember{no_such_device_or_address}{errc}@, // \tcode{ENXIO} + @\libmember{no_such_device}{errc}@, // \tcode{ENODEV} + @\libmember{no_such_file_or_directory}{errc}@, // \tcode{ENOENT} + @\libmember{no_such_process}{errc}@, // \tcode{ESRCH} + @\libmember{not_a_directory}{errc}@, // \tcode{ENOTDIR} + @\libmember{not_a_socket}{errc}@, // \tcode{ENOTSOCK} + @\libmember{not_connected}{errc}@, // \tcode{ENOTCONN} + @\libmember{not_enough_memory}{errc}@, // \tcode{ENOMEM} + @\libmember{not_supported}{errc}@, // \tcode{ENOTSUP} + @\libmember{operation_canceled}{errc}@, // \tcode{ECANCELED} + @\libmember{operation_in_progress}{errc}@, // \tcode{EINPROGRESS} + @\libmember{operation_not_permitted}{errc}@, // \tcode{EPERM} + @\libmember{operation_not_supported}{errc}@, // \tcode{EOPNOTSUPP} + @\libmember{operation_would_block}{errc}@, // \tcode{EWOULDBLOCK} + @\libmember{owner_dead}{errc}@, // \tcode{EOWNERDEAD} + @\libmember{permission_denied}{errc}@, // \tcode{EACCES} + @\libmember{protocol_error}{errc}@, // \tcode{EPROTO} + @\libmember{protocol_not_supported}{errc}@, // \tcode{EPROTONOSUPPORT} + @\libmember{read_only_file_system}{errc}@, // \tcode{EROFS} + @\libmember{resource_deadlock_would_occur}{errc}@, // \tcode{EDEADLK} + @\libmember{resource_unavailable_try_again}{errc}@, // \tcode{EAGAIN} + @\libmember{result_out_of_range}{errc}@, // \tcode{ERANGE} + @\libmember{state_not_recoverable}{errc}@, // \tcode{ENOTRECOVERABLE} + @\libmember{text_file_busy}{errc}@, // \tcode{ETXTBSY} + @\libmember{timed_out}{errc}@, // \tcode{ETIMEDOUT} + @\libmember{too_many_files_open_in_system}{errc}@, // \tcode{ENFILE} + @\libmember{too_many_files_open}{errc}@, // \tcode{EMFILE} + @\libmember{too_many_links}{errc}@, // \tcode{EMLINK} + @\libmember{too_many_symbolic_link_levels}{errc}@, // \tcode{ELOOP} + @\libmember{value_too_large}{errc}@, // \tcode{EOVERFLOW} + @\libmember{wrong_protocol_type}{errc}@, // \tcode{EPROTOTYPE} }; template<> struct is_error_condition_enum : true_type {}; @@ -760,7 +763,7 @@ template constexpr bool @\libglobal{is_error_code_enum_v}@ = is_error_code_enum::value; template - constexpr bool is_error_condition_enum_v = is_error_condition_enum::value; + constexpr bool @\libglobal{is_error_condition_enum_v}@ = is_error_condition_enum::value; } \end{codeblock} @@ -2289,8 +2292,8 @@ \indexlibrarymember{swap}{basic_stacktrace}% \begin{itemdecl} template -void swap(basic_stacktrace& a, basic_stacktrace& b) - noexcept(noexcept(a.swap(b))); + void swap(basic_stacktrace& a, basic_stacktrace& b) + noexcept(noexcept(a.swap(b))); \end{itemdecl} \begin{itemdescr} @@ -2319,7 +2322,7 @@ \indexlibrarymember{to_string}{basic_stacktrace}% \begin{itemdecl} template -string to_string(const basic_stacktrace& st); + string to_string(const basic_stacktrace& st); \end{itemdecl} \begin{itemdescr} diff --git a/source/exceptions.tex b/source/exceptions.tex index 2a4d6d7bd5..df3b639dc0 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -177,7 +177,7 @@ try : i(f(ii)), d(id) { // constructor statements } catch (...) { - // handles exceptions thrown from the ctor-initializer and from the constructor statements + // handles exceptions thrown from the \grammarterm{ctor-initializer} and from the constructor statements } \end{codeblock} \end{example} @@ -556,9 +556,9 @@ \item% a standard pointer conversion\iref{conv.ptr} not involving conversions -to pointers to private or protected or ambiguous classes +to pointers to private or protected or ambiguous classes, \item% -a function pointer conversion\iref{conv.fctptr} +a function pointer conversion\iref{conv.fctptr}, \item% a qualification conversion\iref{conv.qual}, or @@ -781,7 +781,7 @@ \indextext{exception specification!noexcept!constant expression and}% In a \grammarterm{noexcept-specifier}, the \grammarterm{constant-expression}, if supplied, shall be a contextually converted constant expression -of type \keyword{bool}\iref{expr.const}; +of type \keyword{bool}\iref{expr.const.const}; that constant expression is the exception specification of the function type in which the \grammarterm{noexcept-specifier} appears. A \tcode{(} token that follows \keyword{noexcept} is part of the @@ -887,7 +887,7 @@ or \item any of the immediate subexpressions\iref{intro.execution} -of $E$ is potentially-throwing. +of $E$ that is not an unevaluated operand is potentially-throwing. \end{itemize} \pnum @@ -996,7 +996,9 @@ declaration (e.g., an explicit specialization or an overriding virtual function); -\item the function is defined; or +\item the function is defined; + +\item the function is represented by a reflection; or \item the exception specification is needed for a defaulted function that calls the function. @@ -1009,10 +1011,7 @@ \end{note} \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 templated function -is instantiated only when needed. +function is evaluated as described above only when needed. % \indextext{exception specification|)} @@ -1143,7 +1142,7 @@ \item% when \tcode{std::execution::get_parallel_scheduler} is called and -\tcode{std::execution::system_context_replace\-ability::query_parallel_scheduler_backend()} +\tcode{std::execution::parallel_scheduler_re\-placement::query_parallel_scheduler_backend()} returns a null pointer value\iref{exec.par.scheduler}, or \item% diff --git a/source/exec.tex b/source/exec.tex index ad7f167c3c..4f7f72b01c 100644 --- a/source/exec.tex +++ b/source/exec.tex @@ -463,19 +463,25 @@ // \ref{exec.queries}, queries struct @\libglobal{get_domain_t}@ { @\unspec@ }; struct @\libglobal{get_scheduler_t}@ { @\unspec@ }; + struct @\libglobal{get_start_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@ }; + template + struct @\libglobal{get_completion_domain_t}@ { @\unspec@ }; struct get_await_completion_adaptor_t { @\unspec@ }; inline constexpr get_domain_t @\libglobal{get_domain}@{}; inline constexpr get_scheduler_t @\libglobal{get_scheduler}@{}; + inline constexpr get_start_scheduler_t @\libglobal{get_start_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}@{}; + template + constexpr get_completion_domain_t @\libglobal{get_completion_domain}@{}; inline constexpr get_await_completion_adaptor_t get_await_completion_adaptor{}; struct @\libglobal{get_env_t}@ { @\unspec@ }; @@ -484,23 +490,30 @@ template using @\libglobal{env_of_t}@ = decltype(get_env(declval())); + // \ref{exec.domain.indeterminate}, execution domains + template + struct indeterminate_domain; + // \ref{exec.domain.default}, execution domains struct default_domain; // \ref{exec.sched}, schedulers - struct @\libglobal{scheduler_t}@ {}; + struct @\libglobal{scheduler_tag}@ {}; template concept @\libconcept{scheduler}@ = @\seebelow@; // \ref{exec.recv}, receivers - struct @\libglobal{receiver_t}@ {}; + struct @\libglobal{receiver_tag}@ {}; template concept @\libconcept{receiver}@ = @\seebelow@; template - concept @\libconcept{receiver_of}@ = @\seebelow@; + concept @\exposconceptnc{receiver-of}@ = @\seebelownc@; // \expos + + template + concept @\libconcept{inlinable_receiver}@ = @\seebelow@; struct @\libglobal{set_value_t}@ { @\unspec@ }; struct @\libglobal{set_error_t}@ { @\unspec@ }; @@ -511,7 +524,7 @@ inline constexpr set_stopped_t @\libglobal{set_stopped}@{}; // \ref{exec.opstate}, operation states - struct @\libglobal{operation_state_t}@ {}; + struct @\libglobal{operation_state_tag}@ {}; template concept @\libconcept{operation_state}@ = @\seebelow@; @@ -520,7 +533,7 @@ inline constexpr start_t @\libglobal{start}@{}; // \ref{exec.snd}, senders - struct @\libglobal{sender_t}@ {}; + struct @\libglobal{sender_tag}@ {}; template inline constexpr bool enable_sender = @\seebelow@; @@ -535,7 +548,7 @@ concept @\libconcept{dependent_sender}@ = @\seebelow@; template - concept @\libconcept{sender_to}@ = @\seebelow@; + concept @\exposconceptnc{sender-to}@ = @\seebelownc@; // \expos template struct @\exposidnc{type-list}@; // \expos @@ -565,21 +578,15 @@ using @\exposidnc{single-sender-value-type}@ = @\seebelownc@; // \expos template - concept @\exposconcept{single-sender}@ = @\seebelow@; // \expos + concept @\exposconceptnc{single-sender}@ = @\seebelownc@; // \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; + template<@\libconcept{sender}@ Sndr, @\exposconcept{queryable}@ Env> + constexpr decltype(auto) transform_sender(Sndr&& sndr, + const Env& env) noexcept(@\seebelow@); // \ref{exec.snd.apply}, sender algorithm application template @@ -711,9 +718,9 @@ template<@\exposconcept{class-type}@ Promise> struct with_awaitable_senders; - // \ref{exec.affine.on}, coroutine utility \tcode{affine_on} - struct @\libglobal{affine_on_t}@ { @\unspec@ }; - inline constexpr affine_on_t @\libglobal{affine_on}@{}; + // \ref{exec.affine}, coroutine utility \tcode{affine} + struct @\libglobal{affine_t}@ { @\unspec@ }; + inline constexpr affine_t @\libglobal{affine}@{}; // \ref{exec.inline.scheduler}, inline scheduler class @\libglobal{inline_scheduler}@; @@ -729,19 +736,13 @@ template with_error(E) -> with_error; - template<@\libconcept{scheduler}@ Sch> - struct change_coroutine_scheduler { - using type = remove_cvref_t; - type scheduler; - }; - template<@\libconcept{scheduler}@ Sch> - change_coroutine_scheduler(Sch) -> change_coroutine_scheduler; - // \ref{exec.task}, class template \tcode{task} template class @\libglobal{task}@; // \ref{exec.scope.concepts}, scope concepts + template + concept @\libconcept{scope_association}@ = @\seebelow@; template concept @\libconcept{scope_token}@ = @\seebelow@; @@ -755,8 +756,8 @@ class @\libglobal{parallel_scheduler}@; parallel_scheduler get_parallel_scheduler(); - // \ref{exec.sysctxrepl}, namespace \tcode{system_context_replaceability} - namespace @\libglobal{system_context_replaceability}@ { + // \ref{exec.parschedrepl}, namespace \tcode{parallel_scheduler_replacement} + namespace @\libglobal{parallel_scheduler_replacement}@ { struct receiver_proxy; struct bulk_item_receiver_proxy; struct parallel_scheduler_backend; @@ -791,8 +792,7 @@ For type \tcode{Sndr} and pack of types \tcode{Env}, let \tcode{CS} be \tcode{completion_signatures_of_t}. Then \tcode{\exposid{single-sender-value-type}} is ill-formed -if \tcode{CS} is ill-formed or -if \tcode{sizeof...(Env) > 1} is \tcode{true}; +if \tcode{CS} is ill-formed; otherwise, it is an alias for: \begin{itemize} \item @@ -828,6 +828,26 @@ \rSec1[exec.queries]{Queries} +\rSec2[exec.queries.expos]{Query utilities} + +\pnum +Subclause \ref{exec.queries} makes use of the following exposition-only entities. + +\pnum +For subexpressions \tcode{q} and \tcode{tag} and pack \tcode{args}, +let \tcode{\exposid{TRY-QUERY}(q, tag, args...)} be expression-equivalent to +\tcode{\exposid{AS-CONST}(q).query(tag, args...)} +if that expression is well-formed, and +\tcode{\exposid{AS-CONST}(q).query(tag)} otherwise +except that \tcode{args...} is evaluated. + +\pnum +For subexpressions \tcode{q} and \tcode{tag} and pack \tcode{args}, +let \tcode{\exposid{HIDE-SCHED}(q)} be an object \tcode{o} such that +\tcode{o.query(\brk{}tag, args...)} is ill-formed when the decayed type of \tcode{tag} is +\tcode{get_scheduler_t} or \tcode{get_domain_t}, and +\tcode{q.query(tag, args...)} otherwise. + \rSec2[exec.fwd.env]{\tcode{forwarding_query}} \pnum @@ -936,7 +956,14 @@ 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))}. +\tcode{\exposid{MANDATE-NOTHROW}(D())}, +where \tcode{D} is the type of the first +of the following expressions that is well-formed: +\begin{itemize} +\item \tcode{auto(\exposid{AS-CONST}(env).query(get_domain))}. +\item \tcode{get_completion_domain(get_scheduler(env), \exposid{HIDE-SCHED}(env))}. +\item \tcode{default_domain()}, except that \tcode{env} is evaluated. +\end{itemize} \pnum \tcode{forwarding_query(execution::get_domain)} is @@ -951,7 +978,9 @@ 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))}. +\tcode{get_completion_scheduler( +\exposid{MANDATE-NOTHROW}(\exposid{AS-CONST}(env)\brk{}.query(get_scheduler)), +\exposid{HIDE-SCHED}(env))}. \mandates If the expression above is well-formed, @@ -961,6 +990,34 @@ \tcode{forwarding_query(execution::get_scheduler)} is a core constant expression and has value \tcode{true}. +\rSec2[exec.get.start.scheduler]{\tcode{execution::get_start_scheduler}} + +\pnum +\tcode{get_start_scheduler} asks a queryable object +for the scheduler an operation will be or was started on. + +\pnum +The name \tcode{get_start_scheduler} denotes a query object. +For a subexpression \tcode{env}, +\tcode{get_start_scheduler(\brk{}env)} is expression-equivalent to +\tcode{\exposid{MANDATE-NOTHROW}(\exposid{AS-CONST}(env).query(get_start_scheduler))}. + +\mandates +If the expression above is well-formed, +its type satisfies \libconcept{scheduler}. + +\pnum +\tcode{forwarding_query(execution::get_start_scheduler)} +is a core constant expression and has value \tcode{true}. + +\pnum +Given subexpressions \tcode{sndr} and \tcode{rcvr} +such that \tcode{\exposid{sender-to}} is \tcode{true} +and the expression \tcode{get_start_scheduler(get_env(rcvr))} is well-formed, +an operation state that is the result of calling \tcode{connect(sndr, rcvr)} +shall, if it is started, be started on an execution agent +associated with the scheduler \tcode{get_start_scheduler(get_env(rcvr))}. + \rSec2[exec.get.delegation.scheduler]{\tcode{execution::get_delegation_scheduler}} \pnum @@ -1006,16 +1063,12 @@ \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. +\begin{codeblock} +@\exposid{MANDATE-NOTHROW}@(@\exposid{AS-CONST}@(sch).query(get_forward_progress_guarantee)) +\end{codeblock} \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} @@ -1029,34 +1082,72 @@ \rSec2[exec.get.compl.sched]{\tcode{execution::get_completion_scheduler}} \pnum -\tcode{get_completion_scheduler<\exposid{completion-tag>}} obtains +The name \tcode{get_completion_scheduler} denotes a query object template. + +\pnum +Let \exposid{completion-fn} be a completion function\iref{exec.async.ops}; +let \exposid{completion-fn-tag} be +the associated completion tag of \exposid{completion-fn}; +let \tcode{args} and \tcode{envs} be packs of subexpressions; and +let \tcode{sndr} be a subexpression +such that \tcode{\libconcept{sender}} is \tcode{true} and +\tcode{get_completion_scheduler<\exposid{completion-fn-tag}>(get_env(sndr), envs...)} +is well-formed and denotes a scheduler \tcode{sch}. + +\pnum +\tcode{get_completion_scheduler<\exposid{completion-fn-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 +For subexpression \tcode{sch1} and pack \tcode{envs}, +let \tcode{sch2} be +\tcode{\exposid{TRY-QUERY}(sch1, get_completion_scheduler, envs...)} and +let \tcode{\exposid{RECURSE-QUERY}(sch1, envs...)} be +expression-equivalent to \tcode{sch1} +if \tcode{sch2} is ill-formed or +if \tcode{sch1} and \tcode{sch2} have the same type and compare equal; +otherwise, \tcode{\exposid{RECURSE-QUERY}(sch2, envs...)}. + +\pnum +For a subexpression \tcode{q} and pack \tcode{envs}, +the expression \tcode{get_completion_scheduler<\exposid{completion-fn-tag}>(q, envs...)} +is ill-formed if \exposid{completion-fn-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 +Otherwise, the expression +is expression-equivalent to: +\begin{itemize} +\item \begin{codeblock} -@\exposid{MANDATE-NOTHROW}@(@\exposid{AS-CONST}@(q).query(get_completion_scheduler<@\exposid{completion-tag}@>)) +@\exposid{MANDATE-NOTHROW}@(@\exposid{RECURSE-QUERY}@( + @\exposid{TRY-QUERY}@(q, get_completion_scheduler<@\exposid{completion-fn-tag}@>, envs...), envs...)) \end{codeblock} +if that expression is well-formed, +except that \tcode{envs...} is evaluated only once. +\item +Otherwise, \tcode{auto(q)} +if the type of \tcode{q} satisfies \libconcept{scheduler} and +\tcode{envs} is not an empty pack, +except that \tcode{envs...} is evaluated. +\item +Otherwise, \tcode{get_completion_scheduler<\exposid{completion-fn-tag}>(q, envs...)} +is ill-formed. +\end{itemize} \mandates -If the expression above is well-formed, +If \tcode{get_completion_scheduler<\exposid{completion-fn-tag}>(q, envs...)} +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}. +For a type \tcode{Tag}, subexpression \tcode{sndr}, and pack \tcode{envs}, +let \tcode{CS} be +\tcode{completion_signatures_of_t, decltype((envs))...>}. +If both \tcode{get_completion_scheduler(get_env(\newline sndr), envs...)} and +\tcode{CS} are well-formed and +\tcode{CS().\exposid{count-of}(Tag()) == 0} is \tcode{true}, +the program is ill-formed. + +\pnum If an asynchronous operation created by connecting \tcode{sndr} with a receiver \tcode{rcvr} causes the evaluation of \tcode{\exposid{completion-fn}(rcvr, args...)}, @@ -1066,7 +1157,79 @@ \pnum The expression -\tcode{forwarding_query(get_completion_scheduler<\exposid{completion-tag}>)} +\tcode{forwarding_query(get_completion_scheduler<\exposid{completion-fn-tag}>)} +is a core constant expression and has value \tcode{true}. + +\rSec2[exec.get.compl.domain]{\tcode{execution::get_completion_domain}} + +\pnum +\tcode{get_completion_domain<\exposid{completion-tag}>} +obtains the completion domain associated with a completion tag +from a sender's attributes. + +\pnum +The name \tcode{get_completion_domain} denotes a query object template. +For a subexpression \tcode{attrs} and pack \tcode{envs}, +the expression \tcode{get_completion_domain<\exposid{completion-tag}>(attrs, envs...)} +is ill-formed if \exposid{completion-tag} is not one of +\tcode{void}, +\tcode{set_value_t}, +\tcode{set_error_t}, or +\tcode{set_stopped_t}. +Otherwise, the expression is expression-equivalent to +\tcode{\exposid{MANDATE-NOTHROW}(D())}, +where \tcode{D} is: +\begin{itemize} +\item +The type of +\tcode{\exposid{TRY-QUERY}(attrs, get_completion_domain<\exposid{completion-tag}>, envs...)} +if that expression is well-formed. +\item +Otherwise, the type of +\tcode{get_completion_domain(attrs, envs...)} +if \exposid{completion-tag} is \tcode{void}. +\item +Otherwise, the type of +\begin{codeblock} +@\exposidnc{TRY-QUERY}@(get_completion_scheduler<@\exposid{completion-tag}@>(attrs, envs...), + get_completion_domain, envs...) +\end{codeblock} +if that expression is well-formed. +\item +Otherwise, \tcode{default_domain} if +\tcode{\libconcept{scheduler}} is \tcode{true} and +\tcode{envs} is not an empty pack. +\item +Otherwise, \tcode{get_completion_domain<\exposid{completion-tag}>(attrs, envs...)} +is ill-formed. +\end{itemize} + +\pnum +For a type \tcode{Tag}, subexpression \tcode{sndr}, and pack \tcode{envs}, +let \tcode{CS} be +\tcode{completion_signatures_of_t, decltype((envs))...>}. +If both \tcode{get_completion_domain(get_env(sndr), envs...)} and +\tcode{CS} are well-formed and +\tcode{CS().\exposid{count-of}(Tag()) == 0} is \tcode{true}, +the program is ill-formed. + +\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} and \tcode{envs} be packs of subexpressions; and +let \tcode{sndr} be a subexpression such that +\tcode{\libconcept{sender}} is \tcode{true} and +\tcode{get_completion_domain<\exposid{completion-tag}>(get_env(sndr), envs...)} +is well-formed and denotes a domain tag \tcode{D}. +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 of an execution resource +whose associated execution domain tag is \tcode{D}. + +The expression +\tcode{forwarding_query(get_completion_domain<\exposid{completion-tag}>)} is a core constant expression and has value \tcode{true}. \rSec2[exec.get.await.adapt]{\tcode{execution::get_await_completion_adaptor}} @@ -1102,13 +1265,11 @@ namespace std::execution { template concept @\deflibconcept{scheduler}@ = - @\libconcept{derived_from}@::scheduler_concept, scheduler_t> && + @\libconcept{derived_from}@::scheduler_concept, scheduler_tag> && @\exposconcept{queryable}@ && requires(Sch&& sch) { { schedule(std::forward(sch)) } -> @\libconcept{sender}@; - { auto(get_completion_scheduler( - get_env(schedule(std::forward(sch))))) } - -> @\libconcept{same_as}@>; + { get_forward_progress_guarantee(sch) } -> @\libconcept{same_as}@; } && @\libconcept{equality_comparable}@> && @\libconcept{copyable}@>; @@ -1143,24 +1304,50 @@ \pnum For a given scheduler expression \tcode{sch}, -the expression +if the expression \tcode{get_completion_scheduler(get_env(schedule(sch)))} -shall compare equal to \tcode{sch}. +is well-formed, +it 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. +type \tcode{T}, and +pack of subexpressions \tcode{envs}, +the following expressions are either both ill-formed, or +both well-formed with the same type: +\begin{itemize} +\item \tcode{get_completion_domain(sch, envs...)} +\item \tcode{get_completion_domain(get_env(schedule(sch)), envs...)} +\end{itemize} +Likewise, the following expressions are either both ill-formed, or +both well-formed with the same type and value: +\begin{itemize} +\item \tcode{get_completion_scheduler(sch, envs...)} +\item \tcode{get_completion_scheduler(get_env(schedule(sch)), envs...)} +\end{itemize} \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} + +\pnum +The exposition-only \exposconcept{infallible-scheduler} concept +defines the requirements of a scheduler type +whose \tcode{schedule} asynchronous operation +can only complete with \tcode{set_value} unless stop can be requested: +\begin{codeblock} +template + concept @\defexposconcept{infallible-scheduler}@ = + @\libconcept{scheduler}@ && + (@\libconcept{same_as}@, + completion_signatures_of_t())), Env>> || + (!@\libconcept{unstoppable_token}@> && + (@\libconcept{same_as}@, + completion_signatures_of_t())), Env>> || + @\libconcept{same_as}@, + completion_signatures_of_t())), Env>>))); +\end{codeblock} \rSec1[exec.recv]{Receivers} @@ -1170,7 +1357,7 @@ 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 exposition-only concept \exposconcept{receiver-of} 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. @@ -1180,15 +1367,16 @@ namespace std::execution { template concept @\deflibconcept{receiver}@ = - @\libconcept{derived_from}@::receiver_concept, receiver_t> && + @\libconcept{derived_from}@::receiver_concept, receiver_tag> && 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 + @\libconcept{move_constructible}@> && // rvalues are movable, and + @\libconcept{constructible_from}@, Rcvr> && // lvalues are copyable, and + is_nothrow_move_constructible_v>; // no-throw-movable template - concept @\defexposconcept{valid-completion-for}@ = // \expos + concept @\defexposconceptnc{valid-completion-for}@ = // \expos requires (Signature* sig) { [](Tag(*)(Args...)) requires @\exposconcept{callable}@, Args...> @@ -1196,14 +1384,14 @@ }; template - concept @\defexposconcept{has-completions}@ = // \expos + concept @\defexposconceptnc{has-completions}@ = // \expos requires (Completions* completions) { []<@\exposconcept{valid-completion-for}@...Sigs>(completion_signatures*) {}(completions); }; template - concept @\deflibconcept{receiver_of}@ = + concept @\defexposconceptnc{receiver-of}@ = // \expos @\libconcept{receiver}@ && @\exposconcept{has-completions}@; } \end{codeblock} @@ -1228,6 +1416,98 @@ must be destroyed before the invocation of the completion operation. \end{note} +\pnum +\begin{codeblock} +namespace std::execution { + template + concept @\deflibconcept{inlinable_receiver}@ = @\libconcept{receiver}@ && + requires (ChildOp* child) { + { remove_cvref_t::make_receiver_for(child) } noexcept + -> @\libconcept{same_as}@>; + }; +} +\end{codeblock} + +The \libconcept{inlinable_receiver} concept +defines the requirements for a receiver +that can be reconstructed on demand +from a pointer to the operation state object +created when the receiver was connected to a sender. +Given a receiver object \tcode{rcvr} of type \tcode{Rcvr} +which was connected to a sender producing +an operation state object \tcode{op} of type \tcode{Op}, +\tcode{Rcvr} models \tcode{\libconcept{inlinable_receiver}} +only if the expression \tcode{Rcvr::make_receiver_for(addressof(op))} +evaluates to a receiver +that is equal to \tcode{rcvr}\iref{concepts.equality}. +\begin{note} +Such a receiver does not need to be stored as a data member of \tcode{op} +as it can be recreated on demand. +\end{note} +\tcode{ChildOp} may be an incomplete type. + +\pnum +Given objects $O_0, \dotsc, O_n$, +$O_n$ is \defnadj{transitively}{constructed} from $O_0$ if +\begin{itemize} +\item +\tcode{remove_cvref_t} +denotes the same type as +\tcode{remove_cvref_t} and +\item +either +\begin{itemize} +\item +$O_1$ was initialized by decay-copying a reference to $O_0$, or +\item +$n > 1$ and $O_{n-1}$ is transitively constructed from $O_0$ and +$O_n$ was initialized from +a non-const, non-volatile rvalue reference to $O_{n-1}$. +\end{itemize} +\end{itemize} + +\pnum +Let $E$ be some well-formed expression \tcode{connect(sndr, rcvr)}. +$E$ \defn{inlines the receiver} \tcode{rcvr} +if the lifetimes of all objects transitively constructed from +\tcode{rcvr} during the evaluation of $E$ +end within the evaluation of $E$. +\begin{note} +This means such an expression does not store the receiver in the operation state. +\end{note} + +\pnum +Let $E$ be some well-formed expression \tcode{connect(sndr, rcvr)} where +\begin{itemize} +\item +\tcode{sndr} denotes a sender type defined by this document and +\item +$E$ inlines the receiver \tcode{rcvr}. +\end{itemize} +Then, let \tcode{op} be the result of the evaluation of $E$, and +wherever the specification of the operation associated with \tcode{op} +contains a glvalue +which would denote an object transitively constructed from \tcode{rcvr}, +that glvalue instead denotes the result of applying +the temporary materialization conversion to the expression +\tcode{remove_cvref_t::make_receiver_for(addressof(op))}. + +\pnum +Let \tcode{StdRcvr} be a receiver type defined by this document. +Given some operation state type \tcode{Op}, +it is unspecified +whether \tcode{StdRcvr} models \tcode{\libconcept{inlinable_receiver}}. + +\pnum +Let \tcode{StdOp} be some operation state type defined by this document, +and let \tcode{Sndr} and \tcode{Rcvr} be types such that +\tcode{is_same_v, StdOp>} is \tcode{true}. +If \tcode{Rcvr} models \tcode{\libconcept{inlinable_receiver}} +then it is implementation-defined whether, +given an object \tcode{rcvr} of type \tcode{Rcvr}, +the \tcode{connect} operation which produces an object of type \tcode{StdOp} +inlines the receiver \tcode{rcvr}. + \rSec2[exec.set.value]{\tcode{execution::set_value}} \pnum @@ -1240,6 +1520,9 @@ Otherwise, it is expression-equivalent to \tcode{\exposid{MANDATE-NOTHROW}(rcvr.set_value(vs...))}. +\mandates +If the expression above is well-formed, its type is \tcode{void}. + \rSec2[exec.set.error]{\tcode{execution::set_error}} \pnum @@ -1251,6 +1534,9 @@ Otherwise, it is expression-equivalent to \tcode{\exposid{MANDATE-NOTHROW}(rcvr.set_error(err))}. +\mandates +If the expression above is well-formed, its type is \tcode{void}. + \rSec2[exec.set.stopped]{\tcode{execution::set_stopped}} \pnum @@ -1262,6 +1548,9 @@ Otherwise, it is expression-equivalent to \tcode{\exposid{MANDATE-NOTHROW}(rcvr.set_stopped())}. +\mandates +If the expression above is well-formed, its type is \tcode{void}. + \rSec1[exec.opstate]{Operation states} \rSec2[exec.opstate.general]{General} @@ -1273,7 +1562,7 @@ namespace std::execution { template concept @\deflibconcept{operation_state}@ = - @\libconcept{derived_from}@ && + @\libconcept{derived_from}@ && requires (O& o) { start(o); }; @@ -1309,6 +1598,9 @@ Otherwise, it is expression-equivalent to \tcode{\exposid{MANDATE-NOTHROW}(op.start())}. +\mandates +If the expression above is well-formed, its type is \tcode{void}. + \pnum If \tcode{op.start()} does not start\iref{exec.async.ops} the asynchronous operation associated with the operation state \tcode{op}, @@ -1327,13 +1619,15 @@ 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}. +such that \tcode{\exposconcept{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}. + +\pnum Let \tcode{Sigs} be a pack of completion signatures corresponding to this set of completion operations, and let \tcode{CS} be @@ -1345,6 +1639,57 @@ If none of the types in \tcode{Sigs} are dependent on the type \tcode{Env}, then the expression \tcode{get_completion_signatures()} is well-formed and its type is \tcode{CS}. + +\pnum +Each completion operation can potentially be evaluated +on one of several different execution agents +as determined by the semantics of the algorithm, +the environment of the receiver, and +the completions of any child senders. +For a completion tag \tcode{T}, +let $\tcode{Ds}_{\tcode{T}}$ be a pack comprised of the set of domain tags +associated with the execution agents that could potentially evaluate +any of the operation's completions with tag \tcode{T}. +If there are no potentially evaluated completion operations +with tag type \tcode{T}, +then \tcode{get_completion_domain(get_env(sndr), env)} is ill-formed; +otherwise, it has type +\tcode{\exposid{COMMON-DOMAIN}<$\tcode{Ds}_{\tcode{T}}$...>}\iref{exec.snd.expos}. +\begin{example} +Let \tcode{sndr2} be the sender \tcode{then(sndr, fn)}. +\tcode{sndr2} has the same \tcode{set_value} completion domain tag as \tcode{sndr}, +but if \tcode{fn}'s evaluation is potentially throwing, +\tcode{sndr}'s \tcode{set_error} completion domain tag would be +the \exposid{COMMON-DOMAIN} of \tcode{sndr}'s value and error completion domain tags, +in accordance with the semantics of the \tcode{then} algorithm\iref{exec.then}. +\end{example} + +\pnum +If \tcode{sndr} can determine that all of its completion operations +with tag \tcode{T} happen on execution agents +associated with a particular scheduler \tcode{sch} +(as determined by the semantics of the algorithm, +the environment of the receiver, and +the completion schedulers of any child senders), +then \tcode{get_completion_scheduler(get_env(sndr), env)} +is well-formed and has the type and value of \tcode{sch}; +otherwise, it is ill-formed. +\begin{example} +Let \tcode{sndr2} be the sender from the example above. +The \tcode{set_value} completion scheduler of \tcode{sndr2} is +the \tcode{set_value} completion scheduler of \tcode{sndr}, if any. +But \tcode{sndr2} can only report a \tcode{set_error} completion scheduler +when invocations of \tcode{fn} are not potentially throwing or +when \tcode{sndr} has no \tcode{set_error} completions. +When \tcode{fn} can throw, +\tcode{sndr2} could complete with \tcode{set_error} either +by forwarding an error completion from \tcode{sndr} or +by completing with the exception thrown by \tcode{fn}, +which would happen on an agent associated with \tcode{sndr}'s +\tcode{set_value} completion scheduler. +\end{example} + +\pnum If a user-provided implementation of the algorithm that produced \tcode{sndr} is selected instead of the default: @@ -1364,8 +1709,40 @@ shall denote the same type. \end{itemize} +\pnum +\indexlibraryglobal{\tcode{\placeholder{unspecified-exception}}}% +Various function templates in subclause \ref{exec.snd} +can throw an exception of type \exposid{unspecified-exception}. +Each such exception object is of an unspecified type +such that a \grammarterm{handler} of type \tcode{exception} +matches\iref{except.handle} the exception object +but a \grammarterm{handler} of type \tcode{dependent_sender_error} does not. +\begin{note} +There is no requirement that two such exception objects have the same type. +\end{note} + \rSec2[exec.snd.expos]{Exposition-only entities} +\pnum +Given an expression \tcode{sndr}, +whose type is any sender type defined in the standard library, +it is unspecified +whether the expression \tcode{sndr.affine()} is well-formed. +If that expression is well-formed, +then the evaluation thereof meets the semantic requirements of +the \tcode{affine}\iref{exec.affine} algorithm. + +\pnum +Given an expression \tcode{sndr}, +whose type is any sender type defined in the standard library, +and an expression \tcode{p}, +whose type is a promise type, +it is unspecified +whether the expression \tcode{sndr.as_awaitable(p)} is well-formed. +If that expression is well-formed, +then the evaluation thereof meets the semantic requirements of +the \tcode{as_awaitable}\iref{exec.as.awaitable} algorithm. + \pnum Subclause \ref{exec.snd} makes use of the following exposition-only entities. @@ -1384,13 +1761,15 @@ \tcode{decltype(\exposid{FWD-ENV}(declval()))}. \pnum -For a query object \tcode{q} and a subexpression \tcode{v}, +For a query object \tcode{q}, +a subexpression \tcode{v}, and +a pack of subexpressions \tcode{args}, \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 +such that the result of \tcode{env.query(q, args...)} has a value equal to \tcode{v}\iref{concepts.equality}. Unless otherwise stated, -the object to which \tcode{env.query(q)} refers remains valid +the object to which \tcode{env.query(q, args...)} refers remains valid while \tcode{env} remains valid. \pnum @@ -1416,20 +1795,31 @@ with different types and value categories in different contexts for the same arguments. +\pnum +For a pack of subexpressions \tcode{domains}, +\tcode{\exposid{COMMON-DOMAIN}(domains...)} is expression-equivalent to +\tcode{common_type_t()} +if that expression is well-formed, and +\tcode{indeterminate_domain<\brk{}Ds...>()} otherwise, +where \tcode{Ds} is the pack of types consisting of +\tcode{decltype(auto(domains))...} with duplicate types removed. + +\pnum +For a type \tcode{Tag}, subexpression \tcode{sndr}, and pack \tcode{envs}, +\tcode{\exposid{COMPL-DOMAIN}(Tag, sndr, envs)} +is expression-equivalent to \tcode{D()}, +where \tcode{D} is +the type of \tcode{get_completion_domain(get_env(sndr), envs...)} +if that expression is well-formed or \tcode{envs} is an empty pack, and +\tcode{indeterminate_domain()} otherwise. + \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} +\tcode{\exposid{SCHED-ENV}(sch)} is an expression \tcode{o} whose type satisfies \exposconcept{queryable} -such that \tcode{o2.query(get_scheduler)} is a prvalue +such that \tcode{o.query(\brk{}get_start_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 +such that \tcode{o.query(get_domain)} is expression-equivalent to \tcode{sch.query(get_domain)}. \pnum @@ -1453,31 +1843,6 @@ \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}@( @@ -1499,77 +1864,6 @@ The expression in the noexcept clause is \tcode{noexcept(e)}. \end{itemdescr} -\begin{itemdecl} -template - constexpr auto @\exposid{get-domain-early}@(const Sndr& sndr) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return Domain(); -\end{codeblock} -where \tcode{Domain} is -the decayed type of the first of the following expressions that is well-formed: -\begin{itemize} -\item \tcode{get_domain(get_env(sndr))} -\item \tcode{\exposid{completion-domain}(sndr)} -\item \tcode{default_domain()} -\end{itemize} -\end{itemdescr} - -\begin{itemdecl} -template - constexpr auto @\exposid{get-domain-late}@(const Sndr& sndr, const Env& env) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{itemize} -\item -If \tcode{\exposconcept{sender-for}} is \tcode{true}, then -\begin{codeblock} -return Domain(); -\end{codeblock} -where \tcode{Domain} is the type of the following expression: -\begin{codeblock} -[] { - auto [_, sch, _] = sndr; - return @\exposid{query-with-default}@(get_domain, sch, default_domain()); -}(); -\end{codeblock} -\begin{note} -The \tcode{continues_on} algorithm works -in tandem with \tcode{schedule_from}\iref{exec.schedule.from} -to give scheduler authors a way to customize both -how to transition onto (\tcode{continues_on}) and off of (\tcode{schedule_from}) -a given execution context. -Thus, \tcode{continues_on} ignores the domain of the predecessor and -uses the domain of the destination scheduler to select a customization, -a property that is unique to \tcode{continues_on}. -That is why it is given special treatment here. -\end{note} -\item -Otherwise, -\begin{codeblock} -return Domain(); -\end{codeblock} -where \tcode{Domain} is the first of the following expressions -that is well-formed and whose type is not \tcode{void}: -\begin{itemize} -\item \tcode{get_domain(get_env(sndr))} -\item \tcode{\exposid{completion-domain}(sndr)} -\item \tcode{get_domain(env)} -\item \tcode{get_domain(get_scheduler(env))} -\item \tcode{default_domain()} -\end{itemize} -\end{itemize} -\end{itemdescr} - \pnum \begin{codeblock} template<@\exposconcept{callable}@ Fun> @@ -1696,7 +1990,8 @@ \item \tcode{(\libconcept{sender} \&\& ...)} \item% \tcode{\libconcept{dependent_sender} || \libconcept{sender_in}}, -where \tcode{Sndr} is \tcode{\exposid{basic-sender}} +where \tcode{Sndr} is +\tcode{\exposid{basic-sender}, decay_t...>} as defined below. \recommended @@ -1721,26 +2016,9 @@ that models \libconcept{semiregular}. \end{itemdescr} +\pnum \begin{codeblock} namespace std::execution { - template - concept @\defexposconceptnc{completion-tag}@ = // \expos - @\libconcept{same_as}@ || @\libconcept{same_as}@ || @\libconcept{same_as}@; - - struct @\exposidnc{default-impls}@ { // \expos - static constexpr auto @\exposidnc{get-attrs}@ = @\seebelownc@; // \expos - static constexpr auto @\exposidnc{get-env}@ = @\seebelownc@; // \expos - static constexpr auto @\exposidnc{get-state}@ = @\seebelownc@; // \expos - static constexpr auto @\exposidnc{start}@ = @\seebelownc@; // \expos - static constexpr auto @\exposidnc{complete}@ = @\seebelownc@; // \expos - - template - static consteval void @\exposidnc{check-types}@(); // \expos - }; - - template - struct @\exposidnc{impls-for}@ : @\exposidnc{default-impls}@ {}; // \expos - template // \expos using @\exposid{state-type}@ = decay_t<@\exposid{call-result-t}@< decltype(@\exposid{impls-for}@>::@\exposid{get-state}@), Sndr, Rcvr&>>; @@ -1768,110 +2046,68 @@ Rcvr @\exposidnc{rcvr}@; // \expos @\exposidnc{state-type}@ @\exposidnc{state}@; // \expos }; +} +\end{codeblock} +\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 +\begin{codeblock} +namespace std::execution { template requires @\exposconcept{valid-specialization}@<@\exposid{env-type}@, Index, Sndr, Rcvr> struct @\exposidnc{basic-receiver}@ { // \expos - using receiver_concept = receiver_t; + using receiver_concept = receiver_tag; using @\exposidnc{tag-t}@ = tag_of_t; // \expos using @\exposidnc{state-t}@ = @\exposidnc{state-type}@; // \expos static constexpr const auto& @\exposidnc{complete}@ = @\exposidnc{impls-for}@<@\exposidnc{tag-t}@>::@\exposidnc{complete}@; // \expos template - requires @\exposconcept{callable}@ void set_value(Args&&... args) && noexcept { @\exposid{complete}@(Index(), @\exposidnc{op}@->@\exposid{state}@, @\exposidnc{op}@->@\exposid{rcvr}@, set_value_t(), std::forward(args)...); } template - requires @\exposconcept{callable}@ void set_error(Error&& err) && noexcept { @\exposid{complete}@(Index(), @\exposidnc{op}@->@\exposid{state}@, @\exposidnc{op}@->@\exposid{rcvr}@, set_error_t(), std::forward(err)); } - void set_stopped() && noexcept - requires @\exposconcept{callable}@ { + void set_stopped() && noexcept { @\exposid{complete}@(Index(), @\exposidnc{op}@->@\exposid{state}@, @\exposidnc{op}@->@\exposid{rcvr}@, set_stopped_t()); } auto get_env() const noexcept -> @\exposid{env-type}@ { - return @\exposid{impls-for}@::@\exposid{get-env}@(Index(), @\exposidnc{op}@->@\exposid{state}@, @\exposidnc{op}@->@\exposid{rcvr}@); + return @\exposid{impls-for}@<@\exposid{tag-t}@>::@\exposid{get-env}@(Index(), @\exposidnc{op}@->@\exposid{state}@, @\exposidnc{op}@->@\exposid{rcvr}@); } @\exposidnc{basic-state}@* @\exposidnc{op}@; // \expos }; +} +\end{codeblock} +\begin{codeblock} +namespace std::execution { constexpr auto @\exposidnc{connect-all}@ = @\seebelownc@; // \expos template using @\exposidnc{connect-all-result}@ = @\exposidnc{call-result-t}@< // \expos decltype(@\exposid{connect-all}@), @\exposid{basic-state}@*, Sndr, @\exposid{indices-for}@>; - - template - requires @\exposconcept{valid-specialization}@<@\exposid{state-type}@, Sndr, Rcvr> && - @\exposconcept{valid-specialization}@<@\exposid{connect-all-result}@, Sndr, Rcvr> - struct @\exposidnc{basic-operation}@ : @\exposidnc{basic-state}@ { // \expos - using operation_state_concept = operation_state_t; - using @\exposidnc{tag-t}@ = tag_of_t; // \expos - - @\exposidnc{connect-all-result}@ @\exposidnc{inner-ops}@; // \expos - - @\exposidnc{basic-operation}@(Sndr&& sndr, Rcvr&& rcvr) noexcept(@\seebelownc@) // \expos - : @\exposid{basic-state}@(std::forward(sndr), std::move(rcvr)), - @\exposid{inner-ops}@(@\exposid{connect-all}@(this, std::forward(sndr), @\exposid{indices-for}@())) - {} - - void start() & noexcept { - auto& [...ops] = @\exposid{inner-ops}@; - @\exposid{impls-for}@::@\exposid{start}@(this->@\exposid{state}@, this->@\exposid{rcvr}@, ops...); - } - }; - - template - struct @\exposidnc{basic-sender}@ : @\exposidnc{product-type}@ { // \expos - using sender_concept = sender_t; - using @\exposidnc{indices-for}@ = index_sequence_for; // \expos - - decltype(auto) get_env() const noexcept { - auto& [_, data, ...child] = *this; - return @\exposid{impls-for}@::@\exposid{get-attrs}@(data, child...); - } - - template<@\exposconcept{decays-to}@<@\exposid{basic-sender}@> Self, @\libconcept{receiver}@ Rcvr> - auto connect(this Self&& self, Rcvr rcvr) noexcept(@\seebelow@) - -> @\exposid{basic-operation}@ { - return {std::forward(self), std::move(rcvr)}; - } - - template<@\exposconcept{decays-to}@<@\exposid{basic-sender}@> Self, class... Env> - static constexpr auto get_completion_signatures(); - }; } \end{codeblock} -\pnum -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: @@ -1899,29 +2135,53 @@ \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}@())) +namespace std::execution { + template + requires @\exposconcept{valid-specialization}@<@\exposid{state-type}@, Sndr, Rcvr> && + @\exposconcept{valid-specialization}@<@\exposid{connect-all-result}@, Sndr, Rcvr> + struct @\exposidnc{basic-operation}@ : @\exposidnc{basic-state}@ { // \expos + using operation_state_concept = operation_state_tag; + using @\exposidnc{tag-t}@ = tag_of_t; // \expos + + @\exposidnc{connect-all-result}@ @\exposidnc{inner-ops}@; // \expos + + @\exposidnc{basic-operation}@(Sndr&& sndr, Rcvr&& rcvr) noexcept(@\seebelownc@) // \expos + : @\exposid{basic-state}@(std::forward(sndr), std::move(rcvr)), + @\exposid{inner-ops}@(@\exposid{connect-all}@(this, std::forward(sndr), @\exposid{indices-for}@())) + {} + + void start() & noexcept { + auto& [...ops] = @\exposid{inner-ops}@; + @\exposid{impls-for}@<@\exposid{tag-t}@>::@\exposid{start}@(this->@\exposid{state}@, this->@\exposid{rcvr}@, ops...); + } + }; +} \end{codeblock} \pnum The expression in the \tcode{noexcept} clause of -the \tcode{connect} member function of \exposid{basic-sender} is: +the constructor of \exposid{basic-operation} is: \begin{codeblock} -is_nothrow_constructible_v<@\exposid{basic-operation}@, Self, Rcvr> +is_nothrow_constructible_v<@\exposid{basic-state}@, Self, Rcvr> && +noexcept(@\exposid{connect-all}@(this, std::forward(sndr), @\exposid{indices-for}@())) \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<>(); +namespace std::execution { + struct @\exposidnc{default-impls}@ { // \expos + static constexpr auto @\exposidnc{get-env}@ = @\seebelownc@; // \expos + static constexpr auto @\exposidnc{get-state}@ = @\seebelownc@; // \expos + static constexpr auto @\exposidnc{start}@ = @\seebelownc@; // \expos + static constexpr auto @\exposidnc{complete}@ = @\seebelownc@; // \expos + + template + static consteval void @\exposidnc{check-types}@(); // \expos + }; + + template + struct @\exposidnc{impls-for}@ : @\exposidnc{default-impls}@ {}; // \expos } \end{codeblock} @@ -1981,7 +2241,7 @@ \effects Equivalent to: \begin{codeblock} -(get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(), ...); +((void)get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(), ...); \end{codeblock} \pnum @@ -2000,10 +2260,50 @@ \end{note} \end{itemdescr} +\pnum +\begin{codeblock} +namespace std::execution { + template + struct @\exposidnc{basic-sender}@ : @\exposidnc{product-type}@ { // \expos + using sender_concept = sender_tag; + using @\exposidnc{indices-for}@ = index_sequence_for; // \expos + + decltype(auto) get_env() const noexcept { + auto& [_, data, ...child] = *this; + return @\exposid{impls-for}@::@\exposid{get-attrs}@(data, child...); + } + + template<@\exposconcept{decays-to}@<@\exposid{basic-sender}@> Self, @\libconcept{receiver}@ Rcvr> + auto connect(this Self&& self, Rcvr rcvr) noexcept(@\seebelow@) + -> @\exposid{basic-operation}@ { + return {std::forward(self), std::move(rcvr)}; + } + + template<@\exposconcept{decays-to}@<@\exposid{basic-sender}@> Self, class... Env> + static constexpr auto get_completion_signatures(); + }; +} +\end{codeblock} + +\pnum +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 \tcode{connect} member function of \exposid{basic-sender} is: +\begin{codeblock} +is_nothrow_constructible_v<@\exposid{basic-operation}@, Self, Rcvr> +\end{codeblock} + \indexlibrarymember{get_completion_signatures}{\exposid{basic-sender}}% \begin{itemdecl} template - template + template<@\exposconcept{decays-to}@<@\exposid{basic-sender}@> Sndr, class... Env> constexpr auto @\exposid{basic-sender}@::get_completion_signatures(); \end{itemdecl} @@ -2060,7 +2360,7 @@ %%FIXME: Should this be in a namespace? \begin{codeblock} struct @\exposid{not-a-sender}@ { - using sender_concept = sender_t; + using sender_concept = sender_tag; template static consteval auto get_completion_signatures() -> completion_signatures<> { @@ -2068,8 +2368,19 @@ } }; \end{codeblock} -where \tcode{\placeholder{unspecified-exception}} is -a type derived from \tcode{exception}. + +\pnum +\indexlibraryglobal{\exposid{not-a-scheduler}}% +\indexlibrarymember{schedule}{\exposid{not-a-sender}}% +\begin{codeblock} +struct @\exposid{not-a-scheduler}@ { + using scheduler_concept = scheduler_tag; + + constexpr auto schedule() const noexcept { + return @\exposid{not-a-sender}@(); + } +}; +\end{codeblock} \pnum \indexlibraryglobal{\exposid{decay-copyable-result-datums}} @@ -2082,8 +2393,6 @@ }); } \end{codeblock} -where \tcode{\placeholder{unspecified-exception}} is -a type derived from \tcode{exception}. \begin{itemdecl} template @@ -2110,14 +2419,56 @@ otherwise if \tcode{P} is a specialization of \exposid{product-type}, returns an object of type \tcode{P} whose elements are initialized using \begin{codeblock} -make_obj_using_allocator(std::forward_like(e), @\exposid{alloc}@) +make_obj_using_allocator(@\exposid{alloc}@, std::forward_like(e)) \end{codeblock} where \tcode{e} is the corresponding element of \tcode{obj}, \item -otherwise, returns \tcode{make_obj_using_allocator

(std::forward(obj), \exposid{alloc})}. +otherwise, returns \tcode{make_obj_using_allocator

(\exposid{alloc}, std::forward(obj))}. \end{itemize} \end{itemdescr} +\indexlibraryglobal{\exposid{call-with-default}} +\begin{itemdecl} +template + constexpr decltype(auto) @\exposid{call-with-default}@( + Fn&& fn, Default&& value, Args&&... args) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{expr} be the expression +\tcode{std::forward(fn)(std::forward(args)...)} +if that expression is well-formed; +otherwise, it is \tcode{static_cast(std::forward(value))}. + +\pnum +\returns +\tcode{expr}. + +\pnum +\remarks +The expression in the \tcode{noexcept} clause is \tcode{noexcept(expr)}. +\end{itemdescr} + +\pnum +\indexlibraryglobal{\exposid{inline-attrs}}% +\begin{codeblock} +template +struct @\exposid{inline-attrs}@ { + @\seebelow@ +}; +\end{codeblock} + +\pnum +For a subexpression \tcode{env}, +\tcode{\exposid{inline-attrs}\{\}.query(get_completion_scheduler, env)} +is expres\-sion-equivalent to \tcode{get_scheduler(env)}. + +\pnum +For a subexpression \tcode{env}, +\tcode{\exposid{inline-attrs}\{\}.query(get_completion_domain, env)} +is expression-equivalent to \tcode{get_domain(env)}. + \rSec2[exec.snd.concepts]{Sender concepts} \pnum @@ -2126,7 +2477,7 @@ 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 exposition-only concept \exposconcept{sender-to} 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 @@ -2142,7 +2493,7 @@ template concept @\defexposconcept{is-sender}@ = // \expos - @\libconcept{derived_from}@; + @\libconcept{derived_from}@; template concept @\defexposconcept{enable-sender}@ = // \expos @@ -2181,9 +2532,9 @@ @\libconcept{sender}@ && bool_constant<@\exposid{is-dependent-sender-helper}@()>::value; template - concept @\deflibconcept{sender_to}@ = + concept @\defexposconcept{sender-to}@ = // \expos @\libconcept{sender_in}@> && - @\libconcept{receiver_of}@>> && + @\exposconcept{receiver-of}@>> && requires (Sndr&& sndr, Rcvr&& rcvr) { connect(std::forward(sndr), std::forward(rcvr)); }; @@ -2219,7 +2570,7 @@ model \libconcept{sender}, and \tcode{false} for types that do not. Such specializations shall -be usable in constant expressions\iref{expr.const} and +be usable in constant expressions\iref{expr.const.init} and have type \tcode{const bool}. \pnum @@ -2416,75 +2767,103 @@ its members need not be defined. \end{note} -\rSec2[exec.domain.default]{\tcode{execution::default_domain}} +\rSec2[exec.domain.indeterminate]{\tcode{execution::indeterminate_domain}} \pnum +\indexlibraryglobal{indeterminate_domain}% +\indexlibraryctor{indeterminate_domain}% \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 + struct indeterminate_domain { + indeterminate_domain() = default; + constexpr indeterminate_domain(auto&&) noexcept {} - template - static constexpr decltype(auto) apply_sender(Tag, Sndr&& sndr, Args&&... args) + template + static constexpr decltype(auto) transform_sender(Tag, Sndr&& sndr, const Env& env) noexcept(@\seebelow@); }; } \end{codeblock} -\indexlibrarymember{transform_sender}{default_domain}% +\indexlibrarymember{transform_sender}{indeterminate_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@); +template + static constexpr decltype(auto) transform_sender(Tag, Sndr&& sndr, const Env& env) + noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{e} be the expression +\mandates +For each type \tcode{D} in \tcode{Domains...}, +the expression \begin{codeblock} -tag_of_t().transform_sender(std::forward(sndr), env...) +D().transform_sender(Tag(), std::forward(sndr), env) \end{codeblock} -if that expression is well-formed; -otherwise, \tcode{std::forward(sndr)}. +is either ill-formed or has the same decayed type as +\tcode{default_domain().transform_sender(Tag(), std::forward(sndr), env)}. \pnum \returns -\tcode{e}. +\tcode{default_domain().transform_sender(Tag(), std::forward(sndr), env)}. \pnum \remarks -The exception specification is equivalent to \tcode{noexcept(e)}. +For a pack of types \tcode{Ds}, +\begin{codeblock} +common_type_t, indeterminate_domain> +\end{codeblock} +is \tcode{indeterminate_domain} +where \tcode{Us} is a pack that contains each type in +\tcode{Domains..., Ds...} except with duplicate types removed. +For a type \tcode{D} that is not a specialization of \tcode{indeterminate_domain}, +\tcode{common_type_t, D>} +is \tcode{D} if \tcode{Domains} is an empty pack, and +\tcode{common_type_t, indeterminate_domain>} +otherwise. \end{itemdescr} -\indexlibrarymember{transform_env}{default_domain}% +\rSec2[exec.domain.default]{\tcode{execution::default_domain}} + +\pnum +\begin{codeblock} +namespace std::execution { + struct @\libglobal{default_domain}@ { + template + static constexpr decltype(auto) transform_sender(Tag, Sndr&& sndr, const Env& env) + noexcept(@\seebelow@); + + 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> - constexpr @\exposconcept{queryable}@ decltype(auto) transform_env(Sndr&& sndr, Env&& env) noexcept; +template +constexpr decltype(auto) transform_sender(Tag, Sndr&& sndr, const Env& env) + noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum Let \tcode{e} be the expression \begin{codeblock} -tag_of_t().transform_env(std::forward(sndr), std::forward(env)) +tag_of_t().transform_sender(Tag(), std::forward(sndr), env) \end{codeblock} if that expression is well-formed; -otherwise, \tcode{\exposid{FWD-ENV}(std::forward(env))}. - -\pnum -\mandates -\tcode{noexcept(e)} is \tcode{true}. +otherwise, \tcode{static_cast(std::forward(sndr))}. \pnum \returns \tcode{e}. + +\pnum +\remarks +The exception specification is equivalent to \tcode{noexcept(e)}. \end{itemdescr} \indexlibrarymember{apply_sender}{default_domain}% @@ -2519,67 +2898,63 @@ \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) + template<@\libconcept{sender}@ Sndr, @\exposconcept{queryable}@ Env> + constexpr decltype(auto) transform_sender(Sndr&& sndr, const Env& env) noexcept(@\seebelow@); } \end{itemdecl} \begin{itemdescr} \pnum -Let \exposid{transformed-sndr} be the expression +For a subexpression \tcode{s}, +let \exposid{start-domain} be +\tcode{D()} where \tcode{D} is the decayed type of \tcode{get_domain(env)} +if that expression is well-formed, and +\tcode{default_domain} otherwise. + +\pnum +Let \tcode{\exposid{completion-domain}(s)} be +\tcode{D()} where \tcode{D} is the decayed type of +\tcode{get_completion_domain<>(get_env(s), env)} +if that is well-formed; +otherwise, \tcode{D} is \tcode{default_domain}. + +\pnum +Let \tcode{\exposid{transformed-sndr}(dom, tag, s)} be the expression \begin{codeblock} -dom.transform_sender(std::forward(sndr), env...) +dom.transform_sender(tag, s, env) \end{codeblock} if that expression is well-formed; otherwise, \begin{codeblock} -default_domain().transform_sender(std::forward(sndr), env...) +default_domain().transform_sender(tag, s, env) \end{codeblock} -Let \exposid{final-sndr} be the expression \exposid{transformed-sndr} -if \exposid{transformed-sndr} and \exposid{sndr} +Let \tcode{\exposid{transform-recurse}(dom, tag, s)} be +the expression \tcode{\exposid{transformed-sndr}(dom, tag, s)} +if\newline \tcode{\exposid{transformed-sndr}(dom, tag, s)} and \exposid{s} 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} +the expression \tcode{\exposid{transform-recurse}(dom2, tag, s2)}, where +\tcode{s2} is \tcode{\exposid{transformed-sender}(dom, tag, s)} and +\tcode{dom2} is \exposid{start-domain} if \tcode{tag} is \tcode{start}, and +\tcode{\exposid{completion-domain}(s2)} otherwise. -\begin{itemdescr} -\pnum -Let \tcode{e} be the expression +Let \exposid{tmp-sndr} be the expression \begin{codeblock} -dom.transform_env(std::forward(sndr), std::forward(env)) +@\exposid{transform-recurse}@(@\exposid{completion-domain}@(sndr), set_value, sndr) \end{codeblock} -if that expression is well-formed; otherwise, +and let \exposid{final-sndr} be the expression \begin{codeblock} -default_domain().transform_env(std::forward(sndr), std::forward(env)) +@\exposid{transform-recurse}@(@\exposid{start-domain}@, start, @\exposid{tmp-sndr}@) \end{codeblock} \pnum -\mandates -\tcode{noexcept(e)} is \tcode{true}. +\returns +\exposid{final-sndr}. \pnum -\returns -\tcode{e}. +\remarks +The exception specification is equivalent to +\tcode{noexcept(\exposid{final-sndr})}. \end{itemdescr} \rSec2[exec.snd.apply]{\tcode{execution::apply_sender}} @@ -2648,7 +3023,6 @@ where $s$ is the following expression: \begin{codeblock} transform_sender( - @\exposid{get-domain-late}@(declval(), declval()...), declval(), declval()...) \end{codeblock} @@ -2704,7 +3078,8 @@ \tcode{completion_signatures_of_t} and \tcode{completion_signatures_of_t} are both well-formed, -they shall denote the same type. +the former shall be a superset of the latter, +with the difference corresponding to error or stopped completion operations. \pnum Let \tcode{rcvr} be an rvalue @@ -2736,9 +3111,7 @@ 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} +\tcode{transform_sender(\newline sndr, get_env(rcvr))} and let \tcode{DS} and \tcode{DR} be \tcode{decay_t} and \tcode{decay_t}, respectively. @@ -2781,7 +3154,7 @@ \begin{codeblock} namespace std::execution { struct @\exposid{operation-state-task}@ { // \expos - using operation_state_concept = operation_state_t; + using operation_state_concept = operation_state_tag; using promise_type = @\exposid{connect-awaitable-promise}@; explicit @\exposid{operation-state-task}@(coroutine_handle<> h) noexcept : coro(h) {} @@ -2826,7 +3199,7 @@ return awaiter{fn}; } - @\exposid{operation-state-task}@ @\exposid{connect-awaitable}@(DS sndr, DR rcvr) requires @\libconcept{receiver_of}@ { + @\exposid{operation-state-task}@ @\exposid{connect-awaitable}@(DS sndr, DR rcvr) requires @\exposconcept{receiver-of}@ { exception_ptr ep; try { if constexpr (@\libconcept{same_as}@) { @@ -2856,6 +3229,21 @@ Otherwise, \tcode{\exposid{connect-awaitable}(new_sndr, rcvr)}. \end{itemize} Except that \tcode{rcvr} is evaluated only once. +The program is ill-formed, no diagnostic required, +if there exists an rvalue expression \tcode{rcvr2} such that: +\begin{itemize} +\item \tcode{decltype(rcvr2)} models \libconcept{receiver}, +\item \tcode{noexcept(rcvr2)} is \tcode{true}, +\item \tcode{is_same_v} is \tcode{true}, +\item \tcode{noexcept(execution::connect(sndr, rcvr))} is \tcode{true}, and +\item \tcode{noexcept(execution::connect(sndr, rcvr2))} +is well-formed and evaluates to \tcode{false}. +\end{itemize} +\begin{note} +This allows determination of whether \tcode{connect} throws +with only the context of the environment, +such as within \tcode{get_completion_signatures}. +\end{note} \mandates The following are \tcode{true}: @@ -2863,7 +3251,7 @@ \item \tcode{\libconcept{sender_in}>} \item -\tcode{\libconcept{receiver_of}>>} +\tcode{\exposconcept{receiver-of}>>} \end{itemize} \rSec2[exec.factories]{Sender factories} @@ -2884,14 +3272,6 @@ \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 @@ -2986,7 +3366,8 @@ \pnum \throws -An exception of an unspecified type derived from \tcode{exception} if +An exception of type +\tcode{\placeholder{unspecified-exception}}\iref{exec.snd.general} if the expression \tcode{Q()(env)} is ill-formed or has type \tcode{void}, where \tcode{env} is an lvalue subexpression whose type is \tcode{Env}. \end{itemdescr} @@ -3014,10 +3395,18 @@ \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}. +\tcode{\exposid{FWD-ENV}(get_env(sndr))}\iref{exec.fwd.env} +except that the +\tcode{get_completion_scheduler<\exposid{completion-tag}>} and +\tcode{get_completion_domain<\exposid{completion-tag}>} +queries are handled as described in \ref{exec.snd.general}. \item A parent sender with more than one child sender has -an associated attributes object equal to \tcode{env<>\{\}}. +an associated attributes object equal to \tcode{env<>\{\}} +except that the +\tcode{get_completion_scheduler<\exposid{completion-tag}>} and +\tcode{get_completion_domain<\exposid{comple\-tion-tag}>} +queries are handled as described in \ref{exec.snd.general}. \item When a parent sender is connected to a receiver \tcode{rcvr}, any receiver used to connect a child sender has @@ -3048,7 +3437,7 @@ \rSec3[exec.adapt.obj]{Closure objects} -\indexlibrarymisc{\idxcode{operator|}}{pipeable sender adaptor closure objects}% +\indexlibrarymisc{\idxcode{operator"|}}{pipeable sender adaptor 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}. @@ -3076,7 +3465,7 @@ 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}. +where \tcode{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} @@ -3233,38 +3622,24 @@ \pnum Otherwise, the expression \tcode{starts_on(sch, sndr)} is expression-equivalent to: -\begin{codeblock} -transform_sender( - @\exposid{query-with-default}@(get_domain, sch, default_domain()), - @\exposid{make-sender}@(starts_on, sch, sndr)) -\end{codeblock} -except that \tcode{sch} is evaluated only once. +\tcode{\exposid{make-sender}(starts_on, sch, sndr)}. \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: +then the expression +\tcode{starts_on.transform_sender(set_value, out_sndr, env)} is ill-formed; otherwise +\tcode{starts_on.transform_sender(set_value, out_sndr, env)} is equivalent to: \begin{codeblock} auto&& [_, sch, sndr] = out_sndr; return let_value( - schedule(sch), + continues_on(just(), 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 @@ -3284,111 +3659,31 @@ \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}\iref{exec.snd.expos} -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 +\tcode{continues_on} 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. +The name \tcode{continues_on} 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. +\tcode{continues_on(sndr, sch)} is ill-formed. \pnum Otherwise, -the expression \tcode{schedule_from(sch, sndr)} is expression-equivalent to: -\begin{codeblock} -transform_sender( - @\exposid{query-with-default}@(get_domain, sch, default_domain()), - @\exposid{make-sender}@(schedule_from, sch, sndr)) -\end{codeblock} -except that \tcode{sch} is evaluated only once. +the expression \tcode{continues_on(sndr, sch)} is expression-equivalent to +\tcode{\exposid{make-sender}(continues_on, sch, schedule_from(sndr))}. \pnum The exposition-only class template \exposid{impls-for}\iref{exec.snd.expos} -is specialized for \tcode{schedule_from_t} as follows: -\indexlibraryglobal{\exposid{impls-for}}% +is specialized for \tcode{continues_on_t} as follows: +\indexlibraryglobal{\exposid{impls-for}}% \begin{codeblock} namespace std::execution { template<> - struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { - static constexpr auto @\exposid{get-attrs}@ = @\seebelow@; + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { static constexpr auto @\exposid{get-state}@ = @\seebelow@; static constexpr auto @\exposid{complete}@ = @\seebelow@; @@ -3399,21 +3694,11 @@ \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}} +The member \tcode{\exposid{impls-for}::\exposid{get-state}} is initialized with a callable object equivalent to the following lambda: \begin{codeblock} [](Sndr&& sndr, Rcvr& rcvr) noexcept(@\seebelow@) requires @\libconcept{sender_in}@<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(env_of_t)> { - auto& [_, sch, child] = sndr; using sched_t = decltype(auto(sch)); @@ -3480,7 +3765,7 @@ \begin{codeblock} namespace std::execution { struct @\exposid{receiver-type}@ { - using receiver_concept = receiver_t; + using receiver_concept = receiver_tag; @\exposid{state-type}@* @\exposid{state}@; // \expos void set_value() && noexcept { @@ -3517,7 +3802,7 @@ otherwise, \tcode{false}. \pnum -The member \tcode{\exposid{impls-for}::\exposid{complete}} +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 @@ -3538,7 +3823,7 @@ \pnum Let \tcode{out_sndr} be a subexpression denoting -a sender returned from \tcode{schedule_from(sch, sndr)} or one equal to such, +a sender returned from \tcode{continues_on_t(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} @@ -3553,6 +3838,21 @@ an error completion on \tcode{out_rcvr} shall be executed on an unspecified execution agent. +\rSec3[exec.schedule.from]{\tcode{execution::schedule_from}} + +\pnum +The name \tcode{schedule_from} denotes a customization point object. +For some subexpression \tcode{sndr}, +if \tcode{decltype((\brk{}sndr))} does not satisfy \libconcept{sender}, +\tcode{schedule_from(sndr)} is ill-formed. +Otherwise, +the expression \tcode{schedule_from(sndr)} is expression-equivalent to +\tcode{\exposid{make-sender}(schedule_from, \{\}, sndr)}. +\begin{note} +\tcode{schedule_from} is used by schedulers to control +how to transition off of their schedulers' associated execution contexts. +\end{note} + \rSec3[exec.on]{\tcode{execution::on}} \pnum @@ -3594,13 +3894,8 @@ \pnum Otherwise, if \tcode{decltype((sndr))} satisfies \libconcept{sender}, -the expression \tcode{on(sch, sndr)} is expression-equivalent to: -\begin{codeblock} -transform_sender( - @\exposid{query-with-default}@(get_domain, sch, default_domain()), - @\exposid{make-sender}@(on, sch, sndr)) -\end{codeblock} -except that \tcode{sch} is evaluated only once. +the expression \tcode{on(sch, sndr)} is expression-equivalent to +\tcode{\exposid{make-sender}(on, sch, sndr)}. \pnum For subexpressions \tcode{sndr}, \tcode{sch}, and \tcode{closure}, if @@ -3613,73 +3908,33 @@ \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. +otherwise, it is expression-equivalent to +\tcode{\exposid{make-sender}(\brk{}on, \exposid{product-type}\{sch, closure\}, sndr)}. \pnum Let \tcode{out_sndr} and \tcode{env} be subexpressions, let \tcode{OutSndr} be \tcode{decltype((out_sndr))}, and let \tcode{Env} be \tcode{decltype((\linebreak env))}. If \tcode{\exposconcept{sender-for}} is \tcode{false}, -then the expressions \tcode{on.transform_env(out_sndr, env)} and -\tcode{on.transform_sender(out_sndr, env)} are ill-formed. - -\pnum -Otherwise: -Let \exposid{not-a-scheduler} be an unspecified empty class type. - -\pnum -The expression \tcode{on.transform_env(out_sndr, env)} -has effects equivalent to: -\begin{codeblock} -auto&& [_, data, _] = out_sndr; -if constexpr (@\libconcept{scheduler}@) { - return @\exposid{JOIN-ENV}@(@\exposid{SCHED-ENV}@(std::forward_like(data)), @\exposid{FWD-ENV}@(std::forward(env))); -} else { - return std::forward(env); -} -\end{codeblock} +then the expression \tcode{on.transform_sender(set_value, out_sndr, env)} is ill-formed. \pnum -The expression \tcode{on.transform_sender(out_sndr, env)} +Otherwise, the expression \tcode{on.transform_sender(set_value, 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)); - } + auto orig_sch = @\exposid{call-with-default}@(get_start_scheduler, @\exposid{not-a-scheduler}@(), env); + return continues_on( + starts_on(std::forward_like(data), std::forward_like(child)), + std::move(orig_sch)); } else { auto& [sch, closure] = data; - auto orig_sch = @\exposid{query-with-default}@( - get_completion_scheduler, - get_env(child), - @\exposid{query-with-default}@(get_scheduler, env, @\exposid{not-a-scheduler}@())); - - if constexpr (@\libconcept{same_as}@) { - return @\exposid{not-a-sender}@{}; - } else { - return write_env( - continues_on( - std::forward_like(closure)( - continues_on( - write_env(std::forward_like(child), @\exposid{SCHED-ENV}@(orig_sch)), - sch)), - orig_sch), - @\exposid{SCHED-ENV}@(sch)); - } + auto orig_sch = @\exposid{call-with-default}@( + get_completion_scheduler, @\exposid{not-a-scheduler}@(), get_env(child), env); + return continues_on( + std::forward_like(closure)(continues_on(std::forward_like(child), sch)), + orig_sch); } \end{codeblock} @@ -3695,7 +3950,8 @@ Calling \tcode{start(op)} shall \begin{itemize} \item -remember the current scheduler, \tcode{get_scheduler(get_env(rcvr))}; +remember the current scheduler, +which is obtained by \tcode{get_start_scheduler(get_env(rcvr))}; \item start \tcode{sndr} on an execution agent belonging to \tcode{sch}'s associated execution resource; @@ -3723,11 +3979,8 @@ \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} +which is +\tcode{get_completion_scheduler(get_env(\newline sndr), get_env(out_rcvr))}; \item start \tcode{sndr} on the current execution agent; \item @@ -3770,11 +4023,8 @@ \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. +the expression \tcode{\exposid{then-cpo}(sndr, f)} is expression-equivalent to +\tcode{\exposid{make-sender}(\exposid{then-cpo}, f, sndr)}. \pnum For \tcode{then}, \tcode{upon_error}, and \tcode{upon_stopped}, @@ -3816,14 +4066,12 @@ Equivalent to: \begin{codeblock} auto cs = get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(); -auto fn = [](set_value_t(*)(Ts...)) { +auto fn = [](@\exposid{decayed-typeof}@<@\exposid{set-cpo}@>(*)(Ts...)) { if constexpr (!@\libconcept{invocable}@>, Ts...>) throw @\placeholder{unspecified-exception}@(); }; cs.@\exposid{for-each}@(@\exposid{overload-set}@{fn, [](auto){}}); \end{codeblock} -where \tcode{\placeholder{unspecified-exception}} is -a type derived from \tcode{exception}. \end{itemdescr} \pnum @@ -3854,14 +4102,16 @@ \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 +Let \exposid{let-tag} denote a unique, empty class type for each of +\tcode{let_value}, \tcode{let_error}, and \tcode{let_stopped}. +For subexpressions \tcode{sndr} and \tcode{env}, +let \tcode{\exposid{let-env}(sndr, env)} 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)))} +\tcode{\exposid{SCHED-ENV}(get_completion_scheduler<\exposid{decayed-typeof}<\exposid{set-cpo}>>(get_env(sndr),\newline \exposid{FWD-ENV}(env)))} \item -\tcode{\exposid{MAKE-ENV}(get_domain, get_domain(get_env(sndr)))} +\tcode{\exposid{MAKE-ENV}(get_domain, get_completion_domain<\exposid{decayed-typeof}<\exposid{set-cpo}>>(get_env(sndr),\newline \exposid{FWD-ENV}(env)))} \item \tcode{(void(sndr), env<>\{\})} \end{itemize} @@ -3879,25 +4129,37 @@ \pnum Otherwise, -the expression \tcode{\exposid{let-cpo}(sndr, f)} is expression-equivalent to: +the expression \tcode{\exposid{let-cpo}(sndr, f)} is expression-equivalent to +\tcode{\exposid{make-sender}(\exposid{let-cpo}, f, sndr)}. + +\pnum +Let \exposid{let-data} denote the following exposition-only class template: +\begin{codeblock} +template +struct @\exposid{let-data}@ { + Sndr @\exposid{sndr}@; // \expos + Fn @\exposid{fn}@; // \expos +}; +\end{codeblock} + +\pnum +Then let the expression \tcode{\exposid{let-cpo}.transform_sender(s, es...)} +be expression-equivalent to: \begin{codeblock} -transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(@\exposid{let-cpo}@, f, sndr)) +@\exposid{make-sender}@(@\exposid{let-tag}@{}, @\exposid{let-data}@{s.template @\exposid{get}@<2>(), s.template @\exposid{get}@<1>()}) \end{codeblock} -except that \tcode{sndr} is evaluated only once. +except that \tcode{s} is evaluated only once. \pnum The exposition-only class template \exposid{impls-for}\iref{exec.snd.expos} -is specialized for \exposid{let-cpo} as follows: +is specialized for \exposid{let-tag} as follows: \indexlibraryglobal{\exposid{impls-for}<\exposid{decayed-typeof}<\exposid{let-cpo}>>} \begin{codeblock} namespace std::execution { - template - void @\exposid{let-bind}@(State& state, Rcvr& rcvr, Args&&... args); // \expos - template<> - struct @\exposid{impls-for}@<@\exposid{decayed-typeof}@<@\exposid{let-cpo}@>> : @\exposid{default-impls}@ { + struct @\exposid{impls-for}@<@\exposid{let-tag}@> : @\exposid{default-impls}@ { static constexpr auto @\exposid{get-state}@ = @\seebelow@; - static constexpr auto @\exposid{complete}@ = @\seebelow@; + static constexpr auto @\exposid{start}@ = @\seebelow@; template static consteval void @\exposid{check-types}@(); @@ -3911,7 +4173,7 @@ namespace std::execution { template struct @\exposid{receiver2}@ { - using receiver_concept = receiver_t; + using receiver_concept = receiver_tag; template void set_value(Args&&... args) && noexcept { @@ -3942,15 +4204,15 @@ \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; +given a query object \tcode{q} and a pack of subexpressions \tcode{args}, +the expression \tcode{e.query(q, args...)} is expression-equivalent +to \tcode{\exposid{env}.query(q, args...)} if that expression is valid; otherwise, if the type of \tcode{q} satisfies \exposconcept{forwarding-query}, -\tcode{e.query(q)} is expression-equivalent -to \tcode{get_env(\exposid{rcvr}).query(q)}; +\tcode{e.query(q, args...)} is expression-equivalent +to \tcode{get_env(\exposid{rcvr}).query\newline (q, args...)}; otherwise, -\tcode{e.query(q)} is ill-formed. +\tcode{e.query(q, args...)} is ill-formed. \end{itemize} \indexlibrarymember{\exposid{check-types}}{\exposid{impls-for}<\exposid{decayed-typeof}<\exposid{let-cpo}>>} @@ -3972,8 +4234,6 @@ }; cs.@\exposid{for-each}@(@\exposid{overload-set}@(fn, [](auto){})); \end{codeblock} -where \tcode{\placeholder{unspecified-exception}} is -a type derived from \tcode{exception}, and where \tcode{\placeholder{is-valid-let-sender}} is \tcode{true} if and only if all of the following are \tcode{true}: \begin{itemize} @@ -3984,28 +4244,98 @@ \tcode{sizeof...(Env) == 0 || \libconcept{sender_in}\&...>, \placeholder{env-t}\linebreak{}...>} \end{itemize} where \tcode{\placeholder{env-t}} is the pack -\tcode{decltype(\exposid{let-cpo}.transform_env(declval(), declval()))}. +\tcode{decltype(\exposid{JOIN-ENV}(\exposid{let-env}(declval<\exposid{child-type}>(), declval<\brk{}Env>()), \exposid{FWD-ENV}(declval())))}. \end{itemdescr} \pnum -\tcode{\exposid{impls-for}<\exposid{decayed-typeof}<\exposid{let-cpo}>>::\exposid{get-state}} +Let \exposid{let-state} denote the following exposition-only class template: +\begin{codeblock} +template +struct @\exposid{let-state}@ { + using @\exposidnc{env_t}@ = decltype(@\exposidnc{let-env}@(declval()), get_env(declval())); // \expos + Fn @\exposidnc{fn}@; // \expos + env_t @\exposidnc{env}@; // \expos + ArgsVariant @\exposidnc{args}@; // \expos + OpsVariant @\exposidnc{ops}@; // \expos + + template + constexpr void @\exposid{impl}@(Rcvr& rcvr, Tag tag, Ts&&... ts) noexcept // \expos + { + using args_t = @\exposid{decayed-tuple}@; + using receiver_type = @\exposid{receiver2}@; + using sender_type = apply_result_t; + if constexpr (is_same_v) { + try { + auto& tuple = @\exposid{args}@.template emplace(std::forward(ts)...); + @\exposid{ops}@.template emplace(); + auto&& sndr = apply(std::move(@\exposid{fn}@), tuple); + using op_t = connect_result_t; + auto mkop2 = [&] { + return connect(std::forward(sndr), + receiver_type{@\exposid{rcvr}@, @\exposid{env}@}); + }; + auto& op = @\exposid{ops}@.template emplace(@\exposid{emplace-from}@{mkop2}); + start(op); + } catch (...) { + constexpr bool nothrow = + is_nothrow_constructible_v && + is_nothrow_applicable_v && + noexcept(connect(declval(), receiver_type{@\exposid{rcvr}@, @\exposid{env}@})); + if constexpr (!nothrow) { + set_error(std::move(@\exposid{rcvr}@), current_exception()); + } + } + } else { + tag(std::move(@\exposid{rcvr}@), std::forward(ts)...); + } + } + + struct @\exposid{receiver}@ { // \expos + @\exposid{let-state}@& state; // \expos + Rcvr& @\exposid{rcvr}@; // \expos + + using receiver_concept = receiver_tag; + + template + constexpr void set_value(Args&&... args) noexcept { + @\exposid{state}@.@\exposid{impl}@(@\exposid{rcvr}@, execution::set_value, std::forward(args)...); + } + template + constexpr void set_error(Args&&... args) noexcept { + @\exposid{state}@.@\exposid{impl}@(@\exposid{rcvr}@, execution::set_error, std::forward(args)...); + } + template + constexpr void set_stopped(Args&&... args) noexcept { + @\exposid{state}@.@\exposid{impl}@(@\exposid{rcvr}@, execution::set_stopped, std::forward(args)...); + } + + constexpr env_of_t get_env() const noexcept { + return execution::get_env(@\exposid{rcvr}@); + } + }; + + using @\exposidnc{op_t}@ = connect_result_t; // \expos + + constexpr @\exposidnc{let-state}@(Sndr&& sndr, Fn fn, Rcvr& rcvr) // \expos + : @\exposid{fn}@(std::move(fn)), @\exposid{env}@(@\exposid{let-env}@(sndr), get_env(rcvr)), + @\exposid{ops}@(in_place_type<@\exposid{op_t}@>, std::forward(sndr), @\exposid{receiver}@{*this, rcvr}) {} +}; +\end{codeblock} + +\pnum +\tcode{\exposid{impls-for}<\exposid{let-tag}>::\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; + auto& [_, data] = sndr; + auto& [child, fn] = data; + using child_t = decltype(std::forward_like(child)); using fn_t = decay_t; - using env_t = decltype(@\exposid{let-env}@(child)); using args_variant_t = @\seebelow@; - using ops2_variant_t = @\seebelow@; - - struct @\exposid{state-type}@ { - fn_t @\exposid{fn}@; // \expos - env_t @\exposid{env}@; // \expos - args_variant_t @\exposid{args}@; // \expos - ops2_variant_t @\exposid{ops2}@; // \expos - }; - return @\exposid{state-type}@{@\exposid{allocator-aware-forward}@(std::forward_like(fn), rcvr), - @\exposid{let-env}@(child), {}, {}}; + using ops_variant_t = @\seebelow@; + using state_t = @\exposid{let-state}@<@\exposid{decayed-typeof}@<@\exposid{set-cpo}@>, child_t, fn_t, Rcvr, + args_variant_t, ops_variant_t>; + return state_t(std::forward_like(child), std::forward_like(fn), @\exposid{rcvr}@); } \end{codeblock} @@ -4027,10 +4357,12 @@ 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 +Then \tcode{ops_variant_t} denotes the type \begin{codeblock} -variant, @\exposid{receiver2}@>...> +variant, + connect_result_t<@\exposid{as-sndr2}@, @\exposid{receiver2}@>...> \end{codeblock} except with duplicate types removed. @@ -4040,45 +4372,12 @@ 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}} +\tcode{\exposid{impls-for}<\exposid{let-tag}>::\exposid{start}} is initialized with a callable object equivalent to the following: \begin{codeblock} -[] - (auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept -> void { - if constexpr (@\libconcept{same_as}@>) { - @\exposid{TRY-EVAL}@(rcvr, @\exposid{let-bind}@(state, rcvr, std::forward(args)...)); - } else { - Tag()(std::move(rcvr), std::forward(args)...); - } - } -\end{codeblock} - -\pnum -Let \tcode{sndr} and \tcode{env} be subexpressions, and -let \tcode{Sndr} be \tcode{decltype((sndr))}. -If -\tcode{\exposconcept{sender-for}>} -is \tcode{false}, -then the expression \tcode{\exposid{let-cpo}.transform_env(sndr, env)} -is ill-formed. -Otherwise, it is equal to: -\begin{codeblock} -auto& [_, _, child] = sndr; -return @\exposid{JOIN-ENV}@(@\exposid{let-env}@(child), @\exposid{FWD-ENV}@(env)); +[](State& state, Rcvr&) noexcept { + start(get(state.@\exposid{ops}@)); +} \end{codeblock} \pnum @@ -4134,12 +4433,9 @@ Otherwise, the expression \tcode{\placeholder{bulk-algo}(sndr, policy, shape, f)} is expression-equivalent to: - \begin{codeblock} -transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@( - @\placeholder{bulk-algo}@, @\exposid{product-type}@<@\seebelow@, Shape, Func>{policy, shape, f}, sndr)) +@\exposid{make-sender}@(@\placeholder{bulk-algo}@, @\exposid{product-type}@<@\seebelow@, Shape, Func>{policy, shape, f}, sndr) \end{codeblock} -except that \tcode{sndr} is evaluated only once. The first template argument of \exposid{product-type} is \tcode{Policy} if \tcode{Policy} models \libconcept{copy_constructible}, and \tcode{const Policy\&} otherwise. @@ -4148,7 +4444,7 @@ Let \tcode{sndr} and \tcode{env} be subexpressions such that \tcode{Sndr} is \tcode{decltype((sndr))}. If \tcode{\exposconcept{sender-for}} is \tcode{false}, then -the expression \tcode{bulk.transform_sender(sndr, env)} is ill-formed; +the expression \tcode{bulk.transform_sender(set_value, sndr, env)} is ill-formed; otherwise, it is equivalent to: \begin{codeblock} auto [_, data, child] = sndr; @@ -4204,6 +4500,27 @@ if \tcode{Tag} denotes a type other than \tcode{set_value_t} or if the expression \tcode{f(auto(shape), auto(shape), args...)} is well-formed. +\begin{itemdecl} +template + static consteval void @\exposid{check-types}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto cs = get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(); +auto fn = [](set_value_t(*)(Ts...)) { + using data_type = @\exposid{data-type}@; + if constexpr (!@\libconcept{invocable}@&, + remove_cvref_t<@\exposid{data-type}@>, Ts&...>) + throw @\placeholder{unspecified-exception}@(); +}; +cs.@\exposid{for-each}@(@\exposid{overload-set}@(fn, [](auto){})); +\end{codeblock} +\end{itemdescr} + \pnum The exposition-only class template \exposid{impls-for}\iref{exec.snd.expos} is specialized for \tcode{bulk_unchunked_t} as follows: @@ -4212,6 +4529,9 @@ template<> struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { static constexpr auto @\exposid{complete}@ = @\seebelow@; + + template + static consteval void @\exposid{check-types}@(); }; } \end{codeblock} @@ -4253,13 +4573,13 @@ \begin{codeblock} auto cs = get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(); auto fn = [](set_value_t(*)(Ts...)) { - if constexpr (!@\libconcept{invocable}@>, Ts&...>) + using data_type = @\exposid{data-type}@; + if constexpr (!@\libconcept{invocable}@&, + remove_cvref_t<@\exposid{data-type}@>, Ts&...>) throw @\placeholder{unspecified-exception}@(); }; cs.@\exposid{for-each}@(@\exposid{overload-set}@(fn, [](auto){})); \end{codeblock} -where \tcode{\placeholder{unspecified-exception}} is -a type derived from \tcode{exception}. \end{itemdescr} \pnum @@ -4378,12 +4698,8 @@ \pnum The names \tcode{when_all} and \tcode{when_all_with_variant} denote customization point objects. -Let \tcode{sndrs} be a pack of subexpressions, -let \tcode{Sndrs} be a pack of the types \tcode{decltype((sndrs))...}, and -let \tcode{CD} be -the type \tcode{common_type_t}. -Let \tcode{CD2} be \tcode{CD} if \tcode{CD} is well-formed, and -\tcode{default_domain} otherwise. +Let \tcode{sndrs} be a pack of subexpressions and +let \tcode{Sndrs} be a pack of the types \tcode{decltype((sndrs))...}. The expressions \tcode{when_all(sndrs...)} and \tcode{when_all_with_variant(sndrs...)} are ill-formed if any of the following is \tcode{true}: @@ -4395,10 +4711,8 @@ \end{itemize} \pnum -The expression \tcode{when_all(sndrs...)} is expression-equivalent to: -\begin{codeblock} -transform_sender(CD2(), @\exposid{make-sender}@(when_all, {}, sndrs...)) -\end{codeblock} +The expression \tcode{when_all(sndrs...)} is expression-equivalent to +\tcode{\exposid{make-sender}(when_all, \{\}, sndrs...)}. \pnum The exposition-only class template \exposid{impls-for}\iref{exec.snd.expos} @@ -4408,7 +4722,6 @@ 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@; @@ -4428,22 +4741,24 @@ \begin{codeblock} template constexpr auto @\exposid{make-when-all-env}@(inplace_stop_source& stop_src, // \expos - Env&& env) noexcept { - return @\seebelow@; -} + Env&& env) noexcept; \end{codeblock} -Returns an object \tcode{e} such that + +\pnum +\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 +\tcode{stop_src.get_token()}, and \item given a query object \tcode{q} -with type other than \cv{} \tcode{get_stop_token_t} and -whose type satisfies \exposconceptx{forwarding-\brk{}query}{forwarding-query}, -\tcode{e.query(q)} is expression-equivalent to \tcode{get_env(rcvr).query(q)}. +with type other than \cv{} \tcode{get_stop_token_t}, +\tcode{e.query(q)} is expression-equivalent to \tcode{env.query(q)} +if the type of \tcode{q} satisfies \exposconcept{forwarding-query}, and +ill-formed otherwise. \end{itemize} \pnum @@ -4475,30 +4790,8 @@ }; (fn.template operator()<@\exposid{child-type}@>(), ...); \end{codeblock} -where \tcode{\placeholder{unspecified-exception}} is -a type derived from \tcode{exception}. - -\pnum -\throws -Any exception thrown as a result of evaluating the \Fundescx{Effects}, or -an exception of an unspecified type -derived from \tcode{exception} when \tcode{CD} is ill-formed. \end{itemdescr} -\pnum -The member \tcode{\exposid{impls-for}::\exposid{get-attrs}} -is initialized with a callable object -equivalent to the following lambda expression: -\begin{codeblock} -[](auto&&, auto&&... child) noexcept { - if constexpr (@\libconcept{same_as}@) { - return env<>(); - } else { - return @\exposid{MAKE-ENV}@(get_domain, CD()); - } -} -\end{codeblock} - \pnum The member \tcode{\exposid{impls-for}::\exposid{get-env}} is initialized with a callable object @@ -4612,9 +4905,15 @@ \item Otherwise, evaluates: \begin{codeblock} -@\exposid{on_stop}@.reset(); -set_stopped(std::move(rcvr)); +if constexpr (@\placeholder{sends-stopped}@) { + @\exposid{on_stop}@.reset(); + set_stopped(std::move(rcvr)); +} \end{codeblock} +where \tcode{\placeholder{sends-stopped}} equals \tcode{true} +if and only if there exists an element \tcode{S} of \tcode{Sndrs} such that +\tcode{completion_signatures_of_t>} +contains \tcode{set_stopped_t()}. \end{itemize} \pnum @@ -4627,12 +4926,7 @@ 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), ...); - } + (start(ops), ...); } \end{codeblock} @@ -4690,17 +4984,15 @@ \pnum The expression \tcode{when_all_with_variant(sndrs...)} -is expression-equivalent to: -\begin{codeblock} -transform_sender(CD2(), @\exposid{make-sender}@(when_all_with_variant, {}, sndrs...)); -\end{codeblock} +is expression-equivalent to +\tcode{\exposid{make-sender}(when_all_with_variant, \{\}, sndrs...)}. \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)} +then the expression \tcode{when_all_with_variant.transform_sender(set_value, sndr, env)} is ill-formed; otherwise, it is equivalent to: \begin{codeblock} @@ -4729,11 +5021,8 @@ \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. +is expression-equivalent to +\tcode{\exposid{make-sender}(into_variant, \{\}, sndr)}. \pnum The exposition-only class template \exposid{impls-for}\iref{exec.snd.expos} @@ -4794,11 +5083,8 @@ \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. +The expression \tcode{stopped_as_optional(sndr)} is expression-equivalent to +\tcode{\exposid{make-sender}(stopped_as_optional, \{\}, sndr)}. \pnum The exposition-only class template \exposid{impls-for}\iref{exec.snd.expos} @@ -4820,8 +5106,6 @@ }; } \end{codeblock} -where \tcode{\placeholder{unspecified-exception}} is -a type derived from \tcode{exception}. \pnum Let \tcode{sndr} and \tcode{env} be subexpressions @@ -4829,10 +5113,10 @@ \tcode{Env} is \tcode{decltype((env))}. If \tcode{\exposconcept{sender-for}} is \tcode{false} -then the expression \tcode{stopped_as_optional.trans\-form_sender(sndr, env)} +then the expression \tcode{stopped_as_optional.trans\-form_sender(set_value, sndr, env)} is ill-formed; otherwise, -if \tcode{\libconcept{sender_in}<\exposid{child-type}, \exposid{FWD-ENV-T}(Env)>} +if \tcode{\libconcept{sender_in}<\exposid{child-type}, \exposid{FWD-\brk{}ENV-\brk{}T}(Env)>} is \tcode{false}, the expression \tcode{stopped_as_optional.transform_sender(sndr, env)} is equivalent to \tcode{\exposid{not-a-sen\-der}()}; @@ -4864,19 +5148,16 @@ 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. +Otherwise, the expression \tcode{stopped_as_error(sndr, err)} +is expression-equivalent to +\tcode{\exposid{make-sender}(stopped_as_error, err, sndr)}. \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)} +then the expression \tcode{stopped_as_error.transform_sender(set_value, sndr, env)} is ill-formed; otherwise, it is equivalent to: \begin{codeblock} @@ -4904,32 +5185,42 @@ \begin{codeblock} namespace std::execution { template<@\libconcept{scope_token}@ Token, @\libconcept{sender}@ Sender> - struct @\exposid{associate-data}@ { // \expos - using @\exposid{wrap-sender}@ = // \expos + struct @\exposidnc{associate-data}@ { // \expos + using @\exposidnc{wrap-sender}@ = // \expos remove_cvref_t().wrap(declval()))>; + using @\exposidnc{assoc-t}@ = decltype(declval().try_associate()); // \expos + using @\exposidnc{sender-ref}@ = // \expos + unique_ptr<@\exposidnc{wrap-sender}@, decltype([](auto* p) noexcept { destroy_at(p); })>; explicit @\exposid{associate-data}@(Token t, Sender&& s) : @\exposid{sndr}@(t.wrap(std::forward(s))), - @\exposid{token}@(t) { - if (!@\exposid{token}@.try_associate()) - @\exposid{sndr}@.reset(); - } + @\exposid{assoc}@([&] { + @\exposid{sender-ref}@ guard{addressof(@\exposid{sndr}@)}; + auto assoc = t.try_associate(); + if (assoc) { + guard.release(); + } + return assoc; + }()) {} @\exposid{associate-data}@(const @\exposid{associate-data}@& other) noexcept(is_nothrow_copy_constructible_v<@\exposid{wrap-sender}@> && - noexcept(other.@\exposid{token}@.try_associate())); + noexcept(other.@\exposid{assoc}@.try_associate())); @\exposid{associate-data}@(@\exposid{associate-data}@&& other) - noexcept(is_nothrow_move_constructible_v<@\exposid{wrap-sender}@>); + noexcept(is_nothrow_move_constructible_v<@\exposid{wrap-sender}@>) + : @\exposid{associate-data}@(std::move(other).release()) {} ~@\exposid{associate-data}@(); - optional> - release() && noexcept(is_nothrow_move_constructible_v<@\exposid{wrap-sender}@>); + pair<@\exposid{assoc-t}@, @\exposid{sender-ref}@> release() && noexcept; private: - optional<@\exposid{wrap-sender}@> @\exposid{sndr}@; // \expos - Token @\exposid{token}@; // \expos + @\exposidnc{associate-data}@(pair<@\exposidnc{assoc-t}@, @\exposidnc{sender-ref}@> parts); // \expos + union { + @\exposidnc{wrap-sender}@ @\exposidnc{sndr}@; // \expos + }; + @\exposidnc{assoc-t}@ @\exposidnc{assoc}@; // \expos }; template<@\libconcept{scope_token}@ Token, @\libconcept{sender}@ Sender> @@ -4939,7 +5230,7 @@ \pnum For an \exposid{associate-data} object \tcode{a}, -\tcode{a.\exposid{sndr}.has_value()} is \tcode{true} +\tcode{bool(a.\exposid{assoc})} is \tcode{true} if and only if an association was successfully made and is owned by \tcode{a}. @@ -4947,40 +5238,32 @@ \begin{itemdecl} @\exposid{associate-data}@(const @\exposid{associate-data}@& other) noexcept(is_nothrow_copy_constructible_v<@\exposid{wrap-sender}@> && - noexcept(other.@\exposid{token}@.try_associate())); + noexcept(other.@\exposid{assoc}@.try_associate())); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{\libconcept{copy_constructible}<\exposid{wrap-sender}>} is \tcode{true}. +\exposid{wrap-sender} models \libconcept{copy_constructible}. \pnum \effects -Value-initializes \exposid{sndr} and -initializes \exposid{token} with \tcode{other.\exposid{token}}. -If \tcode{other.\exposid{sndr}.has_value()} is \tcode{false}, -no further effects; -otherwise, -calls \tcode{\exposid{token}.try_associate()} and, -if that returns \tcode{true}, -calls \tcode{\exposid{sndr}.emplace(*other.\exposid{sndr})} and, -if that exits with an exception, -calls \tcode{\exposid{token}.disassociate()} before propagating the exception. +Initializes \exposid{assoc} with \tcode{other.\exposid{assoc}.try_associate()}. +If \tcode{bool(\exposid{assoc})} is \tcode{true}, +initializes \exposid{sndr} with \tcode{other.\exposid{sndr}}. \end{itemdescr} \indexlibraryctor{execution::\exposid{associate-data}}% \begin{itemdecl} -@\exposid{associate-data}@(@\exposid{associate-data}@&& other) - noexcept(is_nothrow_move_constructible_v<@\exposid{wrap-sender}@>); +@\exposid{associate-data}@(pair<@\exposid{assoc-t}@, @\exposid{sender-ref}@> parts); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{sndr} with \tcode{std::move(other.\exposid{sndr})} and -initializes \exposid{token} with \tcode{std::move(other.\brk{}\exposid{token})} and -then calls \tcode{other.\exposid{sndr}.reset()}. +Initializes \exposid{assoc} with \tcode{std::move(parts.first)}. +If \tcode{bool(\exposid{assoc})} is \tcode{true}, +initializes \exposid{sndr} with \tcode{std::move(*parts.second)}. \end{itemdescr} \indexlibrarydtor{execution::\exposid{associate-data}}% @@ -4991,32 +5274,22 @@ \begin{itemdescr} \pnum \effects -If \tcode{\exposid{sndr}.has_value()} returns \tcode{false} then no effect; -otherwise, invokes \tcode{\exposid{sndr}.reset()} -before invoking \tcode{\exposid{token}.disassociate()}. +If \tcode{bool(\exposid{assoc})} is \tcode{true}, destroys \exposid{sndr}. \end{itemdescr} \indexlibrarymember{release}{execution::\exposid{associate-data}}% \begin{itemdecl} -optional> - release() && noexcept(is_nothrow_move_constructible_v<@\exposid{wrap-sender}@>); +pair<@\exposid{assoc-t}@, @\exposid{sender-ref}@> release() && noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -If \tcode{\exposid{sndr}.has_value()} returns \tcode{false} then -returns an \tcode{optional} that does not contain a value; -otherwise returns an \tcode{optional} -containing a value of type \tcode{pair} -as if by: -\begin{codeblock} -return optional(pair(@\exposid{token}@, std::move(*@\exposid{sndr}@))); -\end{codeblock} - -\pnum -\ensures -\exposid{sndr} does not contain a value. +Constructs an object \tcode{u} of type \exposid{sender-ref} +that is initialized with \tcode{addressof(\exposid{sndr})} +if \tcode{bool(\exposid{assoc})} is \tcode{true} and +with \tcode{nullptr} otherwise, +then returns \tcode{pair\{std::move(\exposid{assoc}), std::\brk move(u)\}}. \end{itemdescr} \pnum @@ -5031,12 +5304,8 @@ \item Otherwise, the expression \tcode{associate(sndr, token)} -is expression-equivalent to: -\begin{codeblock} -transform_sender(@\exposid{get-domain-early}@(sndr), - @\exposid{make-sender}@(associate, @\exposid{associate-data}@(token, sndr))) -\end{codeblock} -except that \tcode{sndr} is evaluated only once. +is expression-equivalent to +\tcode{\exposid{make-sender}(asso\-ci\-ate, \exposid{associate-data}(token, sndr))}. \end{itemize} \pnum @@ -5066,57 +5335,55 @@ \begin{codeblock} [](Sndr&& sndr, Rcvr& rcvr) noexcept(@\seebelow@) { - auto [_, data] = std::forward(sndr); - auto dataParts = std::move(data).release(); + auto&& [_, data] = std::forward(sndr); - using scope_tkn = decltype(dataParts->first); - using wrap_sender = decltype(dataParts->second); - using op_t = connect_result_t; + using associate_data_t = remove_cvref_t; + using assoc_t = associate_data_t::@\exposid{assoc-t}@; + using sender_ref_t = associate_data_t::@\exposid{sender-ref}@; + + using op_t = connect_result_t; struct op_state { - bool @\exposid{associated}@ = false; // \expos + assoc_t @\exposid{assoc}@; // \expos union { Rcvr* @\exposid{rcvr}@; // \expos - struct { - scope_tkn @\exposid{token}@; // \expos - op_t @\exposid{op}@; // \expos - } @\exposid{assoc}@; // \expos + op_t @\exposid{op}@; // \expos }; - explicit op_state(Rcvr& r) noexcept - : @\exposid{rcvr}@(addressof(r)) {} - - explicit op_state(scope_tkn tkn, wrap_sender&& sndr, Rcvr& r) try - : @\exposid{associated}@(true), - @\exposid{assoc}@(tkn, connect(std::move(sndr), std::move(r))) { - } - catch (...) { - tkn.disassociate(); - throw; + explicit op_state(pair parts, Rcvr& r) + : @\exposid{assoc}@(std::move(parts.first)) { + if (@\exposid{assoc}@) { + ::new (@\placeholdernc{voidify}@(@\exposid{op}@)) op_t(connect(std::move(*parts.second), std::move(r))); + } else { + @\exposid{rcvr}@ = addressof(r); + } } + explicit op_state(associate_data_t&& ad, Rcvr& r) + : op_state(std::move(ad).release(), r) {} + + explicit op_state(const associate_data_t& ad, Rcvr& r) + requires @\libconcept{copy_constructible}@ + : op_state(associate_data_t(ad).release(), r) {} + op_state(op_state&&) = delete; ~op_state() { - if (@\exposid{associated}@) { - @\exposid{assoc}@.@\exposid{op}@.~op_t(); - @\exposid{assoc}@.@\exposid{token}@.disassociate(); - @\exposid{assoc}@.@\exposid{token}@.~scope_tkn(); + if (@\exposid{assoc}@) { + @\exposid{op}@.~op_t(); } } void @\exposid{run}@() noexcept { // \expos - if (@\exposid{associated}@) - start(@\exposid{assoc}@.@\exposid{op}@); - else + if (@\exposid{assoc}@) { + start(@\exposid{op}@); + } else { set_stopped(std::move(*@\exposid{rcvr}@)); + } } }; - if (dataParts) - return op_state{std::move(dataParts->first), std::move(dataParts->second), rcvr}; - else - return op_state{rcvr}; + return op_state{std::forward_like(data), @\exposid{rcvr}@}; } \end{codeblock} @@ -5124,8 +5391,8 @@ The expression in the \tcode{noexcept} clause of \tcode{\exposid{impls-for}::\exposid{get-state}} is \begin{codeblock} -is_nothrow_constructible_v, Sndr> && -is_nothrow_move_constructible_v<@\exposid{wrap-sender}@> && +(is_same_v> || + is_nothrow_constructible_v, Sndr>) && @\exposconcept{nothrow-callable}@ \end{codeblock} where \exposid{wrap-sender} is the type @@ -5170,7 +5437,8 @@ if \tcode{remove_cvref_t} models \libconcept{unstoppable_token} then \tcode{\exposid{stop-when}(\brk{}sndr, token)} is expression-equivalent to -\tcode{sndr}. +\tcode{(void)token, sndr}, +except that \tcode{token} and \tcode{sndr} are indeterminately sequenced. \item Otherwise, @@ -5248,6 +5516,18 @@ are not satisfied, the expression \tcode{spawn_future(sndr, token, env)} is ill-formed. +\pnum +Let \exposid{try-cancelable} be the exposition-only class: + +\indexlibraryglobal{execution::\exposid{try-cancelable}}% +\begin{codeblock} +namespace std::execution { + struct @\exposid{try-cancelable}@ { // \expos + virtual void @\exposid{try-cancel}@() noexcept = 0; // \expos + }; +} +\end{codeblock} + \pnum Let \exposid{spawn-future-state-base} be the exposition-only class template: @@ -5258,7 +5538,8 @@ struct @\exposid{spawn-future-state-base}@; // \expos template - struct @\exposid{spawn-future-state-base}@> { // \expos + struct @\exposid{spawn-future-state-base}@> // \expos + : @\exposid{try-cancelable}@ { using @\exposid{variant-t}@ = @\seebelow@; // \expos @\exposid{variant-t}@ @\exposid{result}@; // \expos virtual void @\exposid{complete}@() noexcept = 0; // \expos @@ -5300,7 +5581,7 @@ namespace std::execution { template struct @\exposid{spawn-future-receiver}@ { // \expos - using receiver_concept = receiver_t; + using receiver_concept = receiver_tag; @\exposid{spawn-future-state-base}@* @\exposid{state}@; // \expos @@ -5340,8 +5621,10 @@ \pnum Let \tcode{\placeholder{ssource-t}} be an unspecified type -that models \exposconcept{stoppable-source} and -let \tcode{ssource} be an lvalue of type \tcode{\placeholder{ssource-t}}. +that models \exposconcept{stoppable-source} and \libconcept{default_initializable}, +such that a default-initialized object of type \tcode{\placeholder{ssource-t}} +has an associated stop state. +Let \tcode{ssource} be an lvalue of type \tcode{\placeholder{ssource-t}}. Let \tcode{\placeholder{stoken-t}} be \tcode{decltype(ssource.get_token())}. Let \exposid{future-spawned-sender} be the alias template: @@ -5358,50 +5641,57 @@ \begin{codeblock} namespace std::execution { template - struct @\exposid{spawn-future-state}@ // \expos + struct @\exposidnc{spawn-future-state}@ // \expos : @\exposid{spawn-future-state-base}@>> { - using @\exposid{sigs-t}@ = // \expos + using @\exposidnc{sigs-t}@ = // \expos completion_signatures_of_t<@\exposid{future-spawned-sender}@>; - using @\exposid{receiver-t}@ = // \expos + using @\exposidnc{receiver-t}@ = // \expos @\exposid{spawn-future-receiver}@<@\exposid{sigs-t}@>; - using @\exposid{op-t}@ = // \expos + using @\exposidnc{op-t}@ = // \expos connect_result_t<@\exposid{future-spawned-sender}@, @\exposid{receiver-t}@>; - @\exposid{spawn-future-state}@(Alloc alloc, Sender&& sndr, Token token, Env env) // \expos + @\exposidnc{spawn-future-state}@(Alloc alloc, Sender&& sndr, Token token, Env env) // \expos : @\exposid{alloc}@(std::move(alloc)), @\exposid{op}@(connect( write_env(@\exposid{stop-when}@(std::forward(sndr), @\exposid{ssource}@.get_token()), std::move(env)), @\exposid{receiver-t}@(this))), - @\exposid{token}@(std::move(token)), - @\exposid{associated}@(token.try_associate()) { - if (associated) + @\exposid{assoc}@(token.try_associate()) { + if (@\exposid{assoc}@) start(@\exposid{op}@); else set_stopped(@\exposid{receiver-t}@(this)); } - void @\exposid{complete}@() noexcept override; // \expos - void @\exposid{consume}@(@\libconcept{receiver}@ auto& rcvr) noexcept; // \expos - void @\exposid{abandon}@() noexcept; // \expos + void @\exposidnc{complete}@() noexcept override; // \expos + void @\exposidnc{consume}@(@\libconcept{receiver}@ auto& rcvr) noexcept; // \expos + void @\exposidnc{abandon}@() noexcept; // \expos + void @\exposidnc{try-cancel}@() noexcept override { // \expos + @\exposid{ssource}@.request_stop(); + @\exposid{try-set-stopped}@(); + } + void @\exposidnc{try-set-stopped}@() noexcept; // \expos private: - using @\exposid{alloc-t}@ = // \expos - allocator_traits::template rebind_alloc<@\exposid{spawn-future-state}@>; + using @\exposidnc{assoc-t}@ = // \expos + remove_cvref_t().try_associate())>; - @\exposid{alloc-t}@ @\exposid{alloc}@; // \expos - @\exposid{ssource-t}@ @\exposid{ssource}@; // \expos - @\exposid{op-t}@ @\exposid{op}@; // \expos - Token @\exposid{token}@; // \expos - bool @\exposid{associated}@; // \expos + Alloc @\exposidnc{alloc}@; // \expos + @\exposidnc{ssource-t}@ @\exposidnc{ssource}@; // \expos + @\exposidnc{op-t}@ @\exposidnc{op}@; // \expos + @\exposidnc{assoc-t}@ @\exposidnc{assoc}@; // \expos - void @\exposid{destroy}@() noexcept; // \expos + void @\exposidnc{destroy}@() noexcept; // \expos }; + + template // \expos + @\exposid{spawn-future-state}@(Alloc alloc, Sender&& sndr, Token token, Env env) + -> @\exposid{spawn-future-state}@; } \end{codeblock} \pnum For purposes of determining the existence of a data race, -\exposid{complete}, \exposid{consume}, and \exposid{abandon} +\exposid{complete}, \exposid{consume}, \exposid{try-set-stopped}, and \exposid{abandon} behave as atomic operations\iref{intro.multithread}. These operations on a single object of a type that is a specialization of \exposid{spawn-future-state} @@ -5418,13 +5708,18 @@ \begin{itemize} \item No effects if this invocation of \exposid{complete} happens before -an invocation of \exposid{consume} or \exposid{abandon} on \tcode{*this}; +an invocation of +\exposid{consume}, \exposid{try-set-\linebreak{}stopped}, or \exposid{abandon} +on \tcode{*this}; \item otherwise, if an invocation of \exposid{consume} on \tcode{*this} happens before -this invocation of \exposid{complete} then +this invocation of \exposid{complete} and +no invocation of \exposid{try-set-stopped} on \tcode{*this} happened before +this invocation of \tcode{complete} then there is a receiver, \tcode{rcvr}, registered and -that receiver is completed as if by \tcode{\exposid{consume}(rcvr)}; +that receiver is deregistered and completed +as if by \tcode{\exposid{consume}(rcvr)}; \item otherwise, \exposid{destroy} is invoked. @@ -5442,10 +5737,20 @@ \begin{itemize} \item If this invocation of \exposid{consume} happens before -an invocation of \exposid{complete} on \tcode{*this} then +an invocation of \exposid{complete} on \tcode{*this} and +no invocation of \exposid{try-set-stopped} on \tcode{*this} happened before +this invocation of \exposid{consume} then \tcode{rcvr} is registered to be completed when \exposid{complete} is subsequently invoked on \tcode{*this}; +\item +otherwise, +if this invocation of \exposid{consume} happens after +an invocation of \exposid{try-set-stopped} on \tcode{*this} and +no invocation of \exposid{complete} on \tcode{*this} happened before +this invocation of \exposid{consume} then +\tcode{rcvr} is completed as if by \tcode{set_stopped(std::move(rcvr))}; + \item otherwise, \tcode{rcvr} is completed as if by: @@ -5458,10 +5763,34 @@ }, std::move(tuple)); } }); +@\exposid{destroy}@(); \end{codeblock} \end{itemize} \end{itemdescr} +\indexlibrarymember{\exposid{try-set-stopped}}{execution::\exposid{spawn-future-state}}% +\begin{itemdecl} +void @\exposid{try-set-stopped}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +If an invocation of \exposid{consume} on \tcode{*this} happens before +this invocation of \exposid{try-set-stopped} and +no invocation of \exposid{complete} on \tcode{*this} happened before +this invocation of \exposid{try-set-stopped} then +there is a receiver, \tcode{rcvr}, registered and +that receiver is deregistered and completed as if by +\tcode{set_stopped(std::move(rcvr)), \exposid{destroy}()}; + +\item +otherwise, no effects. +\end{itemize} +\end{itemdescr} + \indexlibrarymember{\exposid{abandon}}{execution::\exposid{spawn-future-state}}% \begin{itemdecl} void @\exposid{abandon}@() noexcept; @@ -5494,21 +5823,97 @@ \effects Equivalent to: \begin{codeblock} -auto token = std::move(this->@\exposid{token}@); -bool associated = this->@\exposid{associated}@; - +auto associated = std::move(this->@\exposid{associated}@); { - auto alloc = std::move(this->@\exposid{alloc}@); - - allocator_traits<@\exposid{alloc-t}@>::destroy(alloc, this); - allocator_traits<@\exposid{alloc-t}@>::deallocate(alloc, this, 1); + using traits = allocator_traits::template rebind_traits<@\exposid{spawn-future-state}@>; + typename traits::allocator_type alloc(std::move(this->@\exposid{alloc}@)); + traits::destroy(alloc, this); + traits::deallocate(alloc, this, 1); } - -if (associated) - token.disassociate(); \end{codeblock} \end{itemdescr} +\pnum +Let \exposid{future-operation} be the exposition-only class template: + +\begin{codeblock} +namespace std::execution { + template + struct @\exposid{future-operation}@ { // \expos + struct @\exposid{callback}@ { // \expos + @\exposid{try-cancelable}@* @\exposid{state}@; // \expos + + void operator()() noexcept { + @\exposid{state}@->@\exposid{try-cancel}@(); + }; + }; + + using @\exposid{stop-token-t}@ = // \expos + stop_token_of_t>; + + using @\exposid{stop-callback-t}@ = // \expos + stop_callback_for_t<@\exposid{stop-token-t}@, @\exposid{callback}@>; + + struct @\exposid{rcvr-t}@ { // \expos + using receiver_concept = receiver_tag; + @\exposid{future-operation}@* @\exposid{op}@; // \expos + + template + void set_value(T&&... ts) && noexcept { + @\exposid{op}@->@\exposid{set-complete}@(std::forward(ts)...); + } + + template + void set_error(E&& e) && noexcept { + @\exposid{op}@->@\exposid{set-complete}@(std::forward(e)); + } + + void set_stopped() && noexcept { + @\exposid{op}@->@\exposid{set-complete}@(); + } + + env_of_t get_env() const noexcept { + return execution::get_env(@\exposid{op}@->@\exposid{rcvr}@); + } + }; + + Rcvr @\exposid{rcvr}@; // \expos + StatePtr @\exposid{state}@; // \expos + @\exposid{rcvr-t}@ @\exposid{inner}@; // \expos + optional<@\exposid{stop-callback-t}@> @\exposid{stopCallback}@; // \expos + + + @\exposid{future-operation}@(StatePtr state, Rcvr rcvr) noexcept // \expos + : @\exposid{rcvr}@(std::move(rcvr)), @\exposid{state}@(std::move(state)), @\exposid{inner}@(this) + {} + + @\exposid{future-operation}@(@\exposid{future-operation}@&&) = delete; + + void @\exposid{run}@() & noexcept { // \expos + constexpr bool nothrow = + is_nothrow_constructible_v<@\exposid{stop-callback-t}@, @\exposid{stop-token-t}@, @\exposid{callback}@>; + try { + @\exposid{stopCallback}@.emplace(get_stop_token(@\exposid{rcvr}@), @\exposid{callback}@(@\exposid{state}@.get())); + } + catch (...) { + if constexpr (!nothrow) { + set_error(std::move(@\exposid{rcvr}@), current_exception()); + return; + } + } + + @\exposid{state}@.release()->@\exposid{consume}@(@\exposid{inner}@); + } + + template + void @\exposid{set-complete}@(T&&... ts) noexcept { // \expos + @\exposid{stopCallback}@.reset(); + CPO{}(std::move(@\exposid{rcvr}@), std::forward(ts)...); + } + }; +} +\end{codeblock} + \pnum The exposition-only class template \exposid{impls-for}\iref{exec.snd.expos} is specialized for \tcode{spawn_future_t} as follows: @@ -5519,6 +5924,7 @@ template<> struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { static constexpr auto @\exposid{start}@ = @\seebelow@; // \expos + static constexpr auto @\exposid{get-state}@ = @\seebelow@; // \expos }; } \end{codeblock} @@ -5527,8 +5933,19 @@ The member \tcode{\exposid{impls-for}::\exposid{start}} is initialized with a callable object equivalent to the following lambda: \begin{codeblock} -[](auto& state, auto& rcvr) noexcept -> void { - state->@\exposid{consume}@(rcvr); +[](auto& state, auto&) noexcept -> void { + state.@\exposid{run}@(); +} +\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 { + auto& [_, data] = sndr; + using state_ptr = remove_cvref_t; + return @\exposid{future-operation}@(std::move(data), std::move(rcvr)); } \end{codeblock} @@ -5559,8 +5976,8 @@ \begin{itemize} \item -Uses \tcode{alloc} to allocate and construct an object \tcode{s} of -a type that is a specialization of \exposid{spawn-future-\brk{}state} +Uses \tcode{alloc} to allocate and construct an object \tcode{s} of type +\tcode{decltype(\exposid{spawn-future-state}(alloc, token.wrap(sndr), token, senv))} from \tcode{alloc}, \tcode{token.wrap(sndr)}, \tcode{token}, and \tcode{senv}. If an exception is thrown then any constructed objects are destroyed and @@ -5609,6 +6026,10 @@ return @\exposid{loop}@->get_scheduler(); } + auto query(execution::get_start_scheduler_t) const noexcept { + return @\exposid{loop}@->get_scheduler(); + } + auto query(execution::get_delegation_scheduler_t) const noexcept { return @\exposid{loop}@->get_scheduler(); } @@ -5637,11 +6058,11 @@ The name \tcode{this_thread::sync_wait} denotes a customization point object. For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. The expression \tcode{this_thread::sync_wait(sndr)} -is expression-equivalent to the following, -except that \tcode{sndr} is evaluated only once: -\begin{codeblock} -apply_sender(@\exposid{get-domain-early}@(sndr), sync_wait, sndr) -\end{codeblock} +is equivalent to \tcode{apply_sender(Domain(), sync_wait, sndr)}, +where \tcode{Domain} is the type of +\tcode{get_completion_domain(get_env(sndr), \exposid{sync-wait-env}\{\})}. + +\pnum \mandates \begin{itemize} \item @@ -5667,7 +6088,7 @@ template struct @\exposid{sync-wait-receiver}@ { // \expos - using receiver_concept = execution::receiver_t; + using receiver_concept = execution::receiver_tag; @\exposidnc{sync-wait-state}@* @\exposid{state}@; // \expos template @@ -5729,7 +6150,7 @@ \pnum For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. -If \tcode{\libconcept{sender_to}>} +If \tcode{\exposconcept{sender-to}>} is \tcode{false}, the expression \tcode{sync_wait.apply_sender(sndr)} is ill-formed; otherwise, it is equivalent to: @@ -5781,11 +6202,11 @@ For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype(into_variant(sndr))}. The expression \tcode{this_thread::sync_wait_with_variant(sndr)} -is expression-equivalent to the following, -except \tcode{sndr} is evaluated only once: -\begin{codeblock} -apply_sender(@\exposid{get-domain-early}@(sndr), sync_wait_with_variant, sndr) -\end{codeblock} +is equivalent to \tcode{apply_sender(Domain(), sync_wait_with_variant, sndr)}, +where \tcode{Domain} is the type of +\tcode{get_completion_domain(get_env(sndr), \exposid{sync-wait-env}\{\})}. + +\pnum \mandates \begin{itemize} \item @@ -5876,7 +6297,7 @@ \begin{codeblock} namespace std::execution { struct @\exposid{spawn-receiver}@ { // \expos - using receiver_concept = receiver_t; + using receiver_concept = receiver_tag; @\exposid{spawn-state-base}@* @\exposid{state}@; // \expos void set_value() && noexcept { @\exposid{state}@->@\exposid{complete}@(); } @@ -5897,17 +6318,15 @@ @\exposid{spawn-state}@(Alloc alloc, Sender&& sndr, Token token); // \expos void @\exposid{complete}@() noexcept override; // \expos - void @\exposid{run}@(); // \expos + void @\exposid{run}@() noexcept; // \expos private: - using @\exposid{alloc-t}@ = // \expos - allocator_traits::template rebind_alloc<@\exposid{spawn-state}@>; + using @\exposid{assoc-t}@ = // \expos + remove_cvref_t().try_associate())>; - @\exposid{alloc-t}@ @\exposid{alloc}@; // \expos + Alloc @\exposid{alloc}@; // \expos @\exposid{op-t}@ @\exposid{op}@; // \expos - Token @\exposid{token}@; // \expos - - void @\exposid{destroy}@() noexcept; // \expos + @\exposid{assoc-t}@ @\exposid{assoc}@; // \expos }; } \end{codeblock} @@ -5921,17 +6340,14 @@ \pnum \effects Initializes -\exposid{alloc} with \tcode{alloc}, -\exposid{token} with \tcode{token}, and -\exposid{op} with: -\begin{codeblock} -connect(std::move(sndr), @\exposid{spawn-receiver}@(this)) -\end{codeblock} +\exposid{alloc} with \tcode{std::move(alloc)}, +\exposid{op} with \tcode{connect(std::move(sndr), \exposid{spawn-re\-ceiv\-er}(this))}, and +\exposid{assoc} with \tcode{token.try_associate()}. \end{itemdescr} \indexlibrarymember{\exposid{run}}{execution::\exposid{spawn-state}}% \begin{itemdecl} -void @\exposid{run}@(); +void @\exposid{run}@() noexcept; \end{itemdecl} \begin{itemdescr} @@ -5939,10 +6355,10 @@ \effects Equivalent to: \begin{codeblock} -if (@\exposid{token}@.try_associate()) +if (@\exposid{assoc}@) start(@\exposid{op}@); else - @\exposid{destroy}@(); + @\exposid{complete}@(); \end{codeblock} \end{itemdescr} @@ -5956,27 +6372,13 @@ \effects Equivalent to: \begin{codeblock} -auto token = std::move(this->@\exposid{token}@); - -@\exposid{destroy}@(); -token.disassociate(); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{\exposid{destroy}}{execution::\exposid{spawn-state}}% -\begin{itemdecl} -void @\exposid{destroy}@() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -auto alloc = std::move(this->@\exposid{alloc}@); - -allocator_traits<@\exposid{alloc-t}@>::destroy(alloc, this); -allocator_traits<@\exposid{alloc-t}@>::deallocate(alloc, this, 1); +auto assoc = std::move(this->@\exposid{assoc}@); +{ + using traits = allocator_traits::template rebind_traits<@\exposid{spawn-state}@>; + typename traits::allocator_type alloc(this->@\exposid{alloc}@); + traits::destroy(alloc, this); + traits::deallocate(alloc, this, 1); +} \end{codeblock} \end{itemdescr} @@ -6006,9 +6408,9 @@ %%FIXME: Was this supposed to be more than a single bullet? \begin{itemize} \item -Uses \tcode{alloc} to allocate and construct an object \tcode{o} of -type that is a specialization of \tcode{\exposid{spawn-state}} from -\tcode{alloc}, \tcode{write_env(token.wrap(sndr), senv)}, and \tcode{token} +Uses \tcode{alloc} to allocate and construct an object \tcode{o} of type +\tcode{decltype(\exposid{spawn-state}(alloc, write_env(token.wrap(sndr), senv), token))} +from \tcode{alloc}, \tcode{write_env(token.wrap(sndr), senv)}, and \tcode{token} and then invokes \tcode{o.\exposid{run}()}. If an exception is thrown then @@ -6029,7 +6431,7 @@ \begin{example} \begin{codeblock} struct my_sender { - using sender_concept = sender_t; + using sender_concept = sender_tag; using completion_signatures = execution::completion_signatures< set_value_t(), @@ -6132,7 +6534,7 @@ template static constexpr void @\exposid{for-each}@(Fn&& fn) { // \expos - (std::forward(fn)(static_cast(nullptr)), ...); + (fn(static_cast(nullptr)), ...); } }; @@ -6177,7 +6579,7 @@ QueryTag @\exposid{query_}@; // \expos ValueType @\exposid{value_}@; // \expos - constexpr const ValueType& query(QueryTag) const noexcept { + constexpr const ValueType& query(QueryTag, auto&&...) const noexcept { return @\exposid{value_}@; } }; @@ -6207,7 +6609,7 @@ \begin{example} \begin{codeblock} template<@\libconcept{sender}@ Sndr> -sender auto parameterize_work(Sndr sndr) { +@\libconcept{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{}); @@ -6231,8 +6633,8 @@ @\vdots@ Envs@$_{n-1}$@ @$\exposid{envs}_{n-1}$@; // \expos - template - constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@); + template + constexpr decltype(auto) query(QueryTag q, Args&&... args) const noexcept(@\seebelow@); }; template @@ -6275,38 +6677,40 @@ \indexlibrarymember{query}{env}% \begin{itemdecl} -template -constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@); +template +constexpr decltype(auto) query(QueryTag q, Args&&... args) const noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum Let \exposconcept{has-query} be the following exposition-only concept: \begin{codeblock} -template +template concept @\defexposconcept{has-query}@ = // \expos - requires (const Env& env) { - env.query(QueryTag()); + requires (const Env& env, Args&&... args) { + env.query(QueryTag(), std::forward(args)...); }; \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. +such that the expression +\tcode{\exposid{fe}.query(q, std::forward(args)...)} +is well-formed. \pnum \constraints -\tcode{(\exposconcept{has-query} || ...)} is \tcode{true}. +\tcode{(\exposconcept{has-query} || ...)} is \tcode{true}. \pnum \effects -Equivalent to: \tcode{return \exposid{fe}.query(q);} +Equivalent to: \tcode{return \exposid{fe}.query(q, std::forward(args)...);} \pnum \remarks The expression in the \tcode{noexcept} clause is equivalent -to \tcode{noexcept(\exposid{fe}.query(q))}. +to \tcode{noexcept(\exposid{fe}.query(q, std::for\-ward(args)...))}. \end{itemdescr} \rSec1[exec.ctx]{Execution contexts} @@ -6347,7 +6751,7 @@ 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 + virtual void @\exposid{execute}@() noexcept = 0; // \expos run_loop* @\exposid{loop}@; // \expos @\exposid{run-loop-opstate-base}@* @\exposid{next}@; // \expos }; @@ -6355,8 +6759,8 @@ 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 + @\exposid{run-loop-opstate-base}@* @\exposid{pop-front}@() noexcept; // \expos + void @\exposid{push-back}@(@\exposid{run-loop-opstate-base}@*) noexcept; // \expos public: // \ref{exec.run.loop.ctor}, constructor and destructor @@ -6365,9 +6769,9 @@ ~run_loop(); // \ref{exec.run.loop.members}, member functions - @\exposid{run-loop-scheduler}@ get_scheduler(); - void run(); - void finish(); + @\exposid{run-loop-scheduler}@ get_scheduler() noexcept; + void run() noexcept; + void finish() noexcept; }; } \end{codeblock} @@ -6397,6 +6801,12 @@ has type \exposid{run-loop-\newline sender} and is not potentially-throwing if \exposid{sch} is not potentially-throwing. +\pnum +For type \exposid{set-tag} other than \tcode{set_error_t}, +the expression +\tcode{get_completion_scheduler<\exposid{set-tag}>(get_env(schedule(\exposid{sch}))) == \exposid{sch}} +evaluates to \tcode{true}. + \begin{itemdecl} class @\exposid{run-loop-sender}@; \end{itemdecl} @@ -6404,10 +6814,11 @@ \pnum \exposid{run-loop-sender} is an exposition-only type that satisfies \libconcept{sender}. -\tcode{completion_signatures_of_t<\exposid{run-\linebreak{}loop-sender}>} is -\begin{codeblock} -completion_signatures -\end{codeblock} +Let \tcode{E} be the type of an environment. +If \tcode{unstoppable_token>} is \tcode{true}, then +\tcode{completion_signatures_of_t<\exposid{run-loop-sen\-der}, E>} is +\tcode{completion_signatures}. +Otherwise, it is \tcode{completion_signatures}. \pnum An instance of \exposid{run-loop-sender} remains valid @@ -6416,7 +6827,7 @@ \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} +such that \tcode{\exposconcept{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: @@ -6467,11 +6878,7 @@ \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()); -} +@$o$@.@\exposid{loop}@->@\exposid{push-back}@(addressof(@$o$@)); \end{codeblock} \end{itemize} @@ -6506,7 +6913,7 @@ \rSec3[exec.run.loop.members]{Member functions} \begin{itemdecl} -@\exposid{run-loop-opstate-base}@* @\exposid{pop-front}@(); +@\exposid{run-loop-opstate-base}@* @\exposid{pop-front}@() noexcept; \end{itemdecl} \begin{itemdescr} @@ -6527,7 +6934,7 @@ \end{itemdescr} \begin{itemdecl} -void @\exposid{push-back}@(@\exposid{run-loop-opstate-base}@* item); +void @\exposid{push-back}@(@\exposid{run-loop-opstate-base}@* item) noexcept; \end{itemdecl} \begin{itemdescr} @@ -6544,7 +6951,7 @@ \indexlibrarymember{get_scheduler}{run_loop}% \begin{itemdecl} -@\exposid{run-loop-scheduler}@ get_scheduler(); +@\exposid{run-loop-scheduler}@ get_scheduler() noexcept; \end{itemdecl} \begin{itemdescr} @@ -6556,7 +6963,7 @@ \indexlibrarymember{run}{run_loop}% \begin{itemdecl} -void run(); +void run() noexcept; \end{itemdecl} \begin{itemdescr} @@ -6584,7 +6991,7 @@ \indexlibrarymember{finish}{run_loop}% \begin{itemdecl} -void finish(); +void finish() noexcept; \end{itemdecl} \begin{itemdescr} @@ -6616,7 +7023,8 @@ template concept @\defexposconcept{awaitable-sender}@ = @\exposconcept{single-sender}@> && - @\libconcept{sender_to}@ && // \seebelow + @\exposconcept{sender-to}@::@\exposid{awaitable-receiver}@> && // \seebelow requires (Promise& p) { { p.unhandled_stopped() } -> @\libconcept{convertible_to}@>; }; @@ -6663,7 +7071,7 @@ \exposid{awaitable-receiver} is equivalent to: \begin{codeblock} struct @\exposid{awaitable-receiver}@ { - using receiver_concept = receiver_t; + using receiver_concept = receiver_tag; variant* @\exposidnc{result-ptr}@; // \expos coroutine_handle @\exposidnc{continuation}@; // \expos // \seebelow @@ -6674,31 +7082,42 @@ 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: +let \tcode{err} be an expression of type \tcode{Err}. +Let \tcode{\placeholder{MAKE-NOEXCEPT}(expr)} +for some subexpression \tcode{expr} be expression-equivalent to +\tcode{[\&] noexcept -> decltype(auto) \{ return (expr); \}()}. +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: +The expression \tcode{set_value(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(); +@\placeholder{MAKE-NOEXCEPT}@(rcvr.@\exposid{continuation}@.resume()); \end{codeblock} -Otherwise, \tcode{set_value(rcvr, vs...)} is ill-formed. + +\mandates +\tcode{\libconcept{constructible_from}<\exposid{result-type}, decltype((vs))...>} +is satisfied. \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(); +try { + rcvr.@\exposid{result-ptr}@->template emplace<2>(@\exposid{AS-EXCEPT-PTR}@(err)); // see \ref{exec.general} +} catch(...) { + rcvr.@\exposid{result-ptr}@->template emplace<2>(current_exception()); +} +@\placeholder{MAKE-NOEXCEPT}@(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(); +@\placeholder{MAKE-NOEXCEPT}@( + static_cast>( + rcvr.@\exposid{continuation}@.promise().unhandled_stopped()).resume()); \end{codeblock} \item For any expression \tcode{tag} @@ -6706,7 +7125,8 @@ 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...) +tag(get_env(as_const(@\placeholder{MAKE-NOEXCEPT}@(crcvr.@\exposid{continuation}@.promise()))), + as...) \end{codeblock} \end{itemize} @@ -6720,7 +7140,7 @@ Initializes \exposid{state} with \begin{codeblock} connect(std::forward(sndr), - @\exposid{awaitable-receiver}@{addressof(result), coroutine_handle::from_promise(p)}) + @\exposid{awaitable-receiver}@{addressof(@\exposid{result}@), coroutine_handle::from_promise(p)}) \end{codeblock} \end{itemdescr} @@ -6757,37 +7177,42 @@ \tcode{\exposconcept{is-awaitable}} is \tcode{true}, where \tcode{A} is the type of the expression above. \item -Otherwise, \tcode{(void(p), expr)} -if \tcode{\exposconcept{is-awaitable}} is \tcode{true}, -where \tcode{U} is an unspecified class type -that is not \tcode{Promise} and -that lacks a member named \tcode{await_transform}. - -\expects -\tcode{\exposconcept{is-awaitable}} is \tcode{true} and -the expression \tcode{co_await expr} -in a coroutine with promise type \tcode{U} is expression-equivalent to -the same expression in a coroutine with promise type \tcode{Promise}. -\item -Otherwise, \tcode{\exposid{sender-awaitable}\{\exposid{adapted-expr}, p\}} -if +Otherwise, \begin{codeblock} -@\exposid{has-queryable-await-completion-adaptor}@ +@\exposid{adapt-for-await-completion}@(transform_sender(expr, get_env(p))).as_awaitable(p) \end{codeblock} -and +if this expression is well-formed, +\tcode{\libconcept{sender_in}>} is \tcode{true}, and +\tcode{\exposid{single-sen\-der-value-type}>} +is well-formed, +except that \tcode{p} is only evaluated once. +\item +Otherwise, \tcode{(void(p), expr)} +if \tcode{decltype(\exposid{GET-AWAITER}(expr))} +satisfies \tcode{\exposconcept{is-awaiter}}. +\item +Otherwise, \begin{codeblock} -@\exposid{awaitable-sender}@ +@\exposid{sender-awaitable}@{@\exposid{adapt-for-await-completion}@(transform_sender(expr, get_env(p))), p} \end{codeblock} -are both satisfied, where \exposid{adapted-expr} is -\tcode{get_await_completion_adaptor(get_env(expr))(expr)}, -except that \tcode{expr} is evaluated only once. -\item -Otherwise, \tcode{\exposid{sender-awaitable}\{expr, p\}} -if \tcode{\exposconcept{awaitable-sender}} is \tcode{true}. +if \tcode{sender_in>} is \tcode{true} and +\tcode{\exposid{single-sender-value-type}>} +is well-formed, +except that \tcode{p} is only evaluated once. \item Otherwise, \tcode{(void(p), expr)}. \end{itemize} +\pnum +\tcode{\exposid{adapt-for-await-completion}(s)} is expression-equivalent to +\begin{itemize} +\item +\tcode{get_await_completion_adaptor(get_env(s))(s)} if that is well-formed, +except that \tcode{s} is evaluated only once, +\item +otherwise, \tcode{s}. +\end{itemize} + \rSec2[exec.with.awaitable.senders]{\tcode{execution::with_awaitable_senders}} \pnum @@ -6872,65 +7297,88 @@ \end{codeblock} \end{itemdescr} -\rSec2[exec.affine.on]{\tcode{execution::affine_on}} +\rSec2[exec.affine]{\tcode{execution::affine}} \pnum -\tcode{affine_on} adapts a sender into one that completes on -the specified scheduler. +\tcode{affine} adapts a sender into one that completes on +the receiver's scheduler. If the algorithm determines that the adapted sender already completes on the correct scheduler it can avoid any scheduling operation. \pnum -The name \tcode{affine_on} denotes a pipeable sender adaptor +The name \tcode{affine} denotes a pipeable sender adaptor object. -For subexpressions \tcode{sch} and \tcode{sndr}, if \tcode{decltype((sch))} -does not satisfy \libconcept{scheduler}, or \tcode{decltype((sndr))} -does not satisfy \libconcept{sender}, \tcode{affine_on(sndr, sch)} +For a subexpression \tcode{sndr}, if \tcode{decltype((\brk{}sndr))} +does not satisfy \libconcept{sender}, \tcode{affine(sndr)} is ill-formed. \pnum -Otherwise, the expression \tcode{affine_on(sndr, sch)} is -expression-equivalent to: -\begin{codeblock} -transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(affine_on, sch, sndr)) -\end{codeblock} -except that \tcode{sndr} is evaluated only once. +Otherwise, the expression \tcode{affine(sndr)} is +expression-equivalent to \tcode{\exposid{make-sender}(affine, env<>(), sndr)}. \pnum -The exposition-only class template \exposid{impls-for}\iref{exec.snd.expos} -is specialized for \tcode{affine_on_t} as follows: +For a subexpression \tcode{sch} whose type models \libconcept{scheduler}, +let \tcode{\exposid{UNSTOPPABLE-SCHEDULER}(sch)} be an expression \tcode{e} +whose type models \libconcept{scheduler} such that: +\begin{itemize} +\item +\tcode{schedule(e)} is expression-equivalent to \tcode{unstoppable(schedule(sch))}. +\item +For any query object \tcode{q} and pack of subexpressions \tcode{args...}, +\tcode{e.query(q, args...)} is expression-equivalent to +\tcode{sch.query(q, args...)}. +\item +The expression \tcode{e == \exposid{UNSTOPPABLE-SCHEDULER}(other)} +is expression-equivalent to \tcode{sch == other}. +\end{itemize} +\pnum +Let \tcode{sndr} and \tcode{ev} be subexpressions +such that \tcode{Sndr} is \tcode{decltype((sndr))}. +If \tcode{\exposconcept{sender-for}} is \tcode{false}, +then the expression \tcode{affine.transform_sender(sndr, ev)} is ill-formed; +otherwise, it is equal to: \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))); - }; - }; +auto& [_, _, child] = sndr; +if constexpr (requires { std::forward_like(child).affine(); }) { + return std::forward_like(child).affine(); +} else { + return continues_on(std::forward_like(child), + @\exposidnc{UNSTOPPABLE-SCHEDULER}@(get_start_scheduler(ev))); } \end{codeblock} +\pnum +\recommended +Implementations should provide \tcode{affine} member functions +for senders that are known to resume on the scheduler where they were started. +Example senders for which that is the case are +\tcode{just}, +\tcode{just_error}, +\tcode{just_stopped}, +\tcode{read_env}, and +\tcode{write_env}. + \pnum Let \tcode{\placeholder{out_sndr}} be a subexpression denoting a sender -returned from \tcode{affine_on(sndr, sch)} or one equal to such, +returned from \tcode{affine(sndr)} or one equal to such, and let \tcode{\placeholder{OutSndr}} be the type \tcode{decltype((\placeholder{out_sndr}))}. Let \tcode{\placeholder{out_rcvr}} be a subexpression denoting a receiver that -has an environment of type \tcode{Env} such that \tcode{\libconcept{sender_in}<\placeholder{OutSndr}, Env>} -is \tcode{true}. +has an environment of type \tcode{Env}. +If \tcode{get_start_scheduler(get_env(\placeholder{out_rcvr}))} is ill-formed or +does not satisfy \tcode{\exposconcept{infallible-scheduler}}, +then evaluation of +the expression \tcode{get_completion_signatures<\placeholder{OutSndr}, Env>()} +exits with an exception. Let \tcode{\placeholder{op}} be an lvalue referring to the operation state that results from connecting \tcode{\placeholder{out_sndr}} to \tcode{\placeholder{out_rcvr}}. Calling \tcode{start(\placeholder{op})} will start \tcode{sndr} on the current execution agent and execute completion operations on \tcode{\placeholder{out_rcvr}} on an execution agent of the execution resource associated with -\tcode{sch}. +\tcode{\placeholder{sch}}. If the current execution resource is the same as the execution -resource associated with \tcode{sch}, the completion operation on +resource associated with \tcode{\placeholder{sch}}, the completion operation on \tcode{\placeholder{out_rcvr}} may be called before \tcode{start(\placeholder{op})} completes. -If scheduling onto \tcode{sch} fails, an error completion on -\tcode{\placeholder{out_rcvr}} shall be executed on an unspecified execution -agent. \rSec2[exec.inline.scheduler]{\tcode{execution::inline_scheduler}} @@ -6943,7 +7391,7 @@ class @\exposidnc{inline-state}@; // \expos public: - using scheduler_concept = scheduler_t; + using scheduler_concept = scheduler_tag; constexpr @\exposid{inline-sender}@ schedule() noexcept { return {}; } constexpr bool operator==(const inline_scheduler&) const noexcept = default; @@ -6955,6 +7403,11 @@ \tcode{inline_scheduler} is a class that models \libconcept{scheduler}\iref{exec.sched}. All objects of type \tcode{inline_scheduler} are equal. +For a subexpression \tcode{sch} of type \tcode{inline_scheduler}, +a query object \tcode{q}, and +a pack of subexpressions \tcode{args}, +the expression \tcode{sch.query(q, args...)} is expression-equivalent to +\tcode{\exposid{inline-attrs}().query(q, args...)}. \pnum \exposid{inline-sender} is an exposition-only type that satisfies @@ -6965,19 +7418,12 @@ \pnum Let \tcode{sndr} be an expression of type \exposid{inline-sender}, let \tcode{rcvr} be an expression such that -\tcode{\libconcept{receiver_of}} is \tcode{true} +\tcode{\exposconcept{receiver-of}} is \tcode{true} where \tcode{CS} is \tcode{completion_signatures}, -then: -\begin{itemize} -\item the expression \tcode{connect(sndr, rcvr)} has +then the expression \tcode{connect(sndr, rcvr)} has type \tcode{\exposid{inline-state}>} and is potentially-throwing if and only if -\tcode{((void)sndr, auto(rcvr))} is potentially-throwing, and -\item the expression -\tcode{get_completion_scheduler(get_env(sndr))} has -type\brk{} \tcode{inline_\-sched\-ul\-er} and is potentially-throwing -if and only if \tcode{get_env(sndr)} is potentially-throwing. -\end{itemize} +\tcode{((void)sndr, auto(rcvr))} is potentially-throwing. \pnum Let \tcode{\placeholder{o}} be a non-\tcode{const} lvalue of type @@ -6997,30 +7443,31 @@ \begin{codeblock} namespace std::execution { class @\libglobal{task_scheduler}@ { - class @\exposidnc{ts-sender}@; // \expos + class @\exposid{ts-domain}@; // \expos - template<@\libconcept{receiver}@ R> - class @\exposidnc{state}@; // \expos + template<@\libconcept{scheduler}@ Sch> + class @\exposid{backend-for}@; // \expos public: - using scheduler_concept = scheduler_t; + using scheduler_concept = scheduler_tag; template> - requires (!@\libconcept{same_as}@>) - && @\libconcept{scheduler}@ + requires (!@\libconcept{same_as}@>) && @\libconcept{scheduler}@ explicit task_scheduler(Sch&& sch, Allocator alloc = {}); - @\exposid{ts-sender}@ schedule(); + task_scheduler(const task_scheduler&) = default; + task_scheduler& operator=(const task_scheduler&) = default; - friend bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) - noexcept; + @\seebelow@ schedule(); + + friend bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) noexcept; template - requires (!@\libconcept{same_as}@) - && @\libconcept{scheduler}@ + requires (!@\libconcept{same_as}@) && @\libconcept{scheduler}@ friend bool operator==(const task_scheduler& lhs, const Sch& rhs) noexcept; private: - shared_ptr @\exposidnc{sch_}@; // \expos + // see \ref{exec.parschedrepl.psb} + shared_ptr @\exposidnc{sch_}@; // \expos }; } \end{codeblock} @@ -7029,7 +7476,12 @@ \tcode{task_scheduler} is a class that models \libconcept{scheduler}\iref{exec.sched}. Given an object \tcode{s} of type \tcode{task_scheduler}, let -\tcode{\exposid{SCHED}(s)} be the object owned by \tcode{s.\exposid{sch_}}. +\tcode{\exposid{SCHED}(s)} be the object +pointed to by the pointer owned by \tcode{s.\exposid{sch_}}. +The expression \tcode{get_forward_progress_guarantee(s)} is equivalent to +\tcode{get_forward_progress_guarantee(\exposid{SCHED}(s))}. +The expression \tcode{get_completion_domain(s)} is equivalent to +\tcode{task_scheduler::\exposid{ts-domain}()}. \indexlibraryctor{task_scheduler} \begin{itemdecl} @@ -7038,10 +7490,16 @@ explicit task_scheduler(Sch&& sch, Allocator alloc = {}); \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{Sch} satisfies \tcode{\exposconcept{infallible-scheduler}>}. + \pnum \effects -Initialize \exposid{sch_} with -\tcode{allocate_shared>(alloc,\brk{} std::forward\brk{}(sch))}. +Initializes \exposid{sch_} with: +\begin{codeblock} +allocate_shared<@\exposid{backend-for}@>>(alloc, std::forward(sch)) +\end{codeblock} \pnum \recommended @@ -7050,22 +7508,10 @@ \pnum \remarks -Any allocations performed by construction of \exposid{ts-sender} or -\exposid{state} objects resulting from calls on \tcode{*this} are +Any allocations performed by calls on \tcode{*this} are performed using a copy of \tcode{alloc}. \end{itemdescr} -\indexlibrarymember{scheduler}{task_scheduler}% -\begin{itemdecl} -@\exposid{ts-sender}@ schedule(); -\end{itemdecl} -\begin{itemdescr} -\pnum -\effects -Returns an object of type \exposid{ts-sender} containing a sender -initialized with \tcode{sched\-ule(\brk{}\exposid{SCHED}\brk{}(*this))}. -\end{itemdescr} - \indexlibrarymember{operator==}{task_scheduler}% \begin{itemdecl} bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) noexcept; @@ -7091,77 +7537,204 @@ \end{itemdescr} \pnum +For an lvalue \tcode{r} of a type derived from \tcode{receiver_proxy}, +let \tcode{\exposid{WRAP-RCVR}(r)} be an object of a type +that models \libconcept{receiver} and +whose completion handlers result in +invoking the corresponding completion handlers of \tcode{r}. \begin{codeblock} namespace std::execution { - class task_scheduler::@\exposidnc{ts-sender}@ { // \expos + template<@\libconcept{scheduler}@ Sch> + class task_scheduler::@\exposid{backend-for}@ + : public parallel_scheduler_replacement::parallel_scheduler_backend { // \expos public: - using sender_concept = sender_t; + explicit @\exposid{backend-for}@(Sch sch) : @\exposid{sched_}@(std::move(sch)) {} - template<@\libconcept{receiver}@ Rcvr> - @\exposid{state}@ connect(Rcvr&& rcvr); + void schedule(receiver_proxy& r, span s) noexcept override; + void schedule_bulk_chunked(size_t shape, bulk_item_receiver_proxy& r, + span s) noexcept override; + void schedule_bulk_unchunked(size_t shape, bulk_item_receiver_proxy& r, + span s) noexcept override; + + private: + Sch @\exposid{sched_}@; }; } \end{codeblock} -\exposid{ts-sender} is an exposition-only class that models -\libconcept{sender}\iref{exec.snd} and for which -\tcode{completion_signatures_of_t<\exposid{ts-sender}>} denotes: + +\pnum +Let \tcode{env} be a pack of subexpressions, and +let \exposid{just-sndr-like} be a sender +whose only value completion signature is \tcode{set_value_t()} and +for which the expression +\tcode{get_completion_scheduler(get_env(\exposid{just-sndr-like)}, env...)} +is expression-equivalent to +\tcode{get_completion_scheduler(\exposid{sched_}, env...)}. + +\begin{itemdecl} +void schedule(receiver_proxy& r, span s) noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an operation state \tcode{os} +with \tcode{connect(schedule(\exposid{sched_}), \exposid{WRAP-RCVR}(r))} and +calls \tcode{start(os)}. +\end{itemdescr} + +\begin{itemdecl} +void schedule_bulk_chunked(size_t shape, bulk_item_receiver_proxy& r, + span s) noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{chunk_size} be an integer less than or equal to \tcode{shape}, +let \tcode{num_chunks} be \tcode{(shape + chunk_size - 1) / chunk_size}, and +let \tcode{fn} be a function object such that +for an integer \tcode{i}, +\tcode{fn(i)} calls \tcode{r.execute(i * chunk_size, m)}, +where \tcode{m} is the lesser of \tcode{(i + 1) * chunk_size} and \tcode{shape}. +Constructs an operation state \tcode{os} as if with \begin{codeblock} -completion_signatures< - set_value_t(), - set_error_t(error_code), - set_error_t(exception_ptr), - set_stopped_t()> +connect(bulk(@\exposid{just-sndr-like}@, par, num_chunks, fn), @\exposid{WRAP-RCVR}@(r)) \end{codeblock} +and calls \tcode{start(os)}. +\end{itemdescr} + +\begin{itemdecl} +void schedule_bulk_unchunked(size_t shape, bulk_item_receiver_proxy& r, + span s) noexcept override; +\end{itemdecl} +\begin{itemdescr} \pnum -Let \tcode{\placeholder{sch}} be an object of type \tcode{task_scheduler} -and let \tcode{sndr} be an object of type \exposid{ts-sender} obtained -from \tcode{schedule(\placeholder{sch})}. -Then \tcode{get_completion_scheduler(get_env(sndr)) == \placeholder{sch}} -is \tcode{true}. -The object \tcode{\exposid{SENDER}(sndr)} is the sender object contained by -\tcode{sndr} or an object move constructed from it. +\effects +Let \tcode{fn} be a function object such that +for an integer \tcode{i}, +\tcode{fn(i)} is equivalent to \tcode{r.execute(i, i + 1)}. +Constructs an operation state \tcode{os} as if with +\begin{codeblock} +connect(bulk(@\exposid{just-sndr-like}@, par, shape, fn), @\exposid{WRAP-RCVR}@(r)) +\end{codeblock} +and calls \tcode{start(os)}. +\end{itemdescr} -\indexlibrarymember{connect}{task_scheduler::\exposid{ts-sender}}% \begin{itemdecl} -template<@\libconcept{receiver}@ Rcvr> - @\exposid{state}@ connect(Rcvr&& rcvr); +@\seebelow@ schedule(); \end{itemdecl} + \begin{itemdescr} \pnum -\effects -Let \tcode{\placeholder{r}} be an object of a type that models \libconcept{receiver} -and whose completion handlers result in invoking the corresponding -completion handlers of \tcode{rcvr} or copy thereof. -Returns an object of type \tcode{\exposid{state}} containing -an operation state object initialized with \tcode{connect(\exposid{SENDER}(*this), -std::move(\placeholder{r}))}. +\returns +A prvalue \exposid{ts-sndr} whose type models \libconcept{sender} such that: +\begin{itemize} +\item +\tcode{get_completion_scheduler(get_env(\exposid{ts-sndr}))} +is equal to \tcode{*this}. +\item +\tcode{get_completion_domain(get_env(\exposid{ts-sndr}))} +is expression-equivalent to \tcode{\exposid{ts-do\-main}()}. +\item +If a receiver \tcode{rcvr} is connected to \exposid{ts-sndr} and +the resulting operation state is started, +calls \tcode{\exposid{sch_}->schedule(r, s)}, where +\begin{itemize} +\item +\tcode{r} is a proxy for \tcode{rcvr} with base +\tcode{parallel_scheduler_replacement::receiver_proxy}\iref{exec.par.scheduler} +and +\item +\tcode{s} is a preallocated backend storage for \tcode{r}. +\end{itemize} +\item +For any type \tcode{E}, +\tcode{completion_signatures_of_t} denotes +\tcode{completion_signatures} if +\tcode{\libconcept{unstoppable_token}>} is \tcode{true}, and +otherwise \tcode{completion_signatures}. +\end{itemize} \end{itemdescr} -\pnum \begin{codeblock} namespace std::execution { - template<@\libconcept{receiver}@ R> - class task_scheduler::@\exposidnc{state}@ { // \expos + class task_scheduler::@\exposid{ts-domain}@ : public default_domain { // \expos public: - using operation_state_concept = operation_state_t; - - void start() & noexcept; + template + static constexpr auto transform_sender(set_value_t, BulkSndr&& bulk_sndr, const Env& env) + noexcept(@\seebelow@); }; } \end{codeblock} -\exposid{state} is an exposition-only class template whose -specializations model \libconcept{operation_state}\iref{exec.opstate}. -\indexlibrarymember{start}{task_scheduler::\exposid{state}}% \begin{itemdecl} -void start() & noexcept; +template + static constexpr auto transform_sender(BulkSndr&& bulk_sndr, const Env& env) + noexcept(is_nothrow_constructible_v, BulkSndr>); \end{itemdecl} + \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{\libconcept{sender_in}} is \tcode{true}, +\item +\tcode{auto(std::forward(bulk_sndr))} is well-formed, and +\item +either +\begin{itemize} +\item +\tcode{\exposconcept{sender-for}} or +\item +\tcode{\exposconcept{sender-for}} +\end{itemize} +is \tcode{true}. +\end{itemize} + \pnum \effects -Equivalent to \tcode{start(st)} where \tcode{st} is the operation -state object contained by \tcode{*this}. +Equivalent to: +\begin{codeblock} +auto& [_, data, child] = bulk_sndr; +auto& [_, shape, fn] = data; +auto sch = @\exposidnc{call-with-default}@(get_completion_scheduler, + @\exposidnc{not-a-scheduler}@(), get_env(child), @\exposidnc{FWD-ENV}@(env)); +return @$e$@; +\end{codeblock} +where $e$ is \tcode{\exposid{not-a-sender}()} +if the type of \tcode{sch} is not \tcode{task_scheduler}; +otherwise, it is a prvalue whose type models \libconcept{sender} such that, +if it is connected to a receiver \tcode{rcvr} and +the resulting operation state is started, +\tcode{child} is connected to an unspecified receiver \tcode{R} and started. +The expression \tcode{get_env(R)} +is expression-equivalent to \tcode{\exposid{FWD-ENV}(get_env(\exposid{rcvr-copy}))}, +where \exposid{rcvr-copy} is an lvalue subexpression +designating an object decay-copied from \tcode{rcvr}. + +If \tcode{child} completes with an error or a stopped completion, +the completion operation is forwarded unchanged to \tcode{rcvr}. +Otherwise, let \tcode{args} be a pack of lvalue subexpressions +designating objects decay-copied from the value result datums. +Then: +\begin{itemize} +\item +If \tcode{bulk_sndr} was the result of the evaluation of +an expression equivalent to \tcode{bulk_chunked(child, policy, shape, fn)} or +a copy of such, +then \tcode{\exposid{sch_}->schedule_bulk_chunked(shape, r, s)} is called +where \tcode{r} is a bulk chunked proxy\iref{exec.par.scheduler} +for \tcode{rcvr} with callable \tcode{fn} and arguments \tcode{args}, and +\tcode{s} is a preallocated backend storage for \tcode{r}. +\item +Otherwise, calls \tcode{\exposid{sch_}->schedule_bulk_unchunked(shape, r, s)} +where \tcode{r} is a bulk unchunked proxy for \tcode{rcvr} +with callable \tcode{fn} and arguments \tcode{args}, and +\tcode{s} is a preallocated backend storage for \tcode{r}. +\end{itemize} \end{itemdescr} \rSec2[exec.task]{\tcode{execution::task}} @@ -7183,17 +7756,16 @@ \begin{codeblock} namespace std::execution { - template + template> class @\libglobal{task}@ { // \ref{task.state} template<@\libconcept{receiver}@ Rcvr> class @\exposidnc{state}@; // \expos public: - using sender_concept = sender_t; - using completion_signatures = @\seebelow@; + using sender_concept = sender_tag; using allocator_type = @\seebelow@; - using scheduler_type = @\seebelow@; + using start_scheduler_type = @\seebelow@; using stop_source_type = @\seebelow@; using stop_token_type = decltype(declval().get_token()); using error_types = @\seebelow@; @@ -7204,8 +7776,11 @@ task(task&&) noexcept; ~task(); + template + static consteval auto get_completion_signatures(); + template<@\libconcept{receiver}@ Rcvr> - @\exposid{state}@ connect(Rcvr&& rcvr); + @\exposid{state}@ connect(Rcvr&& rcvr) &&; private: coroutine_handle @\exposidnc{handle}@; // \expos @@ -7227,7 +7802,7 @@ \item \tcode{allocator_type} is \tcode{Environment::allocator_type} if that \grammarterm{qualified-id} is valid and denotes a type, \tcode{allocator} otherwise. -\item \tcode{scheduler_type} is \tcode{Environment::scheduler_type} +\item \tcode{start_scheduler_type} is \tcode{Environment::start_scheduler_type} if that \grammarterm{qualified-id} is valid and denotes a type, \tcode{task_scheduler} otherwise. \item \tcode{stop_source_type} is \tcode{Environment::stop_source_type} @@ -7246,21 +7821,9 @@ \tcode{set_error_t(E)} for some type \tcode{E}. \pnum -The type alias \tcode{completion_signatures} is a specialization -of \tcode{execution::completion_signatures} with the template -arguments (in unspecified order): -\begin{itemize} -\item \tcode{set_value_t()} if \tcode{T} is \tcode{void}, -and \tcode{set_value_t(T)} otherwise; -\item template arguments of the specialization of -\tcode{execution::completion_signatures} denoted by \tcode{error_types}; -and -\item \tcode{set_stopped_t()}. -\end{itemize} - -\pnum -\tcode{allocator_type} shall meet the \oldconcept{Allocator} -requirements. +\tcode{allocator_type} shall meet the \oldconcept{Allocator} requirements, +\tcode{scheduler_type} shall model \libconcept{scheduler}, and +\tcode{stop_source_type} shall model \exposconcept{stoppable-source}. \rSec3[task.members]{\tcode{task} members} @@ -7289,12 +7852,45 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{get_completion_signatures}{task}% +\begin{itemdecl} +template + static consteval auto get_completion_signatures(); +\end{itemdecl} +\begin{itemdescr} +\pnum +Let the type \tcode{C} be a specialization +of \tcode{execution::completion_signatures} +with the template arguments (in unspecified order): +\begin{itemize} +\item +\tcode{set_value_t()} if \tcode{T} is \tcode{void}, +and \tcode{set_value_t(T)} otherwise; +\item +template arguments of the specialization of +\tcode{execution::completion_signatures} denoted by \tcode{error_types}; +and +\item \tcode{set_stopped_t()}. +\end{itemize} + +\pnum +\returns +\tcode{C()}. +\end{itemdescr} + \indexlibrarymember{connect}{task}% \begin{itemdecl} template<@\libconcept{receiver}@ Rcvr> - @\exposid{state}@ connect(Rcvr&& recv); + @\exposid{state}@ connect(Rcvr&& recv) &&; \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +At least one of the expressions +\tcode{allocator_type(get_allocator(get_env(rcvr)))} and +\tcode{allocator_type()} +is well-formed. + \pnum \expects \tcode{bool(\exposid{handle})} is \tcode{true}. @@ -7315,7 +7911,7 @@ template<@\libconcept{receiver}@ Rcvr> class task::@\exposidnc{state}@ { // \expos public: - using operation_state_concept = operation_state_t; + using operation_state_concept = operation_state_tag; template @\exposid{state}@(coroutine_handle h, R&& rr); @@ -7324,12 +7920,17 @@ void start() & noexcept; + stop_token_type @\exposidnc{get-stop-token}@(); // \expos + private: using @\exposidnc{own-env-t}@ = @\seebelownc@; // \expos coroutine_handle @\exposidnc{handle}@; // \expos remove_cvref_t @\exposidnc{rcvr}@; // \expos + optional @\exposidnc{source}@; // \expos @\exposidnc{own-env-t}@ @\exposidnc{own-env}@; // \expos Environment @\exposidnc{environment}@; // \expos + optional @\exposidnc{result}@; // \expos; present only if \tcode{is_void_v} is \tcode{false} + exception_ptr @\exposidnc{error}@; // \expos }; } \end{codeblock} @@ -7391,28 +7992,36 @@ \item \tcode{\exposid{STATE}(\placeholder{prom})} is \tcode{*this}. \item \tcode{\exposid{RCVR}(\placeholder{prom})} is \exposid{rcvr}. \item \tcode{\exposid{SCHED}(\placeholder{prom})} is the object initialized -with \tcode{scheduler_type(get_scheduler(get_env(\exposid{rcvr})))} -if that expression is valid and \tcode{scheduler_type()} otherwise. +with \tcode{start_scheduler_type(get_start_scheduler(get_env(\exposid{rcvr})))} +if that expression is valid and \tcode{start_scheduler_type()} otherwise. If neither of these expressions is valid, the program is ill-formed. \end{itemize} -Let \tcode{\placeholder{st}} be \tcode{get_stop_token(get_env(\exposid{rcvr}))}. -Initializes \tcode{\placeholder{prom}.\exposid{token}} and -\tcode{\placeholder{prom}.\exposid{source}} such that +Finally, invokes \tcode{\exposid{handle}.resume()}. +\end{itemdescr} + +\indexlibrarymember{\exposid{get-stop-token}}{task::\exposid{state}}% +\begin{itemdecl} +stop_token_type @\exposidnc{get-stop-token}@(); // \expos +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +If +\tcode{\libconcept{same_as}().get_token()), decltype(get_\linebreak{}stop_token(get_env(\exposid{rcvr})))>} +is \tcode{true}, +returns \tcode{get_stop_token(get_env(\exposid{rcvr}))}. +Otherwise, if \tcode{\exposid{source}.has_value()} is \tcode{false}, +initializes the contained value of \exposid{source} such that \begin{itemize} \item -\tcode{\placeholder{prom}.\exposid{token}.stop_requested()} returns -\tcode{\placeholder{st}.stop_requested()}; -\item -\tcode{\placeholder{prom}.\exposid{token}.stop_possible()} returns -\tcode{\placeholder{st}.stop_possible()}; and +\tcode{\exposid{source}->stop_requested()} returns +\tcode{get_stop_token(get_env(\exposid{rcvr}))->stop_requested()};\linebreak +and \item -for types \tcode{Fn} and \tcode{Init} such that both -\tcode{\libconcept{invocable}} and -\tcode{\libconcept{constructible_from}} are modeled, -\tcode{stop_token_type::callback_type} models -\tcode{\exposconcept{stoppable-callback-for}}. +\tcode{\exposid{source}->stop_possible()} returns +\tcode{get_stop_token(get_env(\exposid{rcvr}))->stop_possible()}. \end{itemize} -After that invokes \tcode{\exposid{handle}.resume()}. +Finally, returns \tcode{\exposid{source}->get_token()}. \end{itemdescr} \rSec3[task.promise]{Class \tcode{task::promise_type}} @@ -7422,44 +8031,33 @@ template class task::promise_type { public: - template - promise_type(const Args&... args); - task get_return_object() noexcept; - auto initial_suspend() noexcept; + static constexpr suspend_always @\libmember{initial_suspend}{task::promise_type}@() noexcept { return {}; } auto final_suspend() noexcept; - void uncaught_exception(); - coroutine_handle<> unhandled_stopped(); + void unhandled_exception(); + coroutine_handle<> unhandled_stopped() noexcept; void return_void(); // present only if \tcode{is_void_v} is \tcode{true} - template + template void return_value(V&& value); // present only if \tcode{is_void_v} is \tcode{false} template @\unspec@ yield_value(with_error error); - template - auto await_transform(A&& a); - template - auto await_transform(change_coroutine_scheduler sch); + template<@\libconcept{sender}@ Sender> + auto await_transform(Sender&& sndr); @\unspec@ get_env() const noexcept; - template - void* operator new(size_t size, Args&&... args); + void* operator new(size_t size); + template + void* operator new(size_t size, allocator_arg_t, Alloc alloc, Args&&...); + template + void* operator new(size_t size, const This&, allocator_arg_t, Alloc alloc, Args&&...); void operator delete(void* pointer, size_t size) noexcept; - - private: - using @\exposidnc{error-variant}@ = @\seebelownc@; // \expos - - allocator_type @\exposidnc{alloc}@; // \expos - stop_source_type @\exposidnc{source}@; // \expos - stop_token_type @\exposidnc{token}@; // \expos - optional @\exposidnc{result}@; // \expos; present only if \tcode{is_void_v} is \tcode{false} - @\exposidnc{error-variant}@ @\exposidnc{errors}@; // \expos }; } \end{codeblock} @@ -7476,32 +8074,6 @@ during evaluation of \tcode{task::\exposid{state}::start} for some receiver \tcode{Rcvr}. -\pnum -\exposid{error-variant} is a \tcode{variant...>}, with duplicate types removed, where \tcode{E...} -are the parameter types of the template arguments of the specialization of -\tcode{execution::completion_signatures} denoted by -\tcode{error_types}. - -\indexlibraryctor{task::promise_type}% -\begin{itemdecl} -template - promise_type(const Args&... args); -\end{itemdecl} -\begin{itemdescr} -\pnum -\mandates -The first parameter of type \tcode{allocator_arg_t} (if any) is not -the last parameter. - -\pnum -\effects -If \tcode{Args} contains an element of type \tcode{allocator_arg_t} -then \exposid{alloc} is initialized with the corresponding next -element of \tcode{args}. -Otherwise, \exposid{alloc} is initialized with \tcode{allocator_type()}. -\end{itemdescr} - \indexlibrarymember{get_return_object}{task::promise_type}% \begin{itemdecl} task get_return_object() noexcept; @@ -7513,22 +8085,6 @@ \tcode{coroutine_handle::\brk{}from_promise\brk{}(*this)}. \end{itemdescr} -\indexlibrarymember{initial_suspend}{task::promise_type}% -\begin{itemdecl} -auto initial_suspend() noexcept; -\end{itemdecl} -\begin{itemdescr} -\pnum -\returns -An awaitable object of unspecified type\iref{expr.await} whose -member functions arrange for -\begin{itemize} -\item the calling coroutine to be suspended, -\item the coroutine to be resumed on an execution agent of the -execution resource associated with \tcode{\exposid{SCHED}(*this)}. -\end{itemize} -\end{itemdescr} - \indexlibrarymember{final_suspend}{task::promise_type}% \begin{itemdecl} auto final_suspend() noexcept; @@ -7538,17 +8094,19 @@ \returns An awaitable object of unspecified type\iref{expr.await} whose member functions arrange for the completion of the asynchronous -operation associated with \tcode{\exposid{STATE}(*this)} by invoking: +operation associated with \tcode{\exposid{STATE}(*this)}. +Let \tcode{st} be a reference to \tcode{\exposid{STATE}(*this)}. +The asynchronous completion first destroys the coroutine frame +using \tcode{st.\exposid{handle}.destroy()} and then invokes: \begin{itemize} \item -\tcode{set_error(std::move(\exposid{RCVR}(*this)), std::move(e))} -if \tcode{\exposid{errors}.index()} is greater than zero and -\tcode{e} is the value held by \exposid{errors}, otherwise +\tcode{set_error(std::move(st.\exposid{rcvr}), std::move(st.\exposid{error}))} +if \tcode{bool(st.\exposid{error})} is \tcode{true}, otherwise \item -\tcode{set_value(std::move(\exposid{RCVR}(*this)))} if \tcode{is_void} is \tcode{true}, +\tcode{set_value(std::move(st.\exposid{rcvr}))} if \tcode{is_void_v} is \tcode{true}, and otherwise \item - \tcode{set_value(std::move(\exposid{RCVR}(*this)), *\exposid{result})}. + \tcode{set_value(std::move(st.\exposid{rcvr}), *std::move(st.\exposid{result}))}. \end{itemize} \end{itemdescr} @@ -7569,64 +8127,81 @@ An awaitable object of unspecified type\iref{expr.await} whose member functions arrange for the calling coroutine to be suspended and then completes the asynchronous operation associated with -\tcode{\exposid{STATE}(*this)} by invoking \tcode{set_error(std::move(\exposid{RCVR}(*this)), +\tcode{\exposid{STATE}(*this)}. +Let \tcode{st} be a reference to \tcode{\exposid{STATE}(*this)}. +Then the asynchronous operation completes by first +destroying the coroutine frame using \tcode{st.\exposid{handle}.destroy()} +and then invoking +\tcode{set_error(std::move(st.\exposid{rcvr}), \placeholder{Cerr}(std::move(err.error)))}. \end{itemdescr} \indexlibrarymember{await_transform}{task::promise_type}% \begin{itemdecl} template<@\libconcept{sender}@ Sender> - auto await_transform(Sender&& sndr) noexcept; + auto await_transform(Sender&& sndr); \end{itemdecl} \begin{itemdescr} \pnum \returns -If \tcode{\libconcept{same_as}} is \tcode{true} -returns \tcode{as_awaitable(\brk{}std::\brk{}for\-ward(sndr), *this)}; -otherwise returns -\tcode{as_awaitable(affine_on(\brk{}std::\brk{}for\-ward(sndr), \exposid{SCHED}(*this)), *this)}. +If \tcode{\libconcept{same_as}} +is \tcode{true}, +returns \tcode{as_awaitable(\brk{}std::forward(sndr), *this)}; +otherwise returns \tcode{as_awaitable(affine(std::forward<\brk{}Sender>(sndr)), *this)}. \end{itemdescr} -\indexlibrarymember{await_transform}{task::promise_type}% +\indexlibrarymember{unhandled_exception}{task::promise_type}% \begin{itemdecl} -template - auto await_transform(change_coroutine_scheduler sch) noexcept; +void unhandled_exception(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return await_transform(just(exchange(@\exposid{SCHED}@(*this), scheduler_type(sch.scheduler))), *this); -\end{codeblock} +If the signature \tcode{set_error_t(exception_ptr)} is not an element +of \tcode{error_types}, calls \tcode{terminate()}\iref{except.terminate}. +Otherwise, stores \tcode{current_exception()} into +\tcode{\exposid{STATE}(*this).\exposid{error}}. \end{itemdescr} -\indexlibrarymember{uncaught_exception}{task::promise_type}% +\indexlibrarymember{unhandled_stopped}{task::promise_type}% \begin{itemdecl} -void uncaught_exception(); +coroutine_handle<> unhandled_stopped() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -If the signature \tcode{set_error_t(exception_ptr)} is not an element -of \tcode{error_types}, calls \tcode{terminate()}\iref{except.terminate}. -Otherwise, stores \tcode{current_exception()} into \exposid{errors}. +Completes the asynchronous operation associated with \tcode{\exposid{STATE}(*this)}. +Let \tcode{st} be a reference to \tcode{\exposid{STATE}(*this)}. +The asynchronous operation is completed by first +destroying the coroutine frame +using \tcode{st.\exposid{handle}.destroy()} and then +invoking \tcode{set_stopped(std::move(st.\exposid{rcvr}))}. +\end{itemdescr} +\begin{itemdescr} +\pnum +\returns +\tcode{noop_coroutine()}. \end{itemdescr} -\indexlibrarymember{unhandled_stopped}{task::promise_type}% +\indexlibrarymember{return_void}{task::promise_type}% \begin{itemdecl} -coroutine_handle<> unhandled_stopped(); +void return_void(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Completes the asynchronous operation associated with \tcode{\exposid{STATE}(*this)} -by invoking \tcode{set_stopped(std::move(\exposid{RCVR}(*this)))}. +Does nothing. \end{itemdescr} + +\indexlibrarymember{return_value}{task::promise_type}% +\begin{itemdecl} +template + void return_value(V&& v); +\end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{noop_coroutine()}. +\effects +Equivalent to \tcode{\exposid{result}.emplace(std::forward(v))}. \end{itemdescr} \indexlibrarymember{get_env}{task::promise_type}% @@ -7638,12 +8213,17 @@ \returns An object \tcode{env} such that queries are forwarded as follows: \begin{itemize} -\item \tcode{env.query(get_scheduler)} returns \tcode{scheduler_type(\exposid{SCHED}(*this))}. -\item \tcode{env.query(get_allocator)} returns \exposid{alloc}. -\item \tcode{env.query(get_stop_token)} returns \exposid{token}. +\item \tcode{env.query(get_start_scheduler)} returns +\tcode{start_scheduler_type(\exposid{SCHED}(*this))}. +\item \tcode{env.query(get_allocator)} returns +\tcode{allocator_type(get_allocator(get_env(\exposid{RCVR}(*this))\brk{}))} +if this expression is well-formed and +\tcode{allocator_type()} otherwise. +\item \tcode{env.query(get_stop_token)} returns +\tcode{\exposid{STATE}(*this).\exposid{get-stop-token}()}. \item For any other query \tcode{q} and arguments \tcode{a...} a call to \tcode{env.query(q, a...)} returns -\tcode{\exposid{STATE}(*this)}. \tcode{environment.query(q, a...)} if this expression +\tcode{\exposid{STATE}(*this)}. \tcode{\exposid{environment}.query(q, a...)} if this expression is well-formed and \tcode{forwarding_query(q)} is well-formed and is \tcode{true}. Otherwise \tcode{env.query(q, a...)} is ill-formed. \end{itemize} @@ -7651,28 +8231,33 @@ \indexlibrarymember{operator new}{task::promise_type}% \begin{itemdecl} -template - void* operator new(size_t size, const Args&... args); +void* operator new(size_t size); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return operator new(size, allocator_arg, allocator_type());} +\end{itemdescr} + +\indexlibrarymember{operator new}{task::promise_type}% +\begin{itemdecl} +template + void* operator new(size_t size, allocator_arg_t, Alloc alloc, Args&&...); +template + void* operator new(size_t size, const This&, allocator_arg_t, Alloc alloc, Args&&...); \end{itemdecl} \begin{itemdescr} \pnum -If there is no parameter with type \tcode{allocator_arg_t} then let -\tcode{alloc} be \tcode{allocator_type()}. -Otherwise, let \tcode{arg_next} be the parameter -following the first \tcode{allocator_arg_t} parameter, -and let \tcode{alloc} be \tcode{allocator_type(arg_next)}. -Let \tcode{PAlloc} be \tcode{allocator_traits::template -rebind_alloc}, where \tcode{U} is an unspecified type +Let \tcode{PAlloc} be +\tcode{allocator_traits::template rebind_alloc}, +where \tcode{U} is an unspecified type whose size and alignment are both \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}. \pnum \mandates -\begin{itemize} -\item The first parameter of type \tcode{allocator_arg_t} (if any) is not the last parameter. -\item \tcode{allocator_type(arg_next)} is a valid expression if there is a parameter -of type \tcode{allocator_arg_t}. -\item \tcode{allocator_traits::pointer} is a pointer type. -\end{itemize} +\tcode{allocator_traits::pointer} is a pointer type. \pnum \effects @@ -7709,10 +8294,68 @@ \rSec2[exec.scope.concepts]{Execution scope concepts} +\pnum +The \libconcept{scope_association} concept defines +the requirements on a type \tcode{Assoc}. +An object of type \tcode{Assoc} is \defn{engaged} +if and only if it owns an association with an async scope, +referred to as its \defnadj{associated}{scope}. + +\begin{codeblock} +namespace std::execution { + template + concept @\deflibconcept{scope_association}@ = + @\libconcept{movable}@ && + is_nothrow_move_constructible_v && + is_nothrow_move_assignable_v && + @\libconcept{default_initializable}@ && + requires(const Assoc assoc) { + { static_cast(assoc) } noexcept; + { assoc.try_associate() } -> @\libconcept{same_as}@; + }; +} +\end{codeblock} + +\pnum +A type \tcode{Assoc} models \libconcept{scope_association} only if: +\begin{itemize} +\item +a default constructed object of type \tcode{Assoc} is not engaged; +\item +for an object \exposid{assoc} of type \tcode{Assoc}, +\tcode{static_cast(assoc)} is \tcode{true} +if and only if \tcode{assoc} is engaged; +\item +no two distinct objects of type \tcode{Assoc} own the same association; +\item +for an object \tcode{assoc} of type \tcode{Assoc}, +destroying \tcode{assoc} releases the association owned by \tcode{assoc}, if any; +\item +for an object \tcode{assoc} of type \tcode{Assoc}, +after it is used as the source operand of a move constructor, +the \tcode{assoc} is not engaged; +\item +for distinct objects \tcode{assoc1} and \tcode{assoc2} of type \tcode{Assoc}, +after evaluating \tcode{assoc1 = std::move(assoc2)}, +the association owned by \tcode{assoc1}, if any, is released and +\tcode{assoc2} is not engaged; +\item +for an object \tcode{assoc} of type \tcode{Assoc} that is engaged, +\tcode{assoc.try_associate()} either +returns an object that is not engaged or +acquires a new association with \tcode{assoc}'s associated scope and +returns an engaged object that owns that association; +\item +for an object \tcode{assoc} of type \tcode{Assoc} that is not engaged, +\tcode{assoc.try_associate()} returns an object that is not engaged. +\end{itemize} + \pnum The \libconcept{scope_token} concept defines the requirements on a type \tcode{Token} that can be used to create associations between senders and an async scope. +Every object of type \tcode{Token} is associated with an async scope +that is referred to as its \term{associated scope}. \pnum Let \placeholder{test-sender} and \placeholder{test-env} @@ -7726,8 +8369,7 @@ concept @\deflibconcept{scope_token}@ = @\libconcept{copyable}@ && requires(const Token token) { - { token.try_associate() } -> @\libconcept{same_as}@; - { token.disassociate() } noexcept -> @\libconcept{same_as}@; + { token.try_associate() } -> @\libconcept{scope_association}@; { token.wrap(declval<@\placeholder{test-sender}@>()) } -> @\libconcept{sender_in}@<@\placeholder{test-env}@>; }; } @@ -7743,7 +8385,14 @@ move construction, copy assignment, or move assignment -of objects of type \tcode{Token}; and +of objects of type \tcode{Token}; + +\item +for an object \tcode{token} of type \tcode{Token}, +\tcode{token.try_associate()} either +returns an object that is not engaged or +acquires a new association with \tcode{token}'s associated scope and +returns an engaged object that owns that association; and \item given an lvalue \tcode{token} of type (possibly const) \tcode{Token}, @@ -7856,6 +8505,9 @@ @\exposid{unused-and-closed}@, // \expos @\exposid{joined}@, // \expos }; + +template + struct @\exposid{association-t}@; // \expos \end{codeblock} \pnum @@ -7871,7 +8523,7 @@ template struct @\exposid{state}@ { // \expos struct @\exposid{rcvr-t}@ { // \expos - using receiver_concept = receiver_t; + using receiver_concept = receiver_tag; Rcvr& @\exposid{rcvr}@; // \expos @@ -7894,7 +8546,7 @@ }; using @\exposid{sched-sender}@ = // \expos - decltype(schedule(get_scheduler(get_env(declval())))); + decltype(schedule(get_start_scheduler(get_env(declval())))); using @\exposid{op-t}@ = // \expos connect_result_t<@\exposid{sched-sender}@, @\exposid{rcvr-t}@>; @@ -7906,7 +8558,7 @@ noexcept(@\exposconcept{nothrow-callable}@) : @\exposid{scope}@(scope), @\exposid{receiver}@(rcvr), - @\exposid{op}@(connect(schedule(get_scheduler(get_env(rcvr))), @\exposid{rcvr-t}@(rcvr))) {} + @\exposid{op}@(connect(schedule(get_start_scheduler(get_env(rcvr))), @\exposid{rcvr-t}@(rcvr))) {} void @\exposid{complete}@() noexcept { // \expos start(@\exposid{op}@); @@ -7933,6 +8585,26 @@ } \end{codeblock} +\pnum +\exposid{association-t} is a class template, +specializations of which model \libconcept{scope_association} and +contain an exposition-only member \exposid{scope} of type \tcode{Scope*}. +For a class type \tcode{Scope} and +an object \tcode{assoc} of type \tcode{\exposid{association-t}}: +\begin{itemize} +\item +\tcode{assoc.\exposid{scope}} points to its associated scope, +\item +\tcode{assoc} is engaged when \tcode{assoc.\exposid{scope} != nullptr} is \tcode{true}, +\item +if \tcode{assoc} is engaged, +then \tcode{assoc.try_associate()} is equivalent to +\tcode{assoc.\exposid{scope}->\exposid{try-associate}()}, and +\item +the association owned by \tcode{assoc} +is released by invoking \tcode{assoc.\exposid{scope}->\exposid{disassociate}()}. +\end{itemize} + \rSec3[exec.scope.simple.counting]{Simple Counting Scope} \rSec4[exec.scope.simple.counting.general]{General} @@ -7945,6 +8617,8 @@ // \ref{exec.simple.counting.token}, token struct token; + using @\exposid{assoc-t}@ = @\exposid{association-t}@; // \expos + static constexpr size_t max_associations = @\UNSP{\impldef{value of \tcode{std::execution::simple_counting_scope::max_associations}}}@; // \ref{exec.simple.counting.ctor}, constructor and destructor @@ -7961,7 +8635,7 @@ size_t @\exposid{count}@; // \expos @\exposid{scope-state-type}@ @\exposid{state}@; // \expos - bool @\exposid{try-associate}@() noexcept; // \expos + @\exposid{assoc-t}@ @\exposid{try-associate}@() noexcept; // \expos void @\exposid{disassociate}@() noexcept; // \expos template bool @\exposid{start-join-sender}@(State& state) noexcept; // \expos @@ -8062,7 +8736,7 @@ \indexlibrarymember{\exposid{try-associate}}{execution::simple_counting_scope}% \begin{itemdecl} -bool @\exposid{try-associate}@() noexcept; +@\exposid{assoc-t}@ @\exposid{try-associate}@() noexcept; \end{itemdecl} \begin{itemdescr} @@ -8083,7 +8757,10 @@ \pnum \returns -\tcode{true} if \exposid{count} was incremented, \tcode{false} otherwise. +If \exposid{count} was incremented, +an object of type \exposid{assoc-t} +that is engaged and associated with \tcode{*this}, and +\tcode{\exposid{assoc-t}()} otherwise. \end{itemdescr} \indexlibrarymember{\exposid{disassociate}}{execution::simple_counting_scope}% @@ -8118,12 +8795,11 @@ \begin{itemdescr} \pnum \effects -If \exposid{state} is +If \tcode{count} is zero, then +changes \exposid{state} to \exposid{joined} and returns \tcode{true}. +Otherwise, if \exposid{state} is \begin{itemize} \item -\exposid{unused}, \exposid{unused-and-closed}, or \exposid{joined}, then -changes \exposid{state} to \exposid{joined} and returns \tcode{true}; -\item \exposid{open} or \exposid{open-and-joining}, then changes \exposid{state} to \exposid{open-and-joining}, registers \tcode{st} with \tcode{*this} and returns \tcode{false}; @@ -8142,8 +8818,7 @@ struct simple_counting_scope::token { template<@\libconcept{sender}@ Sender> Sender&& wrap(Sender&& snd) const noexcept; - bool try_associate() const noexcept; - void disassociate() const noexcept; + @\exposid{assoc-t}@ try_associate() const noexcept; private: simple_counting_scope* @\exposid{scope}@; // \expos @@ -8165,7 +8840,7 @@ \indexlibrarymember{try_associate}{execution::simple_counting_scope::token}% \begin{itemdecl} -bool try_associate() const noexcept; +@\exposid{assoc-t}@ try_associate() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -8174,17 +8849,6 @@ Equivalent to: \tcode{return \exposid{scope}->\exposid{try-associate}();} \end{itemdescr} -\indexlibrarymember{disassociate}{execution::simple_counting_scope::token}% -\begin{itemdecl} -void disassociate() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{\exposid{scope}->\exposid{disassociate}()}. -\end{itemdescr} - \rSec3[exec.scope.counting]{Counting Scope} \indexlibraryglobal{execution::counting_scope}% @@ -8193,11 +8857,12 @@ namespace std::execution { class counting_scope { public: + using @\exposid{assoc-t}@ = @\exposid{association-t}@; // \expos + struct token { template<@\libconcept{sender}@ Sender> @\libconcept{sender}@ auto wrap(Sender&& snd) const noexcept(@\seebelow@); - bool try_associate() const noexcept; - void disassociate() const noexcept; + @\exposid{assoc-t}@ try_associate() const noexcept; private: counting_scope* @\exposid{scope}@; // \expos @@ -8219,7 +8884,7 @@ @\exposid{scope-state-type}@ @\exposid{state}@; // \expos inplace_stop_source @\exposid{s_source}@; // \expos - bool @\exposid{try-associate}@() noexcept; // \expos + @\exposid{assoc-t}@ @\exposid{try-associate}@() noexcept; // \expos void @\exposid{disassociate}@() noexcept; // \expos template @@ -8261,6 +8926,35 @@ Calls to \tcode{request_stop} do not introduce data races. \end{itemdescr} +\indexlibrarymember{\exposid{try-associate}}{execution::counting_scope}% +\begin{itemdecl} +@\exposid{assoc-t}@ @\exposid{try-associate}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \exposid{count} is equal to \tcode{max_associations}, +then no effects. +Otherwise, if \exposid{state} is +\begin{itemize} +\item +\exposid{unused}, then increments \exposid{count} and +changes \exposid{state} to \exposid{open}; +\item +\exposid{open} or \exposid{open-and-joining}, then increments \exposid{count}; +\item +otherwise, no effects. +\end{itemize} + +\pnum +\returns +If \exposid{count} was incremented, +an object of type \exposid{assoc-t} +that is engaged and associated with \tcode{*this}, and +\tcode{\exposid{assoc-t}()} otherwise. +\end{itemdescr} + \indexlibrarymember{wrap}{execution::counting_scope::token}% \begin{itemdecl} template<@\libconcept{sender}@ Sender> @@ -8277,6 +8971,17 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{wrap}{execution::counting_scope::token}% +\begin{itemdecl} +@\exposid{assoc-t}@ counting_scope::token::try_associate() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{scope}->\exposid{try-associate}();} +\end{itemdescr} + \rSec1[exec.par.scheduler]{Parallel scheduler} \begin{codeblock} @@ -8332,24 +9037,6 @@ for operations launched via calls to \tcode{parallel_scheduler_backend}. \end{note} -\pnum -A \defnx{bulk chunked proxy for \tcode{rcvr} -with callable \tcode{f} and arguments \tcode{args}}{proxy!bulk chunked} -is a proxy \tcode{r} for \tcode{rcvr} -with base \tcode{system_context_replaceability::bulk_item_receiver_proxy} -such that -\tcode{r.execute(i, j)} for indices \tcode{i} and \tcode{j} -has effects equivalent to \tcode{f(i, j, args...)}. - -\pnum -A \defnx{bulk unchunked proxy for \tcode{rcvr} -with callable \tcode{f} and arguments \tcode{args}}{proxy!bulk unchunked} -is a proxy \tcode{r} for \tcode{rcvr} -with base \tcode{system_context_replaceability::bulk_item_receiver_proxy} -such that -\tcode{r.execute(i, i + 1)} for index \tcode{i} -has effects equivalent to \tcode{f(i, args...)}. - \pnum Let \tcode{b} be \tcode{\exposid{BACKEND-OF}(sch)}, let \tcode{sndr} be the object returned by \tcode{schedule(sch)}, and @@ -8363,7 +9050,7 @@ \begin{itemize} \item \tcode{r} is a proxy for \tcode{rcvr} -with base \tcode{system_context_replaceability::receiver_proxy} and +with base \tcode{parallel_scheduler_replacement::receiver_proxy} and \item \tcode{s} is a preallocated backend storage for \tcode{r}. \end{itemize} @@ -8372,46 +9059,93 @@ \end{itemize} \pnum -\tcode{parallel_scheduler} provides a customized implementation of -the \tcode{bulk_chunked} algorithm\iref{exec.bulk}. -If a receiver \tcode{rcvr} is connected to the sender -returned by \tcode{bulk_chunked(sndr, pol, shape, f)} and +The expression \tcode{get_domain(sch)} +returns an expression of exposition-only type +\exposid{parallel-scheduler-do\-main}, that is equivalent with: + +\begin{codeblock} +struct @\exposid{parallel-scheduler-domain}@ { + template<@\exposconcept{sender-for}@ Sndr, @\exposconcept{queryable}@ Env> + static constexpr decltype(auto) + transform_sender(set_value_t, Sndr&& sndr, const Env& env) const noexcept { + return @\seebelow@; + } + template<@\exposconcept{sender-for}@ Sndr, @\exposconcept{queryable}@ Env> + static constexpr decltype(auto) + transform_sender(set_value_t, Sndr&& sndr, const Env& env) const noexcept { + return @\seebelow@; + } +}; +\end{codeblock} + +\pnum +For argument \tcode{sndr} of the above \tcode{transform_sender}, +let \tcode{child}, \tcode{pol}, \tcode{shape} and \tcode{f} +be defined by the following declarations: +\begin{codeblock} +auto& [_, data, child] = sndr; +auto& [pol, shape, f] = data; +\end{codeblock} + +\pnum +Let \tcode{p} be +\begin{itemize} +\item +\tcode{true}, if the type of the expression \tcode{pol} is +\cv{}~\tcode{parallel_policy} or \cv{}~\tcode{parallel_unsequenced_policy}; +\item +\impldef{parallelism flag for an implementation-defined execution policy}, +if \tcode{pol} is an implementation-defined execution policy; +\item +\tcode{false}, otherwise. +\end{itemize} + +\pnum +The \tcode{transform_sender} overload +that accepts senders with tag \tcode{bulk_chunked_t} +returns a sender such that if it is connected to a receiver \tcode{rcvr} and the resulting operation state is started, then: \begin{itemize} \item -If \tcode{sndr} completes with values \tcode{vals}, +If \tcode{child} completes with values \tcode{vals}, let \tcode{args} be a pack of lvalue subexpressions designating \tcode{vals}, -then \tcode{b.schedule_bulk_chunked(shape, r, s)} is called, where +then \tcode{b.schedule_bulk_chunked(p ? shape : 1, r, s)} is called, where \begin{itemize} \item -\tcode{r} is a bulk chunked proxy for \tcode{rcvr} -with callable \tcode{f} and arguments \tcode{args} and +\tcode{r} is a proxy for \tcode{rcvr} +with base \tcode{parallel_scheduler_replacement::bulk_item_receiver_proxy} +such that \tcode{r.execute(i, j)} for indices \tcode{i} and \tcode{j} +has effects equivalent to +\tcode{f(i, j, args...)} if \tcode{p} is true and +\tcode{f(0, shape, args...)} otherwise; and \item \tcode{s} is a preallocated backend storage for \tcode{r}. \end{itemize} \item All other completion operations are forwarded unchanged. \end{itemize} -\begin{note} -Customizing the behavior of \tcode{bulk_chunked} -affects the default implementation of \tcode{bulk}. -\end{note} \pnum -\tcode{parallel_scheduler} provides a customized implementation of -the \tcode{bulk_unchunked} algorithm\iref{exec.bulk}. -If a receiver \tcode{rcvr} is connected to the sender -returned by \tcode{bulk_unchunked(sndr, pol, shape, f)} and +The \tcode{transform_sender} overload +that accepts senders with tag \tcode{bulk_unchunked_t} +returns a sender such that if it is connected to a receiver \tcode{rcvr} and the resulting operation state is started, then: \begin{itemize} \item -If \tcode{sndr} completes with values \tcode{vals}, +If \tcode{child} completes with values \tcode{vals}, let \tcode{args} be a pack of lvalue subexpressions designating \tcode{vals}, -then \tcode{b.schedule_bulk_unchunked(shape, r, s)} is called, where +then \tcode{b.schedule_bulk_unchunked(p ? shape : 1, r, s)} is called, where \begin{itemize} \item -\tcode{r} is a bulk unchunked proxy for \tcode{rcvr} -with callable \tcode{f} and arguments \tcode{args} and +\tcode{r} is a proxy for \tcode{rcvr} +with base \tcode{parallel_scheduler_replacement::bulk_item_receiver_proxy} +such that \tcode{r.execute(i, i + 1)} for index \tcode{i} +has effects equivalent to +\tcode{f(i, args...)} if \tcode{p} is true and +\begin{codeblock} +for (decltype(shape) i = 0; i < shape; i++) { f(i, args...); } +\end{codeblock} +otherwise; and \item \tcode{s} is a preallocated backend storage for \tcode{r}. \end{itemize} @@ -8427,28 +9161,26 @@ \begin{itemdescr} \pnum \effects -Let \tcode{eb} be the result of \tcode{system_context_replaceability::query_parallel_scheduler_backend()}. +Let \tcode{eb} be the result of \tcode{parallel_scheduler_replacement::query_parallel_scheduler_backend()}. If \tcode{eb == nullptr} is \tcode{true}, calls \tcode{terminate}\iref{except.terminate}. Otherwise, returns a \tcode{parallel_scheduler} object associated with \tcode{eb}. \end{itemdescr} -\rSec1[exec.sysctxrepl]{Namespace \tcode{system_context_replaceability}} +\rSec1[exec.parschedrepl]{Namespace \tcode{parallel_scheduler_replacement}} -\rSec2[exec.sysctxrepl.general]{General} +\rSec2[exec.parschedrepl.general]{General} \pnum -Facilities in the \tcode{system_context_replaceability} namespace +Facilities in the \tcode{parallel_scheduler_replacement} namespace allow users to replace the default implementation of \tcode{parallel_scheduler}. -\rSec2[exec.sysctxrepl.recvproxy]{Receiver proxies} +\rSec2[exec.parschedrepl.recvproxy]{Receiver proxies} \begin{codeblock} -namespace std::execution::system_context_replaceability { +namespace std::execution::parallel_scheduler_replacement { struct @\libglobal{receiver_proxy}@ { - virtual ~receiver_proxy() = default; - protected: virtual bool @\exposidnc{query-env}@(@\unspecnc@) noexcept = 0; // \expos @@ -8458,7 +9190,7 @@ virtual void set_stopped() noexcept = 0; template - optional

try_query(Query q) noexcept; + optional

try_query(Query q) const noexcept; }; struct @\libglobal{bulk_item_receiver_proxy}@ : receiver_proxy { @@ -8480,7 +9212,7 @@ \begin{itemdecl} template - optional

@\libglobal{try_query}@(Query q) noexcept; + optional

@\libglobal{try_query}@(Query q) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -8500,11 +9232,14 @@ \tcode{P} is not a member of an implementation-defined set of supported result types for \tcode{Query}; or \item -the expression \tcode{q(env)} is not well-formed or -does not have type \cv{} \tcode{P}, +the expression \tcode{q(env)} is not well-formed, \end{itemize} then returns \tcode{nullopt}. -Otherwise, returns \tcode{q(env)}. +Otherwise, if \tcode{q(env)} has type \cv{}~\tcode{P}, +then returns \tcode{q(env)}. +Otherwise, returns an +\impldef{return value of \tcode{receiver_proxy::try_query}} value +of type \tcode{optional

}. \pnum \remarks @@ -8513,9 +9248,22 @@ \tcode{inplace_stop_token} is a member of the implementation-defined set of supported result types for \tcode{get_stop_token_t}. + +\pnum +\recommended +If \tcode{P} is \tcode{inplace_stop_token} and +\tcode{T} is a type other than \tcode{inplace_stop_token} +that models \libconcept{stoppable_token}, +\tcode{try_query} should return an object of type \tcode{inplace_stop_token} +such that until one of +\tcode{set_value}, +\tcode{set_error} or +\tcode{set_stopped} +is called on \tcode{*this}, +all calls to \tcode{try_query} return equivalent \tcode{inplace_stop_token} objects. \end{itemdescr} -\rSec2[exec.sysctxrepl.query]{\tcode{query_parallel_scheduler_backend}} +\rSec2[exec.parschedrepl.query]{\tcode{query_parallel_scheduler_backend}} \indexlibraryglobal{query_parallel_scheduler_backend}% \begin{itemdecl} @@ -8529,18 +9277,23 @@ \pnum \returns -A non-null shared pointer to an object -that implements the \tcode{parallel_scheduler_backend} interface. +An object \tcode{p}, +such that \tcode{p.get()} points to a \tcode{parallel_scheduler_backend} object +that is a base-class subobject +of some most derived object \tcode{o} within its lifetime. +The lifetime of \tcode{o} does not end +as long as there exists a \tcode{shared_ptr} object \tcode{q} within its lifetime +such that \tcode{q.owner_equal(p)} is \tcode{true}. \pnum \remarks This function is replaceable\iref{term.replaceable.function}. \end{itemdescr} -\rSec2[exec.sysctxrepl.psb]{Class \tcode{parallel_scheduler_backend}} +\rSec2[exec.parschedrepl.psb]{Class \tcode{parallel_scheduler_backend}} \begin{codeblock} -namespace std::execution::system_context_replaceability { +namespace std::execution::parallel_scheduler_replacement { struct @\libglobal{parallel_scheduler_backend}@ { virtual ~parallel_scheduler_backend() = default; @@ -8561,13 +9314,13 @@ \begin{itemdescr} \pnum \expects -The ends of -the lifetimes of \tcode{*this}, -the object referred to by \tcode{r}, and -any storage referenced by \tcode{s} +The ends +of the lifetime of \tcode{*this}, +of the lifetime of the object referred to by \tcode{r}, and +of the duration of any storage referenced by \tcode{s} all happen after the beginning of the evaluation of -the call to \tcode{set_value}, \tcode{set_error}, or \tcode{set_done} +the call to \tcode{set_value}, \tcode{set_error}, or \tcode{set_stopped} on \tcode{r} (see below). \pnum @@ -8606,12 +9359,14 @@ \begin{itemdescr} \pnum \expects -The ends of -the lifetimes of \tcode{*this}, -the object referred to by \tcode{r}, and -any storage referenced by \tcode{s} +The ends +of the lifetime of \tcode{*this}, +of the lifetime of the object referred to by \tcode{r}, and +of the duration of any storage referenced by \tcode{s} all happen after -the beginning of the evaluation of one of the expressions below. +the beginning of the evaluation of the call to +\tcode{set_value}, \tcode{set_error}, or \tcode{set_stopped} +on \tcode{r} (see below). \pnum \effects @@ -8665,12 +9420,14 @@ \begin{itemdescr} \pnum \expects -The ends of -the lifetimes of \tcode{*this}, -the object referred to by \tcode{r}, and -any storage referenced by \tcode{s} +The ends +of the lifetime of \tcode{*this}, +of the lifetime of the object referred to by \tcode{r}, and +of the duration of any storage referenced by \tcode{s} all happen after -the beginning of the evaluation of one of the expressions below. +the beginning of the evaluation of the call to +\tcode{set_value}, \tcode{set_error}, or \tcode{set_stopped} +on \tcode{r} (see below). \pnum \effects diff --git a/source/expressions.tex b/source/expressions.tex index 2bfc4057de..eec3be900e 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -95,7 +95,7 @@ \end{codeblock} due to the associativity and precedence of these operators. Thus, the result of the sum \tcode{(a + 32760)} is next added to \tcode{b}, and -that result is then added to 5 which results in the value assigned to +that result is then added to \tcode{5} which results in the value assigned to \tcode{a}. On a machine in which overflows produce an exception and in which the range of values representable by an \tcode{int} is \crange{-32768}{+32767}, the implementation cannot rewrite this @@ -147,7 +147,10 @@ \end{importgraphic} \begin{itemize} -\item A \defn{glvalue} is an expression whose evaluation determines the identity of an object, function, or non-static data member. +\item A \defn{glvalue} is an expression +whose evaluation determines the identity of +an object, function, non-static data member, or +a direct base class relationship. \item A \defn{prvalue} is an expression whose evaluation initializes an object or computes the value of an operand of an operator, as specified by the context in which it appears, @@ -714,11 +717,15 @@ \indextext{conversion!array-to-pointer}% \indextext{decay!array|see{conversion, array-to-pointer}}% \indextext{decay!function|see{conversion, function-to-pointer}}% -An lvalue or rvalue of type ``array of \tcode{N} \tcode{T}'' or ``array +An expression $E$ of type ``array of \tcode{N} \tcode{T}'' or ``array of unknown bound of \tcode{T}'' can be converted to a prvalue of type ``pointer to \tcode{T}''. -The temporary materialization conversion\iref{conv.rval} is applied. -The result is a pointer to the first element of the array. +If $E$ is a prvalue, +the temporary materialization conversion\iref{conv.rval} is applied. +If the result of $E$ (possibly converted) is an object +whose type is similar to the type of $E$, +the result is a pointer to the first element of the array; +otherwise, the behavior is undefined. \rSec2[conv.func]{Function-to-pointer conversion} @@ -1063,7 +1070,8 @@ 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 +if \tcode{B} is a virtual base class of \tcode{D} +or is a base class of 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 @@ -1373,7 +1381,6 @@ \pnum \indextext{name}% -\indextext{id-expression}% An \grammarterm{id-expression} is a restricted form of a \grammarterm{primary-expression}. \begin{note} @@ -1428,7 +1435,7 @@ \pnum If an \grammarterm{id-expression} $E$ denotes -a member $M$ of an anonymous union\iref{class.union.anon} $U$: +a variant member $M$ of an anonymous union\iref{class.union.anon} $U$: \begin{itemize} \item If $U$ is a non-static data member, @@ -1482,6 +1489,10 @@ \end{example} \end{itemize} +\pnum +A \grammarterm{splice-expression} that designates a direct base class relationship +shall appear only as the second operand of a class member access. + \pnum For an \grammarterm{id-expression} that denotes an overload set, overload resolution is performed @@ -1592,6 +1603,35 @@ the type of such an identifier will typically be \keyword{const} qualified. \end{note} +\begin{example} +\begin{codeblock} +void f() { + float x, &r = x; + + [=]() -> decltype((x)) { // lambda returns \tcode{float const\&} because this lambda is not \tcode{mutable} and + // \tcode{x} is an lvalue + decltype(x) y1; // \tcode{y1} has type \tcode{float} + decltype((x)) y2 = y1; // \tcode{y2} has type \tcode{float const\&} + decltype(r) r1 = y1; // \tcode{r1} has type \tcode{float\&} + decltype((r)) r2 = y2; // \tcode{r2} has type \tcode{float const\&} + return y2; + }; + + [=](decltype((x)) y) { + decltype((x)) z = x; // OK, \tcode{y} has type \tcode{float\&}, \tcode{z} has type \tcode{float const\&} + }; + + [=] { + [](decltype((x)) y) {}; // OK, lambda takes a parameter of type \tcode{float const\&} + + [x=1](decltype((x)) y) { + decltype((x)) z = x; // OK, \tcode{y} has type \tcode{int\&}, \tcode{z} has type \tcode{int const\&} + }; + }; +} +\end{codeblock} +\end{example} + \pnum Otherwise, if the \grammarterm{unqualified-id} @@ -1604,7 +1644,7 @@ Otherwise, if the \grammarterm{unqualified-id} names a result binding\iref{dcl.contract.res} -attached to a function \placeholder{f} +attached to a function with return type \tcode{U}, \begin{itemize} \item @@ -1750,36 +1790,6 @@ 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() { - float x, &r = x; - - [=]() -> decltype((x)) { // lambda returns \tcode{float const\&} because this lambda is not \tcode{mutable} and - // \tcode{x} is an lvalue - decltype(x) y1; // \tcode{y1} has type \tcode{float} - decltype((x)) y2 = y1; // \tcode{y2} has type \tcode{float const\&} - decltype(r) r1 = y1; // \tcode{r1} has type \tcode{float\&} - decltype((r)) r2 = y2; // \tcode{r2} has type \tcode{float const\&} - return y2; - }; - - [=](decltype((x)) y) { - decltype((x)) z = x; // OK, \tcode{y} has type \tcode{float\&}, \tcode{z} has type \tcode{float const\&} - }; - - [=] { - [](decltype((x)) y) {}; // OK, lambda takes a parameter of type \tcode{float const\&} - - [x=1](decltype((x)) y) { - decltype((x)) z = x; // OK, \tcode{y} has type \tcode{int\&}, \tcode{z} has type \tcode{int const\&} - }; - }; -} -\end{codeblock} -\end{example} - \pnum An \defnadj{implicitly movable}{entity} is a variable with automatic storage duration @@ -1877,12 +1887,16 @@ A \grammarterm{nested-name-specifier} is \defn{declarative} if it is part of \begin{itemize} \item -a \grammarterm{class-head-name}, +a \grammarterm{class-head-name}\iref{class.pre}, \item -an \grammarterm{enum-head-name}, +an \grammarterm{enum-head-name}\iref{dcl.enum}, \item a \grammarterm{qualified-id} -that is the \grammarterm{id-expression} of a \grammarterm{declarator-id}, or +that is the \grammarterm{id-expression} +of a \grammarterm{declarator-id}\iref{dcl.decl.general}, +\item +an \grammarterm{elaborated-type-specifier} +of an explicit instantiation\iref{temp.explicit}, or \item a declarative \grammarterm{nested-name-specifier}. \end{itemize} @@ -2019,7 +2033,7 @@ \pnum The \grammarterm{constant-expression} shall be -a converted constant expression\iref{expr.const} of type \tcode{std::size_t} +a converted constant expression\iref{expr.const.const} of type \tcode{std::size_t} whose value $V$, termed the index, is such that $0 \le V < \tcode{sizeof...($P$)}$. @@ -2223,7 +2237,8 @@ \end{note} \pnum -The closure type is not an aggregate type\iref{dcl.init.aggr}; +The closure type is not an aggregate type\iref{dcl.init.aggr} +and is not \tcode{final}\iref{class.pre}; 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 @@ -2231,9 +2246,7 @@ 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}, -\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 trivially copyable\iref{class.prop}, or \item whether the closure type is a standard-layout class\iref{class.prop}. \end{itemize} @@ -2787,7 +2800,8 @@ 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 conceptual 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++; }; @@ -3078,12 +3092,13 @@ \end{example} \pnum -When the \grammarterm{lambda-expression} is evaluated, the entities that are +The entities that are captured by copy are used to direct-initialize each corresponding non-static data member of the resulting closure object, and the non-static data members corresponding to the \grammarterm{init-capture}{s} are initialized as indicated by the corresponding \grammarterm{initializer} (which may be copy- or direct-initialization). (For array members, the array elements are direct-initialized in increasing subscript order.) These initializations are performed +when the \grammarterm{lambda-expression} is evaluated and in the (unspecified) order in which the non-static data members are declared. \begin{note} This ensures that the destructions will occur in the reverse order of the constructions. @@ -3354,8 +3369,8 @@ \begin{bnf} \nontermdef{type-requirement}\br \keyword{typename} \opt{nested-name-specifier} type-name \terminal{;}\br - \keyword{typename} splice-specifier\br - \keyword{typename} splice-specialization-specifier + \keyword{typename} splice-specifier \terminal{;}\br + \keyword{typename} splice-specialization-specifier \terminal{;} \end{bnf} \pnum @@ -3376,7 +3391,7 @@ typename T::inner; // required nested member name typename S; // required valid\iref{temp.names} \grammarterm{template-id}; fails if \tcode{T::type} does not exist as a type // to which \tcode{0} can be implicitly converted - typename Ref; // required alias template substitution, fails if \tcode{T} is void + typename Ref; // required alias template substitution, fails if \tcode{T} is \tcode{void} typename [:T::r1:]; // fails if \tcode{T::r1} is not a reflection of a type typename [:T::r2:]; // fails if \tcode{T::r2} is not a reflection of a template \tcode{Z} for which \tcode{Z} is a type }; @@ -3546,7 +3561,7 @@ \end{example} \pnum -For a \grammarterm{splice-expression} of the form \grammarterm{splice-specifier}, +For a \grammarterm{splice-expression} $E$ of the form \grammarterm{splice-specifier}, let $S$ be the construct designated by \grammarterm{splice-specifier}. \begin{itemize} \item @@ -3589,13 +3604,31 @@ does not apply to a \grammarterm{splice-expression}. \end{note} \item +Otherwise, if $S$ is a direct base class relationship $(\tcode{D}, \tcode{B})$, +the expression is an lvalue designating $S$. +The expression has the type \tcode{B}. +\item Otherwise, if $S$ is a variable or a structured binding, $S$ shall either have static or thread storage duration or shall inhabit a scope enclosing the expression. -The expression is an lvalue referring to the object or function $X$ -associated with or referenced by $S$, -has the same type as that of $S$, and +The expression $E$ is an lvalue referring to the object or function $X$ +associated with or referenced by $S$, and is a bit-field if and only if $X$ is a bit-field. +If $E$ appears in the predicate of a contract assertion $C$\iref{basic.contract} +and $S$ 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 $E$ is \tcode{const T}, +otherwise $E$ has the same type as that of $S$. \begin{note} The type of a \grammarterm{splice-expression} designating a variable or structured binding of reference type @@ -4027,7 +4060,7 @@ 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 +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}, @@ -4164,7 +4197,9 @@ For a dot that is followed by an expression that designates a static member or an enumerator, the first expression is a discarded-value expression\iref{expr.context}; -if the expression after the dot designates a non-static data member, +if the expression after the dot designates a +non-static data member\iref{class.mem.general} or +a direct base class relationship\iref{class.derived.general}, the first expression shall be a glvalue. A postfix expression that is followed by an arrow shall be a prvalue having pointer type. @@ -4300,17 +4335,18 @@ whose value is the value of the enumerator. \item -Otherwise, if \tcode{E2} designates a direct base class relationship $(D, B)$ -and the type of \tcode{E1} is \cv{} \tcode{T}, +Otherwise, if \tcode{E2} designates a direct base class relationship $(D, B)$ and +$D$ is either the cv-unqualified class type of \tcode{E1} or a base class thereof, +let \cv{} be the cv-qualification of the type of \tcode{E1}. +\tcode{E1} is implicitly converted to the type ``reference to \cv{}~\tcode{$D$}'' +(where the reference is an lvalue reference if \tcode{E1} is an lvalue +and an rvalue reference otherwise) and the expression designates the direct base class subobject of type $B$ -of the object designated by \tcode{E1}. +of the object designated by the converted \tcode{E1}. If \tcode{E1} is an lvalue, then \tcode{E1.E2} is an lvalue; otherwise, \tcode{E1.E2} is an xvalue. -The type of \tcode{E1.E2} is ``\cv{} \tcode{$B$}''. -\begin{note} -This can only occur in an expression of the form \tcode{e1.[:e2:]}. -\end{note} +The type of \tcode{E1.E2} is \cv{}~\tcode{$B$}. \begin{example} \begin{codeblock} struct B { @@ -4351,7 +4387,8 @@ \pnum If \tcode{E2} designates a non-static member -(possibly after overload resolution) and +(possibly after overload resolution) +or direct base class relationship and the result of \tcode{E1} is an object whose type is not similar\iref{conv.qual} to the type of \tcode{E1}, the behavior is undefined. @@ -4951,17 +4988,13 @@ \indextext{cast!undefined pointer-to-function}% A function pointer can be explicitly converted to a function pointer of a different type. +The function pointer value is unchanged by the conversion. \indextext{function call!undefined}% \begin{note} The effect of calling a function through a pointer to a function -type\iref{dcl.fct} that is not the same as the type used in the +type\iref{dcl.fct} that is not call-compatible with the type used in the definition of the function is undefined\iref{expr.call}. \end{note} -Except that converting -a prvalue of type ``pointer to \tcode{T1}'' to the type ``pointer to -\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. \pnum An object pointer @@ -5431,7 +5464,7 @@ \end{bnf} \pnum -An \grammarterm{await-expression} shall appear only as 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} or \grammarterm{lambda-expression}, in either case @@ -5657,6 +5690,8 @@ When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objects of that type in an array. +The amount and placement of padding in a class type +is a property of the implementation. The result of applying \keyword{sizeof} to a potentially-overlapping subobject is the size of the type, not the size of the subobject. @@ -5701,7 +5736,7 @@ \tcode{std::size_t}. \begin{note} A \keyword{sizeof} expression -is an integral constant expression\iref{expr.const}. +is an integral constant expression\iref{expr.const.const}. The \grammarterm{typedef-name} \tcode{std::size_t} is declared in the standard header \libheader{cstddef}\iref{cstddef.syn,support.types.layout}. \end{note} @@ -5720,7 +5755,7 @@ The result is a prvalue of type \tcode{std::size_t}. \begin{note} An \keyword{alignof} expression -is an integral constant expression\iref{expr.const}. +is an integral constant expression\iref{expr.const.const}. The \grammarterm{typedef-name} \tcode{std::size_t} is declared in the standard header \libheader{cstddef}\iref{cstddef.syn,support.types.layout}. \end{note} @@ -5754,7 +5789,7 @@ \tcode{true} otherwise. \begin{note} A \grammarterm{noexcept-expression} -is an integral constant expression\iref{expr.const}. +is an integral constant expression\iref{expr.const.const}. \end{note} \indextext{expression!unary|)} @@ -5898,7 +5933,7 @@ \pnum Every \grammarterm{constant-expression} in a \grammarterm{noptr-new-declarator} shall be a converted constant -expression\iref{expr.const} of type \tcode{std::size_t} and +expression\iref{expr.const.const} of type \tcode{std::size_t} and its value shall be greater than zero. \begin{example} Given the definition \tcode{int n = 42}, @@ -5953,7 +5988,8 @@ \impldef{maximum size of an allocated object} limit\iref{implimits}; or \item -the \grammarterm{new-initializer} is a \grammarterm{braced-init-list} and the +the \grammarterm{new-initializer} is a \grammarterm{braced-init-list} +or a parenthesized \grammarterm{expression-list} and the number of array elements for which initializers are provided (including the terminating \tcode{'\textbackslash 0'} in a \grammarterm{string-literal}\iref{lex.string}) exceeds the number of elements to initialize. @@ -5962,7 +5998,7 @@ If the value of the \grammarterm{expression} is invalid after converting to \tcode{std::size_t}: \begin{itemize} \item -if the \grammarterm{expression} is a potentially-evaluated core constant expression, +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 @@ -5983,17 +6019,24 @@ \pnum If the allocated type is an array, -the \grammarterm{new-initializer} is a \grammarterm{braced-init-list}, and +the \grammarterm{new-initializer} is a \grammarterm{braced-init-list} +or a parenthesized \grammarterm{expression-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}. +is potentially evaluated and not a core constant expression, +the semantic constraints of initializing a hypothetical element of +the array are checked as follows: +\begin{itemize} +\item +If the \grammarterm{new-initializer} is a \grammarterm{braced-init-list}, +the hypothetical element is copy-initialized +from an empty initializer list\iref{dcl.init.list}. +\item +Otherwise, the hypothetical element is value-initialized\iref{dcl.init.general}. +\end{itemize} \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. +elements in the \grammarterm{new-initializer}, +requiring initialization of the remainder of the array elements as appropriate. \end{note} \pnum @@ -6071,7 +6114,7 @@ \pnum During an evaluation of a constant expression, -a call to a replaceable allocation function is always omitted\iref{expr.const}. +a call to a replaceable allocation function is always omitted\iref{expr.const.core}. \pnum The implementation may @@ -6234,7 +6277,7 @@ \indextext{\idxcode{bad_alloc}}% \indexlibraryglobal{bad_alloc}% \tcode{std::bad_alloc} -exception\iref{basic.stc.dynamic.allocation,except,bad.alloc}; +exception\iref{basic.stc.dynamic.allocation,except.throw,bad.alloc}; it returns a non-null pointer otherwise. If the allocation function has a non-throwing exception specification, it returns null to indicate failure to allocate storage @@ -6324,23 +6367,45 @@ searching for it in the global scope. \pnum -A declaration of a placement deallocation function matches the -declaration of a placement allocation function if it has the same number -of parameters and, after parameter transformations\iref{dcl.fct}, all -parameter types except the first are identical. If -the lookup finds a single matching deallocation function, that function -will be called; otherwise, no deallocation function will be called. If -the lookup finds a usual deallocation -function -and that function, -considered as a placement deallocation function, would have been -selected as a match for the allocation function, the program is -ill-formed. For a non-placement allocation function, the normal deallocation +For a non-placement allocation function, the normal deallocation function lookup is used to find the matching deallocation function\iref{expr.delete}. +For a placement allocation function, the selection process is described below. In any case, the matching deallocation function (if any) shall be non-deleted and accessible from the point where the \grammarterm{new-expression} appears. + +\pnum +For a placement allocation function, +the matching deallocation function is selected as follows: +\begin{itemize} +\item +Each candidate that is a function template is replaced by +the function template specializations (if any) +generated using template argument deduction\iref{temp.over,temp.deduct.call} +with arguments as specified below. +\item +Each candidate whose parameter-type-list is not identical to +that of the allocation function, +ignoring their respective first parameters, +is removed from the set of candidates. +\item +Each candidate whose associated constraints (if any) +are not satisfied\iref{temp.constr.constr} +is removed from the set of candidates. +\item +If exactly one function remains, that function is selected. +\item +Otherwise, no deallocation function is selected. +\end{itemize} +If a usual deallocation function is selected, the program is ill-formed. +\begin{note} +A deallocation function with an additional trailing parameter +compared to the allocation function is never matched, +even if a default argument is provided. +\end{note} + +\pnum \begin{example} \begin{codeblock} struct S { @@ -6354,7 +6419,55 @@ S* p = new (0) S; // error: non-placement deallocation function matches // placement allocation function \end{codeblock} +\end{example} + +\begin{example} +\begin{codeblock} +struct A {}; +struct T { T(); }; + +void* operator new(std::size_t s, A& al); // \#1 + +template +void operator delete(void* p, A& al); // \#2 + +A al; +T* p = new (al) T; // OK, uses \#1 and \#2. +\end{codeblock} +\end{example} + +\begin{example} +\begin{codeblock} +template +struct A {}; +struct T { T(); }; + +void* operator new(std::size_t s, A<0>& al); // \#1 + +template +void operator delete(void* p, A& al); +void operator delete(void* p, A<0>& al); + +A<0> al; +T* p = new (al) T; // OK, uses \#1. No deallocation function is selected (two candidates remain). +\end{codeblock} +\end{example} +\begin{example} +\begin{codeblock} +template +struct A {}; +struct T { T(); }; + +void* operator new(std::size_t s, A<0>& al); // \#1 + +template requires (I > 0) +void operator delete(void* p, A& al); +void operator delete(void* p, A<0>& al); // \#2 + +A<0> al; +T* p = new (al) T; // OK, uses \#1 and \#2. +\end{codeblock} \end{example} \pnum @@ -6677,13 +6790,13 @@ that represents a template shall not be followed by \tcode{<}. \begin{example} \begin{codeblock} -static_assert(std::meta::is_type(^^int())); // \tcode{\caret\caret} applies to the type-id \tcode{int()} +static_assert(std::meta::is_type(^^int())); // \tcode{\caret\caret} applies to the \grammarterm{type-id} \tcode{int()} template struct X {}; consteval bool operator<(std::meta::info, X) { return false; } consteval void g(std::meta::info r, X xv) { r == ^^int && true; // error: \tcode{\caret\caret} applies to the \grammarterm{type-id} \tcode{int\&\&} - r == ^^int & true; // error: \tcode{\caret\caret} applies to the type-id \tcode{int\&} + r == ^^int & true; // error: \tcode{\caret\caret} applies to the \grammarterm{type-id} \tcode{int\&} r == (^^int) && true; // OK r == ^^int &&&& true; // error: \tcode{int \&\&\&\&} is not a valid \grammarterm{type-id} ^^X < xv; // error: \grammarterm{reflect-expression} that represents a template is followed by \tcode{<} @@ -6785,9 +6898,11 @@ a placeholder type\iref{dcl.spec.auto.general}, $R$ is ill-formed. \item -Otherwise, if the \grammarterm{type-id} names a type alias -that is a specialization of an alias template\iref{temp.alias}, -$R$ represents that type alias. +Otherwise, if the \grammarterm{type-id} is of the form +\opt{\grammarterm{nested-name-specifier}} \opt{\keyword{template}} \grammarterm{simple-template-id} +and whose terminal name is a \grammarterm{template-name} +that names an alias template\iref{temp.alias}, +$R$ represents the type alias so named. \item Otherwise, $R$ represents the type denoted by the \grammarterm{type-id}. \end{itemize} @@ -7201,18 +7316,13 @@ \end{note} \pnum -\indextext{\idxcode{ptrdiff_t}!implementation-defined type of}% -\indextext{subtraction!implementation-defined pointer}% \indextext{\idxcode{ptrdiff_t}}% \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 named by -\tcode{std::ptrdiff_t} in the \libheader{cstddef} -header\iref{support.types.layout}. +The result of subtracting two pointer expressions \tcode{P} and \tcode{Q} +is a prvalue of type \tcode{std::ptrdiff_t}\iref{support.types.layout}. \begin{itemize} \item If \tcode{P} and \tcode{Q} both evaluate to null pointer values, -the result is 0. +the value is 0. \item Otherwise, if \tcode{P} and \tcode{Q} point to, respectively, array elements $i$ and $j$ of the same array object \tcode{x}, @@ -8257,265 +8367,108 @@ \end{example} \end{note} -\rSec1[expr.const]{Constant expressions}% +\rSec1[expr.const]{Constant evaluation}% \indextext{expression!constant} +\rSec2[expr.const.general]{General} + +\begin{bnf} +\nontermdef{constant-expression}\br + conditional-expression +\end{bnf} + \pnum Certain contexts require expressions that satisfy additional -requirements as detailed in this subclause; other contexts have different +requirements as detailed in \ref{expr.const}; other contexts have different semantics depending on whether or not an expression satisfies these requirements. Expressions that satisfy these requirements, assuming that copy elision\iref{class.copy.elision} is not performed, are called constant expressions. \begin{note} -Constant expressions can be evaluated -during translation. +Certain constant expressions are evaluated during translation\iref{lex.phases}. \end{note} -\begin{bnf} -\nontermdef{constant-expression}\br - conditional-expression -\end{bnf} - \pnum -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} +\recommended +Implementations should provide consistent results of floating-point evaluations, +irrespective of whether the evaluation is performed +during translation or during program execution. +\begin{note} +Since this document +imposes no restrictions on the accuracy of floating-point operations, it is unspecified whether the +evaluation of a floating-point expression during translation yields the same result as the +evaluation of the same expression (or the same operations on the same values) during program +execution. +\begin{example} +\begin{codeblock} +bool f() { + char array[1 + int(1 + 0.2 - 0.1 - 0.1)]; // Must be evaluated during translation + int size = 1 + int(1 + 0.2 - 0.1 - 0.1); // May be evaluated at runtime + return sizeof(array) == size; +} +\end{codeblock} +It is unspecified whether the value of \tcode{f()} will be \tcode{true} or \tcode{false}. +\end{example} +\end{note} + +\rSec2[expr.const.core]{Core constant expressions} \pnum -The constituent values and constituent references of -a variable \tcode{x} are defined as follows: +\indextext{type!constexpr-unknown representation}% +A type has \defnadj{constexpr-unknown}{representation} if it \begin{itemize} +\item is a union, +\item is a pointer or pointer-to-member type, +\item is volatile-qualified, +\item is a class type with a non-static data member of reference type, or \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}. +has a base class or a non-static member whose +type has constexpr-unknown representation. \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 +An expression $E$ is a \defnadj{core constant}{expression} +unless the evaluation of $E$, following the rules of the abstract +machine\iref{intro.execution}, would evaluate one of the following: \begin{itemize} \item -$o$ has static storage duration, or -\item -$o$ has automatic storage duration, and, letting \tcode{v} denote +\keyword{this}\iref{expr.prim.this}, except \begin{itemize} \item -the variable corresponding to $o$'s complete object or +in a constexpr function\iref{dcl.constexpr} +that is being evaluated as part of $E$ or \item -the variable to whose lifetime that of $o$ is extended, +when appearing as the \grammarterm{postfix-expression} of +an implicit or explicit class member access expression\iref{expr.ref}; \end{itemize} -the smallest scope enclosing \tcode{v} and the smallest scope enclosing $P$ -that are neither -\begin{itemize} -\item -block scopes nor + \item -function parameter scopes associated with -a \grammarterm{requirement-parameter-list} -\end{itemize} -are the same function parameter scope. -\end{itemize} +a control flow that passes through +a declaration of a block variable\iref{basic.scope.block} with +static\iref{basic.stc.static} or +thread\iref{basic.stc.thread} storage duration, +unless that variable is usable in constant expressions; \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. - }; +constexpr char test() { + static const int x = 5; + static constexpr char c[] = "Hello World"; + return *(c + x); } +static_assert(' ' == test()); \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$. +\item +an invocation of a non-constexpr function; +\begin{footnote} +Overload resolution\iref{over.match} +is applied as usual. +\end{footnote} -\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 non-volatile const-qualified integral or enumeration type. - -\pnum -A constant-initialized potentially-constant variable $V$ is -\defn{usable in constant expressions} at a point $P$ if -$V$'s initializing declaration $D$ is reachable from $P$ and -\begin{itemize} -\item $V$ is constexpr, -\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{potentially usable in constant expressions} at point $P$ if it is -\begin{itemize} -\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} -unless the evaluation of $E$, following the rules of the abstract -machine\iref{intro.execution}, would evaluate one of the following: -\begin{itemize} -\item -\keyword{this}\iref{expr.prim.this}, except -\begin{itemize} -\item -in a constexpr function\iref{dcl.constexpr} -that is being evaluated as part of $E$ or -\item -when appearing as the \grammarterm{postfix-expression} of -an implicit or explicit class member access expression\iref{expr.ref}; -\end{itemize} - -\item -a control flow that passes through -a declaration of a block variable\iref{basic.scope.block} with -static\iref{basic.stc.static} or -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; -\begin{footnote} -Overload resolution\iref{over.match} -is applied as usual. -\end{footnote} - -\item -an invocation of an undefined constexpr function; - +an invocation of an undefined constexpr function; + \item an invocation of an instantiated constexpr function that is not constexpr-suitable; @@ -8619,6 +8572,13 @@ \item a \keyword{reinterpret_cast}\iref{expr.reinterpret.cast}; +\item +pointer arithmetic\iref{expr.add} where +one (possibly converted) operand +points to the first element of an array of unknown bound and +the other (possibly converted) operand +is of integral type with non-zero value; + \item 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 @@ -8644,10 +8604,11 @@ 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 +the placement argument to the \grammarterm{new-expression} points +to an object that is transparently replaceable\iref{basic.life} by +the object created by the \grammarterm{new-expression} +or, if \tcode{T} is an array type, +to the first element of such an object, and \item the placement argument points to storage whose duration began within the evaluation of $E$; @@ -8677,6 +8638,11 @@ \tcode{std::current_exception} or \tcode{std::rethrow_exception}\iref{propagation} are destroyed within the evaluation of $E$; +\item +a \grammarterm{throw-expression}\iref{expr.throw} with no operand, +unless there is a currently handled exception +whose exception object was constructed within the evaluation of $E$; + \item an \grammarterm{await-expression}\iref{expr.await}; @@ -8688,6 +8654,34 @@ relational\iref{expr.rel}, or equality\iref{expr.eq} operator where the result is unspecified; +\item +an equality operator comparing pointers to potentially non-unique objects, +if the pointer values of the two operands +are associated with different evaluations\iref{basic.compound} and either +they can both point to the same offset within +the same potentially non-unique object or +one of them points to an object whose +type has constexpr-unknown representation; +\begin{example} +\begin{codeblock} +constexpr const char *f() { return "foo"; } + +constexpr bool b1 = +"foo" == "foo"; // error: non-constant +constexpr bool b2 = f() == f(); // error: non-constant +constexpr const char *p = f(); +constexpr bool b3 = p == p; // OK, value of \tcode{b3} is \tcode{true} +constexpr bool b4 = "xfoo" + 1 == "foo\0y"; // error: non-constant; string literal + // object could contain \tcode{"xfoo\textbackslash{}0y"} +constexpr bool b5 = "foo" == "bar" + 0; // OK, value of \tcode{b5} is \tcode{false} +constexpr bool b6 = (const char*)"foo" == "oo"; // OK, value of \tcode{b6} is \tcode{false}; offsets would + // be different in a merged string literal object + +constexpr std::initializer_list il1 = { (int *)nullptr }; +constexpr std::initializer_list il2 = { 0 }; +constexpr bool b7 = il1.begin() == (void *)il2.begin(); // error: non-constant +\end{codeblock} +\end{example} + \item a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or \keyword{typeid}\iref{expr.typeid} expression @@ -8790,8 +8784,7 @@ For the purposes of determining whether an expression $E$ is a core constant expression, the evaluation of the body of a member function of \tcode{std::allocator} -as defined in \ref{allocator.members}, where \tcode{T} is a literal type, -is ignored. +as defined in \ref{allocator.members}, is ignored. \pnum For the purposes of determining whether $E$ is a core constant expression, @@ -8846,7 +8839,7 @@ all \grammarterm{id-expression}s, \grammarterm{splice-expression}s, and uses of \tcode{*\keyword{this}} that refer to an object or reference -whose lifetime did not begin with the evaluation of $E$ +whose lifetime did not begin within the evaluation of $E$ are treated as referring to a specific instance of that object or reference whose lifetime and that of all subobjects (including all union members) includes the entire constant evaluation. @@ -8911,89 +8904,7 @@ \end{codeblock} \end{example} -\pnum -An object \tcode{a} is said to have \defnadj{constant}{destruction} if -\begin{itemize} -\item - it is not of class type nor (possibly multidimensional) array thereof, or -\item - it is of class type or (possibly multidimensional) array thereof, - that class type has a constexpr destructor\iref{dcl.constexpr}, and - for a hypothetical expression $E$ - whose only effect is to destroy \tcode{a}, - $E$ would be a core constant expression - if the lifetime of \tcode{a} and its non-mutable subobjects - (but not its mutable subobjects) were considered to start within $E$. -\end{itemize} - -\pnum -An \defnadj{integral constant}{expression} -is an expression of integral or -unscoped enumeration type, implicitly converted to a prvalue, where the converted expression is a core constant expression. -\begin{note} -Such expressions can be -used as bit-field lengths\iref{class.bit}, as enumerator -initializers if the underlying type is not fixed\iref{dcl.enum}, -and as alignments\iref{dcl.align}. -\end{note} - -\pnum -If an expression of literal class type is used in a context where an -integral constant expression is required, then that expression is -contextually implicitly converted\iref{conv} to an integral or unscoped -enumeration type -and the selected conversion function shall be \keyword{constexpr}. -\begin{example} -\begin{codeblock} -struct A { - constexpr A(int i) : val(i) { } - constexpr operator int() const { return val; } - constexpr operator long() const { return 42; } -private: - int val; -}; -constexpr A a = alignof(int); -alignas(a) int n; // error: ambiguous conversion -struct B { int n : a; }; // error: ambiguous conversion -\end{codeblock} -\end{example} - -\pnum -A \defnadj{converted constant}{expression} -of type \tcode{T} is an -expression, implicitly converted to type \tcode{T}, where -the converted expression is a constant expression and the -implicit conversion sequence contains only -\begin{itemize} -\item user-defined conversions, -\item lvalue-to-rvalue conversions\iref{conv.lval}, -\item array-to-pointer conversions\iref{conv.array}, -\item function-to-pointer conversions\iref{conv.func}, -\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}, -\end{itemize} -and where the reference binding (if any) binds directly. -\begin{note} -Such expressions can be used in \keyword{new} -expressions\iref{expr.new}, as case expressions\iref{stmt.switch}, -as enumerator initializers if the underlying type is -fixed\iref{dcl.enum}, as array bounds\iref{dcl.array}, -as constant template arguments\iref{temp.arg}, -and as the constant expression of a \grammarterm{splice-specifier}\iref{basic.splice}. -\end{note} -\indextext{contextually converted constant expression of type \tcode{bool}|see{conversion, contextual}}% -\indextext{conversion!contextual to constant expression of type \tcode{bool}}% -A \term{contextually converted constant expression of type \tcode{bool}} is -an expression, contextually converted to \keyword{bool}\iref{conv}, -where the converted expression is a constant expression and -the conversion sequence contains only the conversions above. +\rSec2[expr.const.const]{Constant expressions} \pnum A \defnadj{constant}{expression} is either @@ -9022,7 +8933,7 @@ \end{itemize} or \item -a prvalue core constant expression whose result object\iref{basic.lval} +a prvalue core constant expression whose result object\iref{basic.lval} (if any) satisfies the following constraints: \begin{itemize} \item @@ -9074,27 +8985,265 @@ \end{example} \pnum -\recommended -Implementations should provide consistent results of floating-point evaluations, -irrespective of whether the evaluation is performed -during translation or during program execution. +An \defnadj{integral constant}{expression} +is an expression of integral or +unscoped enumeration type, implicitly converted to a prvalue, where the converted expression is a core constant expression. \begin{note} -Since this document -imposes no restrictions on the accuracy of floating-point operations, it is unspecified whether the -evaluation of a floating-point expression during translation yields the same result as the -evaluation of the same expression (or the same operations on the same values) during program -execution. +Such expressions can be +used as bit-field lengths\iref{class.bit}, as enumerator +initializers if the underlying type is not fixed\iref{dcl.enum}, +and as alignments\iref{dcl.align}. +\end{note} + +\pnum +If an expression of literal class type is used in a context where an +integral constant expression is required, then that expression is +contextually implicitly converted\iref{conv} to an integral or unscoped +enumeration type +and the selected conversion function shall be \keyword{constexpr}. \begin{example} \begin{codeblock} -bool f() { - char array[1 + int(1 + 0.2 - 0.1 - 0.1)]; // Must be evaluated during translation - int size = 1 + int(1 + 0.2 - 0.1 - 0.1); // May be evaluated at runtime - return sizeof(array) == size; -} +struct A { + constexpr A(int i) : val(i) { } + constexpr operator int() const { return val; } + constexpr operator long() const { return 42; } +private: + int val; +}; +constexpr A a = alignof(int); +alignas(a) int n; // error: ambiguous conversion +struct B { int n : a; }; // error: ambiguous conversion \end{codeblock} -It is unspecified whether the value of \tcode{f()} will be \tcode{true} or \tcode{false}. \end{example} + +\pnum +A \defnadj{converted constant}{expression} +of type \tcode{T} is an +expression, implicitly converted to type \tcode{T}, where +the converted expression is a constant expression and the +implicit conversion sequence contains only +\begin{itemize} +\item user-defined conversions, +\item lvalue-to-rvalue conversions\iref{conv.lval}, +\item array-to-pointer conversions\iref{conv.array}, +\item function-to-pointer conversions\iref{conv.func}, +\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}, +\end{itemize} +and where the reference binding (if any) binds directly. +\begin{note} +Such expressions can be used in \keyword{new} +expressions\iref{expr.new}, as case expressions\iref{stmt.switch}, +as enumerator initializers if the underlying type is +fixed\iref{dcl.enum}, as array bounds\iref{dcl.array}, +as constant template arguments\iref{temp.arg}, +and as the constant expression of a \grammarterm{splice-specifier}\iref{basic.splice}. \end{note} +\indextext{contextually converted constant expression of type \tcode{bool}|see{conversion, contextual}}% +\indextext{conversion!contextual to constant expression of type \tcode{bool}}% + +\pnum +A \term{contextually converted constant expression of type \tcode{bool}} is +an expression, contextually converted to \keyword{bool}\iref{conv}, +where the converted expression is a constant expression and +the conversion sequence contains only the conversions above. + +\rSec2[expr.const.init]{Constant initialization} + +\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\iref{intro.object} are +constituent values and references of \tcode{x}. +\item +If \tcode{x} declares a reference, +that reference is a constituent reference of \tcode{x}. +\end{itemize} +For any constituent reference \tcode{r} of a variable \tcode{x}, +if \tcode{r} is bound to a temporary object or subobject thereof +whose lifetime is extended to that of \tcode{r}, +the constituent values and references of that temporary object +are also constituent values and references of \tcode{x}, recursively. + +\pnum +An object $o$ is \defn{constexpr-referenceable} from a point $P$ if +\begin{itemize} +\item +$o$ has static storage duration, or +\item +$o$ has automatic storage duration, and, letting \tcode{v} denote +\begin{itemize} +\item +the variable corresponding to $o$'s complete object or +\item +the variable to whose lifetime that of $o$ is extended, +\end{itemize} +the smallest scope enclosing \tcode{v} and the smallest scope enclosing $P$ +that are neither +\begin{itemize} +\item +block scopes nor +\item +function parameter scopes associated with +a \grammarterm{requirement-parameter-list} +\end{itemize} +are the same function parameter scope. +\end{itemize} +\begin{example} +\begin{codeblock} +struct A { + int m; + const int& r; +}; +void f() { + static int sx; + thread_local int tx; // \tcode{tx} is never constexpr-referenceable + int ax; + A aa = {1, 2}; + static A sa = {3, 4}; + // The objects \tcode{sx}, \tcode{ax}, and \tcode{aa.m}, \tcode{sa.m}, and the temporaries to which \tcode{aa.r} and \tcode{sa.r} are bound, are constexpr-referenceable. + auto lambda = [] { + int ay; + // The objects \tcode{sx}, \tcode{sa.m}, and \tcode{ay} (but not \tcode{ax} or \tcode{aa}), and the + // temporary to which \tcode{sa.r} is bound, are constexpr-referenceable. + }; +} +\end{codeblock} +\end{example} + +\pnum +An object or reference \tcode{x} is +\defn{constexpr-representable} at a point $P$ if, +for each constituent value of \tcode{x} that points to or past an object $o$, +and for each constituent reference of \tcode{x} that refers to an object $o$, +$o$ is constexpr-referenceable from $P$. + +\pnum +\indextext{contract evaluation semantics!ignore} +A variable \tcode{v} is \defn{constant-initializable} if +\begin{itemize} +\item +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} +In the course of this determination, +\tcode{std::is_constant_evaluated()}\iref{meta.const.eval} +has the value \keyword{true}. +\end{note} +\begin{note} +Furthermore, if the initialization is manifestly constant-evaluated, +its evaluation during translation +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 non-volatile const-qualified integral or enumeration type. + +\pnum +A variable $V$ is +\defnx{usable in constant expressions}{usable in constant expressions!variable} at a point $P$ if +$V$ is constant-initialized and potentially-constant, +$V$'s initializing declaration $D$ is reachable from $P$, and +\begin{itemize} +\item $V$ is constexpr, +\item $V$ is not initialized to a TU-local value, or +\item $P$ is in the same translation unit as $D$. +\end{itemize} + +\pnum +An object or reference is +\defn{potentially usable in constant expressions} at point $P$ if it is +\begin{itemize} +\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} + +\pnum +An object or reference is +\defnx{usable in constant expressions}{usable in constant expressions!object or reference} +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} + +\rSec2[expr.const.imm]{Immediate functions} \pnum An expression or conversion is in an \defn{immediate function context} @@ -9111,7 +9260,7 @@ the \grammarterm{compound-statement} of a consteval if statement\iref{stmt.if}. \end{itemize} An invocation is an \defn{immediate invocation} -if it is a potentially-evaluated explicit or implicit invocation of +if it is a potentially evaluated explicit or implicit invocation of an immediate function and is not in an immediate function context. An aggregate initialization is an immediate invocation @@ -9123,7 +9272,7 @@ \indexdefn{conversion!immediate-escalating}% \indexdefn{immediate-escalating!expression|see{expression, immediate-escalating}}% \indexdefn{immediate-escalating!conversion|see{conversion, immediate-escalating}}% -A potentially-evaluated expression or conversion is \defn{immediate-escalating} +A potentially evaluated expression or conversion is \defn{immediate-escalating} if it is neither initially in an immediate function context nor a subexpression of an immediate invocation, and \begin{itemize} @@ -9144,20 +9293,24 @@ the call operator of a lambda that is not declared with the \keyword{consteval} specifier, \item -a defaulted special member function +a non-user-provided defaulted function that is not declared with the \keyword{consteval} specifier, or \item -a function that results from the instantiation +a function that is not a prospective destructor and +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 that is either +An \defnadj{immediate}{function} is a function that is \begin{itemize} \item -declared with the \keyword{consteval} specifier, or +declared with the \keyword{consteval} specifier, +\item +an immediate-escalating function +whose type is consteval-only\iref{basic.types.general}, or \item an immediate-escalating function \tcode{\placeholder{F}} whose function body contains either @@ -9173,6 +9326,8 @@ are considered to be part of the function body\iref{dcl.fct.def.general}. \end{tailnote} \end{itemize} + +\pnum \begin{example} \begin{codeblock} consteval int id(int i) { return i; } @@ -9239,52 +9394,7 @@ \end{codeblock} \end{example} -\pnum -An expression or conversion is \defn{manifestly constant-evaluated} -if it is: -\begin{itemize} -\item a \grammarterm{constant-expression}, or -\item the condition of a constexpr if statement\iref{stmt.if}, or -\item an immediate invocation, or -\item the result of substitution into an atomic constraint expression -to determine whether it is satisfied\iref{temp.constr.atomic}, or -\item the initializer of a variable -that is usable in constant expressions or -has constant initialization\iref{basic.start.static}. -\begin{footnote} -Testing this condition -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} -template struct X {}; -X x; // type \tcode{X} -int y; -const int a = std::is_constant_evaluated() ? y : 1; // dynamic initialization to 1 -double z[a]; // error: \tcode{a} is not usable - // in constant expressions -const int b = std::is_constant_evaluated() ? 2 : y; // static initialization to 2 -int c = y + (std::is_constant_evaluated() ? 2 : y); // dynamic initialization to \tcode{y+y} - -constexpr int f() { - const int n = std::is_constant_evaluated() ? 13 : 17; // \tcode{n} is 13 - int m = std::is_constant_evaluated() ? 13 : 17; // \tcode{m} can be 13 or 17 (see below) - char arr[n] = {}; // char[13] - return m + sizeof(arr); -} -int p = f(); // \tcode{m} is 13; initialized to 26 -int q = p + f(); // \tcode{m} is 17 for this call; initialized to 56 -\end{codeblock} -\end{example} -\end{itemize} -\begin{note} -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} +\rSec2[expr.const.reflect]{Reflection} \pnum The evaluation of an expression can introduce @@ -9332,6 +9442,8 @@ there is a function parameter scope or class scope that encloses exactly one of $C$ or $P$. \end{itemize} + +\pnum \begin{example} \begin{codeblock} struct S0 { @@ -9393,39 +9505,144 @@ \end{example} \pnum -The \defn{evaluation context} is a set of program points -that determines the behavior of certain functions -used for reflection\iref{meta.reflection}. -During the evaluation $V$ of an expression $E$ as a core constant expression, -the evaluation context of an evaluation $X$\iref{intro.execution} -consists of the following points: +During an evaluation $V$\iref{intro.execution} of +an expression, conversion, or initialization $E$ +as a core constant expression, the +\indextext{point of!evaluation}% +\indextext{point!of evaluation}% +\indextext{evaluation!point of evaluation, during}% +\defnx{point of evaluation of $E$ during $V$}{point of evaluation during evaluation} +is the program point $P$ determined as follows: \begin{itemize} \item -The program point $\textit{EVAL-PT}(L)$, -where $L$ is the point at which $E$ appears, and -where $\textit{EVAL-PT}(P)$, for a point $P$, -is a point $R$ determined as follows: -\begin{itemize} -\item -If a potentially-evaluated subexpression\iref{intro.execution} of -a default member initializer $I$ appears at $P$, and -a (possibly aggregate) initialization during $V$ is using $I$, -then $R$ is $\textit{EVAL-PT}(Q)$ -where $Q$ is the point at which that initialization appears. +If $E$ is a potentially-evaluated subexpression of +a default member initializer $I$, and +$V$ is the evaluation of $E$ in the evaluation of $I$ +as an immediate subexpression of a (possibly aggregate) initialization, then +$P$ is the point of evaluation of that initialization. +\begin{tailnote} +For example, +$E$ can be an immediate invocation in a default member initializer +used by an aggregate initialization appearing at $P$. +\end{tailnote} + \item -Otherwise, if a potentially-evaluated subexpression of -a default argument\iref{dcl.fct.default} appears at $P$, and -an invocation of a function\iref{expr.call} during $V$ -is using that default argument, -then $R$ is $\textit{EVAL-PT}(Q)$ -where $Q$ is the point at which that invocation appears. +Otherwise, +if $E$ is a potentially-evaluated subexpression of +a default argument $A$\iref{dcl.fct.default}, and +$V$ is the evaluation of $E$ in the evaluation of $A$ as +an immediate subexpression of a function call\iref{expr.call}, then +$P$ is the point of evaluation of that function call. + \item -Otherwise, $R$ is $P$. +Otherwise, +$P$ is the point at which $E$ appears. \end{itemize} +During the evaluation $V$ of an expression $E$ as a core constant expression, +the \defnadj{evaluation}{context} of an evaluation $X$ +during $V$ is the set $C$ of program points determined as follows: +\begin{itemize} +\item +If $X$ occurs during the evaluation $Y$ of +a manifestly constant-evaluated expression, +where $Y$ occurs during $V$, then +$C$ is the evaluation context of $X$ during $Y$. \item -Each synthesized point corresponding to an injected declaration produced by -any evaluation sequenced before $X$\iref{intro.execution}. +Otherwise, $C$ contains + \begin{itemize} + \item + the point of evaluation of $E$ during $V$ and + each synthesized point in the instantiation context thereof and + \item + each synthesized point corresponding to an injected declaration + produced by any evaluation executed during $V$ that + is sequenced before $X$\iref{intro.execution}. + \end{itemize} +\end{itemize} +\begin{note} +The evaluation context determines the behavior of certain functions +used for reflection\iref{meta.reflection}. +\end{note} +\begin{example} +\begin{codeblock} +struct S; +consteval std::size_t f(int p) { + constexpr std::size_t r = /* @\tcode{Q}@ */ + std::meta::is_complete_type(^^S) ? 1 : 2; // \#1 + if (!std::meta::is_complete_type(^^S)) { // \#2 + std::meta::define_aggregate(^^S, {}); + } + return (p > 0) ? f(p - 1) : r; +} + +consteval { + if (f(1) != 2) { + throw; // OK, not evaluated + } +} +\end{codeblock} +During each evaluation of +\tcode{std::meta::is_complete_type(\caret\caret{}S)} +at \#1\iref{meta.reflection.queries} that is +executed during the evaluation of \tcode{f(1) != 2}, +the evaluation context contains \tcode{Q}, +but does not contain the synthesized point +associated with the injected declaration of \tcode{S}. +However, the synthesized point is in the evaluation context of +\tcode{std::meta::is_complete_type(\caret\caret{}S)} at \#2 +during the evaluation of \tcode{f(0)}. +\end{example} + +\rSec2[expr.const.defns]{Further definitions} + +\pnum +An expression or conversion is \defn{manifestly constant-evaluated} +if it is +\begin{itemize} +\item a \grammarterm{constant-expression}, or +\item the condition of a constexpr if statement\iref{stmt.if}, or +\item the expression corresponding to +a \grammarterm{consteval-block-declaration}\iref{dcl.pre}, or +\item an immediate invocation, or +\item the result of substitution into an atomic constraint expression +to determine whether it is satisfied\iref{temp.constr.atomic}, or +\item the initializer of a variable +that is usable in constant expressions or +has constant initialization\iref{basic.start.static}. +\begin{footnote} +Testing this condition +can involve a notional 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} +template struct X {}; +X x; // type \tcode{X} +int y; +const int a = std::is_constant_evaluated() ? y : 1; // dynamic initialization to 1 +double z[a]; // error: \tcode{a} is not usable + // in constant expressions +const int b = std::is_constant_evaluated() ? 2 : y; // static initialization to 2 +int c = y + (std::is_constant_evaluated() ? 2 : y); // dynamic initialization to \tcode{y+y} + +constexpr int f() { + const int n = std::is_constant_evaluated() ? 13 : 17; // \tcode{n} is 13 + int m = std::is_constant_evaluated() ? 13 : 17; // \tcode{m} can be 13 or 17 (see below) + char arr[n] = {}; // \tcode{char[13]} + return m + sizeof(arr); +} +int p = f(); // \tcode{m} is 13; initialized to 26 +int q = p + f(); // \tcode{m} is 17 for this call; initialized to 56 +\end{codeblock} +\end{example} \end{itemize} +\begin{note} +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} \pnum \indextext{expression!potentially constant evaluated}% @@ -9436,7 +9653,7 @@ a manifestly constant-evaluated expression, \item -a potentially-evaluated expression\iref{basic.def.odr}, +a potentially evaluated expression\iref{basic.def.odr}, \item an immediate subexpression of a \grammarterm{braced-init-list}, @@ -9470,4 +9687,19 @@ a potentially-constant variable named by a potentially constant evaluated expression. \end{itemize} +\pnum +An object \tcode{a} is said to have \defnadj{constant}{destruction} if +\begin{itemize} +\item + it is not of class type nor (possibly multidimensional) array thereof, or +\item + it is of class type or (possibly multidimensional) array thereof, + that class type has a constexpr destructor\iref{dcl.constexpr}, and + for a hypothetical expression $E$ + whose only effect is to destroy \tcode{a}, + $E$ would be a core constant expression + if the lifetime of \tcode{a} and its non-mutable subobjects + (but not its mutable subobjects) were considered to start within $E$. +\end{itemize} + \indextext{expression|)} diff --git a/source/future.tex b/source/future.tex index bba0b7f73c..72dbeabbc5 100644 --- a/source/future.tex +++ b/source/future.tex @@ -576,8 +576,8 @@ 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}. +\item for the first specialization, \tcode{volatile TE}, and +\item for the second specialization, \tcode{const volatile TE}. \end{itemize} \pnum @@ -631,11 +631,42 @@ 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}. +\item for the first specialization, \tcode{volatile VA::type}, and +\item for the second specialization, \tcode{const volatile VA::type}. \end{itemize} \end{itemdescr} +\rSec1[depr.vector.bool.swap]{Deprecated \tcode{vector} swap} + +\pnum +The following member is declared in addition to those members specified in +\ref{vector.bool}: + +\begin{codeblock} +namespace std { + template class vector { + public: + static constexpr void swap(reference x, reference y) noexcept; + }; +} +\end{codeblock} + +\indexlibrarymember{swap}{vector}% +\begin{itemdecl} +static constexpr void swap(reference x, reference y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Exchanges the values denoted by \tcode{x} and \tcode{y} as if by: +\begin{codeblock} +bool b = x; +x = y; +y = b; +\end{codeblock} +\end{itemdescr} + \rSec1[depr.iterator]{Deprecated \tcode{iterator} class template} \pnum @@ -774,7 +805,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return visit(std::forward(vis), arg.value);} +Equivalent to: \tcode{return visit(std::forward(vis), arg.\exposid{value_});} \end{itemdescr} \rSec1[depr.ctime]{Deprecated time formatting} @@ -898,7 +929,7 @@ \begin{itemdescr} \pnum \returns -\tcode{system_encoded_string()}. +\tcode{native_encoded_string()}. \end{itemdescr} \indexlibrarymember{generic_string}{path}% @@ -909,7 +940,7 @@ \begin{itemdescr} \pnum \returns -\tcode{generic_system_encoded_string()}. +\tcode{generic_native_encoded_string()}. \end{itemdescr} \rSec1[depr.atomics]{Deprecated atomic operations} diff --git a/source/intro.tex b/source/intro.tex index 22114ac371..3e24d06dce 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -213,7 +213,7 @@ \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} +as a core constant expression\iref{expr.const.core} \definition{constant subexpression}{defns.const.subexpr} \indexdefn{constant subexpression}% @@ -265,7 +265,7 @@ 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} +Evaluation of a constant expression\iref{expr.const.core} never exhibits behavior specified as erroneous in \ref{intro} through \ref{\lastcorechapter}. \end{defnote} @@ -462,6 +462,11 @@ \end{codeblock} \end{example} +\indexdefn{property!of the implementation}% +\definition{property of the implementation}{defns.impl.prop} +behavior, for a well-formed program\iref{defns.well.formed} +construct and correct data, that depends on the implementation + \definition{referenceable type}{defns.referenceable} \indexdefn{type!referenceable}% type that is either an @@ -525,7 +530,7 @@ 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 +(as specified in~\ref{expr.const.core}) and \item runtime-undefined behavior has no other effect. \end{itemize} @@ -670,7 +675,7 @@ \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 +Evaluation of a constant expression\iref{expr.const.core} never exhibits behavior explicitly specified as undefined in \ref{intro} through \ref{\lastcorechapter}. \end{defnote} @@ -782,7 +787,7 @@ \item a contract assertion\iref{basic.contract.eval} evaluated with a checking semantic -in a manifestly constant-evaluated context\iref{expr.const} +in a manifestly constant-evaluated context\iref{expr.const.defns} resulting in a contract violation, \end{itemize} a conforming implementation @@ -805,7 +810,7 @@ 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} +in a manifestly constant-evaluated context\iref{expr.const.defns} resulting in a contract violation. \end{itemize} @@ -860,6 +865,7 @@ results in a contract violation\iref{structure.specifications}. \pnum +\recommended 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. @@ -919,10 +925,14 @@ \pnum \indextext{behavior!implementation-defined}% -Certain aspects and operations of the abstract machine are described in this +Certain aspects and operations of the abstract machine +constitute the parameters of the abstract machine and +are described in this 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 +\tcode{sizeof(int)}) +or as properties of the implementation (for example, padding in class types). +For implementation-defined behavior, +each implementation shall include documentation describing its characteristics and behavior in these respects. \begin{footnote} This documentation also includes @@ -986,10 +996,9 @@ 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, +If the execution of an operation is 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. +is permitted to terminate the execution of the program. \pnum \recommended diff --git a/source/iostreams.tex b/source/iostreams.tex index d5d867ad11..615ea941ed 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -363,17 +363,19 @@ serves as a base class for class templates \tcode{basic_stringbuf}, \tcode{basic_filebuf}, +\tcode{basic_syncbuf}, and -\tcode{basic_syncbuf}. +\tcode{basic_spanbuf}. \pnum The class template specialization \tcode{basic_istream} serves as a base class for class templates -\tcode{basic_istringstream} +\tcode{basic_istringstream}, +\tcode{basic_ifstream}, and -\tcode{basic_ifstream}. +\tcode{basic_ispanstream}. \pnum The @@ -382,17 +384,19 @@ serves as a base class for class templates \tcode{basic_ostringstream}, \tcode{basic_ofstream}, +\tcode{basic_osyncstream}, and -\tcode{basic_osyncstream}. +\tcode{basic_ospanstream}. \pnum The class template specialization \tcode{basic_iostream} serves as a base class for class templates -\tcode{basic_stringstream} +\tcode{basic_stringstream}, +\tcode{basic_fstream}, and -\tcode{basic_fstream}. +\tcode{basic_spanstream}. \pnum \begin{note} @@ -404,9 +408,8 @@ \end{note} \pnum -Other \grammarterm{typedef-name}{s} define instances of -class templates -specialized for +Other \grammarterm{typedef-name}{s} designate +class template specializations for \tcode{char} or \keyword{wchar_t} @@ -4763,7 +4766,7 @@ } else if (numeric_limits::max() < lval) { state |= ios_base::failbit; val = numeric_limits::max(); -} else +} else val = static_cast(lval); \end{codeblock} \end{itemdescr} @@ -4787,7 +4790,7 @@ } else if (numeric_limits::max() < lval) { state |= ios_base::failbit; val = numeric_limits::max(); -} else +} else val = static_cast(lval); \end{codeblock} \end{itemdescr} @@ -5651,7 +5654,7 @@ calls \tcode{setstate(badbit)} (which may throw -\tcode{ios_base::failure}\iref{iostate.flags}, +\tcode{ios_base::failure}\iref{iostate.flags}), and returns \tcode{-1}. Otherwise, returns zero. @@ -7798,7 +7801,7 @@ \effects Equivalent to: \begin{codeblock} -print(stream, runtime_format(string(fmt.get()) + '\n'), std::forward(args)...); +print(stream, dynamic_format(string(fmt.get()) + '\n'), std::forward(args)...); \end{codeblock} \end{itemdescr} @@ -7924,7 +7927,7 @@ Equivalent to: \begin{codeblock} string out = vformat(fmt, args); -vprint_nonunicode("{}", make_format_args(out)); +vprint_nonunicode(stream, "{}", make_format_args(out)); \end{codeblock} \end{itemdescr} @@ -9328,7 +9331,7 @@ template void str(const T& t); - private: + private: basic_stringbuf @\exposid{sb}@; // \expos }; } @@ -13714,7 +13717,7 @@ basic_string string(const Allocator& a = Allocator()) const; std::string display_string() const; - std::string system_encoded_string() const; + std::string native_encoded_string() const; std::wstring wstring() const; std::u8string u8string() const; std::u16string u16string() const; @@ -13726,7 +13729,7 @@ basic_string generic_string(const Allocator& a = Allocator()) const; std::string generic_display_string() const; - std::string generic_system_encoded_string() const; + std::string generic_native_encoded_string() const; std::wstring generic_wstring() const; std::u8string generic_u8string() const; std::u16string generic_u16string() const; @@ -13786,7 +13789,7 @@ \indexlibrarymember{value_type}{path}% \pnum -\tcode{value_type} is a \keyword{typedef} for the +\tcode{value_type} is a \grammarterm{typedef-name} for the operating system dependent encoded character type used to represent pathnames. \indexlibrarymember{preferred_separator}{path}% @@ -14048,7 +14051,8 @@ so no conversion from \tcode{char} value type arguments or to \tcode{char} value type return values is performed. For Windows-based operating systems, the -native ordinary encoding is determined by calling a Windows API function. +native ordinary encoding is determined by +the current locale encoding and the Windows \tcode{AreFileApisANSI} function. \end{note} \begin{note} This results in behavior identical to other C and \Cpp{} @@ -14701,7 +14705,7 @@ \indexlibrarymember{u16string}{path}% \indexlibrarymember{u32string}{path}% \begin{itemdecl} -std::string system_encoded_string() const; +std::string native_encoded_string() const; std::wstring wstring() const; std::u8string u8string() const; std::u16string u16string() const; @@ -14776,7 +14780,7 @@ \indexlibrarymember{generic_u16string}{path}% \indexlibrarymember{generic_u32string}{path}% \begin{itemdecl} -std::string generic_system_encoded_string() const; +std::string generic_native_encoded_string() const; std::wstring generic_wstring() const; std::u8string generic_u8string() const; std::u16string generic_u16string() const; @@ -17685,7 +17689,7 @@ \begin{itemdecl} void filesystem::create_hard_link(const path& to, const path& new_hard_link); void filesystem::create_hard_link(const path& to, const path& new_hard_link, - error_code& ec) noexcept; + error_code& ec) noexcept; \end{itemdecl} \begin{itemdescr} @@ -17720,7 +17724,7 @@ \begin{itemdecl} void filesystem::create_symlink(const path& to, const path& new_symlink); void filesystem::create_symlink(const path& to, const path& new_symlink, - error_code& ec) noexcept; + error_code& ec) noexcept; \end{itemdecl} \begin{itemdescr} @@ -18276,7 +18280,7 @@ \begin{itemdecl} void filesystem::last_write_time(const path& p, file_time_type new_time); void filesystem::last_write_time(const path& p, file_time_type new_time, - error_code& ec) noexcept; + error_code& ec) noexcept; \end{itemdecl} \begin{itemdescr} diff --git a/source/iterators.tex b/source/iterators.tex index 9914bd249f..ed599d9725 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -33,6 +33,7 @@ \begin{codeblock} #include // see \ref{compare.syn} #include // see \ref{concepts.syn} +#include // see \ref{initializer.list.syn} namespace std { template using @\exposid{with-reference}@ = T&; // \expos @@ -464,53 +465,64 @@ class ostreambuf_iterator; // \ref{iterator.range}, range access - template constexpr auto begin(C& c) -> decltype(c.begin()); // freestanding - template constexpr auto begin(const C& c) -> decltype(c.begin()); // freestanding - template constexpr auto end(C& c) -> decltype(c.end()); // freestanding - template constexpr auto end(const C& c) -> decltype(c.end()); // freestanding + template constexpr auto + begin(C& c) noexcept(noexcept(c.begin())) -> decltype(c.begin()); // freestanding + template constexpr auto + begin(const C& c) noexcept(noexcept(c.begin())) -> decltype(c.begin()); // freestanding + template constexpr auto + end(C& c) noexcept(noexcept(c.end())) -> decltype(c.end()); // freestanding + template constexpr auto + end(const C& c) noexcept(noexcept(c.end())) -> decltype(c.end()); // freestanding template constexpr T* begin(T (&array)[N]) noexcept; // freestanding template constexpr T* end(T (&array)[N]) noexcept; // freestanding - template constexpr auto cbegin(const C& c) // freestanding - noexcept(noexcept(std::begin(c))) -> decltype(std::begin(c)); - template constexpr auto cend(const C& c) // freestanding - noexcept(noexcept(std::end(c))) -> decltype(std::end(c)); - template constexpr auto rbegin(C& c) -> decltype(c.rbegin()); // freestanding - template constexpr auto rbegin(const C& c) -> decltype(c.rbegin()); // freestanding - template constexpr auto rend(C& c) -> decltype(c.rend()); // freestanding - template constexpr auto rend(const C& c) -> decltype(c.rend()); // freestanding - template constexpr reverse_iterator rbegin(T (&array)[N]) // freestanding - template constexpr reverse_iterator rend(T (&array)[N]); // freestanding + template constexpr auto + cbegin(const C& c) noexcept(noexcept(std::begin(c))) + -> decltype(std::begin(c)); // freestanding + template constexpr auto + cend(const C& c) noexcept(noexcept(std::end(c))) -> decltype(std::end(c)); // freestanding + template constexpr auto + rbegin(C& c) noexcept(noexcept(c.rbegin())) -> decltype(c.rbegin()); // freestanding + template constexpr auto + rbegin(const C& c) noexcept(noexcept(c.rbegin())) -> decltype(c.rbegin()); // freestanding + template constexpr auto + rend(C& c) noexcept(noexcept(c.rend())) -> decltype(c.rend()); // freestanding + template constexpr auto + rend(const C& c) noexcept(noexcept(c.rend())) -> decltype(c.rend()); // freestanding + template constexpr reverse_iterator + rbegin(T (&array)[N]) noexcept; // freestanding + template constexpr reverse_iterator + rend(T (&array)[N]) noexcept; // freestanding template constexpr reverse_iterator - rbegin(initializer_list il); // freestanding + rbegin(initializer_list il) noexcept; // freestanding template constexpr reverse_iterator - rend(initializer_list il); // freestanding + rend(initializer_list il) noexcept; // freestanding template constexpr auto - crbegin(const C& c) -> decltype(std::rbegin(c)); // freestanding + crbegin(const C& c) noexcept(noexcept(std::rbegin(c))) + -> decltype(std::rbegin(c)); // freestanding template constexpr auto - crend(const C& c) -> decltype(std::rend(c)); // freestanding + crend(const C& c) noexcept(noexcept(std::rend(c))) -> decltype(std::rend(c)); // freestanding template constexpr auto - size(const C& c) -> decltype(c.size()); // freestanding + size(const C& c) noexcept(noexcept(c.size())) -> decltype(c.size()); // freestanding template constexpr size_t size(const T (&array)[N]) noexcept; // freestanding template constexpr auto - ssize(const C& c) + ssize(const C& c) noexcept(noexcept(c.size())) -> common_type_t>; // freestanding template constexpr ptrdiff_t ssize(const T (&array)[N]) noexcept; // freestanding template constexpr auto - empty(const C& c) -> decltype(c.empty()); // freestanding + empty(const C& c) noexcept(noexcept(c.empty())) -> decltype(c.empty()); // freestanding template constexpr bool empty(const T (&array)[N]) noexcept; // freestanding - template constexpr bool - empty(initializer_list il) noexcept; // freestanding - template constexpr auto data(C& c) -> decltype(c.data()); // freestanding - template constexpr auto data(const C& c) -> decltype(c.data()); // freestanding + template constexpr auto + data(C& c) noexcept(noexcept(c.data())) -> decltype(c.data()); // freestanding + template constexpr auto + data(const C& c) noexcept(noexcept(c.data())) -> decltype(c.data()); // freestanding template constexpr T* data(T (&array)[N]) noexcept; // freestanding - template constexpr const E* data(initializer_list il) noexcept; // freestanding } \end{codeblock} @@ -890,7 +902,7 @@ \pnum \begin{note} -Some legacy output iterators define a nested type named \tcode{value_type} +Some legacy output iterators declare a nested type named \tcode{value_type} that is an alias for \keyword{void}. These types are not \libconcept{indirectly_readable} and have no associated value types. @@ -917,7 +929,7 @@ \begin{codeblock} iterator_traits::iterator_category \end{codeblock} -be defined as the iterator's iterator category. +be declared as the iterator's iterator category. In addition, the types \indexlibrarymember{pointer}{iterator_traits}% \indexlibrarymember{reference}{iterator_traits}% @@ -925,7 +937,7 @@ iterator_traits::pointer iterator_traits::reference \end{codeblock} -shall be defined as the iterator's pointer and reference types; +shall be declared as the iterator's pointer and reference types; that is, for an iterator object \tcode{a} of class type, the same type as @@ -938,12 +950,15 @@ for an iterator of class type \tcode{I} that does not support \tcode{operator->}. Additionally, in the case of an output iterator, the types +\indexlibrarymember{value_type}{iterator_traits}% +\indexlibrarymember{difference_type}{iterator_traits}% +\indexlibrarymember{reference}{iterator_traits}% \begin{codeblock} iterator_traits::value_type iterator_traits::difference_type iterator_traits::reference \end{codeblock} -may be defined as \keyword{void}. +may be declared as \keyword{void}. \pnum The definitions in this subclause make use of the following @@ -1016,11 +1031,11 @@ \tcode{iterator_traits} has the following publicly accessible members: \begin{codeblock} -using iterator_category = I::iterator_category; -using value_type = I::value_type; -using difference_type = I::difference_type; -using pointer = @\seebelow@; -using reference = I::reference; +using @\libmember{iterator_category}{iterator_traits}@ = I::iterator_category; +using @\libmember{value_type}{iterator_traits}@ = I::value_type; +using @\libmember{difference_type}{iterator_traits}@ = I::difference_type; +using @\libmember{pointer}{iterator_traits}@ = @\seebelow@; +using @\libmember{reference}{iterator_traits}@ = I::reference; \end{codeblock} If the \grammarterm{qualified-id} \tcode{I::pointer} is valid and denotes a type, then \tcode{iterator_traits::pointer} names that type; @@ -1095,7 +1110,7 @@ \pnum Explicit or partial specializations of \tcode{iterator_traits} may -have a member type \tcode{iterator_concept} that is used to indicate +have a member type \tcode{\libmember{iterator_concept}{iterator_traits}} that is used to indicate conformance to the iterator concepts\iref{iterator.concepts}. \begin{example} To indicate conformance to the \libconcept{input_iterator} concept @@ -1103,7 +1118,7 @@ the \oldconcept{InputIter\-ator} requirements\iref{input.iterators}, an \tcode{iterator_traits} specialization might have \tcode{iterator_concept} denote \tcode{input_iterator_tag} -but not define \tcode{iterator_category}. +but not declare \tcode{iterator_category}. \end{example} \pnum @@ -1660,6 +1675,7 @@ template concept @\deflibconcept{sentinel_for}@ = @\libconcept{semiregular}@ && + !@\exposid{is-integer-like}@ && @\libconcept{input_or_output_iterator}@ && @\exposconcept{weakly-equality-comparable-with}@; // see \ref{concept.equalitycomparable} \end{itemdecl} @@ -1676,6 +1692,9 @@ \range{++i}{s} denotes a range. \item \tcode{\libconcept{assignable_from}} is either modeled or not satisfied. + +\item If \tcode{I} and \tcode{S} are the same type, then + \tcode{i == i} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -1737,7 +1756,7 @@ for cv-unqualified non-array object types \tcode{S} and \tcode{I} if \tcode{S} and/or \tcode{I} is a program-defined type. Such specializations shall -be usable in constant expressions\iref{expr.const} and +be usable in constant expressions\iref{expr.const.init} and have type \tcode{const bool}. \pnum @@ -2769,7 +2788,7 @@ For every iterator of type \tcode{I}, \tcode{iterator_traits::it\-er\-a\-tor_ca\-te\-go\-ry} -shall be defined to be a category tag that describes the +shall be declared to be a category tag that describes the iterator's behavior. Additionally, \tcode{iterator_traits::it\-er\-a\-tor_con\-cept} @@ -4246,6 +4265,7 @@ @\exposid{iter-const-rvalue-reference-t}@; public: + using iterator_type = Iterator; using iterator_concept = @\seebelow@; using iterator_category = @\seebelow@; // not always present using value_type = iter_value_t; @@ -4383,7 +4403,7 @@ \end{itemize} \pnum -The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +The member \grammarterm{typedef-name} \tcode{iterator_category} is declared if and only if \tcode{Iterator} models \libconcept{forward_iterator}. In that case, \tcode{basic_const_iterator::iterator_category} denotes @@ -4859,7 +4879,7 @@ \end{itemize} \pnum -The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +The member \grammarterm{typedef-name} \tcode{iterator_category} is declared if and only if the \grammarterm{qualified-id} \tcode{iterator_traits::iterator_category} is valid and denotes a type. @@ -5519,7 +5539,7 @@ \pnum 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. +is declared 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} @@ -6575,7 +6595,7 @@ \pnum \remarks If the initializer \tcode{T()} in the declaration \tcode{auto x = T();} -is a constant initializer\iref{expr.const}, +is a constant initializer\iref{expr.const.init}, then these constructors are \keyword{constexpr} constructors. \end{itemdescr} @@ -7241,28 +7261,35 @@ In addition to being available via inclusion of the \libheader{iterator} header, the function templates in \ref{iterator.range} are available when any of the following 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}, -\libheaderref{hive}, -\libheaderrefx{inplace_vector}{inplace.vector.syn}, -\libheaderref{list}, -\libheaderrefx{map}{associative.map.syn}, -\libheaderrefx{regex}{re.syn}, -\libheaderrefx{set}{associative.set.syn}, -\libheaderref{span}, -\libheaderref{string}, -\libheaderrefx{string_view}{string.view.synop}, -\libheaderrefx{unordered_map}{unord.map.syn}, -\libheaderrefx{unordered_set}{unord.set.syn}, and -\libheaderref{vector}. +\begin{itemize} +\item \libheaderref{array} +\item \libheaderref{deque} +\item \libheaderrefx{flat_map}{flat.map.syn} +\item \libheaderrefx{flat_set}{flat.set.syn} +\item \libheaderrefx{forward_list}{forward.list.syn} +\item \libheaderref{hive} +\item \libheaderrefx{inplace_vector}{inplace.vector.syn} +\item \libheaderref{list} +\item \libheaderrefx{map}{associative.map.syn} +\item \libheaderref{optional} +\item \libheaderrefx{regex}{re.syn} +\item \libheaderrefx{set}{associative.set.syn} +\item \libheaderref{span} +\item \libheaderref{stacktrace} +\item \libheaderref{string} +\item \libheaderrefx{string_view}{string.view.synop} +\item \libheaderrefx{unordered_map}{unord.map.syn} +\item \libheaderrefx{unordered_set}{unord.set.syn} +\item \libheaderref{valarray} +\item \libheaderref{vector} +\end{itemize} \indexlibrary{\idxcode{begin(C\&)}}% \begin{itemdecl} -template constexpr auto begin(C& c) -> decltype(c.begin()); -template constexpr auto begin(const C& c) -> decltype(c.begin()); +template constexpr auto begin(C& c) noexcept(noexcept(c.begin())) + -> decltype(c.begin()); +template constexpr auto begin(const C& c) noexcept(noexcept(c.begin())) + -> decltype(c.begin()); \end{itemdecl} \begin{itemdescr} @@ -7273,8 +7300,8 @@ \indexlibrary{\idxcode{end(C\&)}}% \begin{itemdecl} -template constexpr auto end(C& c) -> decltype(c.end()); -template constexpr auto end(const C& c) -> decltype(c.end()); +template constexpr auto end(C& c) noexcept(noexcept(c.end())) -> decltype(c.end()); +template constexpr auto end(const C& c) noexcept(noexcept(c.end())) -> decltype(c.end()); \end{itemdecl} \begin{itemdescr} @@ -7329,8 +7356,10 @@ \indexlibrary{\idxcode{rbegin(C\&)}}% \begin{itemdecl} -template constexpr auto rbegin(C& c) -> decltype(c.rbegin()); -template constexpr auto rbegin(const C& c) -> decltype(c.rbegin()); +template constexpr auto rbegin(C& c) noexcept(noexcept(c.rbegin())) + -> decltype(c.rbegin()); +template constexpr auto rbegin(const C& c) noexcept(noexcept(c.rbegin())) + -> decltype(c.rbegin()); \end{itemdecl} \begin{itemdescr} \pnum @@ -7340,8 +7369,9 @@ \indexlibrary{\idxcode{rend(C\&)}}% \begin{itemdecl} -template constexpr auto rend(C& c) -> decltype(c.rend()); -template constexpr auto rend(const C& c) -> decltype(c.rend()); +template constexpr auto rend(C& c) noexcept(noexcept(c.rend())) -> decltype(c.rend()); +template constexpr auto rend(const C& c) noexcept(noexcept(c.rend())) + -> decltype(c.rend()); \end{itemdecl} \begin{itemdescr} \pnum @@ -7351,7 +7381,7 @@ \indexlibrary{\idxcode{rbegin(T (\&array)[N])}}% \begin{itemdecl} -template constexpr reverse_iterator rbegin(T (&array)[N]); +template constexpr reverse_iterator rbegin(T (&array)[N]) noexcept; \end{itemdecl} \begin{itemdescr} \pnum @@ -7361,7 +7391,7 @@ \indexlibrary{\idxcode{rend(T (\&array)[N])}}% \begin{itemdecl} -template constexpr reverse_iterator rend(T (&array)[N]); +template constexpr reverse_iterator rend(T (&array)[N]) noexcept; \end{itemdecl} \begin{itemdescr} \pnum @@ -7371,7 +7401,7 @@ \indexlibrary{\idxcode{rbegin(initializer_list)}}% \begin{itemdecl} -template constexpr reverse_iterator rbegin(initializer_list il); +template constexpr reverse_iterator rbegin(initializer_list il) noexcept; \end{itemdecl} \begin{itemdescr} \pnum @@ -7381,7 +7411,7 @@ \indexlibrary{\idxcode{rend(initializer_list)}}% \begin{itemdecl} -template constexpr reverse_iterator rend(initializer_list il); +template constexpr reverse_iterator rend(initializer_list il) noexcept; \end{itemdecl} \begin{itemdescr} \pnum @@ -7391,7 +7421,8 @@ \indexlibrary{\idxcode{crbegin(const C\& c)}}% \begin{itemdecl} -template constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c)); +template constexpr auto crbegin(const C& c) noexcept(noexcept(std::rbegin(c))) + -> decltype(std::rbegin(c)); \end{itemdecl} \begin{itemdescr} \pnum @@ -7401,7 +7432,8 @@ \indexlibrary{\idxcode{crend(const C\& c)}}% \begin{itemdecl} -template constexpr auto crend(const C& c) -> decltype(std::rend(c)); +template constexpr auto crend(const C& c) noexcept(noexcept(c.crend())) + -> decltype(std::rend(c)); \end{itemdecl} \begin{itemdescr} \pnum @@ -7411,7 +7443,8 @@ \indexlibrary{\idxcode{size(C\& c)}}% \begin{itemdecl} -template constexpr auto size(const C& c) -> decltype(c.size()); +template constexpr auto size(const C& c) noexcept(noexcept(c.size())) + -> decltype(c.size()); \end{itemdecl} \begin{itemdescr} \pnum @@ -7431,7 +7464,7 @@ \indexlibrary{\idxcode{ssize(C\& c)}}% \begin{itemdecl} -template constexpr auto ssize(const C& c) +template constexpr auto ssize(const C& c) noexcept(noexcept(c.size())) -> common_type_t>; \end{itemdecl} \begin{itemdescr} @@ -7455,7 +7488,8 @@ \indexlibrary{\idxcode{empty(C\& c)}}% \begin{itemdecl} -template constexpr auto empty(const C& c) -> decltype(c.empty()); +template constexpr auto empty(const C& c) noexcept(noexcept(c.empty())) + -> decltype(c.empty()); \end{itemdecl} \begin{itemdescr} \pnum @@ -7473,20 +7507,11 @@ \tcode{false}. \end{itemdescr} -\indexlibrary{\idxcode{empty(initializer_list)}}% -\begin{itemdecl} -template constexpr bool empty(initializer_list il) noexcept; -\end{itemdecl} -\begin{itemdescr} -\pnum -\returns -\tcode{il.size() == 0}. -\end{itemdescr} - \indexlibrary{\idxcode{data(C\& c)}}% \begin{itemdecl} -template constexpr auto data(C& c) -> decltype(c.data()); -template constexpr auto data(const C& c) -> decltype(c.data()); +template constexpr auto data(C& c) noexcept(noexcept(c.data())) -> decltype(c.data()); +template constexpr auto data(const C& c) noexcept(noexcept(c.data())) + -> decltype(c.data()); \end{itemdecl} \begin{itemdescr} \pnum @@ -7503,13 +7528,3 @@ \returns \tcode{array}. \end{itemdescr} - -\indexlibrary{\idxcode{data(initializer_list)}}% -\begin{itemdecl} -template constexpr const E* data(initializer_list il) noexcept; -\end{itemdecl} -\begin{itemdescr} -\pnum -\returns -\tcode{il.begin()}. -\end{itemdescr} diff --git a/source/lex.tex b/source/lex.tex index 8005b33374..bfd55be51d 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -42,6 +42,13 @@ Translation units can be separately translated and then later linked to produce an executable program\iref{basic.link}. \end{note} +\begin{note} +Source files, translation units, and translated translation units +need not necessarily be stored as files, nor need there be any one-to-one +correspondence between these entities and any external representation. +The description is conceptual only, +and does not specify any particular implementation. +\end{note} \indextext{compilation!separate|)} \rSec1[lex.phases]{Phases of translation}% @@ -104,7 +111,7 @@ zero or more whitespace characters other than new-line followed by a new-line character is deleted, splicing 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 +backslash on any physical source line is eligible for being part of such a splice. \begin{note} Line splicing can form @@ -112,7 +119,7 @@ \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 +is processed as if an additional new-line character were appended to the file. \item The source file is decomposed into preprocessing @@ -165,14 +172,14 @@ as specified in \ref{lex.string}. Each such \grammarterm{string-literal} preprocessing token is then considered to have that common \grammarterm{encoding-prefix}. - -\item \indextext{concatenation!string}% -Adjacent \grammarterm{string-literal} preprocessing tokens are concatenated\iref{lex.string}. +Then, adjacent \grammarterm{string-literal} preprocessing tokens are concatenated\iref{lex.string}. \item Each preprocessing token is converted into a token\iref{lex.token}. -The resulting tokens constitute a \defn{translation unit} and + +\item +The tokens constitute a \defn{translation unit} and are syntactically and semantically analyzed as a \grammarterm{translation-unit}\iref{basic.link} and translated. @@ -192,13 +199,6 @@ dependency\iref{module.unit,module.import} are required to be available. \begin{note} -Source files, translation -units and translated translation units need not necessarily be stored as -files, nor need there be any one-to-one correspondence between these -entities and any external representation. The description is conceptual -only, and does not specify any particular implementation. -\end{note} -\begin{note} Previously translated translation units can be preserved individually or in libraries. The separate translation units of a program communicate\iref{basic.link} by (for example) calls to functions whose names have external or module linkage, @@ -227,11 +227,14 @@ that it be instantiated at an earlier point\iref{temp.inst}. \end{note} -Each instantiation results in new program constructs. The program is ill-formed if any instantiation fails. During the analysis and translation of tokens, -certain expressions are evaluated\iref{expr.const}. +each manifestly constant-evaluated expression is evaluated\iref{expr.const.defns}. +The values of these expressions affect +the types named and reflection values used in the program and +thus the syntactic analysis. +Their evaluation also can produce side effects that affect that analysis. Constructs appearing at a program point $P$ are analyzed in a context where each side effect of evaluating an expression $E$ as a full-expression is complete if and only if @@ -261,19 +264,19 @@ void fn() { /* @$p_1$@ */ Incomplete i; // OK } - }; /* @$p_2$@ */ + } /* @$p_2$@ */ ; consteval { define_aggregate(^^Incomplete, {}); } -}; /* @$p_3$@ */ +} /* @$p_3$@ */ ; \end{codeblock} Constructs at $p_1$ are analyzed in a context -where the side effect of the call to \tcode{define_aggregate} is evaluated +where the side effect of the call to \tcode{define_aggregate} is complete because \begin{itemize} \item -$E$ is the expression corresponding to a consteval block, and +the call appears in a consteval block, and \item $p_1$ is in a complete-class context of \tcode{S} and the consteval block is reachable from $p_3$. @@ -283,7 +286,7 @@ \item \indextext{linking}% Translated translation units are combined, and -all external entity references are resolved. Library +all external entity references are resolved\iref{basic.link}. 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 @@ -317,6 +320,9 @@ \pnum The \defnadj{basic}{character set} is a subset of the translation character set, consisting of 99 characters as specified in \tref{lex.charset.basic}. +In this document, +glyphs are often used to identify +elements of the basic character set. \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. @@ -415,7 +421,7 @@ No other element of the translation character set is encoded with a code unit of value \tcode{0}. The code unit value of each decimal digit character after the digit \tcode{0} (\ucode{0030}) -shall be one greater than the value of the previous. +is one greater than the value of the previous. The ordinary and wide literal encodings are otherwise \impldef{ordinary and wide literal encodings}. \indextext{UTF-8}% @@ -468,9 +474,8 @@ 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} +the \grammarterm{c-char-sequence} or \grammarterm{s-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. @@ -548,10 +553,7 @@ \pnum A preprocessing token is the minimal lexical element of the language in translation -phases 3 through 6. -In this document, -glyphs are used to identify -elements of the basic character set\iref{lex.charset}. +phases 3 through 5. The categories of preprocessing token are: header names, placeholder tokens produced by preprocessing \tcode{import} and \tcode{module} directives (\grammarterm{import-keyword}, \grammarterm{module-keyword}, and \grammarterm{export-keyword}), @@ -562,6 +564,8 @@ If a \unicode{0027}{apostrophe}, a \unicode{0022}{quotation mark}, or any character not in the basic character set matches the last category, the program is ill-formed. + +\pnum Preprocessing tokens can be separated by \indextext{whitespace}% whitespace; @@ -572,16 +576,19 @@ new-line, \unicode{000b}{line tabulation}, and \unicode{000c}{form feed}), or both. +\begin{note} As described in \ref{cpp}, in certain circumstances during translation phase 4, whitespace (or the absence thereof) serves as more than preprocessing token separation. Whitespace can appear within a preprocessing token only as part of a header name or between the quotation characters in a character literal or string literal. +\end{note} \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, +a header name, or an operator or punctuator. \pnum @@ -609,7 +616,7 @@ token shall be a raw string literal. Between the initial and final double quote characters of the raw string, any transformations performed in phase 2 (line splicing) are reverted; this reversion -shall apply before any \grammarterm{d-char}, \grammarterm{r-char}, or delimiting +is applied before any \grammarterm{d-char}, \grammarterm{r-char}, or delimiting parenthesis is identified. The raw string literal is defined as the shortest sequence of characters that matches the raw-string pattern \begin{ncbnf} @@ -808,7 +815,7 @@ \end{bnf} Each \grammarterm{operator-or-punctuator} is converted to a single token -in translation phase 7\iref{lex.phases}.% +in translation phase 6\iref{lex.phases}.% \indextext{punctuator|)}% \indextext{operator|)} @@ -831,11 +838,11 @@ \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} +\begin{note} +The ``stringized'' values\iref{cpp.stringize} of +\tcode{[} and \tcode{<:} are different, +maintaining the source spelling. +\end{note} The set of alternative tokens is defined in \tref{lex.digraph}. @@ -869,25 +876,15 @@ identifier\br keyword\br literal\br + header-name\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} +There are six kinds of tokens: identifiers, keywords, literals, +header names, operators, and other separators. -\indextext{whitespace}% -Comments and the characters \unicode{0020}{space}, \unicode{0009}{character tabulation}, -\unicode{000b}{line tabulation}, \unicode{000c}{form feed}, and new-line -(collectively, ``whitespace''), as described below, are ignored except -as they serve to separate tokens. -\begin{note} -Whitespace can separate otherwise adjacent identifiers, keywords, numeric -literals, and alternative tokens containing alphabetic characters. -\end{note} \indextext{token|)} \rSec1[lex.name]{Identifiers} @@ -966,8 +963,6 @@ \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. @@ -976,17 +971,26 @@ token as a regular \grammarterm{identifier}. \begin{multicolfloattable}{Identifiers with special meaning}{lex.name.special} -{llll} -\keyword{final} \\ -\keyword{override} \\\columnbreak -\keyword{import} \\ -\keyword{module} \\\columnbreak -\keyword{post} \\ -\keyword{pre} \\\columnbreak -\keyword{replaceable_if_eligible} \\ -\keyword{trivially_relocatable_if_eligible} \\ +{llllll} +\keyword{final} \\ +\columnbreak +\keyword{import} \\ +\columnbreak +\keyword{module} \\ +\columnbreak +\keyword{override} \\ +\columnbreak +\keyword{post} \\ +\columnbreak +\keyword{pre} \\ \end{multicolfloattable} +\pnum +\begin{note} +Identifiers with special meaning +cannot be used as macro names\iref{cpp.replace.general}. +\end{note} + \pnum \indextext{\idxcode{_}|see{character, underscore}}% \indextext{character!underscore!in identifier}% @@ -1029,7 +1033,7 @@ \indextext{keyword|(}% The identifiers shown in \tref{lex.key} are reserved for use as keywords (that is, they are unconditionally treated as keywords in -phase 7) except in an \grammarterm{attribute-token}\iref{dcl.attr.grammar}. +phases 6 and 7) except in an \grammarterm{attribute-token}\iref{dcl.attr.grammar}. \begin{note} The \keyword{register} keyword is unused but is reserved for future use. @@ -1125,6 +1129,11 @@ \keyword{while} \\ \end{multicolfloattable} +\pnum +\begin{note} +Keywords cannot be used as macro names\iref{cpp.replace.general}. +\end{note} + \pnum Furthermore, the alternative representations shown in \tref{lex.key.digraph} for certain operators and @@ -1149,10 +1158,6 @@ \indextext{constant}% \indextext{literal!constant}% There are several kinds of literals. -\begin{footnote} -The term ``literal'' generally designates, in this -document, those tokens that are called ``constants'' in C. -\end{footnote} \begin{bnf} \nontermdef{literal}\br @@ -1793,16 +1798,30 @@ else the larger or smaller representable value nearest the scaled value, chosen in an \impldef{choice of larger or smaller value of \grammarterm{floating-point-literal}} manner. +\begin{example} +The following example assumes that +\tcode{std::float32_t} is supported\iref{basic.extended.fp}. +\begin{codeblock} +std::float32_t x = 0.0f32; // value \tcode{0} is exactly representable +std::float32_t y = 0.1f32; // rounded to one of two values nearest to \tcode{0.1} +std::float32_t z = 1e1000000000f32; // either greatest finite value or positive infinity +\end{codeblock} +\end{example} \rSec2[lex.string]{String literals} \indextext{literal!string}% \begin{bnf} \nontermdef{string-literal}\br - \opt{encoding-prefix} \terminal{"} \opt{s-char-sequence} \terminal{"}\br + \opt{encoding-prefix} plain-string-literal\br \opt{encoding-prefix} \terminal{R} raw-string \end{bnf} +\begin{bnf} +\nontermdef{plain-string-literal}\br + \terminal{"} \opt{s-char-sequence} \terminal{"} +\end{bnf} + \begin{bnf} \nontermdef{s-char-sequence}\br s-char \opt{s-char-sequence} @@ -1851,7 +1870,6 @@ \pnum \indextext{literal!string}% -\indextext{character string}% \indextext{string!type of}% \indextext{type!\idxcode{wchar_t}}% \indextext{prefix!\idxcode{L}}% @@ -1972,7 +1990,7 @@ \end{note} \pnum -In translation phase 6\iref{lex.phases}, +In translation phase 5\iref{lex.phases}, adjacent \grammarterm{string-literal}s are concatenated. The lexical structure and grouping of the contents of the individual \grammarterm{string-literal}s is retained. @@ -2262,7 +2280,7 @@ 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 +the literal \placeholder{L} is treated as a call of the form \begin{codeblock} operator ""@\placeholder{X}@("@\placeholder{f}@") \end{codeblock} @@ -2321,11 +2339,11 @@ \end{example} \pnum -In translation phase 6\iref{lex.phases}, adjacent \grammarterm{string-literal}s are concatenated and +In translation phase 5\iref{lex.phases}, adjacent \grammarterm{string-literal}s are concatenated and \grammarterm{user-defined-string-literal}{s} are considered \grammarterm{string-literal}s for that purpose. During concatenation, \grammarterm{ud-suffix}{es} are removed and ignored and the concatenation process occurs as described in~\ref{lex.string}. At the end of phase -6, if a \grammarterm{string-literal} is the result of a concatenation involving at least one +5, if a \grammarterm{string-literal} is the result of a concatenation involving at least one \grammarterm{user-defined-string-literal}, all the participating \grammarterm{user-defined-string-literal}{s} shall have the same \grammarterm{ud-suffix} and that suffix is applied to the result of the concatenation. diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 2958545e4a..de00b5b2f8 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -390,12 +390,9 @@ \item When invoking the function in a hardened implementation, prior to any other observable side effects of the function, -one or more contract assertions +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. +are evaluated with a terminating semantic\iref{basic.contract.eval}. \item When invoking the function in a non-hardened implementation, if any hardened precondition is violated, @@ -531,24 +528,24 @@ \pnum Several entities -defined in \ref{\firstlibchapter} through \ref{\lastlibchapter} and \ref{depr} -are only defined for the purpose of exposition. +declared in \ref{\firstlibchapter} through \ref{\lastlibchapter} and \ref{depr} +are provided for exposition only. The declaration of such an entity is followed by a comment ending in \expos. \pnum -The following are defined for exposition only +The following are provided for exposition only to aid in the specification of the library: \indexlibrary{decay-copy@\exposid{decay-copy}}% \begin{codeblock} namespace std { template requires @\libconcept{convertible_to}@> - constexpr decay_t @\exposidnc{decay-copy}@(T&& v) // \expos + constexpr decay_t @\exposidnc{decay-copy}@(T&& v) // \expos noexcept(is_nothrow_convertible_v>) { return std::forward(v); } - constexpr auto @\exposidnc{synth-three-way}@ = // \expos + constexpr auto @\exposidnc{synth-three-way}@ = // \expos [](const T& t, const U& u) requires requires { { t < u } -> @\exposconcept{boolean-testable}@; @@ -565,8 +562,15 @@ }; template - using @\exposidnc{synth-three-way-result}@ = // \expos + using @\exposidnc{synth-three-way-result}@ = // \expos decltype(@\exposidnc{synth-three-way}@(declval(), declval())); + + template + concept @\defexposconceptnc{constexpr-wrapper-like}@ = // \expos + @\libconcept{convertible_to}@ && + @\libconcept{equality_comparable_with}@ && + bool_constant::value && + bool_constant(T()) == T::value>::value; } \end{codeblock} @@ -601,14 +605,14 @@ the library. \pnum -Certain types defined in \ref{input.output} are used to describe implementation-defined types. +Certain types shown in \ref{input.output} are used to describe implementation-defined types. \indextext{types!implementation-defined}% They are based on other types, but with added constraints. \rSec4[enumerated.types]{Enumerated types} \pnum -Several types defined in \ref{input.output} are +Several types specified in \ref{input.output} and \ref{re} are \defnadjx{enumerated}{types}{type}. Each enumerated type may be implemented as an enumeration or as a synonym for an enumeration. @@ -641,7 +645,7 @@ \rSec4[bitmask.types]{Bitmask types} \pnum -Several types defined in \ref{\firstlibchapter} through \ref{\lastlibchapter} +Several types specified in \ref{\firstlibchapter} through \ref{\lastlibchapter} and \ref{depr} are \defnx{bitmask types}{type!bitmask}. Each bitmask type can be implemented as an @@ -871,7 +875,12 @@ \pnum The type of a customization point object, ignoring cv-qualifiers, shall model -\libconcept{semiregular}\iref{concepts.object}. +\libconcept{semiregular}\iref{concepts.object} +and shall be +a structural type\iref{temp.param} and +a trivially copyable type\iref{class.prop}. +Every constructor of this type +shall have a non-throwing exception specification\iref{except.spec}. \pnum All instances of a specific customization point object type shall @@ -1615,9 +1624,9 @@ \ref{support.rtti} & Type identification & \tcode{} \\ \rowsep \ref{support.srcloc} & Source location & \tcode{} \\ \rowsep \ref{support.exception} & Exception handling & \tcode{} \\ \rowsep +\ref{support.contract} & Contract-violation 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 @@ -1815,12 +1824,6 @@ rvalue of type \tcode{const T}. \end{itemize} -\pnum -In general, a default constructor is not required. Certain container class -member function signatures specify \tcode{T()} as a default argument. -\tcode{T()} shall be a well-defined expression\iref{dcl.init} if one of those -signatures is called using the default argument\iref{dcl.fct.default}. - \begin{oldconcepttable}{EqualityComparable}{}{cpp17.equalitycomparable} {x{1in}x{1in}p{3in}} \topline @@ -1848,7 +1851,6 @@ \tcode{<} is a strict weak ordering relation\iref{alg.sorting} \\ \end{oldconcepttable} -\enlargethispage{-3\baselineskip} \begin{oldconcepttable}{DefaultConstructible}{}{cpp17.defaultconstructible} {x{2.15in}p{3in}} \topline @@ -1914,7 +1916,7 @@ {p{1in}p{4.15in}} \topline \hdstyle{Expression} & \hdstyle{Post-condition} \\ \capsep -\tcode{a.\~T()} & All resources owned by \tcode{a} are reclaimed, no exception is propagated. \\ \rowsep +\tcode{a.\~T()} & No exception is propagated. \\ \rowsep \multicolumn{2}{|l|}{ \begin{tailnote} Array types and non-object types are not \oldconcept{Destructible}. @@ -2345,12 +2347,12 @@ \pnum \remarks -If \tcode{Allocator} is a class template instantiation of the form +If \tcode{Allocator} is a class template specialization of the form \tcode{SomeAllocator}, where \tcode{Args} is zero or more type arguments, and \tcode{Allocator} does not supply a \tcode{rebind} member template, the standard \tcode{allocator_traits} template uses \tcode{SomeAllocator} in place of \tcode{Allocator::re\-bind::other} -by default. For allocator types that are not template instantiations of the +by default. For allocator types that are not template specializations of the above form, no default is provided. \pnum @@ -3072,7 +3074,7 @@ Let \tcode{\placeholder{F}} denote a standard library function\iref{global.functions}, a standard library static member function, -or an instantiation +or a specialization of a standard library function template. Unless \tcode{\placeholder{F}} is designated an \defnadj{addressable}{function}, @@ -3094,7 +3096,7 @@ or if it attempts to form a pointer-to-member designating either a standard library non-static member function\iref{member.functions} -or an instantiation of a standard library member function template. +or a specialization of a standard library member function template. \pnum Let \tcode{\placeholder{F}} denote @@ -3102,6 +3104,14 @@ Unless \tcode{\placeholder{F}} is designated an addressable function, it is unspecified if or how a reflection value designating the associated entity can be formed. +For any value \tcode{\placeholder{p}} of type \tcode{meta::info} that +represents a reflection of a parameter of \tcode{\placeholder{F}}, +it is unspecified if \tcode{has_identifier(\placeholder{p})} +returns \tcode{true} or \tcode{false}, and +if \tcode{meta::has_identifier(\placeholder{p})} is \tcode{true}, then +the \ntmbs{} produced by +\tcode{meta::identifier_of(\placeholder{p})} and +\tcode{meta::u8identifier_of(\placeholder{p})} is unspecified. %FIXME: Why is this not an example, but a note that begins with "For example"? \begin{note} For example, it is possible that \tcode{std::meta::members_of} @@ -3382,7 +3392,7 @@ \tcode{::T} and \tcode{std::T} -are reserved to the implementation and, when defined, +are reserved to the implementation and, when declared, \tcode{::T} shall be identical to \tcode{std::T}. @@ -3786,6 +3796,16 @@ the \Cpp{} standard library may be recursively reentered} which functions in the \Cpp{} standard library may be recursively reentered. +\pnum +During the execution of +a standard library non-static member function $F$ on an object, +if that object is accessed through a glvalue that is not obtained, +directly or indirectly, +from the object parameter of $F$, +in a manner that can conflict\iref{intro.races} +with any access that $F$ is permitted to perform\iref{res.on.data.races}, +the behavior is undefined unless otherwise specified. + \rSec3[res.on.data.races]{Data race avoidance} \pnum @@ -3850,20 +3870,6 @@ \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 @@ -3989,7 +3995,7 @@ \rSec3[value.error.codes]{Value of error codes} \pnum -Certain functions in the \Cpp{} standard library report errors via a +Certain functions in the \Cpp{} standard library report errors via an \tcode{error_code}\iref{syserr.errcode.overview} object. That object's \tcode{category()} member shall return \tcode{system_category()} for errors originating from the operating system, or a reference to an diff --git a/source/limits.tex b/source/limits.tex index bdc1f3deb6..e0596a320a 100644 --- a/source/limits.tex +++ b/source/limits.tex @@ -111,7 +111,7 @@ \item% Recursive constexpr function invocations\iref{dcl.constexpr} [512]. \item% -Full-expressions evaluated within a core constant expression\iref{expr.const} [1\,048\,576]. +Full-expressions evaluated within a core constant expression\iref{expr.const.core} [1\,048\,576]. \item% Template parameters in a template declaration\iref{temp.param} [1\,024]. \item% diff --git a/source/macros.tex b/source/macros.tex index ae5591106e..397ea0f2d1 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -406,8 +406,10 @@ \ExplSyntaxOff %% Inline non-parenthesized table reference (override memoir's \tref) +\providecommand{\tref}{} \renewcommand{\tref}[1]{\hyperref[tab:#1]{\tablerefname \nolinebreak[3] \ref*{tab:#1}}} %% Inline non-parenthesized figure reference (override memoir's \fref) +\providecommand{\fref}{} \renewcommand{\fref}[1]{\hyperref[fig:#1]{\figurerefname \nolinebreak[3] \ref*{fig:#1}}} %% NTBS, etc. @@ -609,7 +611,7 @@ #1:}}\CodeBlockSetup}{} % An environment for command / program output that is not C++ code. -\lstnewenvironment{outputblock}{\lstset{language=}}{} +\lstnewenvironment{outputblock}{\lstset{escapechar=@, language=}}{} % A code block in which single-quotes are digit separators % rather than character literals. diff --git a/source/memory.tex b/source/memory.tex index 1b455e868b..be9812fa2d 100644 --- a/source/memory.tex +++ b/source/memory.tex @@ -85,9 +85,11 @@ template constexpr T* assume_aligned(T* ptr); // freestanding template - bool is_sufficiently_aligned(T* ptr); + bool is_sufficiently_aligned(T* ptr); // freestanding // \ref{obj.lifetime}, explicit lifetime management + template + constexpr void start_lifetime(T& r) noexcept; // freestanding template T* start_lifetime_as(void* p) noexcept; // freestanding template @@ -105,10 +107,6 @@ template const volatile T* start_lifetime_as_array(const volatile void* p, // freestanding size_t n) noexcept; - template - T* trivially_relocate(T* first, T* last, T* result); // freestanding - template - constexpr T* relocate(T* first, T* last, T* result); // freestanding // \ref{allocator.tag}, allocator argument tag struct allocator_arg_t { explicit allocator_arg_t() = default; }; // freestanding @@ -417,47 +415,52 @@ O ofirst, S olast); // see \ref{algorithms.parallel.overloads} } - template + template::value_type> constexpr void uninitialized_fill(NoThrowForwardIterator first, // freestanding NoThrowForwardIterator last, const T& x); - template + template::value_type> void uninitialized_fill(ExecutionPolicy&& exec, // freestanding-deleted, NoThrowForwardIterator first, // see \ref{algorithms.parallel.overloads} NoThrowForwardIterator last, const T& x); - template + template::value_type> constexpr NoThrowForwardIterator uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); // freestanding - template + template::value_type> NoThrowForwardIterator 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> + template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S, class T = iter_value_t> requires @\libconcept{constructible_from}@, const T&> constexpr I uninitialized_fill(I first, S last, const T& x); // freestanding - template<@\exposconcept{nothrow-forward-range}@ R, class T> + template<@\exposconcept{nothrow-forward-range}@ R, class T = range_value_t> requires @\libconcept{constructible_from}@, const T&> constexpr borrowed_iterator_t uninitialized_fill(R&& r, const T& x); // freestanding - template<@\exposconcept{nothrow-forward-iterator}@ I, class T> + template<@\exposconcept{nothrow-forward-iterator}@ I, class T = iter_value_t> requires @\libconcept{constructible_from}@, const T&> constexpr I uninitialized_fill_n(I first, // freestanding iter_difference_t n, const T& x); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I, - @\exposconcept{nothrow-sized-sentinel-for}@ S, class T> + @\exposconcept{nothrow-sized-sentinel-for}@ S, class T = iter_value_t> requires @\libconcept{constructible_from}@, const T&> I uninitialized_fill(Ep&& exec, I first, S last, const T& x); // freestanding-deleted, // see \ref{algorithms.parallel.overloads} - template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R, class T> + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R, + class T = range_value_t> requires @\libconcept{constructible_from}@, const T&> borrowed_iterator_t uninitialized_fill(Ep&& exec, R&& r, // freestanding-deleted, const T& x); // see \ref{algorithms.parallel.overloads} - template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I, class T> + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I, class T = iter_value_t> requires @\libconcept{constructible_from}@, const T&> I uninitialized_fill_n(Ep&& exec, I first, // freestanding-deleted, iter_difference_t n, const T& x); // see \ref{algorithms.parallel.overloads} @@ -507,15 +510,15 @@ template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I, @\exposconcept{nothrow-sized-sentinel-for}@ S> requires @\libconcept{destructible}@> - I destroy(Ep&& exec, I first, S last) noexcept; // freestanding-deleted, + I destroy(Ep&& exec, I first, S last); // freestanding-deleted, // see \ref{algorithms.parallel.overloads} template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R> requires @\libconcept{destructible}@> - borrowed_iterator_t destroy(Ep&& exec, R&& r) noexcept; // freestanding-deleted, + borrowed_iterator_t destroy(Ep&& exec, R&& r); // freestanding-deleted, // see \ref{algorithms.parallel.overloads} template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I> requires @\libconcept{destructible}@> - I destroy_n(Ep&& exec, I first, iter_difference_t n) noexcept; // freestanding-deleted, + I destroy_n(Ep&& exec, I first, iter_difference_t n); // freestanding-deleted, // see \ref{algorithms.parallel.overloads} } @@ -841,7 +844,7 @@ the \grammarterm{qualified-id} \tcode{Ptr::rebind} is valid and denotes a type\iref{temp.deduct}; otherwise, \tcode{SomePointer} if -\tcode{Ptr} is a class template instantiation of the form \tcode{SomePointer}, +\tcode{Ptr} is a class template specialization of the form \tcode{SomePointer}, where \tcode{Args} is zero or more type arguments; otherwise, the instantiation of \tcode{rebind} is ill-formed. \end{itemdescr} @@ -850,7 +853,7 @@ \indexlibrarymember{pointer_to}{pointer_traits}% \begin{itemdecl} -static pointer pointer_traits::pointer_to(@\seebelow@ r); +static constexpr pointer pointer_traits::pointer_to(@\seebelow@ r); static constexpr pointer pointer_traits::pointer_to(@\seebelow@ r) noexcept; \end{itemdecl} @@ -1023,6 +1026,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{Alignment} is a power of two. + \pnum \expects \tcode{p} points to @@ -1040,6 +1047,31 @@ \rSec2[obj.lifetime]{Explicit lifetime management} +\indexlibraryglobal{start_lifetime}% +\begin{itemdecl} +template + constexpr void start_lifetime(T& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is a complete type and +an implicit-lifetime\iref{basic.types} aggregate\iref{dcl.init.aggr}. + +\pnum +\effects +If the object referenced by \tcode{r} +is already within its lifetime\iref{basic.life}, +no effects. +Otherwise, begins the lifetime of the object referenced by \tcode{r}. +\begin{note} +No initialization is performed and no subobject has its lifetime started. +If \tcode{r} denotes a member of a union $U$, +it becomes the active member of $U$\iref{class.union}. +\end{note} +\end{itemdescr} + \indexlibraryglobal{start_lifetime_as}% \begin{itemdecl} template @@ -1135,128 +1167,6 @@ a pointer that compares equal to \tcode{p}\iref{expr.eq}. \end{itemdescr} -\indexlibraryglobal{trivially_relocate}% -\begin{itemdecl} -template - T* trivially_relocate(T* first, T* last, T* result); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{is_trivially_relocatable_v \&\& !is_const_v} is \tcode{true}. -\tcode{T} is not an array of unknown bound. - -\pnum -\expects -\begin{itemize} -\item - \range{first}{last} is a valid range. -\item - \range{result}{result + (last - first)} denotes a region of storage that - is a subset of the region reachable through \tcode{result}\iref{basic.compound} - and suitably aligned for the type \tcode{T}. -\item - No element in the range \range{first}{last} is a potentially-overlapping subobject. -\end{itemize} - -\pnum -\ensures -No effect if \tcode{result == first} is \tcode{true}. -Otherwise, the range denoted by \range{result}{result + (last - first)} -contains objects (including subobjects) whose lifetime has begun and whose -object representations are the original object representations of the -corresponding objects in the source range \range{first}{last} except -for any parts of the object representations used by the implementation to -represent type information\iref{intro.object}. If any of the objects has -union type, its active member is the same as that of the corresponding object -in the source range. If any of the aforementioned objects has a non-static -data member of reference type, that reference refers to the same entity as -does the corresponding reference in the source range. The lifetimes of the -original objects in the source range have ended. - -\pnum -\returns -\tcode{result + (last - first)}. - -\pnum -\throws -Nothing. - -\pnum -\complexity -Linear in the length of the source range. - -\pnum -\remarks -The destination region of storage is considered reused\iref{basic.life}. -No constructors or destructors are invoked. - -\begin{note} -Overlapping ranges are supported. -\end{note} -\end{itemdescr} - -\indexlibraryglobal{relocate}% -\begin{itemdecl} -template - constexpr T* relocate(T* first, T* last, T* result); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{is_nothrow_relocatable_v \&\& !is_const_v} is \tcode{true}. -\tcode{T} is not an array of unknown bound. - -\pnum -\expects -\begin{itemize} -\item - \range{first}{last} is a valid range. -\item - \range{result}{result + (last - first)} denotes a region of storage that is - a subset of the region reachable through \tcode{result}\iref{basic.compound} - and suitably aligned for the type \tcode{T}. -\item - No element in the range \range{first}{last} is a potentially-overlapping - subobject. -\end{itemize} - -\pnum -\effects -\begin{itemize} -\item - If \tcode{result == first} is \tcode{true}, no effect; -\item - otherwise, if not called during constant evaluation and - \tcode{is_trivially_relocatable_v} is \tcode{true}, then has - effects equivalent to: \tcode{trivially_relocate(first, last, result);} -\item - otherwise, for each integer \tcode{i} in \range{0}{last - first}, - \begin{itemize} - \item - if \tcode{T} is an array type, equivalent to: - \tcode{relocate(begin(first[i]), end(first[i]), *start_lifetime_as(result + i));} - \item - otherwise, equivalent to: - \tcode{construct_at(result + i, std::move(first[i])); destroy_at(first + i);} - \end{itemize} -\end{itemize} - -\pnum -\returns -\tcode{result + (last - first)}. - -\pnum -\throws -Nothing. - -\begin{note} -Overlapping ranges are supported. -\end{note} -\end{itemdescr} - \rSec2[allocator.tag]{Allocator argument tag} \indexlibraryglobal{allocator_arg_t}% @@ -1326,7 +1236,7 @@ then \tcode{alloc} is ignored. \item Otherwise, if \tcode{T} has a constructor invocable as - \tcode{T(allocator_arg, alloc, args...)} (leading-allocator convention), + \tcode{T(allocator_arg_t\{\}, alloc, args...)} (leading-allocator convention), then uses-allocator construction chooses this constructor form. \item Otherwise, if \tcode{T} has a constructor invocable as @@ -1836,7 +1746,7 @@ \templalias \tcode{Alloc::rebind::other} if the \grammarterm{qualified-id} \tcode{Alloc::rebind::other} is valid and denotes a type\iref{temp.deduct}; otherwise, -\tcode{Alloc} if \tcode{Alloc} is a class template instantiation +\tcode{Alloc} if \tcode{Alloc} is a class template specialization of the form \tcode{Alloc}, where \tcode{Args} is zero or more type arguments; otherwise, the instantiation of \tcode{rebind_alloc} is ill-formed. \end{itemdescr} @@ -2763,6 +2673,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{*declval()} is a well-formed expression. + \pnum \mandates \tcode{reference_converts_from_temporary_v, decltype(\linebreak{}*declval())>} is \tcode{false}. @@ -3559,9 +3473,9 @@ constexpr long use_count() const noexcept; constexpr explicit operator bool() const noexcept; template - constexpr bool owner_before(const shared_ptr& b) const noexcept; + bool owner_before(const shared_ptr& b) const noexcept; template - constexpr bool owner_before(const weak_ptr& b) const noexcept; + bool owner_before(const weak_ptr& b) const noexcept; size_t owner_hash() const noexcept; template constexpr bool owner_equal(const shared_ptr& b) const noexcept; @@ -4167,8 +4081,8 @@ \indexlibrarymember{owner_before}{shared_ptr}% \begin{itemdecl} -template constexpr bool owner_before(const shared_ptr& b) const noexcept; -template constexpr bool owner_before(const weak_ptr& b) const noexcept; +template bool owner_before(const shared_ptr& b) const noexcept; +template bool owner_before(const weak_ptr& b) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4416,13 +4330,13 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is of the form \tcode{U[]}. +\tcode{T} is an array of unknown bound. \pnum \returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]} -with a default initial value, -where \tcode{U} is \tcode{remove_extent_t}. +A \tcode{shared_ptr} to an array of +\tcode{N} elements of type \tcode{remove_extent_t} +with a default initial value. \pnum \begin{example} @@ -4447,7 +4361,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is of the form \tcode{U[N]}. +\tcode{T} is an array of known bound. \pnum \returns @@ -4479,13 +4393,13 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is of the form \tcode{U[]}. +\tcode{T} is an array of unknown bound. \pnum \returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]}, -where \tcode{U} is \tcode{remove_extent_t} and -each array element has an initial value of \tcode{u}. +A \tcode{shared_ptr} to an array of +\tcode{N} elements of type \tcode{remove_extent_t} +where each array element has an initial value of \tcode{u}. \pnum \begin{example} @@ -4513,7 +4427,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is of the form \tcode{U[N]}. +\tcode{T} is an array of known bound. \pnum \returns @@ -4527,7 +4441,7 @@ shared_ptr p = make_shared(1.0); // \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0} shared_ptr q = make_shared({1.0, 0.0}); - // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each double[2] element is \tcode{\{1.0, 0.0\}} + // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each \tcode{double[2]} element is \tcode{\{1.0, 0.0\}} shared_ptr[4]> r = make_shared[4]>({1, 2}); // \tcode{shared_ptr} to a \tcode{vector[4]}, where each vector has contents \tcode{\{1, 2\}} \end{codeblock} @@ -4581,8 +4495,8 @@ \pnum \returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]}, -where \tcode{U} is \tcode{remove_extent_t}. +A \tcode{shared_ptr} to an array of +\tcode{N} elements of type \tcode{remove_extent_t}. \pnum \begin{example} @@ -4884,9 +4798,9 @@ constexpr bool expired() const noexcept; constexpr shared_ptr lock() const noexcept; template - constexpr bool owner_before(const shared_ptr& b) const noexcept; + bool owner_before(const shared_ptr& b) const noexcept; template - constexpr bool owner_before(const weak_ptr& b) const noexcept; + bool owner_before(const weak_ptr& b) const noexcept; size_t owner_hash() const noexcept; template constexpr bool owner_equal(const shared_ptr& b) const noexcept; @@ -5083,8 +4997,8 @@ \indexlibrarymember{owner_before}{weak_ptr}% \begin{itemdecl} -template constexpr bool owner_before(const shared_ptr& b) const noexcept; -template constexpr bool owner_before(const weak_ptr& b) const noexcept; +template bool owner_before(const shared_ptr& b) const noexcept; +template bool owner_before(const weak_ptr& b) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -5158,26 +5072,26 @@ template struct owner_less; template struct owner_less> { - constexpr bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; - constexpr bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; - constexpr bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; + bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; }; template struct owner_less> { - constexpr bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; - constexpr bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; - constexpr bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; }; template<> struct owner_less { template - constexpr bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; + bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; template - constexpr bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; template - constexpr bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; template - constexpr bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; using is_transparent = @\unspec@; }; @@ -6441,7 +6355,11 @@ \begin{itemdescr} \pnum \mandates -\tcode{is_copy_constructible_v} is \tcode{true}. +If +\tcode{allocator_traits::propagate_on_container_move_assignment::val\-ue} +is \tcode{false} and +\tcode{allocator_traits::is_always_equal::value} is \tcode{false}, +\tcode{is_move_con\-structible_v} is \tcode{true}. \pnum \effects @@ -6458,28 +6376,20 @@ \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. +\tcode{*this} becomes valueless. \item Otherwise, +if the allocator needs updating or 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. +\tcode{*this} takes ownership of the owned object of \tcode{other}. \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. +using the allocator in \tcode{*this}. \item The previously owned object in \tcode{*this}, if any, @@ -6661,7 +6571,7 @@ \begin{itemdecl} template constexpr bool operator==(const indirect& lhs, const indirect& rhs) - noexcept(noexcept(*lhs == *rhs)); + noexcept(noexcept(bool(*lhs == *rhs))); \end{itemdecl} \begin{itemdescr} @@ -6700,7 +6610,8 @@ %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)); + constexpr bool operator==(const indirect& lhs, const U& rhs) + noexcept(noexcept(bool(*lhs == rhs))); \end{itemdecl} \begin{itemdescr} @@ -6926,7 +6837,7 @@ using the allocator \exposid{alloc}. \end{itemdescr} -\indexlibraryctor{indirect}% +\indexlibraryctor{polymorphic}% \begin{itemdecl} constexpr explicit polymorphic(allocator_arg_t, const Allocator& a); \end{itemdecl} @@ -7024,8 +6935,9 @@ 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, +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} as an rvalue, using the allocator \exposid{alloc}. \end{itemdescr} @@ -7222,7 +7134,10 @@ \pnum \effects If \tcode{*this} is not valueless, -destroys the owned object using \tcode{allocator_traits::de\-stroy} and +calls \tcode{allocator_traits::destroy(p)}, +where \tcode{p} is a pointer of type \tcode{U*} to +the owned object and +\tcode{U} is the type of the owned object; then the storage is deallocated. \end{itemdescr} @@ -7254,7 +7169,9 @@ \item If \tcode{other} is not valueless, -a new owned object is constructed in \tcode{*this} using +a new owned object of type \tcode{U}, +where \tcode{U} is the type of the owned object in \tcode{other}, +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 @@ -7290,7 +7207,10 @@ \begin{itemdescr} \pnum \mandates -If \tcode{allocator_traits::is_always_equal::value} is \tcode{false}, +If +\tcode{allocator_traits::propagate_on_container_move_assignment::val\-ue} +is \tcode{false} and +\tcode{allocator_traits::is_always_equal::value} is \tcode{false}, \tcode{T} is a complete type. \pnum @@ -7307,22 +7227,21 @@ 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. +If \tcode{other} is valueless, \tcode{*this} becomes valueless. \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. +if the allocator needs updating or +\tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true}, +\tcode{*this} takes ownership of the owned object of \tcode{other}. + +\item +Otherwise, +constructs a new owned object of type \tcode{U}, +where \tcode{U} is the type of the owned object in \tcode{other}, +with the owned object of +\tcode{other} as the argument as an rvalue, +using the allocator in \tcode{*this}. \item The previously owned object in \tcode{*this}, if any, @@ -8141,11 +8060,11 @@ synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); synchronized_pool_resource() - : synchronized_pool_resource(pool_options(), get_default_resource()) {} + : synchronized_pool_resource(pool_options(), get_default_resource()) {} explicit synchronized_pool_resource(memory_resource* upstream) - : synchronized_pool_resource(pool_options(), upstream) {} + : synchronized_pool_resource(pool_options(), upstream) {} explicit synchronized_pool_resource(const pool_options& opts) - : synchronized_pool_resource(opts, get_default_resource()) {} + : synchronized_pool_resource(opts, get_default_resource()) {} synchronized_pool_resource(const synchronized_pool_resource&) = delete; virtual ~synchronized_pool_resource(); @@ -8168,11 +8087,11 @@ unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); unsynchronized_pool_resource() - : unsynchronized_pool_resource(pool_options(), get_default_resource()) {} + : unsynchronized_pool_resource(pool_options(), get_default_resource()) {} explicit unsynchronized_pool_resource(memory_resource* upstream) - : unsynchronized_pool_resource(pool_options(), upstream) {} + : unsynchronized_pool_resource(pool_options(), upstream) {} explicit unsynchronized_pool_resource(const pool_options& opts) - : unsynchronized_pool_resource(opts, get_default_resource()) {} + : unsynchronized_pool_resource(opts, get_default_resource()) {} unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete; virtual ~unsynchronized_pool_resource(); diff --git a/source/meta.tex b/source/meta.tex index f0bd37f53d..632c256ccb 100644 --- a/source/meta.tex +++ b/source/meta.tex @@ -69,6 +69,47 @@ \end{note} \end{itemdescr} +\rSec2[intseq.binding]{Structured binding support} + +\indexlibraryglobal{tuple_size}% +\indexlibraryglobal{tuple_element}% +\begin{itemdecl} +template + struct tuple_size> + : integral_constant { }; + +template + struct tuple_element> { + using type = T; + }; +template + struct tuple_element> { + using type = T; + }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +$\tcode{I} < \tcode{sizeof...(Values)}$. +\end{itemdescr} + +\indexlibrarymember{get}{integer_sequence}% +\begin{itemdecl} +template + constexpr T get(integer_sequence) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +$\tcode{I} < \tcode{sizeof...(Values)}$. + +\pnum +\returns +\tcode{Values...[I]}. +\end{itemdescr} + \rSec1[type.traits]{Metaprogramming and type traits} \rSec2[type.traits.general]{General} @@ -127,7 +168,7 @@ modifies a property of a type. It shall be a class template that takes one template type argument and, optionally, additional arguments that help -define the modification. It shall define a publicly accessible nested type +define the modification. It shall declare a publicly accessible nested type named \tcode{type}, which shall be a synonym for the modified type. \pnum @@ -164,22 +205,6 @@ using @\libglobal{true_type}@ = bool_constant; using @\libglobal{false_type}@ = bool_constant; - // \ref{const.wrap.class}, class template \tcode{constant_wrapper} - template - struct @\exposidnc{cw-fixed-value}@; // \expos - - template<@\exposidnc{cw-fixed-value}@ X, class = typename decltype(X)::@\exposid{type}@> - struct constant_wrapper; - - template - concept @\defexposconceptnc{constexpr-param}@ = // \expos - requires { typename constant_wrapper; }; - - struct @\exposidnc{cw-operators}@; // \expos - - template<@\exposid{cw-fixed-value}@ X> - constexpr auto @\libglobal{cw}@ = constant_wrapper{}; - // \ref{meta.unary.cat}, primary type categories template struct is_void; template struct is_null_pointer; @@ -210,16 +235,14 @@ template struct is_const; template struct is_volatile; template struct is_trivially_copyable; - template struct is_trivially_relocatable; - template struct is_replaceable; template struct is_standard_layout; template struct is_empty; template struct is_polymorphic; template struct is_abstract; template struct is_final; template struct is_aggregate; - template struct is_consteval_only; + template struct is_structural; template struct is_signed; template struct is_unsigned; template struct is_bounded_array; @@ -263,7 +286,6 @@ template struct is_nothrow_swappable; template struct is_nothrow_destructible; - template struct is_nothrow_relocatable; template struct is_implicit_lifetime; @@ -460,8 +482,6 @@ constexpr bool @\libglobal{is_volatile_v}@ = is_volatile::value; template constexpr bool @\libglobal{is_trivially_copyable_v}@ = is_trivially_copyable::value; - template - constexpr bool @\libglobal{is_trivially_relocatable_v}@ = is_trivially_relocatable::value; template constexpr bool @\libglobal{is_standard_layout_v}@ = is_standard_layout::value; template @@ -475,7 +495,7 @@ template constexpr bool @\libglobal{is_aggregate_v}@ = is_aggregate::value; template - constexpr bool @\libglobal{is_consteval_only_v}@ = is_consteval_only::value; + constexpr bool @\libglobal{is_structural_v}@ = is_structural::value; template constexpr bool @\libglobal{is_signed_v}@ = is_signed::value; template @@ -544,12 +564,8 @@ constexpr bool @\libglobal{is_nothrow_swappable_v}@ = is_nothrow_swappable::value; template constexpr bool @\libglobal{is_nothrow_destructible_v}@ = is_nothrow_destructible::value; - template - constexpr bool @\libglobal{is_nothrow_relocatable_v}@ = is_nothrow_relocatable::value; template constexpr bool @\libglobal{is_implicit_lifetime_v}@ = is_implicit_lifetime::value; - template - constexpr bool @\libglobal{is_replaceable_v}@ = is_replaceable::value; template constexpr bool @\libglobal{has_virtual_destructor_v}@ = has_virtual_destructor::value; template @@ -615,7 +631,8 @@ // \ref{meta.const.eval}, constant evaluation context constexpr bool is_constant_evaluated() noexcept; - consteval bool is_within_lifetime(const auto*) noexcept; + template + consteval bool is_within_lifetime(const T*) noexcept; } \end{codeblock} @@ -647,269 +664,6 @@ are used as base classes to define the interface for various type traits. -\rSec2[const.wrap.class]{Class template \tcode{constant_wrapper}} - -\begin{codeblock} -namespace std { - template - struct @\exposidnc{cw-fixed-value}@ { // \expos - using @\exposidnc{type}@ = T; // \expos - constexpr @\exposidnc{cw-fixed-value}@(@\exposidnc{type}@ v) noexcept : @\exposidnc{data}@(v) {} - T @\exposidnc{data}@; // \expos - }; - - template - struct @\exposidnc{cw-fixed-value}@ { // \expos - using @\exposidnc{type}@ = T[Extent]; // \expos - constexpr @\exposidnc{cw-fixed-value}@(T (&arr)[Extent]) noexcept; - T @\exposidnc{data}@[Extent]; // \expos - }; - - template - @\exposidnc{cw-fixed-value}@(T (&)[Extent]) -> @\exposidnc{cw-fixed-value}@; // \expos - - struct @\exposidnc{cw-operators}@ { // \expos - // unary operators - template<@\exposconcept{constexpr-param}@ T> - friend constexpr auto operator+(T) noexcept -> constant_wrapper<(+T::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ T> - friend constexpr auto operator-(T) noexcept -> constant_wrapper<(-T::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ T> - friend constexpr auto operator~(T) noexcept -> constant_wrapper<(~T::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ T> - friend constexpr auto operator!(T) noexcept -> constant_wrapper<(!T::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ T> - friend constexpr auto operator&(T) noexcept -> constant_wrapper<(&T::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ T> - friend constexpr auto operator*(T) noexcept -> constant_wrapper<(*T::value)> - { return {}; } - - // binary operators - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator+(L, R) noexcept -> constant_wrapper<(L::value + R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator-(L, R) noexcept -> constant_wrapper<(L::value - R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator*(L, R) noexcept -> constant_wrapper<(L::value * R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator/(L, R) noexcept -> constant_wrapper<(L::value / R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator%(L, R) noexcept -> constant_wrapper<(L::value % R::value)> - { return {}; } - - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator<<(L, R) noexcept -> constant_wrapper<(L::value << R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator>>(L, R) noexcept -> constant_wrapper<(L::value >> R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator&(L, R) noexcept -> constant_wrapper<(L::value & R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator|(L, R) noexcept -> constant_wrapper<(L::value | R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator^(L, R) noexcept -> constant_wrapper<(L::value ^ R::value)> - { return {}; } - - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - requires (!is_constructible_v || - !is_constructible_v) - friend constexpr auto operator&&(L, R) noexcept - -> constant_wrapper<(L::value && R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - requires (!is_constructible_v || - !is_constructible_v) - friend constexpr auto operator||(L, R) noexcept - -> constant_wrapper<(L::value || R::value)> - { return {}; } - - // comparisons - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator<=>(L, R) noexcept - -> constant_wrapper<(L::value <=> R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator<(L, R) noexcept -> constant_wrapper<(L::value < R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator<=(L, R) noexcept -> constant_wrapper<(L::value <= R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator==(L, R) noexcept -> constant_wrapper<(L::value == R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator!=(L, R) noexcept -> constant_wrapper<(L::value != R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator>(L, R) noexcept -> constant_wrapper<(L::value > R::value)> - { return {}; } - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator>=(L, R) noexcept -> constant_wrapper<(L::value >= R::value)> - { return {}; } - - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator,(L, R) noexcept = delete; - template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> - friend constexpr auto operator->*(L, R) noexcept -> constant_wrapper*(R::value)> - { return {}; } - - // call and index - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@... Args> - constexpr auto operator()(this T, Args...) noexcept - requires requires { constant_wrapper(); } - { return constant_wrapper{}; } - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@... Args> - constexpr auto operator[](this T, Args...) noexcept - -> constant_wrapper<(T::value[Args::value...])> - { return {}; } - - // pseudo-mutators - template<@\exposconcept{constexpr-param}@ T> - constexpr auto operator++(this T) noexcept - requires requires(T::value_type x) { ++x; } - { return constant_wrapper<[] { auto c = T::value; return ++c; }()>{}; } - template<@\exposconcept{constexpr-param}@ T> - constexpr auto operator++(this T, int) noexcept - requires requires(T::value_type x) { x++; } - { return constant_wrapper<[] { auto c = T::value; return c++; }()>{}; } - - template<@\exposconcept{constexpr-param}@ T> - constexpr auto operator--(this T) noexcept - requires requires(T::value_type x) { --x; } - { return constant_wrapper<[] { auto c = T::value; return --c; }()>{}; } - template<@\exposconcept{constexpr-param}@ T> - constexpr auto operator--(this T, int) noexcept - requires requires(T::value_type x) { x--; } - { return constant_wrapper<[] { auto c = T::value; return c--; }()>{}; } - - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator+=(this T, R) noexcept - requires requires(T::value_type x) { x += R::value; } - { return constant_wrapper<[] { auto v = T::value; return v += R::value; }()>{}; } - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator-=(this T, R) noexcept - requires requires(T::value_type x) { x -= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v -= R::value; }()>{}; } - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator*=(this T, R) noexcept - requires requires(T::value_type x) { x *= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v *= R::value; }()>{}; } - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator/=(this T, R) noexcept - requires requires(T::value_type x) { x /= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v /= R::value; }()>{}; } - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator%=(this T, R) noexcept - requires requires(T::value_type x) { x %= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v %= R::value; }()>{}; } - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator&=(this T, R) noexcept - requires requires(T::value_type x) { x &= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v &= R::value; }()>{}; } - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator|=(this T, R) noexcept - requires requires(T::value_type x) { x |= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v |= R::value; }()>{}; } - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator^=(this T, R) noexcept - requires requires(T::value_type x) { x ^= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v ^= R::value; }()>{}; } - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator<<=(this T, R) noexcept - requires requires(T::value_type x) { x <<= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v <<= R::value; }()>{}; } - template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator>>=(this T, R) noexcept - requires requires(T::value_type x) { x >>= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v >>= R::value; }()>{}; } - }; - - template<@\exposid{cw-fixed-value}@ X, class> - struct @\libglobal{constant_wrapper}@ : @\exposid{cw-operators}@ { - static constexpr const auto & value = X.@\exposid{data}@; - using type = constant_wrapper; - using value_type = decltype(X)::@\exposid{type}@; - - template<@\exposconcept{constexpr-param}@ R> - constexpr auto operator=(R) const noexcept - requires requires(value_type x) { x = R::value; } - { return constant_wrapper<[] { auto v = value; return v = R::value; }()>{}; } - - constexpr operator decltype(auto)() const noexcept { return value; } - }; -} -\end{codeblock} - -\pnum -The class template \tcode{constant_wrapper} aids in metaprogramming by ensuring -that the evaluation of expressions comprised entirely of \tcode{constant_wrapper} -are core constant expressions\iref{expr.const}, -regardless of the context in which they appear. -In particular, this enables use of \tcode{constant_wrapper} values -that are passed as arguments to constexpr functions to be used in constant expressions. - -\pnum -\begin{note} -The unnamed second template parameter to \tcode{constant_wrapper} is present -to aid argument-dependent lookup\iref{basic.lookup.argdep} -in finding overloads for which \tcode{constant_wrapper}'s wrapped value is a suitable argument, -but for which the \tcode{constant_wrapper} itself is not. -\end{note} - -\pnum -\begin{example} -\begin{codeblock} - constexpr auto initial_phase(auto quantity_1, auto quantity_2) { - return quantity_1 + quantity_2; - } - - constexpr auto middle_phase(auto tbd) { - return tbd; - } - - void final_phase(auto gathered, auto available) { - if constexpr (gathered == available) - std::cout << "Profit!\n"; - } - - void impeccable_underground_planning() { - auto gathered_quantity = middle_phase(initial_phase(std::cw<42>, std::cw<13>)); - static_assert(gathered_quantity == 55); - auto all_available = std::cw<55>; - final_phase(gathered_quantity, all_available); - } - - void deeply_flawed_underground_planning() { - constexpr auto gathered_quantity = middle_phase(initial_phase(42, 13)); - constexpr auto all_available = 55; - final_phase(gathered_quantity, all_available); // error: \tcode{gathered == available} - // is not a constant expression - } -\end{codeblock} -\end{example} - -\begin{itemdecl} -constexpr @\exposid{cw-fixed-value}@(T (&arr)[Extent]) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initialize elements of \exposid{data} with corresponding elements of \tcode{arr}. -\end{itemdescr} - \rSec2[meta.unary]{Unary type traits} \rSec3[meta.unary.general]{General} @@ -1135,20 +889,6 @@ \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;} & @@ -1195,10 +935,10 @@ \tcode{T} is an aggregate type\iref{dcl.init.aggr} & \tcode{T} shall be an array type, a complete type, or \cv~\keyword{void}. \\ \rowsep -\indexlibraryglobal{is_consteval_only}% +\indexlibraryglobal{is_structural}% \tcode{template}\br - \tcode{struct is_consteval_only;} & - \tcode{T} is consteval-only\iref{basic.types.general} & + \tcode{struct is_structural;} & + \tcode{T} is a structural type\iref{temp.param} & \tcode{remove_all_extents_t} shall be a complete type or \cv~\keyword{void}. \\ \rowsep \indexlibrary{\idxcode{is_signed}!class}% @@ -1517,16 +1257,6 @@ \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;} & @@ -1556,6 +1286,8 @@ 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}. + The full-expression of the variable initialization is + treated as an unevaluated operand\iref{expr.context}. Access checking is performed as if in a context unrelated to \tcode{T} and \tcode{U}. Only the validity of the immediate context of @@ -1579,6 +1311,8 @@ 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}. + The full-expression of the variable initialization is + treated as an unevaluated operand\iref{expr.context}. Access checking is performed as if in a context unrelated to \tcode{T} and \tcode{U}. Only the validity of the immediate context of @@ -1647,6 +1381,8 @@ \begin{note} These tokens are never interpreted as a function declaration. \end{note} +The full-expression of the variable initialization is +treated as an unevaluated operand\iref{expr.context}. Access checking is performed as if in a context unrelated to \tcode{T} and any of the \tcode{Args}. Only the validity of the immediate context of the variable initialization is considered. @@ -1945,7 +1681,8 @@ \indexlibraryglobal{is_convertible}% \pnum The predicate condition for a template specialization \tcode{is_convertible} -shall be satisfied if and only if the return expression in the following code would be +shall be satisfied if and only if +the return statement\iref{stmt.return} in the following code would be well-formed, including any implicit conversions to the return type of the function: \begin{codeblock} @@ -1959,9 +1696,11 @@ array types, function types, and \cv{}~\keyword{void}. \end{note} Access checking is performed -in a context unrelated to \tcode{To} and \tcode{From}. Only the validity of -the immediate context of the \grammarterm{expression} of the \tcode{return} statement\iref{stmt.return} -(including initialization of the returned object or reference) is considered. +in a context unrelated to \tcode{To} and \tcode{From}. +The operand of the \tcode{return} statement +(including initialization of the returned object or reference, if any) +is treated as an unevaluated operand\iref{expr.context}, and +only the validity of its immediate context is considered. \begin{note} The initialization can result in side effects such as the @@ -2302,7 +2041,7 @@ \tcode{template} \tcode{struct common_type;} & Unless this trait is specialized, - the member \tcode{type} is defined or omitted as specified below. + the member \tcode{type} is declared 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 @@ -2318,7 +2057,7 @@ \tcode{template} \tcode{struct \libglobal{common_reference};} & - The member \grammarterm{typedef-name} \tcode{type} is defined or omitted + The member \grammarterm{typedef-name} \tcode{type} is declared or omitted as specified below. Each type in the parameter pack \tcode{T} shall be complete or \cv{} \keyword{void}. \\ \rowsep @@ -2454,7 +2193,7 @@ \pnum 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: +the member \tcode{type} shall be either declared or not present as follows: \begin{itemize} \item If \tcode{sizeof...(T)} is zero, there shall be no member \tcode{type}. @@ -2527,7 +2266,7 @@ \pnum 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 +\tcode{T} of types, the member \tcode{type} shall be either declared or not present as follows: \begin{itemize} \item If \tcode{sizeof...(T)} is zero, there shall be no member \tcode{type}. @@ -2597,7 +2336,7 @@ \pnum \begin{example} -Given these definitions: +Given these declarations: \begin{codeblock} using PF1 = bool (&)(); using PF2 = short (*)(long); @@ -2852,14 +2591,21 @@ \indexlibraryglobal{is_within_lifetime}% \begin{itemdecl} -consteval bool is_within_lifetime(const auto* p) noexcept; +template + consteval bool is_within_lifetime(const T* p) noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{static_cast(p)} is well-formed. + \pnum \returns \tcode{true} if \tcode{p} is a pointer to an object that is -within its lifetime\iref{basic.life}; otherwise, \tcode{false}. +within its lifetime\iref{basic.life} and +\tcode{static_cast(p)} is a constant subexpression; +otherwise, \tcode{false}. \pnum \remarks @@ -2910,6 +2656,7 @@ \indexheader{meta}% \begin{codeblock} +#include // see \ref{compare.syn} #include // see \ref{initializer.list.syn} namespace std { @@ -2930,7 +2677,7 @@ template consteval const ranges::range_value_t* define_static_string(R&& r); template - consteval span> define_static_array(R&& r); + consteval span, @\seebelow@> define_static_array(R&& r); template consteval const remove_cvref_t* define_static_object(T&& r); } @@ -3028,7 +2775,7 @@ consteval bool is_function_parameter(info r); consteval bool is_explicit_object_parameter(info r); consteval bool has_default_argument(info r); - consteval bool has_ellipsis_parameter(info r); + consteval bool is_vararg_function(info r); consteval bool is_template(info r); consteval bool is_function_template(info r); @@ -3075,6 +2822,11 @@ consteval bool has_inaccessible_bases(info r, access_context ctx); consteval bool has_inaccessible_subobjects(info r, access_context ctx); + // \ref{meta.reflection.scope}, scope identification + consteval info current_function(); + consteval info current_class(); + consteval info current_namespace(); + // \ref{meta.reflection.member.queries}, reflection member queries consteval vector members_of(info r, access_context ctx); consteval vector bases_of(info type, access_context ctx); @@ -3096,7 +2848,7 @@ // \ref{meta.reflection.extract}, value extraction template - consteval T extract(info); + consteval T extract(info r); // \ref{meta.reflection.substitute}, reflection substitution template @@ -3120,7 +2872,7 @@ consteval info data_member_spec(info type, data_member_options options); consteval bool is_data_member_spec(info r); template<@\libconcept{reflection_range}@ R = initializer_list> - consteval info define_aggregate(info type_class, R&&); + consteval info define_aggregate(info type_class, R&& mdescrs); // associated with \ref{meta.unary.cat}, primary type categories consteval bool is_void_type(info type); @@ -3152,15 +2904,13 @@ consteval bool is_const_type(info type); consteval bool is_volatile_type(info type); consteval bool is_trivially_copyable_type(info type); - consteval bool is_trivially_relocatable_type(info type); - consteval bool is_replaceable_type(info type); consteval bool is_standard_layout_type(info type); consteval bool is_empty_type(info type); consteval bool is_polymorphic_type(info type); consteval bool is_abstract_type(info type); consteval bool is_final_type(info type); consteval bool is_aggregate_type(info type); - consteval bool is_consteval_only_type(info type); + consteval bool is_structural_type(info type); consteval bool is_signed_type(info type); consteval bool is_unsigned_type(info type); consteval bool is_bounded_array_type(info type); @@ -3207,7 +2957,6 @@ consteval bool is_nothrow_swappable_type(info type); consteval bool is_nothrow_destructible_type(info type); - consteval bool is_nothrow_relocatable_type(info type); consteval bool is_implicit_lifetime_type(info type); @@ -3281,6 +3030,9 @@ consteval size_t tuple_size(info type); consteval info tuple_element(size_t index, info type); + consteval bool is_applicable_type(info fn, info tuple); + consteval bool is_nothrow_applicable_type(info fn, info tuple); + consteval info apply_result(info fn, info tuple); consteval size_t variant_size(info type); consteval info variant_alternative(size_t index, info type); @@ -3295,6 +3047,13 @@ specified in this header is a designated addressable function\iref{namespace.std}. +\pnum +When a function or function template specialization $F$ specified in this header +throws a \tcode{meta::exception} $E$, +\tcode{$E$.from()} is a reflection representing $F$ and +\tcode{$E$.where()} is a \tcode{source_location} +representing from where the call to $F$ originated. + \pnum The behavior of any function specified in namespace \tcode{std::meta} is \impldef{behavior of any function in \tcode{std::meta} @@ -3328,8 +3087,15 @@ \pnum Any function in namespace \tcode{std::meta} whose return type is \tcode{string_view} or \tcode{u8string_view} -returns an object \exposid{V} such that -\tcode{\exposid{V}.data()[\exposid{V}.size()]} equals \tcode{'\textbackslash 0'}. +returns an object \tcode{V} such that +\tcode{V.data()[V.size()]} equals \tcode{'\textbackslash 0'}. +Each element of the range +$\tcode{V.data()} + \crange{0}{\tcode{V.size()}}$ +is a potentially non-unique object with static storage duration that +is usable in constant expressions\iref{intro.object, expr.const}; +a pointer to such an element is not suitable for use as +a template argument for a constant template parameter of +pointer type\iref{temp.arg.nontype}. \begin{example} \begin{codeblock} struct C { }; @@ -3362,7 +3128,7 @@ \returns \begin{itemize} \item - If \tcode{p} points to an unspecified object\iref{expr.const}, + If \tcode{p} points to an unspecified object\iref{expr.const.core}, \tcode{false}. \item Otherwise, if \tcode{p} points to a subobject @@ -3400,8 +3166,8 @@ \pnum Let $V$ be the pack of values of type \tcode{CharT} whose elements are the corresponding elements of \tcode{r}, -except that if \tcode{r} refers to a string literal object, -then $V$ does not include the trailing null terminator of \tcode{r}. +except that if \tcode{r} is a reference to a string literal object, +then $V$ does not include the terminating \unicode{0000}{null} character of \tcode{r}. \pnum Let $P$ be the template parameter object\iref{temp.param} @@ -3426,31 +3192,46 @@ \begin{itemdescr} \pnum -Let \tcode{T} be \tcode{ranges::range_value_t}. +Let \tcode{U} be \tcode{ranges::range_value_t} and +\tcode{T} be \tcode{remove_all_extents_t}. \pnum \mandates -\tcode{T} is a structural type\iref{temp.param}, -\tcode{is_constructible_v>} is \tcode{true}, and -\tcode{is_copy_constructible_v} is \tcode{true}. +\begin{itemize} +\item \tcode{T} is a structural type\iref{temp.param}, +\item \tcode{T} satisfies \libconcept{copy_constructible}, and +\item +if \tcode{U} is not an array type, then +\tcode{is_constructible_v>} is \tcode{true}. +\end{itemize} \pnum Let $V$ be the pack of values of type \tcode{info} of the same size as \tcode{r}, -where the $i^\text{th}$ element is \tcode{reflect_constant($\tcode{e}_i$)}, -where $\tcode{e}_i$ is the $i^\text{th}$ element of \tcode{r}. +where the $i^\text{th}$ element is +\begin{itemize} +\item +\tcode{reflect_constant_array(*$\tcode{\placeholder{it}}_i$)} +if \tcode{U} is an array type, +\item +\tcode{reflect_constant(static_cast(*$\tcode{\placeholder{it}}_i$))} +otherwise, +\end{itemize} +and $\tcode{\placeholder{it}}_i$ is an iterator to +the $i^\text{th}$ element of \tcode{r}. \pnum Let $P$ be \begin{itemize} \item - If \tcode{sizeof...($V$) > 0} is \tcode{true}, - then the template parameter object\iref{temp.param} - of type \tcode{const T[\brk{}sizeof...(\brk{}$V$)]} - initialized with \tcode{\{[:$V$:]...\}}. + the template parameter object\iref{temp.param} + of type \tcode{const T[sizeof...($V$)]}, + such that \tcode{$P$[$I$]} is template-argument-equivalent\iref{temp.type} + to the object represented by \tcode{$V$...[$I$]} + for all $I$ in the range \range{0}{sizeof...($V$)} + if \tcode{sizeof...($V$) > 0} is \tcode{true}, otherwise \item - Otherwise, the template parameter object - of type \tcode{const array} + the template parameter object of type \tcode{const array} initialized with \tcode{\{\}}. \end{itemize} @@ -3460,13 +3241,25 @@ \pnum \throws -\tcode{meta::exception} unless -\tcode{reflect_constant(e)} is a constant subexpression -for every element \tcode{e} of \tcode{r}. +Any of +\begin{itemize} +\item +an exception thrown by any operation +on \tcode{r} or +on iterators and sentinels referring to \tcode{r}, +\item +an exception thrown +by the evaluation of any argument of \tcode{reflect_constant} or +by any evaluation of \tcode{reflect_constant_array}, or +\item +\tcode{meta::exception} +if any invocation of \tcode{reflect_constant} +would exit via an exception. +\end{itemize} \pnum \begin{note} -$P$ is a potentially non-unique object\iref{intro.object}. +When \tcode{r} is not empty, $P$ is a potentially non-unique object\iref{intro.object}. \end{note} \end{itemdescr} @@ -3488,7 +3281,7 @@ \indexlibraryglobal{define_static_array}% \begin{itemdecl} template - consteval span> define_static_array(R&& r); + consteval span, @\seebelow@> define_static_array(R&& r); \end{itemdecl} \begin{itemdescr} @@ -3499,11 +3292,19 @@ using T = ranges::range_value_t; meta::info array = meta::reflect_constant_array(r); if (meta::is_array_type(meta::type_of(array))) { - return span(meta::extract(array), meta::extent(meta::type_of(array))); + return span(meta::extract(array), + meta::extent(meta::type_of(array))); } else { - return span(); + return span(static_cast(nullptr), 0); } \end{codeblock} + +\pnum +\remarks +If \tcode{ranges::size(r)} is a constant expression, +the second template argument of the returned \tcode{span} type +is \tcode{static_cast(ranges::size(r))}; +otherwise, it is \tcode{dynamic_extent}. \end{itemdescr} \indexlibraryglobal{define_static_object}% @@ -3518,8 +3319,12 @@ Equivalent to: \begin{codeblock} using U = remove_cvref_t; -if constexpr (meta::is_class_type(^^U)) { - return addressof(meta::extract(meta::reflect_constant(std::forward(t)))); +if constexpr (meta::is_class_type(^^U) || meta::is_union_type(^^U)) { + return addressof(meta::extract( + meta::reflect_constant(std::forward(t)))); +} else if constexpr (meta::is_array_type(^^U)) { + return addressof(meta::extract( + meta::reflect_constant_array(std::forward(t)))); } else { return define_static_array(span(addressof(t), 1)).data(); } @@ -3784,8 +3589,19 @@ Otherwise, if \tcode{r} represents an unnamed entity, then \tcode{false}. \item - Otherwise, if \tcode{r} represents a class type, + Otherwise, if \tcode{r} represents a type alias, then \tcode{!has_template_arguments(r)}. +\item + Otherwise, if \tcode{r} represents a type, + then \tcode{true} if + \begin{itemize} + \item + \tcode{r} represents a cv-unqualified class type and + \tcode{has_template_arguments(r)} is \tcode{false}, or + \item + \tcode{r} represents a cv-unqualified enumeration type. + \end{itemize} + Otherwise, \tcode{false}. \item Otherwise, if \tcode{r} represents a function, then \tcode{true} if \tcode{has_template_arguments(r)} is \tcode{false} @@ -3812,7 +3628,7 @@ Otherwise, if \tcode{r} represents the parameter $P$ of a function $F$, then let $S$ be the set of declarations, ignoring any explicit instantiations, - that precede some point in the evaluation context + that are reachable from a point in the evaluation context and that declare either $F$ or a templated function of which $F$ is a specialization; \tcode{true} if @@ -3853,9 +3669,6 @@ then \tcode{false} if the declaration of that structured binding was instantiated from a structured binding pack. Otherwise, \tcode{true}. -\item - Otherwise, if \tcode{r} represents a type alias, - then \tcode{!has_template_arguments(r)}. \item Otherwise, if \tcode{r} represents an enumerator, @@ -3867,10 +3680,12 @@ Otherwise, if \tcode{r} represents a direct base class relationship, then \tcode{has_identifier(type_of(r))}. \item - Otherwise, \tcode{r} represents a data member description - $(T, N, A, W, \mathit{NUA})$\iref{class.mem.general}; + Otherwise, if \tcode{r} represents a data member description + $(T, N, A, W, \mathit{NUA}, \mathit{ANN})$\iref{class.mem.general}; \tcode{true} if $N$ is not $\bot$. Otherwise, \tcode{false}. +\item + Otherwise, \tcode{false}. \end{itemize} \end{itemdescr} @@ -3901,7 +3716,7 @@ Otherwise, if \tcode{r} represents the parameter $P$ of a function $F$, then let $S$ be the set of declarations, ignoring any explicit instantiations, - that precede some point in the evaluation context + that are reachable from a point in the evaluation context and that declare either $F$ or a templated function of which $F$ is a specialization; the name that was introduced by a declaration in $S$ @@ -3915,7 +3730,7 @@ respectively. \item Otherwise, \tcode{r} represents a data member description - $(T, N, A, W, NUA)$\iref{class.mem.general}; + $(T, N, A, W, \mathit{NUA}, \mathit{ANN})$\iref{class.mem.general}; a \tcode{string_view} or \tcode{u8string_view}, respectively, containing the identifier $N$. \end{itemize} @@ -4030,7 +3845,7 @@ \begin{itemize} \item If $E$ is defined by a declaration $D$ - that precedes a point $P$ in the evaluation context + that is reachable from a point $P$ in the evaluation context and $P$ does not occur within an \grammarterm{enum-specifier} of $D$, then a reflection of $E$. \item @@ -4043,7 +3858,7 @@ a direct base class relationship $(D, B)$, then a reflection of $B$. \item - Otherwise, for a data member description $(T, N, A, W, \mathit{NUA})$\iref{class.mem.general}, + Otherwise, for a data member description $(T, N, A, W, \mathit{NUA}, \mathit{ANN})$\iref{class.mem.general}, a reflection of the type $T$. \end{itemize} @@ -4085,7 +3900,7 @@ and if that variable is a reference $R$, then either \begin{itemize} \item - $R$ is usable in constant expressions\iref{expr.const}, or + $R$ is usable in constant expressions\iref{expr.const.init}, or \item the lifetime of $R$ began within the core constant expression currently under evaluation. @@ -4098,7 +3913,7 @@ int x; int& y = x; -static_assert(^^x != ^^y); // OK, \tcode{r} and \tcode{y} are different variables so their +static_assert(^^x != ^^y); // OK, \tcode{r} and \tcode{y} are different variables, so their // reflections compare different static_assert(object_of(^^x) == object_of(^^y)); // OK, because \tcode{y} is a reference // to \tcode{x}, their underlying objects are the same @@ -4124,6 +3939,10 @@ \begin{codeblock} if constexpr (is_annotation(@$R$@)) { return @$C$@; +} else if constexpr (is_array_type(type_of(@$R$@))) { + return reflect_constant_array([: @$R$@ :]); +} else if constexpr (is_function_type(type_of(@$R$@))) { + return reflect_function([: @$R$@ :]); } else { return reflect_constant([: @$R$@ :]); } @@ -4144,20 +3963,25 @@ static_assert(^^x != ^^y); // OK, \tcode{x} and \tcode{y} are different variables, // so their reflections compare different -static_assert(constant_of(^^x) == - constant_of(^^y)); // OK, both \tcode{constant_of(\reflexpr{x})} and - // \tcode{constant_of(\reflexpr{y})} represent the value \tcode{0} -static_assert(constant_of(^^x) == - reflect_constant(0)); // OK, likewise + +static_assert(constant_of(^^x) == // OK, both \tcode{constant_of(\reflexpr{x})} and + constant_of(^^y)); // \tcode{constant_of(\reflexpr{y})} represent the value \tcode{0} + +static_assert(constant_of(^^x) == // OK, likewise + reflect_constant(0)); struct S { int m; }; constexpr S s {42}; + static_assert(is_object(constant_of(^^s)) && is_object(reflect_object(s))); -static_assert(constant_of(^^s) != // OK, template parameter object that is template-argument- - reflect_object(s)); // equivalent to \tcode{s} is a different object than \tcode{s} + +static_assert(constant_of(^^s) != // OK, template parameter object that is + reflect_object(s)); // template-argument-equivalent to \tcode{s} + // is a different object than \tcode{s} + static_assert(constant_of(^^s) == - constant_of(reflect_object(s))); // OK + constant_of(reflect_object(s))); consteval info fn() { constexpr int x = 42; @@ -4311,7 +4135,7 @@ \returns \tcode{true} if \tcode{r} represents a bit-field, or if \tcode{r} represents a data member description -$(T, N, A, W, \mathit{NUA})$\iref{class.mem.general} +$(T, N, A, W, \mathit{NUA},\brk{} \mathit{ANN})$\iref{class.mem.general} for which $W$ is not $\bot$. Otherwise, \tcode{false}. \end{itemdescr} @@ -4344,7 +4168,7 @@ \pnum \returns -\tcode{true} if \tcode{T} represents a const or volatile type, respectively, +\tcode{true} if $T$ represents a const or volatile type, respectively, or a const- or volatile-qualified function type, respectively. Otherwise, \tcode{false}. \end{itemdescr} @@ -4404,13 +4228,11 @@ \indexlibraryglobal{has_internal_linkage}% \indexlibraryglobal{has_module_linkage}% \indexlibraryglobal{has_external_linkage}% -\indexlibraryglobal{has_c_language_linkage}% \indexlibraryglobal{has_linkage}% \begin{itemdecl} consteval bool has_internal_linkage(info r); consteval bool has_module_linkage(info r); consteval bool has_external_linkage(info r); -consteval bool has_c_language_linkage(info r); consteval bool has_linkage(info r); \end{itemdecl} @@ -4426,11 +4248,27 @@ whose name has internal linkage, module linkage, -C language linkage, or +external linkage, or any linkage, respectively\iref{basic.link}. Otherwise, \tcode{false}. \end{itemdescr} +\indexlibraryglobal{has_c_language_linkage}% +\begin{itemdecl} +consteval bool has_c_language_linkage(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a +variable, +function, or +function type +with C language linkage. +Otherwise, \tcode{false}. +\end{itemdescr} + \indexlibraryglobal{is_complete_type}% \begin{itemdecl} consteval bool is_complete_type(info r); @@ -4644,29 +4482,29 @@ \item If $F$ is a specialization of a templated function $T$, then \tcode{true} if there exists a declaration $D$ of $T$ - that precedes some point in the evaluation context + that is reachable from a point in the evaluation context and $D$ specifies a default argument for the parameter of $T$ corresponding to $P$. Otherwise, \tcode{false}. \item Otherwise, if there exists a declaration $D$ of $F$ - that precedes some point in the evaluation context + that is reachable from a point in the evaluation context and $D$ specifies a default argument for $P$, then \tcode{true}. \end{itemize} Otherwise, \tcode{false}. \end{itemdescr} -\indexlibraryglobal{has_ellipsis_parameter}% +\indexlibraryglobal{is_vararg_function}% \begin{itemdecl} -consteval bool has_ellipsis_parameter(info r); +consteval bool is_vararg_function(info r); \end{itemdecl} \begin{itemdescr} \pnum \returns \tcode{true} if \tcode{r} represents a function or function type -that has an ellipsis in its parameter-type-list\iref{dcl.fct}. +that is a vararg function\iref{dcl.fct}. Otherwise, \tcode{false}. \end{itemdescr} @@ -4910,12 +4748,9 @@ \begin{itemdescr} \pnum \returns -A reflection representing the underlying entity of what \tcode{r} represents. - -\pnum -\throws -\tcode{meta::exception} unless -\tcode{r} represents an entity. +If \tcode{r} represents an entity, then +a reflection representing the underlying entity of what \tcode{r} represents. +Otherwise, \tcode{r}. \pnum \begin{example} @@ -5107,61 +4942,16 @@ or \tcode{r} represents a function type. \end{itemdescr} -\rSec2[meta.reflection.access.context]{Access control context} +\rSec2[meta.reflection.scope]{Scope identification} \pnum -The \tcode{access_context} class is a non-aggregate type -that represents a namespace, class, or function -from which queries pertaining to access rules may be performed, -as well as the designating class\iref{class.access.base}, if any. +The functions in this subclause retrieve information +about where in the program they are invoked. -\indexlibraryglobal{access_context}% \pnum -An \tcode{access_context} has an associated scope and designating class. - -\indexlibraryglobal{access_context}% -\begin{codeblock} -namespace std::meta { - struct access_context { - access_context() = delete; - - consteval info scope() const; - consteval info designating_class() const; - - static consteval access_context current() noexcept; - static consteval access_context unprivileged() noexcept; - static consteval access_context unchecked() noexcept; - consteval access_context via(info cls) const; - }; -} -\end{codeblock} +None of the functions in this subclause +is an addressable function\iref{namespace.std}. -\pnum -\tcode{access_context} is a structural type. -Two values \tcode{ac1} and \tcode{ac2} of type \tcode{access_context} -are template-argument-equivalent\iref{temp.type} -if \tcode{ac1.scope()} and \tcode{ac2.scope()} -are template-argument-equivalent -and \tcode{ac1.desig\-nating_class()} and \tcode{ac2.desig\-nating_class()} -are template-argument-equivalent. - -\begin{itemdecl} -consteval info @\libmember{scope}{access_context}@() const; -consteval info @\libmember{designating_class}{access_context}@() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The \tcode{access_context}'s associated scope -and designating class, respectively. -\end{itemdescr} - -\begin{itemdecl} -static consteval access_context @\libmember{current}{access_context}@() noexcept; -\end{itemdecl} - -\begin{itemdescr} \pnum Given a program point $P$, let \tcode{\exposid{eval-point}($P$)} be the following program point: @@ -5247,14 +5037,153 @@ where $S'$ is the parent scope of $S$. \end{itemize} +\pnum +Let \tcode{\exposid{CURRENT-SCOPE}($P$)} for a point $P$ be +a reflection representing the function, class, or namespace +whose corresponding +function parameter scope, +class scope, or +namespace scope, respectively, +is \tcode{\exposid{ctx-scope}($S$)}, +where $S$ is the immediate scope of \tcode{\exposid{eval-point}($P$)}. + +\indexlibraryglobal{current_function}% +\begin{itemdecl} +consteval info current_function(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +An invocation of \tcode{current_function} that appears at a program point $P$ +is value-dependent\iref{temp.dep.constexpr} +if \tcode{\exposid{eval-point}($P$)} +is enclosed by a scope corresponding to a templated entity. + +\pnum +Let $S$ be \tcode{\exposid{CURRENT-SCOPE}($P$)}, +where $P$ is the point at which the invocation of +\tcode{current_function} lexically appears. + +\pnum +\returns +$S$. + +\pnum +\throws +\tcode{meta::exception} unless $S$ represents a function. +\end{itemdescr} + +\indexlibraryglobal{current_class}% +\begin{itemdecl} +consteval info current_class(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +An invocation of \tcode{current_class} that appears at a program point $P$ +is value-dependent\iref{temp.dep.constexpr} +if \tcode{\exposid{eval-point}($P$)} +is enclosed by a scope corresponding to a templated entity. + +\pnum +Let $S$ be \tcode{\exposid{CURRENT-SCOPE}($P$)} +where $P$ is the point at which the invocation of +\tcode{current_class} lexically appears. + +\pnum +\returns +$S$ if $S$ represents a class. +Otherwise, \tcode{parent_of($S$)}. + +\pnum +\throws +\tcode{meta::exception} unless $S$ represents +either a class or a member function. +\end{itemdescr} + +\indexlibraryglobal{current_namespace}% +\begin{itemdecl} +consteval info current_namespace(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +An invocation of \tcode{current_namespace} that appears at a program point $P$ +is value-dependent\iref{temp.dep.constexpr} +if \tcode{\exposid{eval-point}($P$)} +is enclosed by a scope corresponding to a templated entity. + +\pnum +Let $S$ be \tcode{\exposid{CURRENT-SCOPE}($P$)} +where $P$ is the point at which the invocation of +\tcode{current_namespace} lexically appears. + +\pnum +\returns +$S$ if $S$ represents a namespace. +Otherwise, a reflection representing the nearest enclosing namespace +of the entity represented by $S$. +\end{itemdescr} + +\rSec2[meta.reflection.access.context]{Access control context} + +\pnum +The class \tcode{access_context} +represents a namespace, class, or function +from which queries pertaining to access rules may be performed, +as well as the designating class\iref{class.access.base}, if any. + +\indexlibraryglobal{access_context}% +\pnum +An \tcode{access_context} has an associated scope and designating class. + +\indexlibraryglobal{access_context}% +\begin{codeblock} +namespace std::meta { + struct access_context { + access_context() = delete; + + consteval info scope() const; + consteval info designating_class() const; + + static consteval access_context current() noexcept; + static consteval access_context unprivileged() noexcept; + static consteval access_context unchecked() noexcept; + consteval access_context via(info cls) const; + }; +} +\end{codeblock} + +\pnum +The type \tcode{access_context} is a structural, consteval-only, non-aggregate type. +Two values \tcode{ac1} and \tcode{ac2} of type \tcode{access_context} +are template-argument-equivalent\iref{temp.type} +if \tcode{ac1.scope()} and \tcode{ac2.scope()} are template-argument-equivalent +and \tcode{ac1.designating_class()} and \tcode{ac2.designating_class()} +are template-argument-equivalent. + +\begin{itemdecl} +consteval info @\libmember{scope}{access_context}@() const; +consteval info @\libmember{designating_class}{access_context}@() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The \tcode{access_context}'s associated scope +and designating class, respectively. +\end{itemdescr} + +\begin{itemdecl} +static consteval access_context @\libmember{current}{access_context}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} \pnum \returns An \tcode{access_context} whose designating class is the null reflection -and whose scope represents the function, class, or namespace -whose corresponding function parameter scope, class scope, or namespace scope, respectively, -is \tcode{\exposid{ctx-scope}($S$)}, -where $S$ is the immediate scope of \tcode{\exposid{eval-point}($P$)} -and $P$ is the point at which the invocation of \tcode{current} lexically appears. +and whose scope is \tcode{\exposid{CURRENT-SCOPE}($P$)}, +where $P$ is the point at which the invocation of \tcode{current} lexically appears. \pnum \remarks @@ -5286,14 +5215,14 @@ }; namespace NS { - static_assert(Agg{}.s == access_context::current().scope()); // OK - static_assert(Agg{}.eq()); // OK - static_assert(B(1).s == ^^B); // OK - static_assert(is_constructor(B{1, 2}.s) && parent_of(B{1, 2}.s) == ^^B); // OK - static_assert(is_constructor(C{1, 2}.s) && parent_of(C{1, 2}.s) == ^^B); // OK + static_assert(Agg{}.s == access_context::current().scope()); + static_assert(Agg{}.eq()); + static_assert(B(1).s == ^^B); + static_assert(is_constructor(B{1, 2}.s) && parent_of(B{1, 2}.s) == ^^B); + static_assert(is_constructor(C{1, 2}.s) && parent_of(C{1, 2}.s) == ^^B); auto fn() -> [:is_namespace(access_context::current().scope()) ? ^^int : ^^bool:]; - static_assert(type_of(^^fn) == ^^auto()->int); // OK + static_assert(type_of(^^fn) == ^^auto()->int); template struct TCls { @@ -5302,7 +5231,7 @@ return true; // OK, scope is \tcode{TCls}. } }; - static_assert(TCls<0>{}.fn()); // OK + static_assert(TCls<0>{}.fn()); } \end{codeblock} \end{example} @@ -5429,14 +5358,8 @@ \pnum \throws \tcode{meta::exception} if -\begin{itemize} -\item \tcode{r} represents a class member - for which \tcode{\exposid{PARENT-CLS}(r)} is an incomplete class or -\item - \tcode{r} represents a direct base class relationship $(D, B)$ - for which $D$ is incomplete. -\end{itemize} + for which \tcode{\exposid{PARENT-CLS}(r)} is an incomplete class. \pnum \begin{example} @@ -5452,9 +5375,9 @@ static constexpr auto r = ^^mem; }; -static_assert(is_accessible(Cls::r, fn())); // OK -static_assert(!is_accessible(Cls::r, access_context::current())); // OK -static_assert(is_accessible(Cls::r, access_context::unchecked())); // OK +static_assert(is_accessible(Cls::r, fn())); +static_assert(!is_accessible(Cls::r, access_context::current())); +static_assert(is_accessible(Cls::r, access_context::unchecked())); \end{codeblock} \end{example} \end{itemdescr} @@ -5473,13 +5396,14 @@ \pnum \throws -\tcode{meta::exception} unless +\tcode{meta::exception} if \begin{itemize} \item - \tcode{nonstatic_data_members_of(\brk{}r, access_context::\brk{}unchecked())} - is a constant subexpression and + the evaluation of + \tcode{nonstatic_data_members_of(r, access_context::unchecked())} + would exit via an exception or \item - \tcode{r} does not represent a closure type. + \tcode{r} represents a closure type. \end{itemize} \end{itemdescr} @@ -5496,9 +5420,9 @@ \pnum \throws -\tcode{meta::exception} unless +\tcode{meta::exception} if the evaluation of \tcode{bases_of(r, access_context::unchecked())} -is a constant subexpression. +would exit via an exception. \end{itemdescr} \indexlibraryglobal{has_inaccessible_subobjects}% @@ -5822,7 +5746,7 @@ If \begin{itemize} \item \tcode{r} represents a non-static data member of type $T$ or -a data member description $(T, N, A, W, \mathit{NUA})$ or +a data member description $(T, N, A, W, \mathit{NUA},\brk{} \mathit{ANN})$ or \item \tcode{dealias(r)} represents a type $T$, \end{itemize} then \tcode{sizeof($T$)} if $T$ is not a reference type @@ -5850,7 +5774,7 @@ variable of non-reference type, non-static data member that is not a bit-field, direct base class relationship, or -data member description $(T, N, A, W, \mathit{NUA})$\iref{class.mem.general} +data member description $(T, N, A, W, \mathit{NUA}, \mathit{ANN})$\iref{class.mem.general} where $W$ is $\bot$. \item If \tcode{dealias(r)} represents a type, @@ -5883,7 +5807,7 @@ corresponding to $M$ of a complete object of type $C$. \item Otherwise, \tcode{r} represents a data member description - $(T, N, A, W, \mathit{NUA})$\iref{class.mem.general}. + $(T, N, A, W, \mathit{NUA}, \mathit{ANN})$\iref{class.mem.general}. If $A$ is not $\bot$, then the value $A$. Otherwise, \tcode{alignment_of(\reflexpr{$T$})}. @@ -5901,7 +5825,9 @@ variable of non-reference type, non-static data member that is not a bit-field, direct base class relationship, or -data member description. +data member description +$(T, N, A, W, \mathit{NUA}, \mathit{ANN})$\iref{class.mem.general} +where $W$ is $\bot$. \item If \tcode{dealias(r)} represents a type, then \tcode{is_complete_type(r)} is \tcode{true}. @@ -5925,7 +5851,7 @@ then $W$. \item Otherwise, if \tcode{r} represents a data member description - $(T, N, A, W, \mathit{NUA})$\iref{class.mem.general} + $(T, N, A, W, \mathit{NUA}, \mathit{ANN})$\iref{class.mem.general} and $W$ is not $\bot$, then $W$. \item @@ -5962,20 +5888,33 @@ \begin{itemdescr} \pnum -Let $E$ be -\begin{itemize} -\item - the corresponding \grammarterm{base-specifier} - if \tcode{item} represents a direct base class relationship, -\item - otherwise, the entity represented by \tcode{item}. -\end{itemize} +For a function $F$, +let $S(F)$ be the set of declarations, +ignoring any explicit instantiations, +that declare either $F$ or +a templated function of which $F$ is a specialization. \pnum \returns A \tcode{vector} containing all of the reflections $R$ -representing each annotation applying to each declaration of $E$ that precedes either -some point in the evaluation context\iref{expr.const} or +representing each annotation applying to: +\begin{itemize} +\item + if \tcode{item} represents a function parameter $P$ of a function $F$, + then the declaration of $P$ in each declaration of $F$ in $S(F)$, +\item + otherwise, if \tcode{item} represents a function $F$, + then each declaration of $F$ in $S(F)$, +\item + otherwise, if \tcode{item} represents + a direct base class relationship $(D, B)$, + then the corresponding \grammarterm{base-specifier} + in the definition of $D$, +\item + otherwise, each declaration of the entity represented by \tcode{item}, +\end{itemize} +such that each specified declaration is reachable from either +some point in the evaluation context\iref{expr.const.reflect} or a point immediately following the \grammarterm{class-specifier} of the outermost class for which such a point is in a complete-class context. For any two reflections $R_1$ and $R_2$ in the returned \tcode{vector}, @@ -5996,6 +5935,7 @@ type alias, variable, function, +function parameter, namespace, enumerator, direct base class relationship, or @@ -6058,7 +5998,8 @@ \tcode{meta::exception} unless \begin{itemize} \item - \tcode{annotations_of(item)} is a constant expression and + the evaluation of + \tcode{annotations_of(item)} would not exit via an exception and \item \tcode{dealias(type)} represents a type and \tcode{is_complete_type(type)} is \tcode{true}. @@ -6182,7 +6123,8 @@ and the cv-unqualified types of \tcode{T} and \tcode{U} are the same, \item \tcode{U} is an array type, - \tcode{T} is a pointer type, and + \tcode{T} is a pointer type, + \tcode{remove_extent_t*} and \tcode{T} are similar types, and the value \tcode{r} represents is convertible to \tcode{T}, or \item \tcode{U} is a closure type, @@ -6217,6 +6159,19 @@ \rSec2[meta.reflection.substitute]{Reflection substitution} +\pnum +Let \tcode{\placeholder{TARG-SPLICE}(x)} be: +\begin{itemize} +\item +\tcode{template [: x :]} if \tcode{is_template(x)} is \tcode{true}, otherwise + +\item +\tcode{typename [: x :]} if \tcode{is_type(x)} is \tcode{true}, otherwise + +\item +\tcode{([: x :])}. +\end{itemize} + \begin{itemdecl} template concept @\deflibconcept{reflection_range}@ = @@ -6237,7 +6192,7 @@ \pnum \returns -\tcode{true} if \tcode{Z<[:Args:]...>} is a valid \grammarterm{template-id}\iref{temp.names} +\tcode{true} if \tcode{Z<\placeholder{TARG-SPLICE}(Args)...>} is a valid \grammarterm{template-id}\iref{temp.names} that does not name a function whose type contains an undeduced placeholder type. Otherwise, \tcode{false}. @@ -6251,7 +6206,7 @@ \pnum \begin{note} -If forming \tcode{Z<[:Args:]...>} leads to a failure +If forming \tcode{Z<\placeholder{TARG-SPLICE}(Args)...>} leads to a failure outside of the immediate context, the program is ill-formed. \end{note} @@ -6272,7 +6227,7 @@ \pnum \returns -\tcode{\reflexpr{Z<[:Args:]...>}}. +\tcode{\reflexpr{Z<\placeholder{TARG-SPLICE}(Args)...>}}. \pnum \throws @@ -6281,7 +6236,7 @@ \pnum \begin{note} -If forming \tcode{Z<[:Args:]...>} leads to a failure outside of the immediate context, +If forming \tcode{Z<\placeholder{TARG-SPLICE}(Args)...>} leads to a failure outside of the immediate context, the program is ill-formed. \end{note} @@ -6291,13 +6246,14 @@ template auto fn1(); -static_assert(!can_substitute(^^fn1, {^^int})); // OK +static_assert(!can_substitute(^^fn1, {^^int})); constexpr info r1 = substitute(^^fn1, {^^int}); // error: \tcode{fn1} contains an undeduced // placeholder type for its return type template auto fn2() { - static_assert(^^T != ^^int); // static assertion failed during instantiation of \tcode{fn2} + static_assert(^^T != ^^int); // static assertion failed during + // instantiation of \tcode{fn2} return 0; } @@ -6312,8 +6268,8 @@ consteval info to_integral_constant(unsigned i) { return substitute(^^integral_constant, {^^unsigned, reflect_constant(i)}); } -constexpr info r = to_integral_constant(2); // OK, \tcode{r} represents the type - // \tcode{integral_constant} +constexpr info r = to_integral_constant(2); // OK, \tcode{r} represents the type + // \tcode{integral_constant} \end{codeblock} \end{example} \end{itemdescr} @@ -6379,9 +6335,9 @@ static_assert(is_object(r2)); static_assert(r2 == template_arguments_of(^^A)[0]); -constexpr info r3 = reflect_constant(K{nullptr}); // OK -constexpr info r4 = reflect_constant(K{"ebab"}); // error: constituent pointer - // points to string literal +constexpr info r3 = reflect_constant(K{nullptr}); +constexpr info r4 = reflect_constant(K{"ebab"}); // error: constituent pointer + // points to string literal \end{codeblock} \end{example} \end{itemdescr} @@ -6403,9 +6359,11 @@ \pnum \throws -\tcode{meta::exception} unless -\tcode{expr} is suitable for use as a constant template argument -for a constant template parameter of type \tcode{T\&}\iref{temp.arg.nontype}. +\tcode{meta::exception} if +\tcode{E} is not suitable for use as a constant template argument +for a constant template parameter of type \tcode{T\&}\iref{temp.arg.nontype}, +where \tcode{E} is an lvalue constant expression that +computes the object that \tcode{expr} refers to. \end{itemdescr} \indexlibraryglobal{reflect_function}% @@ -6425,9 +6383,11 @@ \pnum \throws -\tcode{meta::exception} unless -\tcode{fn} is suitable for use as a constant template argument -for a constant template parameter of type \tcode{T\&}\iref{temp.arg.nontype}. +\tcode{meta::exception} if +\tcode{F} is not suitable for use as a constant template argument +for a constant template parameter of type \tcode{T\&}\iref{temp.arg.nontype}, +where \tcode{F} is an lvalue constant expression that +computes the function that \tcode{fn} refers to. \end{itemdescr} \rSec2[meta.reflection.define.aggregate]{Reflection class definition generation} @@ -6453,6 +6413,7 @@ optional alignment; optional bit_width; bool no_unique_address = false; + vector annotations; }; } \end{codeblock} @@ -6513,7 +6474,7 @@ \pnum \returns A reflection of a data member description -$(T, N, A, W, \mathit{NUA})$\iref{class.mem.general} where +$(T, N, A, W, \mathit{NUA}, \mathit{ANN})$\iref{class.mem.general} where \begin{itemize} \item $T$ is the type represented by \tcode{dealias(type)}, @@ -6525,9 +6486,12 @@ or $\bot$ if \tcode{options.alignment} does not contain a value, \item $W$ is either the value held by \tcode{options.bit_width} - or $\bot$ if \tcode{options.bit_width} does not contain a value, and + or $\bot$ if \tcode{options.bit_width} does not contain a value, \item - $\mathit{NUA}$ is the value held by \tcode{options.no_unique_address}. + $\mathit{NUA}$ is the value held by \tcode{options.no_unique_address}, and +\item + $\mathit{ANN}$ is the sequence of values \tcode{constant_of(r)} + for each \tcode{r} in \tcode{options.annotations}. \end{itemize} \begin{note} The returned reflection value is primarily useful @@ -6548,28 +6512,26 @@ \item \tcode{holds_alternative(options.name->\exposid{contents})} is \tcode{true} and \tcode{get(\brk{}options.name->\exposid{contents})} - contains a valid identifier\iref{lex.name} - that is not a keyword\iref{lex.key} + contains the spelling of a valid \grammarterm{token} + that is an \grammarterm{identifier}\iref{lex.name} when interpreted with UTF-8, or \item \tcode{holds_alternative(options.name->\exposid{contents})} is \tcode{true} and \tcode{get(opt\-ions.name->\exposid{contents})} - contains a valid identifier\iref{lex.name} - that is not a keyword\iref{lex.key} + contains the spelling of a valid \grammarterm{token} + that is an \grammarterm{identifier}\iref{lex.name} when interpreted with the ordinary literal encoding; \end{itemize} \begin{note} - The name corresponds to the spelling of an identifier~token - after phase~6 of translation\iref{lex.phases}. Lexical constructs like - \grammarterm{universal-character-name}s\iref{lex.universal.char} are not processed - and will cause evaluation to fail. + \grammarterm{universal-character-name}s\iref{lex.universal.char} are not processed. For example, \tcode{R"(\textbackslash u03B1)"} is an invalid identifier and is not interpreted as \tcode{"$\alpha$"}. \end{note} \item if \tcode{options.name} does not contain a value, - then \tcode{options.bit_width} contains a value; + then \tcode{options.bit_width} contains a value and + \tcode{options.annotations} is empty; \item if \tcode{options.bit_width} contains a value $V$, then \begin{itemize} @@ -6578,15 +6540,25 @@ \item \tcode{options.alignment} does not contain a value, \item - \tcode{options.no_unique_address} is \tcode{false}, and + \tcode{options.no_unique_address} is \tcode{false}, + \item + $V$ is not negative, and \item if $V$ equals \tcode{0}, then \tcode{options.name} does not contain a value; and + \item + if \tcode{options.name} does not contain a value, then + \tcode{is_const(type) || is_volatile(type)} is \tcode{false}; and \end{itemize} \item if \tcode{options.alignment} contains a value, it is an alignment value\iref{basic.align} - not less than \tcode{alignment_of(type)}. + not less than \tcode{alignment_of(type)}; and + \item + for every reflection \tcode{r} in \tcode{options.annotations}, + \tcode{\exposid{has-type}(r)} is \tcode{true}, + \tcode{type_of(r)} represents a non-array object type, and + evaluation of \tcode{constant_of(r)} does not exit via an exception. \end{itemize} \end{itemdescr} @@ -6610,15 +6582,17 @@ \begin{itemdescr} \pnum -Let $C$ be the class represented by \tcode{class_type} +Let $C$ be the type represented by \tcode{class_type} and $r_K$ be the $K^\text{th}$ reflection value in \tcode{mdescrs}. For every $r_K$ in \tcode{mdescrs}, -let $(T_K, N_K, A_K, W_K, \mathit{NUA}_K)$ be +let $(T_K, N_K, A_K, W_K, \mathit{NUA}_K, \mathit{ANN}_K)$ be the corresponding data member description represented by $r_K$. \pnum \constantwhen \begin{itemize} +\item + \tcode{class_type} represents a cv-unqualified class type; \item $C$ is incomplete from every point in the evaluation context; \begin{note} @@ -6637,9 +6611,9 @@ then either: \begin{itemize} \item - \tcode{$N_K$ != $N_L$} is \tcode{true} or + $N_K$ is not the same identifier as $N_L$ or \item - \tcode{$N_K$ == u8"_"} is \tcode{true}. + $N_K$ is the identifier \tcode{_} (\ucode{005f} low line). \begin{note} Every provided identifier is unique or \tcode{"_"}. \end{note} @@ -6648,7 +6622,7 @@ \pnum \effects -Produces an injected declaration $D$\iref{expr.const} +Produces an injected declaration $D$\iref{expr.const.reflect} that defines $C$ and has properties as follows: \begin{itemize} \item @@ -6659,7 +6633,7 @@ follows immediately after the core constant expression currently under evaluation. \item - The characteristic sequence of $D$\iref{expr.const} + The characteristic sequence of $D$\iref{expr.const.reflect} is the sequence of reflection values $r_K$. \item If $C$ is a specialization of a templated class $T$, @@ -6668,6 +6642,7 @@ \item For each $r_K$, there is a corresponding entity $M_K$ + with public access belonging to the class scope of $D$ with the following properties: \begin{itemize} @@ -6675,7 +6650,7 @@ If $N_K$ is $\bot$, $M_K$ is an unnamed bit-field. Otherwise, $M_K$ is a non-static data member whose name is the identifier - determined by the character sequence encoded by $N_K$ in UTF-8. + $N_K$. \item The type of $M_K$ is $T_K$. \item @@ -6689,6 +6664,10 @@ If $A_K$ is not $\bot$, $M_K$ has the \grammarterm{alignment-specifier} \tcode{alignas($A_K$)}. Otherwise, $M_K$ has no \grammarterm{alignment-specifier}. + \item + For every reflection \tcode{r} in $\mathit{ANN}_K$, + $M_K$ has an annotation + whose underlying constant\iref{dcl.attr.annotation} is \tcode{r}. \end{itemize} \item For every $r_L$ in \tcode{mdescrs} such that $K < L$, @@ -6699,6 +6678,12 @@ \pnum \returns \tcode{class_type}. + +\pnum +\remarks +If $C$ is a specialization of a templated class and +it has not been instantiated, +$C$ is treated as an explicit specialization. \end{itemdescr} \rSec2[meta.reflection.traits]{Reflection type traits} @@ -6757,15 +6742,13 @@ consteval bool @\libglobal{is_const_type}@(info type); consteval bool @\libglobal{is_volatile_type}@(info type); consteval bool @\libglobal{is_trivially_copyable_type}@(info type); -consteval bool @\libglobal{is_trivially_relocatable_type}@(info type); -consteval bool @\libglobal{is_replaceable_type}@(info type); consteval bool @\libglobal{is_standard_layout_type}@(info type); consteval bool @\libglobal{is_empty_type}@(info type); consteval bool @\libglobal{is_polymorphic_type}@(info type); consteval bool @\libglobal{is_abstract_type}@(info type); consteval bool @\libglobal{is_final_type}@(info type); consteval bool @\libglobal{is_aggregate_type}@(info type); -consteval bool @\libglobal{is_consteval_only_type}@(info type); +consteval bool @\libglobal{is_structural_type}@(info type); consteval bool @\libglobal{is_signed_type}@(info type); consteval bool @\libglobal{is_unsigned_type}@(info type); consteval bool @\libglobal{is_bounded_array_type}@(info type); @@ -6812,7 +6795,6 @@ consteval bool @\libglobal{is_nothrow_swappable_type}@(info type); consteval bool @\libglobal{is_nothrow_destructible_type}@(info type); -consteval bool @\libglobal{is_nothrow_relocatable_type}@(info type); consteval bool @\libglobal{is_implicit_lifetime_type}@(info type); @@ -6881,6 +6863,41 @@ consteval info @\libglobal{unwrap_ref_decay}@(info type); \end{codeblock} +\pnum +For a function or function template $F$ defined in this subclause, +let $C$ be its associated class template. +For the evaluation of a call to $F$, +let $S$ be the specialization of $C$ in terms of which the call is specified. +\begin{itemize} +\item + If + \begin{itemize} + \item + the template arguments of $S$ violate a condition specified + in a \Fundescx{Mandates} element in the specification of $C$; + \item + the call is specified to produce a reflection of a type, + but $S$ would have no member named \tcode{type}; or + \item + the call is specified to return \tcode{$S$::value}, + but that expression would not be a valid converted constant expression of type \tcode{R}, + where \tcode{R} is the return type of $F$; + \end{itemize} + then an exception of type \tcode{meta::exception} is thrown. + \begin{note} + For the first case, $S$ is not instantiated. + \end{note} + \item + Otherwise, if the instantiation of $S$ would result in undefined behavior + due to dependence on an incomplete type\iref{meta.rqmts}, + then the call is not a constant subexpression. + \item + Otherwise, if the template arguments of $S$ do not meet the preconditions of $C$, + then it is unspecified whether the call is a constant subexpression. + If it is, the call produces the result + that would be produced if $C$ had no preconditions. +\end{itemize} + \pnum Each function or function template declared above has the following behavior based on the signature and return type of that function or function template. @@ -6899,20 +6916,20 @@ \tcode{bool meta::\placeholder{UNARY}(info type);\br bool meta::\placeholder{UNARY}_type(info type);} & -\tcode{std::\placeholder{UNARY}_v<$T$>}, +\tcode{std::\placeholder{UNARY}<$T$>::value}, where $T$ is the type or type alias represented by \tcode{type} \\ \rowsep \tcode{bool meta::\placeholder{BINARY}(info t1, info t2);\br bool meta::\placeholder{BINARY}_type(info t1, info t2);} & -\tcode{std::\placeholder{BINARY}_v<$T_1$, $T_2$>}, +\tcode{std::\placeholder{BINARY}<$T_1$, $T_2$>::value}, where $T_1$ and $T_2$ are the types or type aliases represented by \tcode{t1} and \tcode{t2}, respectively \\ \rowsep \tcode{template\br bool meta::\placeholder{VARIADIC}_type(info type, R\&\& args);} & -\tcode{std::\placeholder{VARIADIC}_v<$T$, $U$...>}, +\tcode{std::\placeholder{VARIADIC}<$T$, $U$...>::value}, where $T$ is the type or type alias represented by \tcode{type} and \tcode{U...} is the pack of types or type aliases whose elements are represented by the corresponding elements of \tcode{args} @@ -6920,7 +6937,7 @@ \tcode{template\br bool meta::\placeholder{VARIADIC}_type(info t1, info t2, R\&\& args);} & -\tcode{std::\placeholder{VARIADIC}_v<$T_1$, $T_2$, $U$...>}, +\tcode{std::\placeholder{VARIADIC}<$T_1$, $T_2$, $U$...>::value}, where $T_1$ and $T_2$ are the types or type aliases represented by \tcode{t1} and \tcode{t2}, respectively, and \tcode{$U$...} is the pack of types or type aliases @@ -6929,14 +6946,14 @@ \tcode{info meta::\placeholder{UNARY}(info type);} & A reflection representing the type denoted by -\tcode{std::\placeholder{UNARY}_t<\brk{}$T$>}, +\tcode{std::\placeholder{UNARY}<\brk{}$T$>::type}, where $T$ is the type or type alias represented by \tcode{type} \\ \rowsep \tcode{template\br info meta::\placeholder{VARIADIC}(R\&\& args);} & A reflection representing the type denoted by -\tcode{std::\placeholder{VARIADIC}_t<$T$...>}, +\tcode{std::\placeholder{VARIADIC}<$T$...>::type}, where \tcode{$T$...} is the pack of types or type aliases whose elements are represented by the corresponding elements of \tcode{args} \\ \rowsep @@ -6944,7 +6961,7 @@ \tcode{template\br info meta::\placeholder{VARIADIC}(info type, R\&\& args);} & A reflection representing the type denoted by -\tcode{std::\placeholder{VARIADIC}_t<$T$, $U$...>}, +\tcode{std::\placeholder{VARIADIC}<$T$, $U$...>::type}, where \tcode{$T$} is the type or type alias represented by \tcode{type} and \tcode{$U$...} is the pack of types or type aliases whose elements are represented by the corresponding elements of \tcode{args} @@ -6974,7 +6991,7 @@ \begin{itemdescr} \pnum \returns -\tcode{rank_v<$T$>}, +\tcode{std::rank<$T$>::value}, where $T$ is the type represented by \tcode{dealias(type)}. \end{itemdescr} @@ -6986,7 +7003,7 @@ \begin{itemdescr} \pnum \returns -\tcode{extent_v<$T$, $I$>}, +\tcode{std::extent<$T$, $I$>::value}, where $T$ is the type represented by \tcode{dealias(type)} and $I$ is a constant equal to \tcode{i}. \end{itemdescr} @@ -6999,7 +7016,7 @@ \begin{itemdescr} \pnum \returns -\tcode{tuple_size_v<$T$>}, +\tcode{std::tuple_size<$T$>::value}, where $T$ is the type represented by \tcode{dealias(type)}. \end{itemdescr} @@ -7012,7 +7029,7 @@ \pnum \returns A reflection representing -the type denoted by \tcode{tuple_element_t<$I$, $T$>}, +the type denoted by \tcode{std::tuple_element<$I$, $T$>::type}, where $T$ is the type represented by \tcode{dealias(type)} and $I$ is a constant equal to \tcode{index}. \end{itemdescr} @@ -7025,7 +7042,7 @@ \begin{itemdescr} \pnum \returns -\tcode{variant_size_v<$T$>}, +\tcode{std::variant_size<$T$>::value}, where $T$ is the type represented by \tcode{dealias(type)}. \end{itemdescr} @@ -7038,7 +7055,7 @@ \pnum \returns A reflection representing the type denoted by -\tcode{variant_alternative_t<$I$, $T$>}, +\tcode{std::variant_alternative<$I$, $T$>::type}, where $T$ is the type represented by \tcode{dealias(type)} and $I$ is a constant equal to \tcode{index}. \end{itemdescr} @@ -7051,9 +7068,9 @@ \begin{itemdescr} \pnum \returns -\tcode{type_order_v<$T_1$, $T_2$>}, +\tcode{std::type_order<$T_1$, $T_2$>::value}, where $T_1$ and $T_2$ are the types -represented by \tcode{dealias(t1)} and \tcode{dealias(t2)}, respectively. +represented by \tcode{de\-alias(\brk{}t1)} and \tcode{dealias(t2)}, respectively. \end{itemdescr} \rSec1[ratio]{Compile-time rational arithmetic} @@ -7310,5 +7327,5 @@ \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. +declared; if either of the constants is not representable by \tcode{intmax_t}, +the typedef is not declared. diff --git a/source/modules.tex b/source/modules.tex index cfe20205b1..4db5625672 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -254,7 +254,7 @@ namespace { export int a2; // error: export of name with internal linkage } -export static int b; // error: b explicitly declared static +export static int b; // error: \tcode{b} explicitly declared static export int f(); // OK export namespace N { } // OK export using namespace N; // OK @@ -334,8 +334,9 @@ \pnum \begin{note} -Names introduced by exported declarations -have either external linkage or no linkage; see \ref{basic.link}. +Names introduced by exported declarations never have module linkage. +They have external linkage, no linkage, or +(in the case of header units) internal linkage; see \ref{basic.link}. Namespace-scope declarations exported by a module can be found by name lookup in any translation unit importing that module\iref{basic.lookup}. Class and enumeration member names can be found by name lookup in any @@ -587,13 +588,6 @@ module-keyword \terminal{;} \opt{declaration-seq} \end{bnf} -\pnum -\begin{note} -Prior to phase 4 of translation, -only preprocessing directives can appear -in the \grammarterm{declaration-seq}\iref{cpp.pre}. -\end{note} - \pnum A \grammarterm{global-module-fragment} specifies the contents of the \defn{global module fragment} for a module unit. @@ -927,7 +921,7 @@ that resulted from the evaluation of an expression as a core constant expression, the instantiation context contains -each point in the evaluation context\iref{expr.const}. +each point in the evaluation context\iref{expr.const.reflect}. \begin{note} Implicit instantiations can result from invocations of library functions\iref{meta.reflection}. @@ -1070,7 +1064,7 @@ The value of \tcode{n} is 1. The member \tcode{Incomplete::x} members-of-precedes\iref{meta.reflection.member.queries} -the synthesized point P associated with the injected declaration +the synthesized point $P$ associated with the injected declaration produced by the call to \tcode{define_aggregate}. \end{example} diff --git a/source/numerics.tex b/source/numerics.tex index c4310e62fb..544aa42865 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -51,7 +51,7 @@ These include arithmetic types, pointers, the library class \tcode{complex}, -and instantiations of +and specializations of \tcode{valarray} for value types. \end{footnote} @@ -1446,12 +1446,12 @@ 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); + 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); + constexpr O generate_random(O first, S last, G&& g, D&& d); } // \ref{rand.dist.uni.int}, class template \tcode{uniform_int_distribution} @@ -1558,62 +1558,60 @@ \pnum Throughout \ref{rand}, -the effect of instantiating a template: +where the template parameters are not constrained, +the names of template parameters are used to express type requirements +on an instantiated template $T$: \begin{itemize} \item - that has a template type parameter + If \tcode{T} has a template type parameter named + \tcode{Sseq}, \tcode{URBG}, \tcode{Engine}, + \tcode{RealType}, \tcode{IntType}, or \tcode{UIntType}, + the program is ill-formed if the corresponding template argument is cv-qualified. + \item + A template argument corresponding to a template parameter named \tcode{Sseq} - is undefined unless the corresponding template argument - is cv-unqualified and - meets the requirements + shall meet the requirements of seed sequence\iref{rand.req.seedseq}. \item - that has a template type parameter + A template argument corresponding to a template parameter named \tcode{URBG} - is undefined unless the corresponding template argument - is cv-unqualified and - meets the requirements + shall meet the requirements of uniform random bit generator\iref{rand.req.urng}. \item - that has a template type parameter + A template argument corresponding to a template parameter named \tcode{Engine} - is undefined unless the corresponding template argument - is cv-unqualified and - meets the requirements + shall meet the requirements of random number engine\iref{rand.req.eng}. \item - that has a template type parameter + If a template argument corresponding to a template parameter named \tcode{RealType} - is undefined unless the corresponding template argument - is cv-unqualified and - is one of - \tcode{float}, \tcode{double}, or \tcode{long double}. + is neither + a standard floating-point type\iref{basic.fundamental} nor + a member of an + \impldef{subset of extended floating-point types that can be used as \tcode{RealType} + template arguments} subset of extended floating-point types, + the program is ill-formed. \item - that has a template type parameter + If a template argument corresponding to a template parameter named \tcode{IntType} - is undefined unless the corresponding template argument - is cv-unqualified and - is one of - \tcode{short}, - \tcode{int}, - \tcode{long}, - \tcode{long long}, - \tcode{unsigned short}, - \tcode{unsigned int}, - \tcode{unsigned long}, - or - \tcode{unsigned long long}. + is neither + a standard signed nor a standard unsigned integer type\iref{basic.fundamental}, nor + an extended integer type whose width is + greater or equal to that of \tcode{char} and + less than or equal to that of \tcode{long long}, nor + a member of an + \impldef{subset of integer types that can be used as \tcode{IntType} template arguments} + subset of integer types, the program is ill-formed. \item - that has a template type parameter + If a template argument corresponding to a template parameter named \tcode{UIntType} - is undefined unless the corresponding template argument - is cv-unqualified and - is one of - \tcode{unsigned short}, - \tcode{unsigned int}, - \tcode{unsigned long}, - or - \tcode{unsigned long long}. + is neither + a standard or extended unsigned integer type whose width is + greater or equal to that of \tcode{short} and + less than or equal to that of \tcode{long long}, nor + a member of an + \impldef{subset of unsigned integer types that can be used as \tcode{UIntType} template arguments} + subset of unsigned integer types, the program is ill-formed. \end{itemize} \pnum @@ -3280,7 +3278,7 @@ 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 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; @@ -4452,7 +4450,7 @@ \pnum \begin{note} If the values $g_i$ produced by \tcode{g} are uniformly distributed, -the instantiation's results are distributed as uniformly as possible. +\tcode{generate_canonical}'s results are distributed as uniformly as possible. Obtaining a value in this way can be a useful step in the process of transforming @@ -7120,11 +7118,6 @@ template valarray sqrt (const valarray&); template valarray tan (const valarray&); template valarray tanh (const valarray&); - - template @\unspec{1}@ begin(valarray& v); - template @\unspec{2}@ begin(const valarray& v); - template @\unspec{1}@ end(valarray& v); - template @\unspec{2}@ end(const valarray& v); } \end{codeblock} @@ -7157,6 +7150,7 @@ is permitted to return an object of another type, provided all the const member functions of \tcode{valarray} +other than \tcode{begin} and \tcode{end} are also applicable to this type. This return type shall not add more than two levels of template nesting over the most deeply nested @@ -7175,8 +7169,7 @@ \begin{itemize} \item for every function taking a -\tcode{const valarray\&} other than \tcode{begin} and -\tcode{end}\iref{valarray.range}, +\tcode{const valarray\&}, identical functions taking the replacement types shall be added; \item for every function taking two @@ -7214,7 +7207,9 @@ namespace std { template class valarray { public: - using value_type = T; + using value_type = T; + using iterator = @\unspec@; + using const_iterator = @\unspec@; // \ref{valarray.cons}, construct/destroy valarray(); @@ -7283,6 +7278,12 @@ valarray& operator<<=(const valarray&); valarray& operator>>=(const valarray&); + // \ref{valarray.range}, range access + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + // \ref{valarray.members}, member functions void swap(valarray&) noexcept; @@ -7447,7 +7448,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to \tcode{valarray(il.begin(), il.size())}. +Equivalent to \tcode{valarray(il.data(), il.size())}. \end{itemdescr} \indexlibraryctor{valarray}% @@ -8505,7 +8506,7 @@ const slice_array& operator=(const slice_array&) const; void operator=(const T&) const; - slice_array() = delete; // as implied by declaring copy constructor above + slice_array() = delete; }; } \end{codeblock} @@ -8787,7 +8788,7 @@ const gslice_array& operator=(const gslice_array&) const; void operator=(const T&) const; - gslice_array() = delete; // as implied by declaring copy constructor above + gslice_array() = delete; }; } \end{codeblock} @@ -8915,7 +8916,7 @@ const mask_array& operator=(const mask_array&) const; void operator=(const T&) const; - mask_array() = delete; // as implied by declaring copy constructor above + mask_array() = delete; }; } \end{codeblock} @@ -9032,7 +9033,7 @@ const indirect_array& operator=(const indirect_array&) const; void operator=(const T&) const; - indirect_array() = delete; // as implied by declaring copy constructor above + indirect_array() = delete; }; } \end{codeblock} @@ -9154,20 +9155,20 @@ object refers. \end{itemdescr} -\rSec2[valarray.range]{\tcode{valarray} range access} +\rSec2[valarray.range]{Range access} \pnum -In the \tcode{begin} and \tcode{end} function templates that follow, \unspec{1} +The \tcode{iterator} type is a type that meets the requirements of a mutable \oldconcept{RandomAccessIterator}\iref{random.access.iterators} -and models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}, -whose \tcode{value_type} is the template -parameter \tcode{T} and whose \tcode{reference} type is \tcode{T\&}. \unspec{2} is a -type that meets the requirements of a constant +and models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}. +Its \tcode{value_type} is the template +parameter \tcode{T} and its \tcode{reference} type is \tcode{T\&}. +The \tcode{const_iterator} type meets the requirements of a constant \oldconcept{RandomAccessIterator} -and models \libconcept{contiguous_iterator}, -whose \tcode{value_type} is the template -parameter \tcode{T} and whose \tcode{reference} type is \tcode{const T\&}. +and models \libconcept{contiguous_iterator}. +Its \tcode{value_type} is the template +parameter \tcode{T} and its \tcode{reference} type is \tcode{const T\&}. \pnum The iterators returned by \tcode{begin} and \tcode{end} for an array @@ -9178,8 +9179,8 @@ \indexlibrarymember{begin}{valarray}% \begin{itemdecl} -template @\unspec{1}@ begin(valarray& v); -template @\unspec{2}@ begin(const valarray& v); +iterator begin(); +const_iterator begin() const; \end{itemdecl} \begin{itemdescr} @@ -9190,8 +9191,8 @@ \indexlibrarymember{end}{valarray}% \begin{itemdecl} -template @\unspec{1}@ end(valarray& v); -template @\unspec{2}@ end(const valarray& v); +iterator end(); +const_iterator end() const; \end{itemdecl} \begin{itemdescr} @@ -9761,7 +9762,7 @@ // \ref{sf.cmath.ellint.3}, incomplete elliptic integral of the third kind @\placeholdernc{floating-point-type}@ ellint_3(@\placeholdernc{floating-point-type}@ k, @\placeholdernc{floating-point-type}@ nu, - @\placeholdernc{floating-point-type}@ phi); + @\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); @@ -9905,7 +9906,7 @@ \indexlibrary{\idxcode{hypot}!3-argument form}% \begin{itemdecl} -constexpr @\placeholder{floating-point-type}@ hypot(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y, +constexpr @\placeholdernc{floating-point-type}@ hypot(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y, @\placeholder{floating-point-type}@ z); \end{itemdecl} @@ -9919,7 +9920,7 @@ \indexlibraryglobal{lerp}% \begin{itemdecl} -constexpr @\placeholder{floating-point-type}@ lerp(@\placeholder{floating-point-type}@ a, @\placeholder{floating-point-type}@ b, +constexpr @\placeholdernc{floating-point-type}@ lerp(@\placeholder{floating-point-type}@ a, @\placeholder{floating-point-type}@ b, @\placeholder{floating-point-type}@ t) noexcept; \end{itemdecl} \begin{itemdescr} @@ -10961,7 +10962,7 @@ struct explicit_diagonal_t; inline constexpr explicit_diagonal_t explicit_diagonal; - // \ref{linalg.layout.packed}, class template layout_blas_packed + // \ref{linalg.layout.packed}, class template \tcode{layout_blas_packed} template class layout_blas_packed; @@ -10990,7 +10991,7 @@ concept @\exposconcept{inout-matrix}@ = @\seebelow@; // \expos template - concept @\exposconcept{possibly-packed-inout-matrix}@ = @\seebelow@; // \expos + concept @\exposconcept{possibly-packed-out-matrix}@ = @\seebelow@; // \expos template concept @\exposconcept{in-object}@ = @\seebelow@; // \expos @@ -11001,6 +11002,9 @@ template concept @\exposconcept{inout-object}@ = @\seebelow@; // \expos + template + concept @\exposconcept{scalar}@ = @\seebelow@; // \expos + // \ref{linalg.scaled}, scaled in-place transformation // \ref{linalg.scaled.scaledaccessor}, class template \tcode{scaled_accessor} @@ -11081,9 +11085,9 @@ void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y); // \ref{linalg.algs.blas1.scal}, multiply elements by scalar - template + template<@\exposconcept{scalar}@ Scalar, @\exposconcept{inout-object}@ InOutObj> void scale(Scalar alpha, InOutObj x); - template + template void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x); // \ref{linalg.algs.blas1.copy}, copy elements @@ -11099,42 +11103,28 @@ 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> + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar> Scalar dot(InVec1 v1, InVec2 v2, Scalar init); - template + 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> + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar> Scalar dotc(InVec1 v1, InVec2 v2, Scalar init); - template + 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> + template<@\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar> Scalar vector_two_norm(InVec v, Scalar init); - template + template Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init); template<@\exposconcept{in-vector}@ InVec> auto vector_two_norm(InVec v); @@ -11142,9 +11132,9 @@ 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> + template<@\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar> Scalar vector_abs_sum(InVec v, Scalar init); - template + template Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init); template<@\exposconcept{in-vector}@ InVec> auto vector_abs_sum(InVec v); @@ -11158,9 +11148,9 @@ 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> + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar> Scalar matrix_frob_norm(InMat A, Scalar init); - template + template Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<@\exposconcept{in-matrix}@ InMat> auto matrix_frob_norm(InMat A); @@ -11168,9 +11158,9 @@ 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> + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar> Scalar matrix_one_norm(InMat A, Scalar init); - template + template Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<@\exposconcept{in-matrix}@ InMat> auto matrix_one_norm(InMat A); @@ -11178,9 +11168,9 @@ 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> + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar> Scalar matrix_inf_norm(InMat A, Scalar init); - template + template Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<@\exposconcept{in-matrix}@ InMat> auto matrix_inf_norm(InMat A); @@ -11305,60 +11295,112 @@ 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); + // overwriting nonsymmetric rank-1 matrix update + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat> + void matrix_rank_1_update(InVec1 x, InVec2 y, OutMat A); + template + void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, OutMat A); + + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat> + void matrix_rank_1_update_c(InVec1 x, InVec2 y, OutMat A); + template + void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, OutMat A); + + // updating nonsymmetric rank-1 matrix update + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat, @\exposconcept{out-matrix}@ OutMat> + void matrix_rank_1_update(InVec1 x, InVec2 y, InMat E, OutMat A); + template + void matrix_rank_1_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InMat E, OutMat A); + + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat, @\exposconcept{out-matrix}@ OutMat> + void matrix_rank_1_update_c(InVec1 x, InVec2 y, InMat E, OutMat A); + template + void matrix_rank_1_update_c(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InMat E, OutMat 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); + + // overwriting symmetric rank-1 matrix update + template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, OutMat A, Triangle t); template + @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> 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); + Scalar alpha, InVec x, OutMat A, Triangle t); - template - void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); + // overwriting Hermitian rank-1 matrix update + template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, OutMat A, Triangle t); template + @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> 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); + Scalar alpha, InVec x, OutMat A, Triangle t); + + // updating symmetric rank-1 matrix update + template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, + class Triangle> + void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InMat E, OutMat A, Triangle t); + template + void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InMat E, OutMat A, Triangle t); + + // updating Hermitian rank-1 matrix update + template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, + class Triangle> + void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InMat E, OutMat A, Triangle t); template - void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t); + @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, + class Triangle> + void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InMat E, OutMat A, Triangle t); // \ref{linalg.algs.blas2.rank2}, symmetric and Hermitian rank-2 matrix updates - // symmetric rank-2 matrix update + // overwriting symmetric rank-2 matrix update + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, OutMat A, Triangle t); + template + void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, OutMat A, Triangle t); + + // overwriting Hermitian rank-2 matrix update + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, OutMat A, Triangle t); + template + void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, OutMat A, Triangle t); + + // updating 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); + @\exposconcept{in-matrix}@ InMat, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t); template + @\exposconcept{in-matrix}@ InMat, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec, - InVec1 x, InVec2 y, InOutMat A, Triangle t); + InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t); - // Hermitian rank-2 matrix update + // updating 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); + @\exposconcept{in-matrix}@ InMat, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t); template + @\exposconcept{in-matrix}@ InMat, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec, - InVec1 x, InVec2 y, InOutMat A, Triangle t); + InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t); // \ref{linalg.algs.blas3}, BLAS 3 algorithms @@ -11499,57 +11541,83 @@ // \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 + // overwriting rank-k symmetric matrix update + template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, OutMat C, Triangle t); + template void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, - InMat A, InOutMat C, Triangle t); + Scalar alpha, InMat A, OutMat C, Triangle t); - // rank-k Hermitian matrix update - template - void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); + // overwriting rank-k Hermitian matrix update + template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, OutMat C, Triangle t); template + @\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, - Scalar alpha, InMat A, InOutMat C, Triangle t); + Scalar alpha, InMat A, OutMat 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); + // updating rank-k symmetric matrix update + template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_k_update(Scalar alpha, InMat1 A, InMat2 E, OutMat C, Triangle t); template - void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, - InMat A, InOutMat C, Triangle t); + @\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, + InMat1 A, InMat2 E, OutMat C, Triangle t); + + // updating rank-k Hermitian matrix update + template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_k_update(Scalar alpha, InMat1 A, InMat2 E, OutMat C, Triangle t); + template + void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, + InMat1 A, InMat2 E, OutMat C, Triangle t); // \ref{linalg.algs.blas3.rank2k}, rank-2k update of a symmetric or Hermitian matrix - // rank-2k symmetric matrix update + // overwriting 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); + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, OutMat C, Triangle t); template + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec, - InMat1 A, InMat2 B, InOutMat C, Triangle t); + InMat1 A, InMat2 B, OutMat C, Triangle t); - // rank-2k Hermitian matrix update + // overwriting 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); + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, OutMat C, Triangle t); template + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, OutMat C, Triangle t); + + // updating symmetric rank-2k matrix update + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t); + template + void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t); + + // updating Hermitian rank-2k matrix update + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t); + template void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec, - InMat1 A, InMat2 B, InOutMat C, Triangle t); + InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t); // \ref{linalg.algs.blas3.trsm}, solve multiple triangular linear systems @@ -11698,6 +11766,9 @@ \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 of diagonal elements \tcode{m[i, i]}, +\tcode{F} will use the value \tcode{\exposid{real-if-needed}(m[i, i])} +if the name of \tcode{F} starts with \tcode{hermitian}. For accesses \tcode{m[i, j]} outside the triangle specified by \tcode{t}, \tcode{F} will use the value \begin{itemize} @@ -11802,7 +11873,7 @@ \end{itemize} \pnum -Linear algebra value types shall model \libconcept{semiregular}. +Linear algebra value types shall model \exposconcept{scalar}. \pnum A value-initialized object of linear algebra value type @@ -12051,17 +12122,17 @@ template class @\libglobal{layout_blas_packed}@ { public: - using triangle_type = Triangle; - using storage_order_type = StorageOrder; + using @\libmember{triangle_type}{layout_blas_packed}@ = Triangle; + using @\libmember{storage_order_type}{layout_blas_packed}@ = StorageOrder; template - struct mapping { + struct @\libmember{mapping}{layout_blas_packed}@ { public: - using extents_type = Extents; - using index_type = extents_type::index_type; - using size_type = extents_type::size_type; - using rank_type = extents_type::rank_type; - using layout_type = layout_blas_packed; + using @\libmember{extents_type}{layout_blas_packed::mapping}@ = Extents; + using @\libmember{index_type}{layout_blas_packed::mapping}@ = extents_type::index_type; + using @\libmember{size_type}{layout_blas_packed::mapping}@ = extents_type::size_type; + using @\libmember{rank_type}{layout_blas_packed::mapping}@ = extents_type::rank_type; + using @\libmember{layout_type}{layout_blas_packed::mapping}@ = layout_blas_packed; // \ref{linalg.layout.packed.cons}, constructors constexpr mapping() noexcept = default; @@ -12074,28 +12145,28 @@ constexpr mapping& operator=(const mapping&) noexcept = default; // \ref{linalg.layout.packed.obs}, observers - constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } + constexpr const extents_type& @\libmember{extents}{layout_blas_packed::mapping}@() 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 { + static constexpr bool @\libmember{is_always_unique}{layout_blas_packed::mapping}@() 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 + static constexpr bool @\libmember{is_always_exhaustive}{layout_blas_packed::mapping}@() noexcept { return true; } + static constexpr bool @\libmember{is_always_strided}{layout_blas_packed::mapping}@() noexcept { return is_always_unique(); } - constexpr bool is_unique() const noexcept { + constexpr bool @\libmember{is_unique}{layout_blas_packed::mapping}@() const noexcept { return @\exposid{extents_}@.extent(0) < 2; } - constexpr bool is_exhaustive() const noexcept { return true; } - constexpr bool is_strided() const noexcept { + constexpr bool @\libmember{is_exhaustive}{layout_blas_packed::mapping}@() const noexcept { return true; } + constexpr bool @\libmember{is_strided}{layout_blas_packed::mapping}@() const noexcept { return @\exposid{extents_}@.extent(0) < 2; } @@ -12427,7 +12498,7 @@ constexpr bool @\exposid{is-layout-blas-packed}@> = true; template - concept @\defexposconcept{possibly-packed-inout-matrix}@ = + concept @\defexposconcept{possibly-packed-out-matrix}@ = @\exposid{is-mdspan}@ && T::rank() == 2 && is_assignable_v && (T::is_always_unique() || @\exposid{is-layout-blas-packed}@); @@ -12445,6 +12516,10 @@ concept @\defexposconcept{inout-object}@ = @\exposid{is-mdspan}@ && (T::rank() == 1 || T::rank() == 2) && is_assignable_v && T::is_always_unique(); + +template + concept @\defexposconcept{scalar}@ = + @\libconcept{semiregular}@ && (!@\exposid{is-mdspan}@) && (!is_execution_policy_v); \end{codeblock} \pnum @@ -12463,7 +12538,7 @@ \exposconcept{out-vector}, \exposconcept{out-matrix}, \exposconcept{out-object}, or -\exposconcept{possibly-packed-inout-matrix} +\exposconcept{possibly-packed-out-matrix} parameter of a function in \ref{linalg} shall not overlap any other \tcode{mdspan} parameter of the function. @@ -12604,11 +12679,12 @@ 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; + using @\libmember{element_type}{scaled_accessor}@ = + const decltype(declval() * + declval()); + using @\libmember{reference}{scaled_accessor}@ = remove_const_t; + using @\libmember{data_handle_type}{scaled_accessor}@ = NestedAccessor::data_handle_type; + using @\libmember{offset_policy}{scaled_accessor}@ = scaled_accessor; constexpr scaled_accessor() = default; template @@ -12620,8 +12696,8 @@ 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}@; } + constexpr const ScalingFactor& @\libmember{scaling_factor}{scaled_accessor}@() const noexcept { return @\exposid{scaling-factor}@; } + constexpr const NestedAccessor& @\libmember{nested_accessor}{scaled_accessor}@() const noexcept { return @\exposid{nested-accessor}@; } private: ScalingFactor @\exposid{scaling-factor}@{}; // \expos @@ -12694,7 +12770,7 @@ \pnum \returns \begin{codeblock} -scaling_factor() * NestedAccessor::element_type(@\exposid{nested-accessor}@.access(p, i)) +scaling_factor() * typename NestedAccessor::element_type(@\exposid{nested-accessor}@.access(p, i)) \end{codeblock} \end{itemdescr} @@ -12706,7 +12782,7 @@ \begin{itemdescr} \pnum \returns -\tcode{\exposid{nested-accessor}.offset(p, i)} +\tcode{\exposid{nested-accessor}.offset(p, i)}. \end{itemdescr} \rSec3[linalg.scaled.scaled]{Function template \tcode{scaled}} @@ -12776,11 +12852,11 @@ template class @\libglobal{conjugated_accessor}@ { public: - using element_type = - add_const_t()))>; - using reference = remove_const_t; - using data_handle_type = NestedAccessor::data_handle_type; - using offset_policy = conjugated_accessor; + using @\libmember{element_type}{conjugated_accessor}@ = + const decltype(@\exposid{conj-if-needed}@(declval())); + using @\libmember{reference}{conjugated_accessor}@ = remove_const_t; + using @\libmember{data_handle_type}{conjugated_accessor}@ = NestedAccessor::data_handle_type; + using @\libmember{offset_policy}{conjugated_accessor}@ = conjugated_accessor; constexpr conjugated_accessor() = default; constexpr conjugated_accessor(const NestedAccessor& acc); @@ -12793,7 +12869,7 @@ constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const; - constexpr const NestedAccessor& nested_accessor() const noexcept { return @\exposid{nested-accessor_}@; } + constexpr const NestedAccessor& @\libmember{nested_accessor}{conjugated_accessor}@() const noexcept { return @\exposid{nested-accessor_}@; } private: NestedAccessor @\exposid{nested-accessor_}@{}; // \expos @@ -12853,7 +12929,9 @@ \begin{itemdescr} \pnum \returns -\tcode{\exposid{conj-if-needed}(NestedAccessor::element_type(\exposid{nested-accessor_}.access(p, i)))} +\begin{codeblock} +@\exposid{conj-if-needed}@(typename NestedAccessor::element_type(@\exposid{nested-accessor_}@.access(p, i))) +\end{codeblock} \end{itemdescr} \indexlibrarymember{conjugated_accessor}{offset}% @@ -12864,7 +12942,7 @@ \begin{itemdescr} \pnum \returns -\tcode{\exposid{nested-accessor_}.offset(p, i)} +\tcode{\exposid{nested-accessor_}.offset(p, i)}. \end{itemdescr} \rSec3[linalg.conj.conjugated]{Function template \tcode{conjugated}} @@ -12975,7 +13053,7 @@ \begin{itemdescr} \pnum \returns -\tcode{extents(in.extent(1), in.extent(0))} +\tcode{extents(in.extent(1), in.extent(0))}. \end{itemdescr} \begin{codeblock} @@ -12996,45 +13074,45 @@ template class @\libglobal{layout_transpose}@ { public: - using nested_layout_type = Layout; + using @\libmember{nested_layout_type}{layout_transpose}@ = Layout; template - struct mapping { + struct @\libmember{mapping}{layout_transpose}@ { private: using @\exposid{nested-mapping-type}@ = Layout::template mapping<@\exposid{transpose-extents-t}@>; // \expos public: - using extents_type = Extents; - using index_type = extents_type::index_type; - using size_type = extents_type::size_type; - using rank_type = extents_type::rank_type; - using layout_type = layout_transpose; + using @\libmember{extents_type}{layout_transpose::mapping}@ = Extents; + using @\libmember{index_type}{layout_transpose::mapping}@ = extents_type::index_type; + using @\libmember{size_type}{layout_transpose::mapping}@ = extents_type::size_type; + using @\libmember{rank_type}{layout_transpose::mapping}@ = extents_type::rank_type; + using @\libmember{layout_type}{layout_transpose::mapping}@ = layout_transpose; constexpr explicit mapping(const @\exposid{nested-mapping-type}@&); - constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } + constexpr const extents_type& @\libmember{extents}{layout_transpose::mapping}@() const noexcept { return @\exposid{extents_}@; } - constexpr index_type required_span_size() const - { return @\exposid{nested-mapping_}@.required_span_size(); + constexpr index_type @\libmember{required_span_size}{layout_transpose::mapping}@() const + { return @\exposid{nested-mapping_}@.required_span_size(); } template - constexpr index_type operator()(Index0 ind0, Index1 ind1) const + constexpr index_type @\libmember{operator()}{layout_transpose::mapping}@(Index0 ind0, Index1 ind1) const { return @\exposid{nested-mapping_}@(ind1, ind0); } - constexpr const @\exposid{nested-mapping-type}@& nested_mapping() const noexcept + constexpr const @\exposid{nested-mapping-type}@& @\libmember{nested_mapping}{layout_transpose::mapping}@() const noexcept { return @\exposid{nested-mapping_}@; } - static constexpr bool is_always_unique() noexcept + static constexpr bool @\libmember{is_always_unique}{layout_transpose::mapping}@() noexcept { return @\exposid{nested-mapping-type}@::is_always_unique(); } - static constexpr bool is_always_exhaustive() noexcept + static constexpr bool @\libmember{is_always_exhaustive}{layout_transpose::mapping}@() noexcept { return @\exposid{nested-mapping-type}@::is_always_exhaustive(); } - static constexpr bool is_always_strided() noexcept + static constexpr bool @\libmember{is_always_strided}{layout_transpose::mapping}@() 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 bool @\libmember{is_unique}{layout_transpose::mapping}@() const { return @\exposid{nested-mapping_}@.is_unique(); } + constexpr bool @\libmember{is_exhaustive}{layout_transpose::mapping}@() const { return @\exposid{nested-mapping_}@.is_exhaustive(); } + constexpr bool @\libmember{is_strided}{layout_transpose::mapping}@() const { return @\exposid{nested-mapping_}@.is_strided(); } constexpr index_type stride(size_t r) const; @@ -13096,7 +13174,7 @@ \pnum \returns -\tcode{\exposid{nested-mapping_}.stride(r == 0 ? 1 : 0)} +\tcode{\exposid{nested-mapping_}.stride(r == 0 ? 1 : 0)}. \end{itemdescr} \indexlibrarymember{layout_transpose::mapping}{operator==}% @@ -13491,9 +13569,9 @@ \indexlibraryglobal{scale}% \begin{itemdecl} -template +template<@\exposconcept{scalar}@ Scalar, @\exposconcept{inout-object}@ InOutObj> void scale(Scalar alpha, InOutObj x); -template +template void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x); \end{itemdecl} @@ -13606,9 +13684,9 @@ \indexlibraryglobal{dot}% \begin{itemdecl} -template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar> Scalar dot(InVec1 v1, InVec2 v2, Scalar init); -template +template Scalar dot(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init); \end{itemdecl} @@ -13673,9 +13751,9 @@ \indexlibraryglobal{dotc}% \begin{itemdecl} -template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar> Scalar dotc(InVec1 v1, InVec2 v2, Scalar init); -template +template Scalar dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init); \end{itemdecl} @@ -13736,62 +13814,13 @@ \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> +template<@\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar> Scalar vector_two_norm(InVec v, Scalar init); -template +template Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init); \end{itemdecl} @@ -13803,13 +13832,24 @@ \pnum \mandates +\tcode{InVec::value_type} and \tcode{Scalar} are either a floating-point type, or +a specialization of \tcode{complex}. Let \tcode{a} be -\tcode{\exposid{abs-if-needed}(declval())}. -Then, \tcode{decltype(\linebreak init + a * a} is convertible to \tcode{Scalar}. +\tcode{\exposid{abs-if-needed}(declval())} and +let \tcode{init_abs} be \tcode{\exposid{abs-if-needed}(init)}. +Then, \tcode{decltype(init_abs * init_abs + 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}. +The square root of the sum +whose terms are the following: +\begin{itemize} +\item +the square of the absolute value of \tcode{init}, and +\item +the squares of the absolute values of the elements of \tcode{v}. +\end{itemize} \begin{note} For \tcode{init} equal to zero, this is the Euclidean norm (also called 2-norm) of the vector \tcode{v}. @@ -13817,16 +13857,9 @@ \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 +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}% @@ -13863,9 +13896,9 @@ \indexlibraryglobal{vector_abs_sum}% \begin{itemdecl} -template<@\exposconcept{in-vector}@ InVec, class Scalar> +template<@\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar> Scalar vector_abs_sum(InVec v, Scalar init); -template +template Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init); \end{itemdecl} @@ -13999,9 +14032,9 @@ \indexlibraryglobal{matrix_frob_norm}% \begin{itemdecl} -template<@\exposconcept{in-matrix}@ InMat, class Scalar> +template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar> Scalar matrix_frob_norm(InMat A, Scalar init); -template +template Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init); \end{itemdecl} @@ -14009,15 +14042,24 @@ \pnum \mandates +\tcode{InMat::value_type} and \tcode{Scalar} are either a floating-point type, or +a specialization of \tcode{complex}. Let \tcode{a} be -\tcode{\exposid{abs-if-needed}(declval())}. -Then, \tcode{decltype(\linebreak init + a * a)} +\tcode{\exposid{abs-if-needed}(declval())} and +let \tcode{init_abs} be \tcode{\exposid{abs-if-needed}(init)}. +Then, \tcode{decltype(init_abs * init_abs + 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}. +The square root of the sum +whose terms are the following: +\begin{itemize} +\item +the square of the absolute value of \tcode{init}, and +\item +the squares of the absolute values of the elements of \tcode{A}. +\end{itemize} \begin{note} For \tcode{init} equal to zero, this is the Frobenius norm of the matrix \tcode{A}. @@ -14025,9 +14067,7 @@ \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 +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} @@ -14073,9 +14113,9 @@ \indexlibraryglobal{matrix_one_norm}% \begin{itemdecl} -template<@\exposconcept{in-matrix}@ InMat, class Scalar> +template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar> Scalar matrix_one_norm(InMat A, Scalar init); -template +template Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init); \end{itemdecl} @@ -14091,7 +14131,7 @@ \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$. +otherwise, the sum of \tcode{init} and the one norm of the matrix \tcode{A}. \end{itemize} \begin{note} The one norm of the matrix \tcode{A} @@ -14147,9 +14187,9 @@ \indexlibraryglobal{matrix_inf_norm}% \begin{itemdecl} -template<@\exposconcept{in-matrix}@ InMat, class Scalar> +template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar> Scalar matrix_inf_norm(InMat A, Scalar init); -template +template Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init); \end{itemdecl} @@ -14233,7 +14273,7 @@ \tcode{\exposid{possibly-multipliable}()} is \tcode{true}, and \item -\tcode{\exposid{possibly-addable}()} +\tcode{\exposid{possibly-addable}()} is \tcode{true} for those overloads that take a \tcode{z} parameter. \end{itemize} @@ -14243,12 +14283,12 @@ \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. +\tcode{\exposid{addable}(y,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)}}. +\bigoh{\tcode{A.extent(0)} \times \tcode{x.extent(0)}}. \indexlibraryglobal{matrix_vector_product}% \begin{itemdecl} @@ -14343,7 +14383,7 @@ \tcode{\exposid{possibly-multipliable}()} is \tcode{true}; and \item -\tcode{\exposid{possibly-addable}()} +\tcode{\exposid{possibly-addable}()} is \tcode{true} for those overloads that take a \tcode{z} parameter. \end{itemize} @@ -14355,13 +14395,13 @@ \item \tcode{\exposid{multipliable}(A,x,y)} is \tcode{true}, and \item -\tcode{\exposid{addable}(x,y,z)} is \tcode{true} +\tcode{\exposid{addable}(y,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)}}. +\bigoh{\tcode{A.extent(0)} \times \tcode{x.extent(0)}}. \indexlibraryglobal{symmetric_matrix_vector_product}% \begin{itemdecl} @@ -14435,7 +14475,7 @@ \tcode{\exposid{possibly-multipliable}()} is \tcode{true}; and \item -\tcode{\exposid{possibly-addable}()} +\tcode{\exposid{possibly-addable}()} is \tcode{true} for those overloads that take a \tcode{z} parameter. \end{itemize} @@ -14447,12 +14487,12 @@ \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. +\tcode{\exposid{addable}(y, 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)}}. +\bigoh{\tcode{A.extent(0)} \times \tcode{x.extent(0)}}. \indexlibraryglobal{hermitian_matrix_vector_product}% \begin{itemdecl} @@ -14571,7 +14611,7 @@ \pnum \complexity -\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. +\bigoh{\tcode{A.extent(0)} \times \tcode{x.extent(0)}}. \end{itemdescr} \indexlibraryglobal{triangular_matrix_vector_product}% @@ -14603,7 +14643,7 @@ \pnum \complexity -\bigoh{\tcode{y.extent(0)} \times \tcode{A.extent(1)}}. +\bigoh{\tcode{A.extent(0)} \times \tcode{y.extent(0)}}. \end{itemdescr} \indexlibraryglobal{triangular_matrix_vector_product}% @@ -14631,7 +14671,7 @@ \pnum \complexity -\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. +\bigoh{\tcode{A.extent(0)} \times \tcode{x.extent(0)}}. \pnum \remarks @@ -14817,17 +14857,46 @@ \rSec3[linalg.algs.blas2.rank1]{Rank-1 (outer product) update of a matrix} +\pnum +The following elements apply to all functions in~\ref{linalg.algs.blas2.rank1}. + +\pnum +\mandates +\begin{itemize} +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}, and +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads with an \tcode{E} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(A, y, x)} +is \tcode{true}, and +\item +\tcode{\exposid{addable}(A, E, A)} +is \tcode{true} for those overloads with an \tcode{E} parameter. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{y.extent(0)}}. + \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); +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat> + void matrix_rank_1_update(InVec1 x, InVec2 y, OutMat A); +template + void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, OutMat A); \end{itemdecl} \begin{itemdescr} \pnum -These functions perform a nonsymmetric nonconjugated rank-1 update. +These functions perform an overwriting nonsymmetric nonconjugated rank-1 update. \begin{note} These functions correspond to the BLAS functions \tcode{xGER} (for real element types) and @@ -14835,35 +14904,48 @@ \end{note} \pnum -\mandates -\tcode{\exposid{possibly-multipliable}()} -is \tcode{true}. +\effects +Computes $A = x y^T$. +\end{itemdescr} + +\indexlibraryglobal{matrix_rank_1_update}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat, @\exposconcept{out-matrix}@ OutMat> + void matrix_rank_1_update(InVec1 x, InVec2 y, InMat E, OutMat A); +template + void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InMat E, OutMat A); +\end{itemdecl} +\begin{itemdescr} \pnum -\expects -\tcode{\exposid{multipliable}(A, y, x)} is \tcode{true}. +These functions perform an updating 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 \effects -Computes a matrix $A'$ such that $A' = A + x y^T$, -and assigns each element of $A'$ to the corresponding element of $A$. +Computes $A = E + x y^T$. \pnum -\complexity -\bigoh{\tcode{x.extent(0)} \times \tcode{y.extent(0)}}. +\remarks +\tcode{A} may alias \tcode{E}. \end{itemdescr} -\indexlibraryglobal{matrix_rank_1_update}% +\indexlibraryglobal{matrix_rank_1_update_c}% \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); +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat> + void matrix_rank_1_update_c(InVec1 x, InVec2 y, OutMat A); +template + void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, OutMat A); \end{itemdecl} \begin{itemdescr} \pnum -These functions perform a nonsymmetric conjugated rank-1 update. +These functions perform an overwriting nonsymmetric conjugated rank-1 update. \begin{note} These functions correspond to the BLAS functions \tcode{xGER} (for real element types) and @@ -14887,6 +14969,41 @@ \end{itemize} \end{itemdescr} +\indexlibraryglobal{matrix_rank_1_update_c}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat, @\exposconcept{out-matrix}@ OutMat> + void matrix_rank_1_update_c(InVec1 x, InVec2 y, InMat E, OutMat A); +template + void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InMat E, OutMat A); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an updating 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), E, A); +\end{codeblock} +\item +otherwise, equivalent to: +\begin{codeblock} +matrix_rank_1_update(std::forward(exec), x, conjugated(y), E, A); +\end{codeblock} +\end{itemize} +\end{itemdescr} + \rSec3[linalg.algs.blas2.symherrank1]{Symmetric or Hermitian Rank-1 (outer product) update of a matrix} \pnum @@ -14895,34 +15012,61 @@ \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. +$A = A - x x^T$ in noncomplex arithmetic otherwise. \end{note} \pnum The following elements apply to all functions in \ref{linalg.algs.blas2.symherrank1}. +\pnum +For any function \tcode{F} in this subclause with +a parameter named \tcode{t}, +an \tcode{InMat} template parameter, and +a function parameter \tcode{InMat E}, +\tcode{t} applies to accesses done through the parameter \tcode{E}. +\tcode{F} only accesses the triangle of \tcode{E} specified by \tcode{t}. +For accesses of diagonal elements \tcode{E[i, i]}, +\tcode{F} only uses the value \tcode{\exposid{real-if-needed}(E[i, i])} +if the name of \tcode{F} starts with \tcode{hermitian}. +For accesses \tcode{E[i, j]} outside the triangle specified by \tcode{t}, +\tcode{F} only uses the value +\begin{itemize} +\item +\tcode{\exposid{conj-if-needed}(E[j, i])} +if the name of \tcode{F} starts with \tcode{hermitian}, or +\item +\tcode{E[j, i]} +if the name of \tcode{F} starts with \tcode{symmetric}. +\end{itemize} + \pnum \mandates \begin{itemize} \item -If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +If \tcode{OutMat} 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 +is \tcode{true}; \item \tcode{\exposid{compatible-static-extents}(0, 0)} -is \tcode{true}. +is \tcode{true}; and +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads with an \tcode{E} parameter. \end{itemize} \pnum \expects \begin{itemize} \item -\tcode{A.extent(0)} equals \tcode{A.extent(1)}, and +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{A.extent(0)} equals \tcode{x.extent(0)}, and \item -\tcode{A.extent(0)} equals \tcode{x.extent(0)}. +\tcode{\exposid{addable}(A, E, A)} is \tcode{true} +for those overloads with an \tcode{E} parameter. \end{itemize} \pnum @@ -14931,94 +15075,107 @@ \indexlibraryglobal{symmetric_matrix_rank_1_update}% \begin{itemdecl} -template - void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); +template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, OutMat A, Triangle t); template + @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, - Scalar alpha, InVec x, InOutMat A, Triangle t); + Scalar alpha, InVec x, OutMat A, Triangle t); \end{itemdecl} \begin{itemdescr} \pnum These functions perform -a symmetric rank-1 update of the symmetric matrix \tcode{A}, +an overwriting 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$. +Computes a matrix $A = \alpha x x^T$, +where the scalar $\alpha$ is \tcode{alpha}. \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); +template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, + class Triangle> + void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InMat E, OutMat A, Triangle t); +template + void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InMat E, OutMat A, Triangle t); \end{itemdecl} \begin{itemdescr} \pnum These functions perform -a symmetric rank-1 update of the symmetric matrix \tcode{A}, +an updating symmetric rank-1 update of the symmetric matrix \tcode{A} +using the symmetric matrix \tcode{E}, taking into account the \tcode{Triangle} parameter -that applies to \tcode{A}\iref{linalg.general}. +that applies to \tcode{A} and \tcode{E}\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$. +Computes $A = E + \alpha x x^T$, +where the scalar $\alpha$ is \tcode{alpha}. + +\pnum +\remarks +\tcode{A} may alias \tcode{E}. \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<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, OutMat A, Triangle t); template + @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, - Scalar alpha, InVec x, InOutMat A, Triangle t); + Scalar alpha, InVec x, OutMat A, Triangle t); \end{itemdecl} \begin{itemdescr} \pnum These functions perform -a Hermitian rank-1 update of the Hermitian matrix \tcode{A}, +an overwriting 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$. +Computes $A = \alpha x x^H$, +where the scalar $\alpha$ is \tcode{\exposid{real-if-needed}(alpha)}. \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<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, + class Triangle> + void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InMat E, OutMat A, Triangle t); template - void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t); + @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, + class Triangle> + void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InMat E, OutMat A, Triangle t); \end{itemdecl} \begin{itemdescr} \pnum These functions perform -a Hermitian rank-1 update of the Hermitian matrix \tcode{A}, +an updating Hermitian rank-1 update of the Hermitian matrix \tcode{A} +using the Hermitian matrix \tcode{E}, taking into account the \tcode{Triangle} parameter -that applies to \tcode{A}\iref{linalg.general}. +that applies to \tcode{A} and \tcode{E}\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$. +Computes $A = E + \alpha x x^H$, +where the scalar $\alpha$ is \tcode{\exposid{real-if-needed}(alpha)}. + +\pnum +\remarks +\tcode{A} may alias \tcode{E}. \end{itemdescr} \rSec3[linalg.algs.blas2.rank2]{Symmetric and Hermitian rank-2 matrix updates} @@ -15026,34 +15183,66 @@ \pnum \begin{note} These functions correspond to the BLAS functions -\tcode{xSYR2},\tcode{xSPR2}, \tcode{xHER2} and \tcode{xHPR2}\supercite{blas2}. +\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 +For any function \tcode{F} in this subclause with +a parameter named \tcode{t}, +an \tcode{InMat} template parameter, and +a function parameter \tcode{InMat E}, +\tcode{t} applies to accesses done through the parameter \tcode{E}. +\tcode{F} only accesses the triangle of \tcode{E} specified by \tcode{t}. +For accesses of diagonal elements \tcode{E[i, i]}, +\tcode{F} only uses the value \tcode{\exposid{real-if-needed}(E[i, i])} +if the name of \tcode{F} starts with \tcode{hermitian}. +For accesses \tcode{E[i, j]} outside the triangle specified by \tcode{t}, +\tcode{F} only uses the value +\begin{itemize} +\item +\tcode{\exposid{conj-if-needed}(E[j, i])} +if the name of \tcode{F} starts with \tcode{hermitian}, or +\item +\tcode{E[j, i]} +if the name of \tcode{F} starts with \tcode{symmetric}. +\end{itemize} + \pnum \mandates \begin{itemize} \item -If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +If \tcode{OutMat} 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 +If the function has an \tcode{InMat} template parameter and +\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}; and +is \tcode{true}; \item \tcode{\exposid{possibly-multipliable}()} -is \tcode{true}. +is \tcode{true}; and +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads with an \tcode{E} parameter. \end{itemize} \pnum \expects \begin{itemize} \item -\tcode{A.extent(0)} equals \tcode{A.extent(1)}, and +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{\exposid{multipliable}(A, x, y)} is \tcode{true}, and \item -\tcode{\exposid{multipliable}(A, x, y)} is \tcode{true}. +\tcode{\exposid{addable}(A, E, A)} is \tcode{true} +for those overloads with an \tcode{E} parameter. \end{itemize} \pnum @@ -15063,49 +15252,103 @@ \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); + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, OutMat A, Triangle t); template + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec, - InVec1 x, InVec2 y, InOutMat A, Triangle t); + InVec1 x, InVec2 y, OutMat A, Triangle t); \end{itemdecl} \begin{itemdescr} \pnum These functions perform -a symmetric rank-2 update of the symmetric matrix \tcode{A}, +an overwriting 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$. +Computes $A = x y^T + y x^T$. +\end{itemdescr} + +\indexlibraryglobal{symmetric_matrix_rank_2_update}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t); +template + void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +an updating symmetric rank-2 update of the symmetric matrix \tcode{A} +using the symmetric matrix \tcode{E}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A} and \tcode{E}\iref{linalg.general}. + +\pnum +\effects +Computes $A = E + x y^T + y x^T$. + +\pnum +\remarks +\tcode{A} may alias \tcode{E}. \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); + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, OutMat A, Triangle t); template + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec, - InVec1 x, InVec2 y, InOutMat A, Triangle t); + InVec1 x, InVec2 y, OutMat A, Triangle t); \end{itemdecl} \begin{itemdescr} \pnum These functions perform -a Hermitian rank-2 update of the Hermitian matrix \tcode{A}, +an overwriting 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$. +Computes $A = x y^H + y x^H$. +\end{itemdescr} + +\indexlibraryglobal{hermitian_matrix_rank_2_update}% +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t); +template + void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +an updating Hermitian rank-2 update of the Hermitian matrix \tcode{A} +using the Hermitian matrix \tcode{E}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A} and \tcode{E}\iref{linalg.general}. + +\pnum +\effects +Computes $A = E + x y^H + y x^H$. + +\pnum +\remarks +\tcode{A} may alias \tcode{E}. \end{itemdescr} \rSec2[linalg.algs.blas3]{BLAS 3 algorithms} @@ -15554,107 +15797,138 @@ \pnum The following elements apply to all functions in \ref{linalg.algs.blas3.rankk}. +\pnum +For any function \tcode{F} in this subclause with +a parameter named \tcode{t}, +an \tcode{InMat2} template parameter, and +a function parameter \tcode{InMat2 E}, +\tcode{t} applies to accesses done through the parameter \tcode{E}. +\tcode{F} only accesses the triangle of \tcode{E} specified by \tcode{t}. +For accesses of diagonal elements \tcode{E[i, i]}, +\tcode{F} only uses the value \tcode{\exposid{real-if-needed}(E[i, i])} +if the name of \tcode{F} starts with \tcode{hermitian}. +For accesses \tcode{E[i, j]} outside the triangle specified by \tcode{t}, +\tcode{F} only uses the value +\begin{itemize} +\item +\tcode{\exposid{conj-if-needed}(E[j, i])} +if the name of \tcode{F} starts with \tcode{hermitian}, or +\item +\tcode{E[j, i]} +if the name of \tcode{F} starts with \tcode{symmetric}. +\end{itemize} + \pnum \mandates \begin{itemize} \item -If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +If \tcode{OutMat} 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}; +If the function has an \tcode{InMat2} template parameter and +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; \item -\tcode{\exposid{compatible-static-extents}(0, 1)} +\tcode{\exposid{possibly-multipliable}()} is \tcode{true}; and \item -\tcode{\exposid{compatible-static-extents}(0, 0)} -is \tcode{true}. +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads with an \tcode{E} parameter. \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 +\tcode{\exposid{multipliable}(A, transposed(A), C)} +is \tcode{true}; and +\begin{note} +This implies that \tcode{C} is square. +\end{note} \item -\tcode{A.extent(0)} equals \tcode{C.extent(0)}. +\tcode{\exposid{addable}(C, E, C)} +is \tcode{true} for those overloads with an \tcode{E} parameter. \end{itemize} \pnum \complexity -\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{A.extent(0)}}. + +\pnum +\remarks +\tcode{C} may alias \tcode{E} for those overloads with an \tcode{E} parameter. \indexlibraryglobal{symmetric_matrix_rank_k_update}% \begin{itemdecl} - template - void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); - template + template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, OutMat C, Triangle t); + template void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, - Scalar alpha, InMat A, InOutMat C, Triangle t); + Scalar alpha, InMat A, OutMat 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$. +Computes $C = \alpha A A^T$, +where the scalar $\alpha$ is \tcode{alpha}. \end{itemdescr} -\indexlibraryglobal{symmetric_matrix_rank_k_update}% +\indexlibraryglobal{hermitian_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); +template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, + class Triangle> +void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, OutMat C, Triangle t); +template +void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat A, + OutMat 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$. +Computes $C = \alpha A A^H$, +where the scalar $\alpha$ is \tcode{\exposid{real-if-needed}(alpha)}. \end{itemdescr} -\indexlibraryglobal{hermitian_matrix_rank_k_update}% +\indexlibraryglobal{symmetric_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); +template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{possibly-packed-out-matrix}@ OutMat, + class Triangle> +void symmetric_matrix_rank_k_update(Scalar alpha, InMat1 A, InMat2 E, OutMat C, Triangle t); +template +void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat1 A, InMat2 E, + OutMat 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$. +Computes $C = E + \alpha A A^T$, +where the scalar $\alpha$ is \tcode{alpha}. \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); +template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{possibly-packed-out-matrix}@ OutMat, + class Triangle> +void hermitian_matrix_rank_k_update(Scalar alpha, InMat1 A, InMat2 E, OutMat C, Triangle t); +template +void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat1 A, InMat2 E, + OutMat 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$. +Computes $C = E + \alpha A A^H$, +where the scalar $\alpha$ is \tcode{\exposid{real-if-needed}(alpha)}. \end{itemdescr} \rSec3[linalg.algs.blas3.rank2k]{Rank-2k update of a symmetric or Hermitian matrix} @@ -15668,69 +15942,143 @@ \pnum The following elements apply to all functions in \ref{linalg.algs.blas3.rank2k}. +\pnum +For any function \tcode{F} in this subclause with +a parameter named \tcode{t}, +an \tcode{InMat3} template parameter, and +a function parameter \tcode{InMat3 E}, +\tcode{t} applies to accesses done through the parameter \tcode{E}. +\tcode{F} only accesses the triangle of \tcode{E} specified by \tcode{t}. +For accesses of diagonal elements \tcode{E[i, i]}, +\tcode{F} only uses the value \tcode{\exposid{real-if-needed}(E[i, i])} +if the name of \tcode{F} starts with \tcode{hermitian}. +For accesses \tcode{E[i, j]} outside the triangle specified by \tcode{t}, +\tcode{F} only uses the value +\begin{itemize} +\item +\tcode{\exposid{conj-if-needed}(E[j, i])} +if the name of \tcode{F} starts with \tcode{hermitian}, or +\item +\tcode{E[j, i]} +if the name of \tcode{F} starts with \tcode{symmetric}. +\end{itemize} + \pnum \mandates \begin{itemize} \item -If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +If \tcode{OutMat} 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 +If the function has an \tcode{InMat3} template parameter and +if \tcode{InMat3} 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}()} +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; +\item +\tcode{\exposid{possibly-multipliable}()} is \tcode{true}; and \item -\tcode{\exposid{compatible-static-extents}(0, 1)} -is \tcode{true}. +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads with an \tcode{E} parameter. \end{itemize} \pnum \expects \begin{itemize} \item -\tcode{\exposid{addable}(A, B, C)} is \tcode{true}, and +\tcode{\exposid{multipliable}(A, transposed(B), C)} +is \tcode{true}, +\item +\tcode{\exposid{multipliable}(B, transposed(A), C)} +is \tcode{true}, and +\begin{note} +This and the previous imply that \tcode{C} is square. +\end{note} \item -\tcode{A.extent(0)} equals \tcode{A.extent(1)}. +\tcode{\exposid{addable}(C, E, C)} +is \tcode{true} for those overloads with an \tcode{E} parameter. \end{itemize} \pnum \complexity -\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(0)}}. + +\pnum +\remarks +\tcode{C} may alias \tcode{E} for those overloads with an \tcode{E} parameter. \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); + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, OutMat C, Triangle t); template + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec, - InMat1 A, InMat2 B, InOutMat C, Triangle t); + InMat1 A, InMat2 B, OutMat 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$. +Computes $C = A B^T + B A^T$. \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); + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> + void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, OutMat C, Triangle t); template + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec, - InMat1 A, InMat2 B, InOutMat C, Triangle t); + InMat1 A, InMat2 B, OutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes $C = A B^H + B A^H$. +\end{itemdescr} + +\indexlibraryglobal{symmetric_matrix_rank_2k_update}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle> +void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t); +template +void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes $C = E + A B^T + B A^T$. +\end{itemdescr} + +\indexlibraryglobal{hermitian_matrix_rank_2k_update}% +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{possibly-packed-out-matrix}@ OutMat, + class Triangle> +void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t); +template +void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InMat3 E, + OutMat 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$. +Computes $C = E + A B^H + B A^H$. \end{itemdescr} \rSec3[linalg.algs.blas3.trsm]{Solve multiple triangular linear systems} @@ -15793,7 +16141,7 @@ \pnum \complexity -\bigoh{\tcode{A.extent(0)} \times \tcode{X.extent(1)} \times \tcode{X.extent(1)}}. +\bigoh{\tcode{A.extent(0)} \times \tcode{B.extent(1)} \times \tcode{B.extent(1)}}. \end{itemdescr} \pnum @@ -16007,7 +16355,7 @@ \pnum \complexity -\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. +\bigoh{\tcode{B.extent(0)} \times \tcode{A.extent(0)} \times \tcode{A.extent(1)}}. \end{itemdescr} \indexlibraryglobal{triangular_matrix_matrix_left_solve}% @@ -16206,6 +16554,11 @@ \tcode{T} is \defn{value-preserving} if all possible values of \tcode{U} can be represented with type \tcode{T}. +\pnum +If a program declares an explicit or partial specialization of +any of the templates specified in subclause \ref{simd}, +the program is ill-formed, no diagnostic required. + \rSec2[simd.expos]{Exposition-only types, variables, and concepts} \begin{codeblock} @@ -16214,19 +16567,18 @@ template constexpr @\exposidnc{simd-size-type} \exposidnc{simd-size-v} = \seebelownc@; // \expos +template + constexpr @\exposidnc{simd-size-type} \exposidnc{mask-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 + concept @\defexposconceptnc{explicitly-convertible-to}@ = // \expos + requires { + static_cast(declval()); + }; template using @\exposidnc{deduced-vec-t} = \seebelownc@; // \expos -template using @\exposidnc{make-compatible-simd-t} = \seebelownc@; // \expos - template concept @\defexposconceptnc{simd-vec-type}@ = // \expos @\libconcept{same_as}@> && @@ -16252,13 +16604,9 @@ concept @\defexposconceptnc{simd-complex}@ = // \expos @\exposconcept{simd-vec-type}@ && @\libconcept{same_as}@>>; -template +template concept @\defexposconceptnc{math-floating-point}@ = // \expos - (@\exposconceptnc{simd-floating-point}<\exposidnc{deduced-vec-t}@> || ...); - -template - requires @\exposconceptnc{math-floating-point}@ - using @\exposidnc{math-common-simd-t} = \seebelownc@; // \expos + @\exposconceptnc{simd-floating-point}<\exposidnc{deduced-vec-t}@>; template concept @\exposconceptnc{reduction-binary-operation} = \seebelownc@; // \expos @@ -16307,36 +16655,30 @@ \end{itemdescr} \begin{itemdecl} -template constexpr size_t @\exposid{mask-element-size}@ = @\seebelow@; +template + constexpr @\exposid{simd-size-type} \exposid{mask-size-v}@ = @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\tcode{\exposid{mask-element-size}>} has the value -\tcode{Bytes}. +\tcode{\exposid{mask-size-v}} denotes +the width of \tcode{basic_mask} +if the specialization \tcode{ba\-sic_mask} is enabled, or +\tcode{0} otherwise. \end{itemdescr} \begin{itemdecl} -template using @\exposid{deduced-vec-t}@ = @\seebelow@; +template constexpr size_t @\exposid{mask-element-size}@ = @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{x} denote an lvalue of type \tcode{const T}. - -\pnum -\tcode{\exposid{deduced-vec-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_vec}; otherwise - \item - \tcode{void}. -\end{itemize} +\tcode{\exposid{mask-element-size}>} has the value +\tcode{Bytes}. \end{itemdescr} \begin{itemdecl} -template using @\exposid{make-compatible-simd-t}@ = @\seebelow@; +template using @\exposid{deduced-vec-t}@ = @\seebelow@; \end{itemdecl} \begin{itemdescr} @@ -16344,55 +16686,7 @@ 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-vec-t}}, if that type is not \tcode{void}, - otherwise - \item - \tcode{vec}. -\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-vec-t}}, if \tcode{sizeof...(Ts)} equals $1$; - otherwise - \item - \tcode{common_type_t<\exposid{deduced-vec-t}, - \exposid{deduced-vec-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-vec-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} +\tcode{\exposid{deduced-vec-t}} is an alias for \tcode{decltype(x + x)}. \end{itemdescr} \begin{itemdecl} @@ -16447,26 +16741,26 @@ An implementation defines ABI tag types as necessary for the following aliases. \pnum -\tcode{\exposid{deduce-abi-t}} is defined if +\tcode{\exposid{deduce-abi-t}} names an ABI tag type if and only 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} +Otherwise, \tcode{\exposid{deduce-abi-t}} names an unspecified type. The \impldef{maximum width for \tcode{vec} and \tcode{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 +If \tcode{\exposid{deduce-abi-t}} names an ABI tag type, +the following is \tcode{true}: \begin{itemize} - \item - \tcode{\exposid{simd-size-v}>} equals - \tcode{N}, \item \tcode{basic_vec>} is - enabled\iref{simd.overview}, and - \item - \tcode{basic_mask, N>>} is enabled. +\item + \tcode{\exposid{simd-size-v}>} + equals \tcode{N}, and +\item + \tcode{basic_vec>} + is enabled\iref{simd.overview}. \end{itemize} \pnum @@ -16531,6 +16825,12 @@ const basic_vec& x, const typename basic_vec::mask_type& mask, BinaryOperation binary_op = {}, type_identity_t identity_element = @\seebelow@); + template> + constexpr T reduce(const T&, BinaryOperation = {}); + template> + constexpr T reduce(const T& x, @\libconcept{same_as}@ auto mask, BinaryOperation binary_op = {}, + type_identity_t identity_element = @\seebelow@); + template constexpr T reduce_min(const basic_vec&) noexcept; template @@ -16542,6 +16842,11 @@ constexpr T reduce_max(const basic_vec&, const typename basic_vec::mask_type&) noexcept; + template constexpr T reduce_min(const T&) noexcept; + template constexpr T reduce_min(const T&, @\libconcept{same_as}@ auto) noexcept; + template constexpr T reduce_max(const T&) noexcept; + template constexpr T reduce_max(const T&, @\libconcept{same_as}@ auto) noexcept; + // \ref{simd.loadstore}, load and store functions template requires ranges::@\libconcept{sized_range}@ @@ -16581,90 +16886,86 @@ flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void unchecked_store(const basic_vec& v, R&& r, flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void unchecked_store(const basic_vec& v, R&& r, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, iter_difference_t n, flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, iter_difference_t n, const typename basic_vec::mask_type& mask, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, S last, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, S last, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void partial_store(const basic_vec& v, R&& r, flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void partial_store(const basic_vec& v, R&& r, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void partial_store( const basic_vec& v, I first, iter_difference_t n, flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void partial_store( const basic_vec& v, I first, iter_difference_t n, const typename basic_vec::mask_type& mask, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, S last, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, S last, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); // \ref{simd.permute.static}, static permute - static constexpr @\exposid{simd-size-type}@ @\libmember{zero_element}{simd}@ = @\impdefx{value of \tcode{simd::zero_element}}@; - static constexpr @\exposid{simd-size-type}@ @\libmember{uninit_element}{simd}@ = @\impdefx{value of \tcode{simd::uninit_element}}@; + inline constexpr @\exposid{simd-size-type}@ @\libmember{zero_element}{simd}@ = @\impdefx{value of \tcode{simd::zero_element}}@; + inline constexpr @\exposid{simd-size-type}@ @\libmember{uninit_element}{simd}@ = @\impdefx{value of \tcode{simd::uninit_element}}@; template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-vec-type}@ V, class IdxMap> constexpr resize_t permute(const V& v, IdxMap&& idxmap); - template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-mask-type}@ M, class IdxMap> - constexpr resize_t permute(const M& v, IdxMap&& idxmap); + template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-mask-type}@ V, class IdxMap> + constexpr resize_t permute(const V& v, IdxMap&& idxmap); // \ref{simd.permute.dynamic}, dynamic permute template<@\exposconcept{simd-vec-type}@ V, @\exposconcept{simd-integral}@ I> constexpr resize_t permute(const V& v, const I& indices); - template<@\exposconcept{simd-mask-type}@ M, @\exposconcept{simd-integral}@ I> - constexpr resize_t permute(const M& v, const I& indices); + template<@\exposconcept{simd-mask-type}@ V, @\exposconcept{simd-integral}@ I> + constexpr resize_t permute(const V& v, const I& indices); // \ref{simd.permute.mask}, mask permute template<@\exposconcept{simd-vec-type}@ V> constexpr V compress(const V& v, const typename V::mask_type& selector); - template<@\exposconcept{simd-mask-type}@ M> - constexpr M compress(const M& v, const type_identity_t& selector); + template<@\exposconcept{simd-mask-type}@ V> + constexpr V compress(const V& v, const type_identity_t& selector); template<@\exposconcept{simd-vec-type}@ V> constexpr V compress(const V& v, const typename V::mask_type& selector, const typename V::value_type& fill_value); - template<@\exposconcept{simd-mask-type}@ M> - constexpr M compress(const M& v, const type_identity_t& selector, - const typename M::value_type& fill_value); + template<@\exposconcept{simd-mask-type}@ V> + constexpr V compress(const V& v, const type_identity_t& selector, + const typename V::value_type& fill_value); template<@\exposconcept{simd-vec-type}@ V> constexpr V expand(const V& v, const typename V::mask_type& selector, const V& original = {}); - template<@\exposconcept{simd-mask-type}@ M> - constexpr M expand(const M& v, const type_identity_t& selector, - const M& original = {}); + template<@\exposconcept{simd-mask-type}@ V> + constexpr V expand(const V& v, const type_identity_t& selector, + const V& original = {}); // \ref{simd.permute.memory}, memory permute template @@ -16713,12 +17014,11 @@ constexpr auto chunk(const basic_mask& x) noexcept; template - constexpr basic_vec::size() + ...)>> - cat(const basic_vec&...) noexcept; + constexpr resize_t<(basic_vec::size() + ...), + basic_vec> cat(const basic_vec&...) noexcept; template - constexpr basic_mask, - (basic_mask::size() + ...)>> - cat(const basic_mask&...) noexcept; + constexpr resize_t<(basic_mask::size() + ...), + basic_mask> cat(const basic_mask&...) noexcept; // \ref{simd.alg}, algorithms template @@ -16746,8 +17046,12 @@ template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ acos(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ asin(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-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-vec-t}@ atan2(const V& y, const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ atan2(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ atan2(const V& x, const @\exposid{deduced-vec-t}@& y); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ cos(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ sin(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ tan(const V& x); @@ -16785,12 +17089,35 @@ constexpr basic_vec abs(const basic_vec& j); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ abs(const V& j); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-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-vec-t}@ hypot(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const V& x, const V& y, const V& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const @\exposid{deduced-vec-t}@& x, const V& y, const V& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const V& x, const @\exposid{deduced-vec-t}@& y, const V& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const V& x, const V& y, const @\exposid{deduced-vec-t}@& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const @\exposid{deduced-vec-t}@& x, const @\exposid{deduced-vec-t}@& y, + @\itcorr@ const V& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const @\exposid{deduced-vec-t}@& x, const V& y, + @\itcorr@ const @\exposid{deduced-vec-t}@& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const V& x, const @\exposid{deduced-vec-t}@& y, + @\itcorr@ const @\exposid{deduced-vec-t}@& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ pow(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ pow(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ pow(const V& x, const @\exposid{deduced-vec-t}@& y); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ sqrt(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ erf(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ erfc(const V& x); @@ -16812,28 +17139,92 @@ constexpr rebind_t> llround(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-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 @\exposid{deduced-vec-t}@ fmod(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmod(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmod(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ remainder(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ remainder(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ remainder(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + remquo(const V& x, const V& y, rebind_t>* quo); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + remquo(const @\exposid{deduced-vec-t}@& x, const V& y, rebind_t>* quo); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + remquo(const V& x, const @\exposid{deduced-vec-t}@& y, rebind_t>* quo); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ copysign(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ copysign(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ copysign(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ nextafter(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ nextafter(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ nextafter(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fdim(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fdim(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fdim(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmax(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmax(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmax(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmin(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmin(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmin(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fma(const V& x, const V& y, const V& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fma(const @\exposid{deduced-vec-t}@& x, const V& y, const V& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fma(const V& x, const @\exposid{deduced-vec-t}@& y, const V& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fma(const V& x, const V& y, const @\exposid{deduced-vec-t}@& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fma(const @\exposid{deduced-vec-t}@& x, const @\exposid{deduced-vec-t}@& y, + @\itcorr@ const V& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fma(const @\exposid{deduced-vec-t}@& x, const V& y, + @\itcorr@ const @\exposid{deduced-vec-t}@& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fma(const V& x, const @\exposid{deduced-vec-t}@& y, + @\itcorr@ const @\exposid{deduced-vec-t}@& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + lerp(const V& a, const V& b, const V& t) noexcept; + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ lerp(const @\exposid{deduced-vec-t}@& x, const V& y, const V& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ lerp(const V& x, const @\exposid{deduced-vec-t}@& y, const V& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ lerp(const V& x, const V& y, const @\exposid{deduced-vec-t}@& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ lerp(const @\exposid{deduced-vec-t}@& x, const @\exposid{deduced-vec-t}@& y, + @\itcorr@ const V& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ lerp(const @\exposid{deduced-vec-t}@& x, const V& y, + @\itcorr@ const @\exposid{deduced-vec-t}@& z); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ lerp(const V& x, const @\exposid{deduced-vec-t}@& y, + @\itcorr@ const @\exposid{deduced-vec-t}@& z); template<@\exposconcept{math-floating-point}@ V> constexpr rebind_t> fpclassify(const V& x); template<@\exposconcept{math-floating-point}@ V> @@ -16846,50 +17237,133 @@ constexpr typename @\exposid{deduced-vec-t}@::mask_type isnormal(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr typename @\exposid{deduced-vec-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> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isgreater(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isgreater(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isgreater(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isgreaterequal(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isgreaterequal(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isgreaterequal(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isless(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isless(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isless(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessequal(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessequal(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessequal(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessgreater(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessgreater(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessgreater(const V& x, const @\exposid{deduced-vec-t}@& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isunordered(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isunordered(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isunordered(const V& x, const @\exposid{deduced-vec-t}@& y); template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ assoc_laguerre(const rebind_t>& n, - const rebind_t>& m, const V& x); + @\itcorr@ const rebind_t>& m, const V& x); template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-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); + @\itcorr@ const rebind_t>& m, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ beta(const V& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ beta(const @\exposid{deduced-vec-t}@& x, const V& y); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ beta(const V& x, const @\exposid{deduced-vec-t}@& y); template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ comp_ellint_1(const V& k); template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-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-vec-t}@ comp_ellint_3(const V& k, const V& nu); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ comp_ellint_3(const @\exposid{deduced-vec-t}@& k, const V& nu); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ comp_ellint_3(const V& k, const @\exposid{deduced-vec-t}@& nu); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_i(const V& nu, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_i(const @\exposid{deduced-vec-t}@& nu, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_i(const V& nu, const @\exposid{deduced-vec-t}@& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_j(const V& nu, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_j(const @\exposid{deduced-vec-t}@& nu, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_j(const V& nu, const @\exposid{deduced-vec-t}@& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_k(const V& nu, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_k(const @\exposid{deduced-vec-t}@& nu, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_k(const V& nu, const @\exposid{deduced-vec-t}@& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_neumann(const V& nu, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_neumann(const @\exposid{deduced-vec-t}@& nu, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_neumann(const V& nu, const @\exposid{deduced-vec-t}@& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_1(const V& k, const V& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_1(const @\exposid{deduced-vec-t}@& k, const V& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_1(const V& k, const @\exposid{deduced-vec-t}@& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_2(const V& k, const V& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_2(const @\exposid{deduced-vec-t}@& k, const V& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_2(const V& k, const @\exposid{deduced-vec-t}@& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const V& k, const V& nu, const V& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const @\exposid{deduced-vec-t}@& k, const V& nu, const V& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const V& k, const @\exposid{deduced-vec-t}@& nu, const V& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const V& k, const V& nu, const @\exposid{deduced-vec-t}@& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const @\exposid{deduced-vec-t}@& k, const @\exposid{deduced-vec-t}@& nu, + @\itcorr@ const V& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const @\exposid{deduced-vec-t}@& k, const V& nu, + @\itcorr@ const @\exposid{deduced-vec-t}@& phi); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const V& k, const @\exposid{deduced-vec-t}@& nu, + @\itcorr@ const @\exposid{deduced-vec-t}@& phi); template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ expint(const V& x); template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ hermite(const rebind_t>& n, const V& x); @@ -16911,7 +17385,7 @@ // \ref{simd.bit}, bit manipulation template<@\exposconcept{simd-vec-type}@ V> constexpr V byteswap(const V& v) noexcept; - template<@\exposconcept{simd-vec-type}@ V> constexpr V bit_ceil(const V& v) noexcept; + template<@\exposconcept{simd-vec-type}@ V> constexpr V bit_ceil(const V& v); template<@\exposconcept{simd-vec-type}@ V> constexpr V bit_floor(const V& v) noexcept; template<@\exposconcept{simd-vec-type}@ V> @@ -16988,9 +17462,9 @@ template<@\exposconcept{simd-complex}@ V> constexpr V pow(const V& x, const V& y); // \ref{simd.mask.class}, class template \tcode{basic_mask} - template>> class basic_mask; + template class basic_mask; template>> - using @\libmember{mask}{simd}@ = basic_mask>; + using @\libmember{mask}{simd}@ = vec::mask_type; // \ref{simd.mask.reductions}, reductions template @@ -17148,14 +17622,8 @@ \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_mask} and \tcode{U} is - \tcode{bool}, or - \item - \tcode{T} is a specialization of \tcode{basic_vec} and \tcode{U} is a - vectorizable type. -\end{itemize} +\tcode{T} is a specialization of \tcode{basic_vec} and +\tcode{U} is a vectorizable type. \pnum If \tcode{value} is present, the type \tcode{alignment} is a @@ -17167,10 +17635,6 @@ (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} \indexlibrarymember{rebind}{simd} @@ -17184,8 +17648,7 @@ \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}. +\item \tcode{\exposid{deduce-abi-t}} names an ABI tag type. \end{itemize} \pnum @@ -17210,34 +17673,33 @@ \begin{itemdescr} \pnum -Let \tcode{T} denote +Let \tcode{Abi1} denote an ABI tag \begin{itemize} \item - \tcode{typename V::value_type} if \tcode{V} is a specialization of - \tcode{basic_vec}, + such that \tcode{\exposid{simd-size-v}} + equals \tcode{N} if \tcode{V} is a specialization of \tcode{basic_vec}, \item - otherwise \tcode{\exposid{integer-from}<\exposid{mask-element-size}>} if - \tcode{V} is a specialization of \tcode{basic_mask}. + otherwise such that + \tcode{\exposid{mask-size-v}<\exposid{mask-element-size}, Abi1>} + equals \tcode{N} if \tcode{V} is a specialization of \tcode{basic_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}. +\item + \tcode{V} is a data-parallel type, and +\item + there exists at least one ABI tag + that satisfies the above constraints for \tcode{Abi1}. \end{itemize} \pnum -If \tcode V is a specialization of \tcode{basic_vec}, let \tcode{Abi1} denote an -ABI tag such that \tcode{basic_vec::\brk{}size()} equals \tcode{N}. -If \tcode V is a specialization of \tcode{basic_mask}, let \tcode{Abi1} -denote an ABI tag such that \tcode{basic_mask::size()} equals \tcode{N}. - -\pnum -Where present, the member typedef \tcode{type} names \tcode{basic_vec} -if \tcode V is a specialization of \tcode{basic_vec} or -\tcode{basic_mask} if \tcode V is a specialization of -\tcode{basic_mask}. +Where present, the member typedef \tcode{type} names +\tcode{basic_vec} +if \tcode{V} is a specialization of \tcode{basic_vec}, or +\tcode{basic_mask<\exposid{mask-element-size}, Abi1>} +if \tcode{V} is a specialization of \tcode{basic_mask}. \end{itemdescr} \rSec2[simd.flags]{Load and store flags} @@ -17267,7 +17729,7 @@ \rSec3[simd.flags.oper]{\tcode{flags} operators} -\indexlibrarymember{operator|}{simd::flags} +\indexlibrarymember{operator"|}{simd::flags} \begin{itemdecl} template friend consteval auto operator|(flags a, flags b); @@ -17555,6 +18017,7 @@ \begin{codeblock} namespace std::simd { template class basic_vec { + using @\exposid{real-type}@ = @\seebelow@; // \expos public: using @\libmember{value_type}{basic_vec}@ = T; using @\libmember{mask_type}{basic_vec}@ = basic_mask; @@ -17574,7 +18037,7 @@ // \ref{simd.ctor}, \tcode{basic_vec} constructors template - constexpr explicit(@\seebelow@) basic_vec(U&& value) noexcept; + constexpr basic_vec(U&& value) noexcept; template constexpr explicit(@\seebelow@) basic_vec(const basic_vec&) noexcept; template @@ -17583,8 +18046,7 @@ constexpr basic_vec(R&& range, flags = {}); template constexpr basic_vec(R&& range, const mask_type& mask, flags = {}); - template<@\exposconcept{simd-floating-point}@ V> - constexpr explicit(@\seebelow@) basic_vec(const V& reals, const V& imags = {}) noexcept; + constexpr basic_vec(const @\exposid{real-type}@& reals, const @\exposid{real-type}@& imags = {}) noexcept; // \ref{simd.subscr}, \tcode{basic_vec} subscript operators constexpr value_type operator[](@\exposid{simd-size-type}@) const; @@ -17592,12 +18054,10 @@ constexpr resize_t operator[](const I& indices) const; // \ref{simd.complex.access}, \tcode{basic_vec} complex 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; + constexpr @\exposid{real-type}@ real() const noexcept; + constexpr @\exposid{real-type}@ imag() const noexcept; + constexpr void real(const @\exposid{real-type}@& v) noexcept; + constexpr void imag(const @\exposid{real-type}@& v) noexcept; // \ref{simd.unary}, \tcode{basic_vec} unary operators constexpr basic_vec& operator++() noexcept; @@ -17652,6 +18112,9 @@ template basic_vec(R&& r, Ts...) -> @\seebelow@; + + template + basic_vec(basic_mask) -> @\seebelow@; } \end{codeblock} @@ -17661,7 +18124,8 @@ \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{N} in the range \crange{1}{64}, + such that \tcode{Abi} names the ABI tag denoted by \tcode{\exposid{deduce-abi-t}}, \item otherwise, disabled, if \tcode{T} is not a vectorizable type, @@ -17676,14 +18140,26 @@ In addition only the \tcode{value_type}, \tcode{abi_type}, and \tcode{mask_type} members are present. -If \tcode{basic_vec} is enabled, then \tcode{basic_vec} 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 +If \tcode{basic_vec} is enabled, then +\begin{itemize} +\item + \tcode{basic_vec} is trivially copyable, +\item + default-initialization of an object of such a type + default-initializes all elements, +\item + value-initialization value-initializes all elements\iref{dcl.init.general}, +\item + \tcode{basic_vec::mask_type} is an alias + for an enabled specialization of \tcode{basic_mask}, and +\item + \tcode{basic_vec::size()} is equal to + \tcode{basic_vec::mask_type::size()}. +\end{itemize} + +\pnum +\recommended +Implementations should support implicit conversions between specializations of \tcode{basic_vec} and appropriate \impldef{conversions of \tcode{basic_vec} from/to implementation-specific vector types} types. \begin{note} @@ -17691,11 +18167,17 @@ implementation. \end{note} +\pnum +If \tcode{T} is a specialization of \tcode{complex}, +\exposid{real-type} denotes the same type as +\tcode{rebind_t>}, +otherwise an unspecified non-array object type. + \rSec3[simd.ctor]{Constructors} \indexlibraryctor{basic_vec} \begin{itemdecl} -template constexpr explicit(@\seebelow@) basic_vec(U&& value) noexcept; +template constexpr basic_vec(U&& value) noexcept; \end{itemdecl} \begin{itemdescr} @@ -17704,29 +18186,25 @@ \pnum \constraints -\tcode{value_type} satisfies \tcode{\libconcept{constructible_from}}. +\begin{itemize} +\item +\tcode{U} satisfies \tcode{\libconcept{convertible_to}} and +\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_cvref_t} is an arithmetic type, and +\tcode{From::value} is representable by \tcode{value_type}. +\end{itemize} \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} \indexlibraryctor{basic_vec} @@ -17738,7 +18216,10 @@ \begin{itemdescr} \pnum \constraints -\tcode{\exposid{simd-size-v} == size()} is \tcode{true}. +\begin{itemize} +\item \tcode{\exposid{simd-size-v} == size()} is \tcode{true}, and +\item \tcode{U} satisfies \tcode{\exposconcept{explicitly-convertible-to}}. +\end{itemize} \pnum \effects @@ -17810,20 +18291,17 @@ \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()}. +\item \tcode{ranges::size(r)} is a constant expression, +\item \tcode{ranges::size(r)} is equal to \tcode{size()}, and +\item \tcode{ranges::range_value_t} is a vectorizable type and + satisfies \tcode{\exposconcept{explicitly-convertible-to}}. \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} +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. \pnum \expects @@ -17862,37 +18340,42 @@ \pnum \remarks -The deduced type is equivalent to \tcode{vec, -ranges::size(r)>}. +The deduced type is equivalent to +\begin{codeblock} +vec, static_cast<@\exposid{simd-size-type}@>(ranges::size(r))> +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template + basic_vec(basic_mask k) -> @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{basic_mask} is an enabled specialization of \tcode{basic_mask} and +\tcode{decltype(+k)} is a valid type. + +\pnum +\remarks +The deduced type is equivalent to \tcode{decltype(+k)}. \end{itemdescr} \indexlibraryctor{basic_vec} \begin{itemdecl} -template<@\exposconcept{simd-floating-point}@ V> - constexpr explicit(@\seebelow@) - basic_vec(const V& reals, const V& imags = {}) noexcept; +constexpr basic_vec(const @\exposid{real-type}@& reals, const @\exposid{real-type}@& 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} +\tcode{\exposconcept{simd-complex}} is modeled. \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]{Subscript operator} @@ -17933,8 +18416,8 @@ \indexlibrarymember{real}{basic_vec} \indexlibrarymember{imag}{basic_vec} \begin{itemdecl} -constexpr auto real() const noexcept; -constexpr auto imag() const noexcept; +constexpr @\exposid{real-type}@ real() const noexcept; +constexpr @\exposid{real-type}@ imag() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -17944,9 +18427,9 @@ \pnum \returns -An object of type \tcode{rebind_t} +An object of type \exposid{real-type} where the $i^\text{th}$ element is initialized to the result of -\tcode{\placeholder{cmplx-func}(operator[]($i$))} for all $i$ in the range +\tcode{\placeholder{cmplx-func}(\brk{}operator[]($i$))} for all $i$ in the range \range{0}{size()}, where \tcode{\placeholder{cmplx-func}} is the corresponding function from \libheader{complex}. \end{itemdescr} @@ -17954,24 +18437,14 @@ \indexlibrarymember{real}{basic_vec} \indexlibrarymember{imag}{basic_vec} \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; +constexpr void real(const @\exposid{real-type}@& v) noexcept; +constexpr void imag(const @\exposid{real-type}@& 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} +\tcode{\exposconcept{simd-complex}} is modeled. \pnum \effects @@ -18062,7 +18535,7 @@ A copy of \tcode{*this} before decrementing. \end{itemdescr} -\indexlibrarymember{operator!}{basic_vec} +\indexlibrarymember{operator"!}{basic_vec} \begin{itemdecl} constexpr mask_type operator!() const noexcept; \end{itemdecl} @@ -18078,7 +18551,7 @@ \tcode{!operator[]($i$)} for all $i$ in the range of \range{0}{size()}. \end{itemdescr} -\indexlibrarymember{operator~}{basic_vec} +\indexlibrarymember{operator\~{}}{basic_vec} \begin{itemdecl} constexpr basic_vec operator~() const noexcept; \end{itemdecl} @@ -18135,7 +18608,7 @@ \indexlibrarymember{operator/}{basic_vec} \indexlibrarymember{operator\%}{basic_vec} \indexlibrarymember{operator\&}{basic_vec} -\indexlibrarymember{operator|}{basic_vec} +\indexlibrarymember{operator"|}{basic_vec} \indexlibrarymember{operator\caret}{basic_vec} \indexlibrarymember{operator<<}{basic_vec} \indexlibrarymember{operator>>}{basic_vec} @@ -18199,7 +18672,7 @@ \indexlibrarymember{operator/=}{basic_vec} \indexlibrarymember{operator\%=}{basic_vec} \indexlibrarymember{operator\&=}{basic_vec} -\indexlibrarymember{operator|=}{basic_vec} +\indexlibrarymember{operator"|=}{basic_vec} \indexlibrarymember{operator\caret=}{basic_vec} \indexlibrarymember{operator<<=}{basic_vec} \indexlibrarymember{operator>>=}{basic_vec} @@ -18259,7 +18732,7 @@ \rSec3[simd.comparison]{Comparison operators} \indexlibrarymember{operator==}{basic_vec} -\indexlibrarymember{operator!=}{basic_vec} +\indexlibrarymember{operator"!=}{basic_vec} \indexlibrarymember{operator>=}{basic_vec} \indexlibrarymember{operator<=}{basic_vec} \indexlibrarymember{operator>}{basic_vec} @@ -18389,6 +18862,50 @@ \end{itemize} \end{itemdescr} +\begin{itemdecl} +template> + constexpr T reduce(const T& x, BinaryOperation binary_op = {}); +template> + constexpr T reduce(const T& x, @\libconcept{same_as}@ auto mask, BinaryOperation binary_op = {}, + type_identity_t identity_element = @\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{mask} be \tcode{true} for the overload with no \tcode{mask} parameter. + +\pnum +\constraints +\begin{itemize} +\item \tcode{T} is vectorizable. +\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 +\returns +If \tcode{mask} is \tcode{false}, returns \tcode{identity_element}. +Otherwise, returns \tcode{x}. + +\pnum +\throws +Nothing. + +\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} + \indexlibrarymember{reduce_min}{simd} \begin{itemdecl} template constexpr T reduce_min(const basic_vec& x) noexcept; @@ -18463,6 +18980,32 @@ \tcode{mask}. \end{itemdescr} +\begin{itemdecl} +template constexpr T reduce_min(const T& x) noexcept; +template constexpr T reduce_min(const T& x, @\libconcept{same_as}@ auto mask) noexcept; +template constexpr T reduce_max(const T& x) noexcept; +template constexpr T reduce_max(const T& x, @\libconcept{same_as}@ auto mask) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{mask} be \tcode{true} for the overloads with no \tcode{mask} parameter. + +\pnum +\constraints +\begin{itemize} +\item \tcode{T} is vectorizable. +\item \tcode{T} models \tcode{totally_ordered}. +\end{itemize} + +\pnum +\returns +If \tcode{mask} is \tcode{false}, returns \tcode{numeric_limits::max()} for +\tcode{reduce_min} and \tcode{numeric_limits::lowest()} for +\tcode{reduce_max}. +Otherwise, returns \tcode{x}. +\end{itemdescr} + \rSec3[simd.loadstore]{Load and store functions} \indexlibrarymember{unchecked_load}{simd} @@ -18559,14 +19102,17 @@ \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. + parameter; + \item + \tcode{T} be \tcode{typename V::value_type}. \end{itemize} \pnum \mandates \begin{itemize} \item - \tcode{ranges::range_value_t} is a vectorizable type, + \tcode{ranges::range_value_t} is a vectorizable type and + satisfies \tcode{\exposconcept{explicitly-convertible-to}}, \item \tcode{\libconcept{same_as}, V>} is \tcode{true}, \item @@ -18598,11 +19144,12 @@ \end{itemize} \pnum -\effects -Initializes the $i^\text{th}$ element with\\ +\returns +A \tcode{basic_vec} object whose $i^\text{th}$ element is initialized 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()}. +\range{0}{V::size()}, +where \tcode{T} is \tcode{V::value_type}. \pnum \remarks @@ -18613,28 +19160,27 @@ \indexlibrarymember{unchecked_store}{simd} \begin{itemdecl} template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void unchecked_store(const basic_vec& v, R&& r, flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void unchecked_store(const basic_vec& v, R&& r, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, iter_difference_t n, flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, iter_difference_t n, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, S last, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, S last, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); \end{itemdecl} \begin{itemdescr} @@ -18679,28 +19225,27 @@ \indexlibrarymember{partial_store}{simd} \begin{itemdecl} template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void partial_store(const basic_vec& v, R&& r, flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void partial_store(const basic_vec& v, R&& r, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, iter_difference_t n, flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, iter_difference_t n, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, S last, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, S last, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); \end{itemdecl} \begin{itemdescr} @@ -18719,6 +19264,17 @@ parameter. \end{itemize} +\pnum +\constraints +\begin{itemize} + \item + \tcode{ranges::iterator_t} models + \tcode{\libconcept{indirectly_writable}>}, and + \item + \tcode{T} satisfies + \tcode{\exposconcept{explicitly-convertible-to}>}. +\end{itemize} + \pnum \mandates \begin{itemize} @@ -18754,7 +19310,7 @@ \effects For all $i$ in the range of \range{0}{basic_vec::size()}, if \tcode{mask[$i$] \&\& $i$ < ranges::\brk{}size(r)} is \tcode{true}, evaluates -\tcode{ranges::data(r)[$i$] = v[$i$]}. +\tcode{ranges::data(r)[$i$] = static_cast>(v[\brk{}$i$])}. \end{itemdescr} \rSec3[simd.permute.static]{Static permute} @@ -18763,8 +19319,8 @@ \begin{itemdecl} template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-vec-type}@ V, class IdxMap> constexpr resize_t permute(const V& v, IdxMap&& idxmap); -template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-mask-type}@ M, class IdxMap> - constexpr resize_t permute(const M& v, IdxMap&& idxmap); +template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-mask-type}@ V, class IdxMap> + constexpr resize_t permute(const V& v, IdxMap&& idxmap); \end{itemdecl} \begin{itemdescr} @@ -18822,8 +19378,8 @@ \begin{itemdecl} template<@\exposconcept{simd-vec-type}@ V, @\exposconcept{simd-integral}@ I> constexpr resize_t permute(const V& v, const I& indices); -template<@\exposconcept{simd-mask-type}@ M, @\exposconcept{simd-integral}@ I> - constexpr resize_t permute(const M& v, const I& indices); +template<@\exposconcept{simd-mask-type}@ V, @\exposconcept{simd-integral}@ I> + constexpr resize_t permute(const V& v, const I& indices); \end{itemdecl} \begin{itemdescr} @@ -18844,8 +19400,8 @@ \begin{itemdecl} template<@\exposconcept{simd-vec-type}@ V> constexpr V compress(const V& v, const typename V::mask_type& selector); -template<@\exposconcept{simd-mask-type}@ M> - constexpr M compress(const M& v, const type_identity_t& selector); +template<@\exposconcept{simd-mask-type}@ V> + constexpr V compress(const V& v, const type_identity_t& selector); \end{itemdecl} \begin{itemdescr} @@ -18877,9 +19433,9 @@ template<@\exposconcept{simd-vec-type}@ V> constexpr V compress(const V& v, const typename V::mask_type& selector, const typename V::value_type& fill_value); -template<@\exposconcept{simd-mask-type}@ M> - constexpr M compress(const M& v, const type_identity_t& selector, - const typename M::value_type& fill_value); +template<@\exposconcept{simd-mask-type}@ V> + constexpr V compress(const V& v, const type_identity_t& selector, + const typename V::value_type& fill_value); \end{itemdecl} \begin{itemdescr} @@ -18906,8 +19462,8 @@ \begin{itemdecl} template<@\exposconcept{simd-vec-type}@ V> constexpr V expand(const V& v, const typename V::mask_type& selector, const V& original = {}); -template<@\exposconcept{simd-mask-type}@ M> - constexpr M expand(const M& v, const type_identity_t& selector, const M& original = {}); +template<@\exposconcept{simd-mask-type}@ V> + constexpr V expand(const V& v, const type_identity_t& selector, const V& original = {}); \end{itemdecl} \begin{itemdescr} @@ -18988,6 +19544,11 @@ \tcode{T} be \tcode{typename V::value_type}. \end{itemize} +\pnum +\constraints +\tcode{ranges::range_value_t} is a vectorizable type and satisfies +\tcode{\exposconceptx{explicitly-convert\-ible-to}{explicitly-convertible-to}}. + \pnum \mandates \begin{itemize} @@ -19079,7 +19640,16 @@ \pnum \constraints -\tcode{V::size() == I::size()} is \tcode{true}. +\begin{itemize} +\item +\tcode{V::size() == I::size()} is \tcode{true}, +\item +\tcode{ranges::iterator_t} models +\tcode{\libconcept{indirectly_writable}>}, and +\item +\tcode{typename V::value_type} satisfies +\tcode{\exposconcept{explicitly-convertible-to}>}. +\end{itemize} \pnum \mandates @@ -19111,7 +19681,7 @@ \effects For all $i$ in the range \range{0}{I::size()}, if \tcode{mask[$i$] \&\& (indices[$i$] < ranges::size(out))} is \tcode{true}, evaluates -\tcode{ranges::data(out)[indices[$i$]] = v[$i$]}. +\tcode{ranges::data(out)[indices[$i$]] = static_cast>(v[\brk{}$i$])}. \end{itemdescr} \rSec3[simd.creation]{Creation} @@ -19197,28 +19767,14 @@ \indexlibrarymember{cat}{simd} \begin{itemdecl} template - constexpr vec::size() + ...)> - cat(const basic_vec&... xs) noexcept; + constexpr resize_t<(basic_vec::size() + ...), + basic_vec> cat(const basic_vec&... xs) noexcept; template - constexpr basic_mask, - (basic_mask::size() + ...)>> - cat(const basic_mask&... xs) noexcept; + constexpr resize_t<(basic_mask::size() + ...), + basic_mask> cat(const basic_mask&... xs) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\begin{itemize} - \item - For the first overload \tcode{vec::size() + ...)>} - is enabled. - \item - For the second overload - \tcode{basic_mask, - (basic_mask::size() + ...)>>} is enabled. -\end{itemize} - \pnum \returns A data-parallel object initialized with the concatenated values in the @@ -19337,10 +19893,6 @@ \rSec3[simd.math]{Mathematical functions} \indexlibrarymember{ilogb}{simd} -\indexlibrarymember{ldexp}{simd} -\indexlibrarymember{scalbn}{simd} -\indexlibrarymember{scalbln}{simd} -\indexlibrarymember{abs}{simd} \indexlibrarymember{abs}{simd} \indexlibrarymember{fabs}{simd} \indexlibrarymember{ceil}{simd} @@ -19376,15 +19928,6 @@ \begin{itemdecl} template<@\exposconcept{math-floating-point}@ V> constexpr rebind_t> ilogb(const V& x); -template<@\exposconcept{math-floating-point}@ V> - constexpr @\exposid{deduced-vec-t}@ ldexp(const V& x, const rebind_t>& exp); -template<@\exposconcept{math-floating-point}@ V> - constexpr @\exposid{deduced-vec-t}@ scalbn(const V& x, const rebind_t>& n); -template<@\exposconcept{math-floating-point}@ V> - constexpr @\exposid{deduced-vec-t}@ - scalbln(const V& x, const rebind_t>& n); -template<@\libconcept{signed_integral}@ T, class Abi> - constexpr basic_vec abs(const basic_vec& j); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ abs(const V& j); template<@\exposconcept{math-floating-point}@ V> @@ -19407,24 +19950,67 @@ 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-vec-t}@ fmod(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmod(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmod(const V& x, const @\exposid{deduced-vec-t}@& y); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-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 @\exposid{deduced-vec-t}@ remainder(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ remainder(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ remainder(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ copysign(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ copysign(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ copysign(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ nextafter(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ nextafter(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ nextafter(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fdim(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fdim(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fdim(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmax(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmax(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmax(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmin(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmin(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fmin(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fma(const V& x, const V& y, const V& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fma(const @\exposid{deduced-vec-t}@& x, const V& y, const V& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fma(const V& x, const @\exposid{deduced-vec-t}@& y, const V& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ fma(const V& x, const V& y, const @\exposid{deduced-vec-t}@& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + fma(const @\exposid{deduced-vec-t}@& x, const @\exposid{deduced-vec-t}@& y, const V& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + fma(const @\exposid{deduced-vec-t}@& x, const V& y, const @\exposid{deduced-vec-t}@& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + fma(const V& x, const @\exposid{deduced-vec-t}@& y, const @\exposid{deduced-vec-t}@& z); template<@\exposconcept{math-floating-point}@ V> constexpr rebind_t> fpclassify(const V& x); template<@\exposconcept{math-floating-point}@ V> @@ -19437,19 +20023,57 @@ constexpr typename @\exposid{deduced-vec-t}@::mask_type isnormal(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr typename @\exposid{deduced-vec-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> + constexpr typename @\exposid{deduced-vec-t}@::mask_type isgreater(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type isgreater(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type isgreater(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isgreaterequal(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isgreaterequal(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isgreaterequal(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isless(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isless(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isless(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessequal(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessequal(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessequal(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessgreater(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessgreater(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + islessgreater(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isunordered(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isunordered(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-vec-t}@::mask_type + isunordered(const V& x, const @\exposid{deduced-vec-t}@& y); \end{itemdecl} \begin{itemdescr} @@ -19459,9 +20083,9 @@ Let \tcode{\placeholder{math-func-vec}} denote: \begin{codeblock} template -Ret @\placeholder{math-func-vec}@(Args... args) { +Ret @\placeholder{math-func-vec}@(const Args&... args) { return Ret([&](@\exposid{simd-size-type}@ i) { - return @\placeholder{math-func}@(@\exposid{make-compatible-simd-t}@(args)[i]...); + return @\placeholder{math-func}@(@\exposid{deduced-vec-t}@(args)[i]...); }); } \end{codeblock} @@ -19469,7 +20093,7 @@ \pnum \returns A value \tcode{ret} of type \tcode{Ret}, that is element-wise equal to the -result of calling \tcode{\placeholder{math-func-vec}} with the arguments of the above +result of calling \tcode{\placeholder{math-func-vec}} with the parameters of the above functions. If in an invocation of a scalar overload of \tcode{\placeholder{math-func}} for index \tcode{i} in \tcode{\placeholder{math-func-vec}} a domain, pole, or range error would @@ -19480,6 +20104,64 @@ It is unspecified whether \tcode{errno}\iref{errno} is accessed. \end{itemdescr} +\indexlibrarymember{ldexp}{simd} +\indexlibrarymember{scalbn}{simd} +\indexlibrarymember{scalbln}{simd} +\begin{itemdecl} +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ ldexp(const V& x, const rebind_t>& exp); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ scalbn(const V& x, const rebind_t>& n); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + scalbln(const V& x, const rebind_t>& n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Ret} be \tcode{\exposid{deduced-vec-t}}. +Let \tcode{\placeholder{math-func}} denote the name of the function template. +Let \tcode{\placeholder{math-func-vec}} denote: +\begin{codeblock} +Ret @\placeholder{math-func-vec}@(const @\exposid{deduced-vec-t}@& a, const auto& b) { + return Ret([&](@\exposid{simd-size-type}@ i) { + return @\placeholder{math-func}@(a[i], b[i]); + }); +} +\end{codeblock} + +\pnum +\returns +A value \tcode{ret} of type \tcode{Ret}, that is element-wise equal to the +result of calling \tcode{\placeholder{math-func-vec}} with the parameters of the above +functions. +If in an invocation of a scalar overload of \tcode{\placeholder{math-func}} for index +\tcode{i} in \tcode{\placeholder{math-func-vec}} 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} + +\indexlibrarymember{abs}{simd} +\begin{itemdecl} +template<@\libconcept{signed_integral}@ T, class Abi> + constexpr basic_vec abs(const basic_vec& j); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{all_of(j >= -numeric_limits::max())} is \tcode{true}. + +\pnum +\returns +An object where the $i^{\textrm{th}}$ element is initialized to the result of +\tcode{std::abs(j[$i$])} for all $i$ in the range \range{0}{j.size()}. + +\end{itemdescr} + \indexlibrarymember{acos}{simd} \indexlibrarymember{asin}{simd} \indexlibrarymember{atan}{simd} @@ -19511,8 +20193,6 @@ \indexlibrarymember{lgamma}{simd} \indexlibrarymember{tgamma}{simd} \indexlibrarymember{lerp}{simd} -\indexlibrarymember{assoc_laguerre}{simd} -\indexlibrarymember{assoc_legendre}{simd} \indexlibrarymember{beta}{simd} \indexlibrarymember{comp_ellint_1}{simd} \indexlibrarymember{comp_ellint_2}{simd} @@ -19525,19 +20205,16 @@ \indexlibrarymember{ellint_2}{simd} \indexlibrarymember{ellint_3}{simd} \indexlibrarymember{expint}{simd} -\indexlibrarymember{hermite}{simd} -\indexlibrarymember{laguerre}{simd} -\indexlibrarymember{legendre}{simd} -\indexlibrarymember{riemann_zeta}{simd} -\indexlibrarymember{sph_bessel}{simd} -\indexlibrarymember{sph_legendre}{simd} -\indexlibrarymember{sph_neumann}{simd} \begin{itemdecl} template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ acos(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ asin(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-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-vec-t}@ atan2(const V& y, const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ atan2(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ atan2(const V& x, const @\exposid{deduced-vec-t}@& y); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ cos(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ sin(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ tan(const V& x); @@ -19556,61 +20233,123 @@ template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ log2(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ logb(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-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-vec-t}@ hypot(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const V& x, const @\exposid{deduced-vec-t}@& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const V& x, const V& y, const V& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const @\exposid{deduced-vec-t}@& x, const V& y, const V& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const V& x, const @\exposid{deduced-vec-t}@& y, const V& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ hypot(const V& x, const V& y, const @\exposid{deduced-vec-t}@& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + hypot(const @\exposid{deduced-vec-t}@& x, const @\exposid{deduced-vec-t}@& y, const V& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + hypot(const @\exposid{deduced-vec-t}@& x, const V& y, const @\exposid{deduced-vec-t}@& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + hypot(const V& x, const @\exposid{deduced-vec-t}@& y, const @\exposid{deduced-vec-t}@& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ pow(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ pow(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ pow(const V& x, const @\exposid{deduced-vec-t}@& y); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ sqrt(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ erf(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ erfc(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@ lgamma(const V& x); template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-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-vec-t}@ assoc_laguerre(const rebind_t>& n, const - rebind_t>& m, const V& x); + constexpr @\exposid{deduced-vec-t}@ lerp(const V& a, const V& b, const V& t) noexcept; +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ lerp(const @\exposid{deduced-vec-t}@& x, const V& y, const V& z); template<@\exposconcept{math-floating-point}@ V> - @\exposid{deduced-vec-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); + constexpr @\exposid{deduced-vec-t}@ lerp(const V& x, const @\exposid{deduced-vec-t}@& y, const V& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ lerp(const V& x, const V& y, const @\exposid{deduced-vec-t}@& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + lerp(const @\exposid{deduced-vec-t}@& x, const @\exposid{deduced-vec-t}@& y, const V& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + lerp(const @\exposid{deduced-vec-t}@& x, const V& y, const @\exposid{deduced-vec-t}@& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + lerp(const V& x, const @\exposid{deduced-vec-t}@& y, const @\exposid{deduced-vec-t}@& z); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ beta(const V& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ beta(const @\exposid{deduced-vec-t}@& x, const V& y); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ beta(const V& x, const @\exposid{deduced-vec-t}@& y); template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ comp_ellint_1(const V& k); template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-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-vec-t}@ comp_ellint_3(const V& k, const V& nu); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ comp_ellint_3(const @\exposid{deduced-vec-t}@& k, const V& nu); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ comp_ellint_3(const V& k, const @\exposid{deduced-vec-t}@& nu); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_i(const V& nu, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_i(const @\exposid{deduced-vec-t}@& nu, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_i(const V& nu, const @\exposid{deduced-vec-t}@& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_j(const V& nu, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_j(const @\exposid{deduced-vec-t}@& nu, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_j(const V& nu, const @\exposid{deduced-vec-t}@& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_k(const V& nu, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_k(const @\exposid{deduced-vec-t}@& nu, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_bessel_k(const V& nu, const @\exposid{deduced-vec-t}@& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_neumann(const V& nu, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_neumann(const @\exposid{deduced-vec-t}@& nu, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ cyl_neumann(const V& nu, const @\exposid{deduced-vec-t}@& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_1(const V& k, const V& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_1(const @\exposid{deduced-vec-t}@& k, const V& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_1(const V& k, const @\exposid{deduced-vec-t}@& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_2(const V& k, const V& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_2(const @\exposid{deduced-vec-t}@& k, const V& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_2(const V& k, const @\exposid{deduced-vec-t}@& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const V& k, const V& nu, const V& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const @\exposid{deduced-vec-t}@& k, const V& nu, const V& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const V& k, const @\exposid{deduced-vec-t}@& nu, const V& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const V& k, const V& nu, const @\exposid{deduced-vec-t}@& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const @\exposid{deduced-vec-t}@& k, const @\exposid{deduced-vec-t}@& nu, const V& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const @\exposid{deduced-vec-t}@& k, const V& nu, const @\exposid{deduced-vec-t}@& phi); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ ellint_3(const V& k, const @\exposid{deduced-vec-t}@& nu, const @\exposid{deduced-vec-t}@& phi); template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ expint(const V& x); -template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ hermite(const rebind_t>& n, const V& x); -template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ laguerre(const rebind_t>& n, const V& x); -template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ legendre(const rebind_t>& l, const V& x); template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ riemann_zeta(const V& x); -template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ sph_bessel(const rebind_t>& n, const V& x); -template<@\exposconcept{math-floating-point}@ V> - @\exposid{deduced-vec-t}@ sph_legendre(const rebind_t>& l, - const rebind_t>& m, - const V& theta); -template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@ sph_neumann(const rebind_t>& n, const V& x); \end{itemdecl} \begin{itemdescr} @@ -19620,9 +20359,9 @@ Let \tcode{\placeholder{math-func-vec}} denote: \begin{codeblock} template -Ret @\placeholder{math-func-vec}@(Args... args) { +Ret @\placeholder{math-func-vec}@(const Args&... args) { return Ret([&](@\exposid{simd-size-type}@ i) { - return @\placeholder{math-func}@(@\exposid{make-compatible-simd-t}@(args)[i]...); + return @\placeholder{math-func}(\exposid{deduced-vec-t}@(args)[i]...); }); } \end{codeblock} @@ -19630,7 +20369,7 @@ \pnum \returns A value \tcode{ret} of type \tcode{Ret}, that is element-wise approximately -equal to the result of calling \tcode{\placeholder{math-func-vec}} with the arguments +equal to the result of calling \tcode{\placeholder{math-func-vec}} with the parameters of the above functions. If in an invocation of a scalar overload of \tcode{\placeholder{math-func}} for index \tcode{i} in \tcode{\placeholder{math-func-vec}} a domain, pole, or range error would @@ -19641,6 +20380,74 @@ It is unspecified whether \tcode{errno}\iref{errno} is accessed. \end{itemdescr} +\indexlibrarymember{assoc_laguerre}{simd} +\indexlibrarymember{assoc_legendre}{simd} +\indexlibrarymember{sph_legendre}{simd} +\begin{itemdecl} +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ assoc_laguerre(const rebind_t>& n, + @\itcorr@ const rebind_t>& m, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ assoc_legendre(const rebind_t>& l, + @\itcorr@ const rebind_t>& m, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ sph_legendre(const rebind_t>& l, + @\itcorr@ const rebind_t>& m, const V& theta); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{\placeholder{math-func}} denote the name of the function template. +Let \tcode{\placeholder{math-func-vec}} denote: +\begin{codeblock} +auto @\placeholder{math-func-vec}@(const auto& a, const auto& b, const @\exposid{deduced-vec-t}@& c) { + return @\exposid{deduced-vec-t}@([&](@\exposid{simd-size-type}@ i) { + return std::@\placeholder{math-func}@(a[i], b[i], c[i]); + }); +} +\end{codeblock} + +\pnum +\returns +An object that is element-wise approximately equal to the result of calling +\tcode{\placeholder{math-func-vec}} with the parameters of the above functions. +\end{itemdescr} + +\indexlibrarymember{hermite}{simd} +\indexlibrarymember{laguerre}{simd} +\indexlibrarymember{legendre}{simd} +\indexlibrarymember{riemann_zeta}{simd} +\indexlibrarymember{sph_bessel}{simd} +\indexlibrarymember{sph_neumann}{simd} +\begin{itemdecl} +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ hermite(const rebind_t>& n, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ laguerre(const rebind_t>& n, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ legendre(const rebind_t>& l, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ sph_bessel(const rebind_t>& n, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-vec-t}@ sph_neumann(const rebind_t>& n, const V& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{\placeholder{math-func}} denote the name of the function template. +Let \tcode{\placeholder{math-func-vec}} denote: +\begin{codeblock} +auto @\placeholder{math-func-vec}@(const auto& a, const @\exposid{deduced-vec-t}@& b) { + return @\exposid{deduced-vec-t}@([&](@\exposid{simd-size-type}@ i) { return std::@\placeholder{math-func}@(a[i], b[i]); }); +} +\end{codeblock} + +\pnum +\returns +An object that is element-wise approximately equal to the result of calling +\tcode{\placeholder{math-func-vec}} with the parameters of the above functions. +\end{itemdescr} + \indexlibrarymember{frexp}{simd} \begin{itemdecl} template<@\exposconcept{math-floating-point}@ V> @@ -19653,10 +20460,10 @@ Let \tcode{\placeholder{frexp-vec}} denote: \begin{codeblock} template -pair> @\placeholder{frexp-vec}@(const V& x) { +pair> @\placeholder{frexp-vec}@(const @\exposid{deduced-vec-t}@& x) { int r1[Ret::size()]; Ret r0([&](@\exposid{simd-size-type}@ i) { - return frexp(@\exposid{make-compatible-simd-t}@(x)[i], &r1[i]); + return frexp(x[i], &r1[i]); }); return {r0, rebind_t(r1)}; } @@ -19674,29 +20481,30 @@ \tcode{ret.first}. \end{itemdescr} -\indexlibrarymember{remquo}{simd} \begin{itemdecl} -template - constexpr @\exposid{math-common-simd-t}@ remquo(const V0& x, const V1& y, - rebind_t>* quo); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ remquo(const V& x, const V& y, + rebind_t>* quo); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + remquo(const @\exposid{deduced-vec-t}@& x, const V& y, rebind_t>* quo); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-vec-t}@ + remquo(const V& x, const @\exposid{deduced-vec-t}@& y, rebind_t>* quo); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{Ret} be \tcode{\exposid{math-common-simd-t}}. +Let \tcode{V0} be \tcode{\exposid{deduced-vec-t}}. Let \tcode{\placeholder{remquo-vec}} denote: \begin{codeblock} -template -pair> @\placeholder{remquo-vec}@(const V0& x, const V1& y) { - int r1[Ret::size()]; - Ret r0([&](@\exposid{simd-size-type}@ i) { - return remquo(@\exposid{make-compatible-simd-t}@(x)[i], - @\exposid{make-compatible-simd-t}@(y)[i], &r1[i]); - }); - return {r0, rebind_t(r1)}; +pair> @\placeholder{remquo-vec}@(const V0& x, const V0& y) { + int r1[V0::size()]; + V0 r0([&](@\exposid{simd-size-type}@ i) { return remquo(x[i], y[i], &r1[i]); }); + return {r0, rebind_t(r1)}; } \end{codeblock} -Let \tcode{ret} be a value of type \tcode{pair>} +Let \tcode{ret} be a value of type \tcode{pair>} that is the same value as the result of calling \tcode{\placeholder{remquo-vec}(x, y)}. If in an invocation of a scalar overload of \tcode{remquo} for index \tcode{i} @@ -19769,7 +20577,7 @@ \indexlibrarymember{bit_ceil}{simd} \begin{itemdecl} -template<@\exposconcept{simd-vec-type}@ V> constexpr V bit_ceil(const V& v) noexcept; +template<@\exposconcept{simd-vec-type}@ V> constexpr V bit_ceil(const V& v); \end{itemdecl} \begin{itemdescr} @@ -19792,7 +20600,7 @@ \pnum \remarks A function call expression that violates the precondition in the \expects -element is not a core constant expression\iref{expr.const}. +element is not a core constant expression\iref{expr.const.core}. \end{itemdescr} \indexlibrarymember{bit_floor}{simd} @@ -20032,19 +20840,21 @@ constexpr default_sentinel_t @\libmember{end}{basic_mask}@() const noexcept { return {}; } constexpr default_sentinel_t @\libmember{cend}{basic_mask}@() const noexcept { return {}; } - static constexpr integral_constant<@\exposid{simd-size-type}@, @\exposid{simd-size-v}@<@\exposid{integer-from}@, Abi>> - @\libmember{size}{basic_mask}@ {}; + static constexpr integral_constant<@\exposid{simd-size-type}@, @\exposid{mask-size-v}@> @\libmember{size}{basic_mask}@ {}; constexpr basic_mask() noexcept = default; // \ref{simd.mask.ctor}, \tcode{basic_mask} constructors - constexpr explicit basic_mask(value_type) noexcept; + constexpr explicit basic_mask(@\libconcept{same_as}@ auto) noexcept; template constexpr explicit basic_mask(const basic_mask&) noexcept; template constexpr explicit basic_mask(G&& gen); - constexpr basic_mask(const bitset& b) noexcept; - constexpr explicit basic_mask(@\libconcept{unsigned_integral}@ auto val) noexcept; + template<@\libconcept{same_as}@> T> + constexpr basic_mask(const T& b) noexcept; + template<@\libconcept{unsigned_integral}@ T> + requires (!@\libconcept{same_as}@) + constexpr explicit basic_mask(T val) noexcept; // \ref{simd.mask.subscr}, \tcode{basic_mask} subscript operators constexpr value_type operator[](@\exposid{simd-size-type}@) const; @@ -20053,9 +20863,9 @@ // \ref{simd.mask.unary}, \tcode{basic_mask} unary operators constexpr basic_mask operator!() const noexcept; - constexpr basic_vec<@\exposid{integer-from}@, Abi> operator+() const noexcept; - constexpr basic_vec<@\exposid{integer-from}@, Abi> operator-() const noexcept; - constexpr basic_vec<@\exposid{integer-from}@, Abi> operator~() const noexcept; + constexpr @\seebelow@ operator+() const noexcept; + constexpr @\seebelow@ operator-() const noexcept; + constexpr @\seebelow@ operator~() const noexcept; // \ref{simd.mask.conv}, \tcode{basic_mask} conversions template @@ -20118,9 +20928,9 @@ 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}}, + value \tcode{N} in the range \crange{1}{64} + such that \tcode{Bytes} is equal to \tcode{sizeof(T)} and + \tcode{Abi} names the ABI tag denoted by \tcode{\exposid{decude-abi-t}}, \item otherwise, it is \impldef{set of enabled \tcode{basic_mask} specializations} if such a specialization is enabled. @@ -20148,7 +20958,7 @@ \indexlibraryctor{basic_mask} \begin{itemdecl} -constexpr explicit basic_mask(value_type x) noexcept; +constexpr explicit basic_mask(@\libconcept{same_as}@ auto) noexcept; \end{itemdecl} \begin{itemdescr} @@ -20200,7 +21010,8 @@ \indexlibraryctor{basic_mask} \begin{itemdecl} -constexpr basic_mask(const bitset& b) noexcept; +template<@\libconcept{same_as}@> T> + constexpr basic_mask(const T& b) noexcept; \end{itemdecl} \begin{itemdescr} @@ -20212,7 +21023,9 @@ \indexlibraryctor{basic_mask} \begin{itemdecl} -constexpr explicit basic_mask(@\libconcept{unsigned_integral}@ auto val) noexcept; +template<@\libconcept{unsigned_integral}@ T> + requires (!@\libconcept{same_as}@) + constexpr explicit basic_mask(T val) noexcept; \end{itemdecl} \begin{itemdescr} @@ -20260,15 +21073,15 @@ \rSec3[simd.mask.unary]{Unary operators} -\indexlibrarymember{operator!}{basic_mask} +\indexlibrarymember{operator"!}{basic_mask} \indexlibrarymember{operator+}{basic_mask} \indexlibrarymember{operator-}{basic_mask} -\indexlibrarymember{operator~}{basic_mask} +\indexlibrarymember{operator\~{}}{basic_mask} \begin{itemdecl} constexpr basic_mask operator!() const noexcept; -constexpr basic_vec<@\exposid{integer-from}@, Abi> operator+() const noexcept; -constexpr basic_vec<@\exposid{integer-from}@, Abi> operator-() const noexcept; -constexpr basic_vec<@\exposid{integer-from}@, Abi> operator~() const noexcept; +constexpr @\seebelow@ operator+() const noexcept; +constexpr @\seebelow@ operator-() const noexcept; +constexpr @\seebelow@ operator~() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -20280,6 +21093,17 @@ 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()}. + +\pnum +\remarks +If there exists a vectorizable signed integer type \tcode{I} such that +\tcode{sizeof(I) == Bytes} is \tcode{true}, +\tcode{operator+}, \tcode{operator-}, and \tcode{operator~} +return an enabled specialization \tcode{R} of \tcode{basic_vec} such that +\tcode{R::value_type} denotes \tcode{\exposid{integer-from}} and +\tcode{R::size() == size()} is \tcode{true}. +Otherwise, +these operators are defined as deleted and their return types are unspecified. \end{itemdescr} \rSec3[simd.mask.conv]{Conversions} @@ -20343,9 +21167,9 @@ \rSec3[simd.mask.binary]{Binary operators} \indexlibrarymember{operator\&\&}{basic_mask} -\indexlibrarymember{operator||}{basic_mask} +\indexlibrarymember{operator"|"|}{basic_mask} \indexlibrarymember{operator\&}{basic_mask} -\indexlibrarymember{operator|}{basic_mask} +\indexlibrarymember{operator"|}{basic_mask} \indexlibrarymember{operator\caret}{basic_mask} \begin{itemdecl} friend constexpr basic_mask @@ -20374,7 +21198,7 @@ \rSec3[simd.mask.cassign]{Compound assignment} \indexlibrarymember{operator\&=}{basic_mask} -\indexlibrarymember{operator|=}{basic_mask} +\indexlibrarymember{operator"|=}{basic_mask} \indexlibrarymember{operator\caret=}{basic_mask} \begin{itemdecl} friend constexpr basic_mask& @@ -20402,7 +21226,7 @@ \rSec3[simd.mask.comparison]{Comparisons} \indexlibrarymember{operator==}{basic_mask} -\indexlibrarymember{operator!=}{basic_mask} +\indexlibrarymember{operator"!=}{basic_mask} \indexlibrarymember{operator>=}{basic_mask} \indexlibrarymember{operator<=}{basic_mask} \indexlibrarymember{operator<}{basic_mask} @@ -20648,7 +21472,7 @@ \pnum \mandates Each of the types \tcode{type1}, \tcode{type2}, and \tcode{type3} is a -cv-unqualified signed or unsigned integer type\iref{basic.fundamental}. +signed or unsigned integer type\iref{basic.fundamental}. \pnum \remarks diff --git a/source/overloading.tex b/source/overloading.tex index 2340f35644..52883f84dd 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -602,12 +602,16 @@ ``reference to function of ($\tcode{P}_1, \dotsc, \tcode{P}_n$) returning \tcode{R}'', a \defn{surrogate call function} with the unique name \placeholder{call-function} -and having the form +and having a declaration of the form \begin{ncbnf} \terminal{R} \placeholder{call-function} \terminal{(} conversion-type-id \ % -\terminal{F, P$_1$ a$_1$, $\dotsc$, P$_n$ a$_n$)} \terminal{\{} \keyword{return} \terminal{F (a$_1$, $\dotsc$, a$_n$); \}} +\terminal{F, P$_1$ a$_1$, $\dotsc$, P$_n$ a$_n$);} \end{ncbnf} is also considered as a candidate function. +\begin{note} +If a surrogate call function is selected by overload resolution, +the behavior is as described in~\ref{over.call}. +\end{note} Similarly, surrogate call functions are added to the set of candidate functions for each non-explicit conversion function declared in a base class of @@ -1052,7 +1056,8 @@ class. The argument list is the \grammarterm{expression-list} or \grammarterm{assignment-expression} -of the \grammarterm{initializer}. +of the \grammarterm{initializer}; +for default-initialization, the argument list is empty. For default-initialization in the context of copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed. @@ -1156,23 +1161,23 @@ the candidate functions are selected as follows: \begin{itemize} \item -Let $R$ be a set of types including +Let $R$ be the set of all \begin{itemize} \item -``lvalue reference to \cvqual{cv2} \tcode{T2}'' +lvalue reference types (when converting to an lvalue) and \item -``\cvqual{cv2} \tcode{T2}'' -and ``rvalue reference to \cvqual{cv2} \tcode{T2}'' -(when converting to an rvalue or an lvalue of function type) +non-reference types and rvalue reference types +(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 the members of $R$ +having the form ``\cv{}~\tcode{T2}'' or ``reference to \cvqual{cv2}~\tcode{T2}'' where ``\cvqual{cv1} \tcode{T}'' is reference-compatible\iref{dcl.init.ref} with ``\cvqual{cv2} \tcode{T2}''. For direct-initialization, the permissible types for explicit conversion functions are the members of $R$ +having the form ``\cv{}~\tcode{T2}'' or ``reference to \cvqual{cv2}~\tcode{T2}'' where \tcode{T2} can be converted to type \tcode{T} with a (possibly trivial) qualification conversion\iref{conv.qual}; otherwise there are none. @@ -1427,6 +1432,21 @@ \end{codeblock} \end{example} +\pnum +When resolving a placeholder for a deduced class type +where the \grammarterm{template-name} +designates a type template template parameter \tcode{P}, +the type template template argument for \tcode{P} +shall be a deducible template. +Let \tcode{A} be an alias template +whose template parameter list is that of \tcode{P} and +whose \grammarterm{defining-type-id} is a \grammarterm{simple-template-id} +whose \grammarterm{template-name} designates the type template template argument and +whose \grammarterm{template-argument-list} is the template argument list of \tcode{P}. +The alias template \tcode{A} is then used +instead of the original \grammarterm{template-name} +to resolve the placeholder. + \pnum When resolving a placeholder for a deduced class type\iref{dcl.type.simple} where @@ -1684,6 +1704,25 @@ \indextext{overloading!argument lists|)}% \indextext{overloading!candidate functions|)} +\pnum +\begin{example} +\begin{codeblock} +template +struct Y { + Y(); + Y(Ts ...); +}; +template class X> +void f() { + X x; // OK, deduces \tcode{Y} + X x0{}; // OK, deduces \tcode{Y} + X x1{1}; // OK, deduces \tcode{Y} + X x2{1, 2}; // error: cannot deduce \tcode{X} from \tcode{Y} +} +template void f(); +\end{codeblock} +\end{example} + \rSec2[over.match.viable]{Viable functions}% \indextext{overloading!resolution!viable functions|(} @@ -2397,10 +2436,10 @@ 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, +If the argument expression has a type \tcode{D} that +is a derived class of \tcode{T}, the implicit conversion sequence is a derived-to-base -conversion\iref{over.best.ics}. +conversion from \tcode{D} to \tcode{T}\iref{over.best.ics}. \item Otherwise, @@ -3079,15 +3118,6 @@ \end{codeblock} \end{example} -\item -binding of an expression of type -\tcode{C} -to a reference to type -\tcode{B} -is better than binding an expression of type -\tcode{C} -to a reference to type -\tcode{A}, \item conversion of \tcode{A::*} @@ -3116,16 +3146,6 @@ to \tcode{A*}, \item -binding of an expression of type -\tcode{B} -to a reference to type -\tcode{A} -is better than binding an expression of type -\tcode{C} -to a -reference to type -\tcode{A}, -\item conversion of \tcode{B::*} to @@ -3708,6 +3728,15 @@ \begin{ncsimplebnf} \terminal{(} postfix-expression . \keyword{operator} \terminal{->} \terminal{(}\terminal{)} \terminal{)} \terminal{->} \opt{\keyword{template}} id-expression \end{ncsimplebnf} +Analogously, for an expression of the form +\begin{ncsimplebnf} +postfix-expression \terminal{->} splice-expression +\end{ncsimplebnf} +the operator function is selected by overload resolution, +and the expression is interpreted as +\begin{ncsimplebnf} +\terminal{(} postfix-expression . \keyword{operator} \terminal{->} \terminal{(}\terminal{)} \terminal{)} \terminal{->} splice-expression +\end{ncsimplebnf} \rSec2[over.inc]{Increment and decrement} \indextext{increment operator!overloaded|see{overloading, increment operator}}% @@ -3904,7 +3933,7 @@ \pnum For every pair of types \tcode{\placeholder{L}} and \tcode{\placeholder{R}}, where each of \tcode{\placeholder{L}} and \tcode{\placeholder{R}} is a -floating-point or promoted integral type, +cv-unqualified floating-point or promoted integral type, there exist candidate operator functions of the form \begin{codeblock} @\placeholder{LR}@ operator*(@\placeholder{L}@, @\placeholder{R}@); @@ -3926,14 +3955,14 @@ \tcode{\placeholder{R}}. \pnum -For every integral type \tcode{\placeholder{T}} +For every cv-unqualified integral type \tcode{\placeholder{T}} there exists a candidate operator function of the form \begin{codeblock} std::strong_ordering operator<=>(@\placeholder{T}@, @\placeholder{T}@); \end{codeblock} \pnum -For every pair of floating-point types +For every pair of cv-unqualified floating-point types \tcode{\placeholder{L}} and \tcode{\placeholder{R}}, there exists a candidate operator function of the form \begin{codeblock} @@ -4010,8 +4039,9 @@ \pnum For every triple (\tcode{\placeholder{L}}, \cvqual{vq}, \tcode{\placeholder{R}}), -where \tcode{\placeholder{L}} is an arithmetic type, -and \tcode{\placeholder{R}} is a floating-point or promoted integral type, +where \tcode{\placeholder{L}} is a cv-unqualified arithmetic type +and \tcode{\placeholder{R}} is +a cv-unqualified floating-point or promoted integral type, there exist candidate operator functions of the form \begin{codeblock} @\cvqual{vq} \placeholder{L}@& operator=(@\cvqual{vq} \placeholder{L}@&, @\placeholder{R}@); @@ -4061,7 +4091,7 @@ \tcode{\placeholder{R}}), where \tcode{\placeholder{L}} -is an integral type, and +is a cv-unqualified integral type and \tcode{\placeholder{R}} is a promoted integral type, there exist candidate operator functions of the form @@ -4085,7 +4115,7 @@ \pnum For every pair of types \tcode{\placeholder{L}} and \tcode{\placeholder{R}}, where each of \tcode{\placeholder{L}} and \tcode{\placeholder{R}} is a -floating-point or promoted integral type, +cv-unqualified floating-point or promoted integral type, there exist candidate operator functions of the form \begin{codeblock} @\placeholder{LR}@ operator?:(bool, @\placeholder{L}@, @\placeholder{R}@); diff --git a/source/preprocessor.tex b/source/preprocessor.tex index bab9b3be73..0bfb7f194f 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -18,7 +18,7 @@ \begin{bnf} \nontermdef{module-file}\br - \opt{pp-global-module-fragment} pp-module \opt{group} \opt{pp-private-module-fragment} + \opt{line-directives} \opt{pp-global-module-fragment} pp-module \opt{group} \opt{pp-private-module-fragment} \end{bnf} \begin{bnf} @@ -55,13 +55,18 @@ \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 + line-directive\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 \end{bnf} +\begin{bnf} +\nontermdef{line-directives}\br + line-directive \opt{line-directives} +\end{bnf} + \begin{bnf} \nontermdef{if-section}\br if-group \opt{elif-groups} \opt{else-group} endif-line @@ -204,8 +209,7 @@ immediately followed on the same logical source line by a \grammarterm{header-name}, \tcode{<}, -\grammarterm{identifier}, -\grammarterm{string-literal}, or +\grammarterm{identifier}, or \tcode{:} preprocessing token, or @@ -225,15 +229,6 @@ 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, -preprocessing directives are commonly called ``lines''. -These ``lines'' have no other syntactic significance, -as all whitespace is equivalent except in certain situations -during preprocessing (see the -\tcode{\#} -character string literal creation operator in~\ref{cpp.stringize}, for example). -\end{footnote} \begin{note} A new-line character ends the preprocessing directive even if it occurs within what would otherwise be an invocation of a function-like macro. @@ -354,7 +349,7 @@ \begin{bnf} \nontermdef{header-name-tokens}\br - string-literal\br + plain-string-literal\br \terminal{<} h-pp-tokens \terminal{>} \end{bnf} @@ -504,12 +499,6 @@ 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 -Each preprocessing token that remains (in the list of preprocessing tokens that -will become the controlling expression) -after all macro replacements have occurred -shall be in the lexical form of a token\iref{lex.token}. - \pnum Preprocessing directives of the forms \begin{ncsimplebnf} @@ -553,7 +542,7 @@ \grammarterm{has-embed-expression}s, and \grammarterm{has-attribute-expression}s have been performed, -all remaining identifiers and keywords, +all remaining identifiers (including those lexically identical to keywords), except for \tcode{true} and @@ -570,7 +559,7 @@ \pnum The resulting tokens comprise the controlling constant expression -which is evaluated according to the rules of~\ref{expr.const} +which is evaluated according to the rules of~\ref{expr.const.core} using arithmetic that has at least the ranges specified in~\ref{support.limits}. For the purposes of this token conversion and evaluation all signed and unsigned integer types @@ -757,9 +746,13 @@ 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). -Then, an attempt is made to form a \grammarterm{header-name} +The resulting sequence of preprocessing tokens shall be of the form +\begin{ncsimplebnf} +header-name-tokens +\end{ncsimplebnf} +An attempt is then made to form a \grammarterm{header-name} preprocessing token\iref{lex.header} from the whitespace and the characters -of the spellings of the resulting sequence of preprocessing tokens; +of the spellings of the \grammarterm{header-name-tokens}; the treatment of whitespace is \impldef{treatment of whitespace when processing a \tcode{\#include} directive}. If the attempt succeeds, the directive with the so-formed \grammarterm{header-name} @@ -1216,23 +1209,16 @@ \begin{bnf} \nontermdef{pp-module}\br - \opt{\keyword{export}} \keyword{module} \opt{pp-tokens} \terminal{;} new-line + \opt{\keyword{export}} \keyword{module} \opt{pp-tokens} new-line \end{bnf} -\pnum -A \grammarterm{pp-module} shall not -appear in a context where \tcode{module} -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 +where the grammar non-terminals are defined as: \begin{ncbnf} \nontermdef{pp-module-name}\br @@ -1249,15 +1235,9 @@ \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. -\begin{note} -Each identifier currently defined as a macro name -is replaced by its replacement list of preprocessing tokens. -\end{note} +shall currently be defined as an object-like macro +or followed by \tcode{(} as the next preprocessing token at +the start of phase 4 of translation\iref{lex.phases}. \pnum The \tcode{module} and \tcode{export} (if it exists) preprocessing tokens @@ -1267,6 +1247,69 @@ This makes the line no longer a directive so it is not removed at the end of phase 4. \end{note} +After this replacement, +the preprocessing tokens that constituted the directive are +a \grammarterm{text-line} and are processed as normal text. +\begin{note} +No macro expansion is possible for +the \grammarterm{pp-module-name} and \grammarterm{pp-module-partition}. +\end{note} +After such processing, +there shall be a \tcode{;} or \tcode{[} preprocessing token following +the \grammarterm{pp-module-name} and +optional \grammarterm{pp-module-partition}. + +\pnum +\begin{example} +\begin{codeblocktu}{Importable header \tcode{"common.h"}} +#define DOT_BAR .bar +#define MOD_ATTR [[vendor::shiny_module]] +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \tcode{\#1}} +module; +#include "common.h" + +export module foo DOT_BAR; // error: expansion of \tcode{DOT_BAR;} does not begin with \tcode{;} or \tcode{[} +\end{codeblocktu} + +\begin{codeblocktu}{Translation unit \tcode{\#2}} +module; +#include "common.h" + +export module M MOD_ATTR ; // OK +\end{codeblocktu} +\end{example} + +\begin{example} +\begin{codeblock} +export module a +.b; // error: preprocessing token after \grammarterm{pp-module-name} is not \tcode{;} or \tcode{[} +\end{codeblock} +\end{example} + +\begin{example} +\begin{codeblock} +export module M [[ +attr1, +attr2 ]] ; // OK +\end{codeblock} +\end{example} + +\begin{example} +\begin{codeblock} +export module M +[[ attr1, +attr2 ]] ; // OK +\end{codeblock} +\end{example} + +\begin{example} +\begin{codeblock} +export module M; int +n; // OK +\end{codeblock} +\end{example} \rSec1[cpp.import]{Header unit importation} \indextext{header unit!preprocessing}% @@ -1280,12 +1323,6 @@ \opt{\keyword{export}} \keyword{import} pp-tokens \terminal{;} new-line \end{bnf} -\pnum -A \grammarterm{pp-import} shall not -appear in a context where \tcode{import} -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 The preprocessing tokens after the \tcode{import} preprocessing token in the \tcode{import} \grammarterm{control-line} @@ -1305,9 +1342,10 @@ first two forms of \grammarterm{pp-import} is immediately after the \grammarterm{new-line} terminating the \grammarterm{pp-import}. -The last form of \grammarterm{pp-import} is only considered -if the first two forms did not match, and -does not have a point of macro import. +The last form of \grammarterm{pp-import} +does not have a point of macro import, and +is only considered if, after macro replacement, +the first two forms did not match. \pnum If a \grammarterm{pp-import} is produced by source file inclusion @@ -1533,11 +1571,17 @@ \indextext{unit!translation}% A translation unit shall not \tcode{\#define} or \tcode{\#undef} macro names lexically identical -to keywords, +to keywords\iref{lex.key}, to the identifiers listed in \tref{lex.name.special}, or to the \grammarterm{attribute-token}{s} described in~\ref{dcl.attr}, except that the macro names \tcode{likely} and \tcode{unlikely} may be -defined as function-like macros. +defined as function-like macros and may be undefined. +\begin{note} +An alternative token\iref{lex.digraph} is not an identifier, +even when its spelling consists entirely of letters and underscores. +Therefore it is not possible to define a macro +whose name is the same as that of an alternative token. +\end{note} \pnum If a @@ -1567,12 +1611,6 @@ \end{footnote} to be replaced by the replacement list of preprocessing tokens that constitute the remainder of the directive. -\begin{footnote} -An alternative token\iref{lex.digraph} is not an identifier, -even when its spelling consists entirely of letters and underscores. -Therefore it is not possible to define a macro -whose name is the same as that of an alternative token. -\end{footnote} The replacement list is then rescanned for more macro names as specified in \ref{cpp.rescan}. @@ -2070,6 +2108,11 @@ \indextext{preprocessing directive!line control}% \indextext{\idxcode{\#line}|see{preprocessing directive, line control}} +\begin{bnf} +\nontermdef{line-directive}\br + \terminal{\# line} pp-tokens new-line +\end{bnf} + \pnum The \grammarterm{string-literal} of a \tcode{\#line} @@ -2095,9 +2138,8 @@ the following sequence of source lines begins with a source line that has a line number as specified by the digit sequence (interpreted as a decimal integer). -If the digit sequence specifies zero -or a number greater than 2147483647, -the program is ill-formed. +Digit sequences representing a number +outside of the range \crange{1}{2147483647} are conditionally supported. \pnum A preprocessing directive of the form @@ -2219,20 +2261,22 @@ \item \indextext{__file__@\mname{FILE}}% \mname{FILE}\\ -The presumed name of the current source file (a character string -literal). -\begin{footnote} -The presumed source file name can be changed by the \tcode{\#line} directive. -\end{footnote} +A character string literal representing the presumed name of +the current source file. +\begin{note} +The presumed source file name can be changed by the \tcode{\#line} directive\iref{cpp.line}. +\end{note} \item \indextext{__line__@\mname{LINE}}% \mname{LINE}\\ -The presumed line number (within the current source file) of the current source line -(an integer literal). -\begin{footnote} -The presumed line number can be changed by the \tcode{\#line} directive. -\end{footnote} +The integer literal \tcode{0} or a decimal integer literal\iref{lex.icon}, +with no digit separators and no \grammarterm{integer-suffix}, +representing the presumed line number of +the current source line within the current source file. +\begin{note} +The presumed line number can be changed by the \tcode{\#line} directive\iref{cpp.line}. +\end{note} \item \indextext{stdc__embed_not_found__@\mname{STDC_EMBED_NOT_FOUND}}% @@ -2366,7 +2410,7 @@ \defnxname{cpp_if_constexpr} & \tcode{201606L} \\ \rowsep \defnxname{cpp_impl_coroutine} & \tcode{201902L} \\ \rowsep \defnxname{cpp_impl_destroying_delete} & \tcode{201806L} \\ \rowsep -\defnxname{cpp_impl_reflection} & \tcode{202506L} \\ \rowsep +\defnxname{cpp_impl_reflection} & \tcode{202603L} \\ \rowsep \defnxname{cpp_impl_three_way_comparison} & \tcode{201907L} \\ \rowsep \defnxname{cpp_implicit_move} & \tcode{202207L} \\ \rowsep \defnxname{cpp_inheriting_constructors} & \tcode{201511L} \\ \rowsep @@ -2398,8 +2442,7 @@ \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_trivial_union} & \tcode{202603L} \\ \rowsep \defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep \defnxname{cpp_unicode_literals} & \tcode{200710L} \\ \rowsep \defnxname{cpp_user_defined_literals} & \tcode{200809L} \\ \rowsep @@ -2445,7 +2488,7 @@ \item \indextext{__stdcpp_threads__@\mname{STDCPP_THREADS}}% \mname{STDCPP_THREADS}\\ -Defined, and has the value integer literal 1, if and only if a program +Defined, and has the value integer literal \tcode{1}, if and only if a program can have more than one thread of execution\iref{intro.multithread}. \end{description} @@ -2477,12 +2520,12 @@ \indextext{operator!pragma|see{macro, pragma operator}} \pnum -A unary operator expression of the form: +A unary operator expression of the form \begin{ncbnf} \terminal{_Pragma} \terminal{(} string-literal \terminal{)} \end{ncbnf} is processed as follows: The \grammarterm{string-literal} is \defnx{destringized}{destringization} -by deleting the \tcode{L} prefix, if present, deleting the leading and trailing +by deleting any \grammarterm{encoding-prefix}, deleting the leading and trailing double-quotes, replacing each escape sequence \tcode{\textbackslash"} by a double-quote, and replacing each escape sequence \tcode{\textbackslash\textbackslash} by a single backslash. The resulting sequence of characters is processed through translation phase 3 diff --git a/source/ranges.tex b/source/ranges.tex index c93b855ec9..29b5ae53b6 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -562,16 +562,16 @@ namespace views { inline constexpr @\unspec@ cache_latest = @\unspec@; } - // \ref{range.to.input}, to input view + // \ref{range.as.input}, as input view template<@\libconcept{input_range}@ V> requires @\libconcept{view}@ - class to_input_view; + class as_input_view; template - constexpr bool enable_borrowed_range> = + constexpr bool enable_borrowed_range> = enable_borrowed_range; - namespace views { inline constexpr @\unspec@ to_input = @\unspec@; } + namespace views { inline constexpr @\unspec@ as_input = @\unspec@; } } namespace std { @@ -1409,7 +1409,7 @@ Pursuant to \ref{namespace.std}, users may specialize \tcode{enable_borrowed_range} for cv-unqualified program-defined types. Such specializations shall be -usable in constant expressions\iref{expr.const} and +usable in constant expressions\iref{expr.const.init} and have type \tcode{const bool}. \pnum @@ -1518,7 +1518,7 @@ users may specialize \tcode{disable_sized_range} for cv-unqualified program-defined types. Such specializations shall -be usable in constant expressions\iref{expr.const} and +be usable in constant expressions\iref{expr.const.init} and have type \tcode{const bool}. \pnum @@ -1623,7 +1623,7 @@ 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 +be usable in constant expressions\iref{expr.const.init} and have type \tcode{const bool}. \end{itemdescr} @@ -3119,7 +3119,8 @@ requires @\exposconcept{weakly-equality-comparable-with}@ && @\libconcept{copyable}@ struct iota_view::@\exposid{iterator}@ { private: - W @\exposid{value_}@ = W(); // \expos + W @\exposid{value_}@ = W(); // \expos + constexpr explicit @\exposid{iterator}@(W value); // \expos public: using iterator_concept = @\seebelow@; @@ -3129,7 +3130,6 @@ using difference_type = @\placeholdernc{IOTA-DIFF-T}@(W); @\exposid{iterator}@() requires @\libconcept{default_initializable}@ = default; - constexpr explicit @\exposid{iterator}@(W value); constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v); @@ -3500,11 +3500,11 @@ requires @\exposconcept{weakly-equality-comparable-with}@ && @\libconcept{copyable}@ struct iota_view::@\exposid{sentinel}@ { private: - Bound @\exposid{bound_}@ = Bound(); // \expos + Bound @\exposid{bound_}@ = Bound(); // \expos + constexpr explicit @\exposid{sentinel}@(Bound bound); // \expos public: @\exposid{sentinel}@() = default; - constexpr explicit @\exposid{sentinel}@(Bound bound); friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); @@ -4100,8 +4100,6 @@ using difference_type = ptrdiff_t; using value_type = Val; - constexpr explicit @\exposid{iterator}@(basic_istream_view& parent) noexcept; - @\exposid{iterator}@(const @\exposid{iterator}@&) = delete; @\exposid{iterator}@(@\exposid{iterator}@&&) = default; @@ -4116,7 +4114,8 @@ friend bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); private: - basic_istream_view* @\exposid{parent_}@; // \expos + constexpr explicit @\exposid{iterator}@(basic_istream_view& parent) noexcept; // \expos + basic_istream_view* @\exposid{parent_}@; // \expos }; } \end{codeblock} @@ -4213,7 +4212,7 @@ \rSec2[range.adaptor.object]{Range adaptor objects} -\indexlibrarymisc{\idxcode{operator|}}{range adaptor closure objects}% +\indexlibrarymisc{\idxcode{operator"|}}{range adaptor closure objects}% \pnum A \defnadj{range adaptor closure}{object} is a unary function object that accepts a range argument. For @@ -4796,10 +4795,10 @@ @\exposidnc{movable-box}@ @\exposid{pred_}@; // \expos // \ref{range.filter.iterator}, class \tcode{filter_view::\exposid{iterator}} - class @\exposid{iterator}@; // \expos + template class @\exposid{iterator}@; // \expos // \ref{range.filter.sentinel}, class \tcode{filter_view::\exposid{sentinel}} - class @\exposid{sentinel}@; // \expos + template class @\exposid{sentinel}@; // \expos public: filter_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; @@ -4810,12 +4809,21 @@ constexpr const Pred& pred() const; - constexpr @\exposid{iterator}@ begin(); + constexpr @\exposid{iterator}@ begin(); + constexpr @\exposid{iterator}@ begin() const + requires (@\libconcept{input_range}@ && !@\libconcept{forward_range}@ && + @\libconcept{indirect_unary_predicate}@>); + constexpr auto end() { if constexpr (@\libconcept{common_range}@) - return @\exposid{iterator}@{*this, ranges::end(@\exposid{base_}@)}; + return @\exposid{iterator}@{*this, ranges::end(@\exposid{base_}@)}; else - return @\exposid{sentinel}@{*this}; + return @\exposid{sentinel}@{*this}; + } + constexpr @\exposid{sentinel}@ end() const + requires (@\libconcept{input_range}@ && !@\libconcept{forward_range}@ && + @\libconcept{indirect_unary_predicate}@>) { + return @\exposid{sentinel}@{*this}; } }; @@ -4849,7 +4857,7 @@ \indexlibrarymember{begin}{filter_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@ begin(); +constexpr @\exposid{iterator}@ begin(); \end{itemdecl} \begin{itemdescr} @@ -4870,7 +4878,27 @@ \tcode{filter_view} for use on subsequent calls. \end{itemdescr} -\rSec3[range.filter.iterator]{Class \tcode{filter_view::\exposid{iterator}}} +\indexlibrarymember{begin}{filter_view}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ begin() const + requires (@\libconcept{input_range}@ && !@\libconcept{forward_range}@ && + @\libconcept{indirect_unary_predicate}@>); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. + +\pnum +\returns +\tcode{\{*this, ranges::find_if(\exposid{base_}, ref(*\exposid{pred_}))\}}. +\begin{note} +This function does not cache the result within the \tcode{filter_view}. +\end{note} +\end{itemdescr} + +\rSec3[range.filter.iterator]{Class template \tcode{filter_view::\exposid{iterator}}} \indexlibraryglobal{filter_view::\exposid{iterator}}% \indexlibrarymember{iterator}{filter_view}% @@ -4878,55 +4906,67 @@ namespace std::ranges { template<@\libconcept{input_range}@ V, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{view}@ && is_object_v + template class filter_view::@\exposid{iterator}@ { private: - iterator_t @\exposid{current_}@ = iterator_t(); // \expos - filter_view* @\exposid{parent_}@ = nullptr; // \expos + using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + iterator_t<@\exposidnc{Base}@> @\exposid{current_}@ = iterator_t<@\exposidnc{Base}@>(); // \expos + @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + constexpr @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent, iterator_t<@\exposidnc{Base}@> current); // \expos public: using iterator_concept = @\seebelownc@; - using iterator_category = @\seebelownc@; // not always present - using value_type = range_value_t; - using difference_type = range_difference_t; + using iterator_category = @\seebelownc@; // not always present + using value_type = range_value_t<@\exposidnc{Base}@>; + using difference_type = range_difference_t<@\exposidnc{Base}@>; - @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; - constexpr @\exposid{iterator}@(filter_view& parent, iterator_t current); + @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; + constexpr @\exposid{iterator}@(iterator i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposidnc{Base}@>>; - constexpr const iterator_t& base() const & noexcept; - constexpr iterator_t base() &&; - constexpr range_reference_t operator*() const; - constexpr iterator_t operator->() const - requires @\exposconcept{has-arrow}@> && @\libconcept{copyable}@>; + constexpr const iterator_t<@\exposidnc{Base}@>& base() const & noexcept; + constexpr iterator_t<@\exposidnc{Base}@> base() &&; + constexpr range_reference_t<@\exposidnc{Base}@> operator*() const; + constexpr iterator_t<@\exposidnc{Base}@> operator->() const + requires @\exposconcept{has-arrow}@> && @\libconcept{copyable}@>; constexpr @\exposid{iterator}@& operator++(); constexpr void operator++(int); - constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@; + constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposidnc{Base}@>; - constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; - constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposidnc{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposidnc{Base}@>; friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@>; + requires @\libconcept{equality_comparable}@>; - friend constexpr range_rvalue_reference_t iter_move(const @\exposid{iterator}@& i) + friend constexpr range_rvalue_reference_t<@\exposidnc{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}@>; + requires @\libconcept{indirectly_swappable}@>; }; } \end{codeblock} \pnum -Modification of the element a \tcode{filter_view::\exposid{iterator}} denotes is -permitted, but results in undefined behavior if the resulting value does not -satisfy the filter predicate. +\begin{note} +Modification of the element a \tcode{filter_view::\exposid{iterator}} denotes +can result in undefined behavior +if the underlying range is a \libconcept{forward_range} and +the resulting value does not satisfy the filter predicate +when the predicate is next evaluated for that element\iref{concepts.equality}. +\end{note} \pnum \tcode{\exposid{iterator}::iterator_concept} is defined as follows: \begin{itemize} -\item If \tcode{V} models \libconcept{bidirectional_range}, then +\item If \tcode{Const} is \tcode{true}, +then \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. + +\item Otherwise, if \tcode{V} models \libconcept{bidirectional_range}, then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. \item Otherwise, if \tcode{V} models \libconcept{forward_range}, then @@ -4936,13 +4976,13 @@ \end{itemize} \pnum -The member \grammarterm{typedef-name} \tcode{iterator_category} is defined -if and only if \tcode{V} models \libconcept{forward_range}. +The member \grammarterm{typedef-name} \tcode{iterator_category} is declared +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}. +\tcode{iterator_traits>::iterator_category}. \item If \tcode{C} models \tcode{\libconcept{derived_from}}, @@ -4957,7 +4997,7 @@ \indexlibraryctor{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(filter_view& parent, iterator_t current); +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current); \end{itemdecl} \begin{itemdescr} @@ -4967,9 +5007,22 @@ \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} +\indexlibraryctor{filter_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{parent_} with \tcode{i.\exposid{parent_}} and +\exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +\end{itemdescr} + \indexlibrarymember{base}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr const iterator_t& base() const & noexcept; +constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; \end{itemdecl} \begin{itemdescr} @@ -4980,7 +5033,7 @@ \indexlibrarymember{base}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr iterator_t base() &&; +constexpr iterator_t<@\exposid{Base}@> base() &&; \end{itemdecl} \begin{itemdescr} @@ -4991,7 +5044,7 @@ \indexlibrarymember{operator*}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr range_reference_t operator*() const; +constexpr range_reference_t<@\exposid{Base}@> operator*() const; \end{itemdecl} \begin{itemdescr} @@ -5002,8 +5055,8 @@ \indexlibrarymember{operator->}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr iterator_t operator->() const - requires @\exposconcept{has-arrow}@> && @\libconcept{copyable}@>; +constexpr iterator_t<@\exposid{Base}@> operator->() const + requires @\exposconcept{has-arrow}@> && @\libconcept{copyable}@>; \end{itemdecl} \begin{itemdescr} @@ -5041,7 +5094,7 @@ \indexlibrarymember{operator++}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@; +constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -5057,7 +5110,7 @@ \indexlibrarymember{operator--}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -5074,7 +5127,7 @@ \indexlibrarymember{operator--}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -5091,7 +5144,7 @@ \indexlibrarymember{operator==}{filter_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@>; + requires @\libconcept{equality_comparable}@>; \end{itemdecl} \begin{itemdescr} @@ -5102,7 +5155,7 @@ \indexlibrarymember{iter_move}{filter_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr range_rvalue_reference_t iter_move(const @\exposid{iterator}@& i) +friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i) noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); \end{itemdecl} @@ -5116,7 +5169,7 @@ \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}@>; + requires @\libconcept{indirectly_swappable}@>; \end{itemdecl} \begin{itemdescr} @@ -5125,7 +5178,7 @@ Equivalent to \tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_})}. \end{itemdescr} -\rSec3[range.filter.sentinel]{Class \tcode{filter_view::\exposid{sentinel}}} +\rSec3[range.filter.sentinel]{Class template \tcode{filter_view::\exposid{sentinel}}} \indexlibraryglobal{filter_view::\exposid{sentinel}}% \indexlibrarymember{sentinel}{filter_view}% @@ -5133,24 +5186,42 @@ namespace std::ranges { template<@\libconcept{input_range}@ V, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{view}@ && is_object_v + template class filter_view::@\exposid{sentinel}@ { private: - sentinel_t @\exposid{end_}@ = sentinel_t(); // \expos + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + sentinel_t<@\exposidnc{Base}@> @\exposid{end_}@ = sentinel_t<@\exposidnc{Base}@>(); // \expos + constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{Parent}@& parent); // \expos public: @\exposid{sentinel}@() = default; - constexpr explicit @\exposid{sentinel}@(filter_view& parent); + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposidnc{Base}@>>; - constexpr sentinel_t base() const; + constexpr sentinel_t<@\exposidnc{Base}@> base() const; - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); }; } \end{codeblock} \indexlibraryctor{filter_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(filter_view& parent); +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposidnc{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}. +\end{itemdescr} + +\indexlibraryctor{filter_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent); \end{itemdecl} \begin{itemdescr} @@ -5161,7 +5232,7 @@ \indexlibrarymember{base}{filter_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr sentinel_t base() const; +constexpr sentinel_t<@\exposidnc{Base}@> base() const; \end{itemdecl} \begin{itemdescr} @@ -5172,7 +5243,9 @@ \indexlibrarymember{operator==}{filter_view::\exposid{sentinel}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +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} @@ -5380,10 +5453,11 @@ template class transform_view::@\exposid{iterator}@ { private: - using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - iterator_t<@\exposidnc{Base}@> @\exposid{current_}@ = iterator_t<@\exposidnc{Base}@>(); // \expos - @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + iterator_t<@\exposidnc{Base}@> @\exposid{current_}@ = iterator_t<@\exposidnc{Base}@>(); // \expos + @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposidnc{Base}@> current); // \expos public: using iterator_concept = @\seebelownc@; @@ -5393,7 +5467,6 @@ using difference_type = range_difference_t<@\exposid{Base}@>; @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; - constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current); constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; @@ -5465,7 +5538,7 @@ \end{itemize} \pnum -The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +The member \grammarterm{typedef-name} \tcode{iterator_category} is declared if and only if \exposid{Base} models \libconcept{forward_range}. In that case, \tcode{\exposid{iterator}::iterator_category} is defined as follows: @@ -5767,10 +5840,10 @@ using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); // \expos public: @\exposid{sentinel}@() = default; - constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -5898,6 +5971,11 @@ except that the evaluations of \tcode{E} and \tcode{F} are indeterminately sequenced. +\item +Otherwise, if \tcode{T} is a specialization of +\tcode{optional} and \tcode{T} models \libconcept{view}, then +\tcode{(static_cast(F) == D() ? ((void)E, T()) : \exposidnc{decay-copy}(E))}. + \item Otherwise, if \tcode{T} models \libconcept{random_access_range} and \libconcept{sized_range} @@ -6104,10 +6182,10 @@ template using @\exposid{CI}@ = counted_iterator>>; // \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 explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ s) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -6287,14 +6365,14 @@ @\libconcept{indirect_unary_predicate}@> template class take_while_view::@\exposidnc{sentinel}@ { - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - sentinel_t<@\exposidnc{Base}@> @\exposid{end_}@ = sentinel_t<@\exposidnc{Base}@>(); // \expos - const Pred* @\exposid{pred_}@ = nullptr; // \expos + sentinel_t<@\exposidnc{Base}@> @\exposid{end_}@ = sentinel_t<@\exposidnc{Base}@>(); // \expos + const Pred* @\exposid{pred_}@ = nullptr; // \expos + constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end, const Pred* pred); // \expos public: @\exposid{sentinel}@() = default; - constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end, const Pred* pred); constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ s) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -6381,6 +6459,11 @@ except that the evaluations of \tcode{E} and \tcode{F} are indeterminately sequenced. +\item +Otherwise, if \tcode{T} is a specialization of \tcode{optional} +and \tcode{T} models \libconcept{view}, then +\tcode{(static_cast(F) == D() ? \exposidnc{decay-copy}(E) : ((void)E, T()))}. + \item Otherwise, if \tcode{T} models \libconcept{random_access_range} and \libconcept{sized_range} @@ -6870,7 +6953,7 @@ \end{itemize} \pnum -The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +The member \grammarterm{typedef-name} \tcode{iterator_category} is declared if and only if \exposid{ref-is-glvalue} is \tcode{true}, \exposid{Base} models \libconcept{forward_range}, and \tcode{range_reference_t<\exposid{Base}>} models \libconcept{forward_range}. @@ -7142,11 +7225,11 @@ using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent); // \expos public: @\exposid{sentinel}@() = default; - constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent); constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ s) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -7443,7 +7526,7 @@ \end{itemize} \pnum -The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +The member \grammarterm{typedef-name} \tcode{iterator_category} is declared if and only if \exposid{ref-is-glvalue} is \tcode{true}, and \exposid{Base} and \exposid{InnerBase} each model \libconcept{forward_range}. In that case, @@ -7915,7 +7998,8 @@ } } - constexpr auto begin() const requires @\libconcept{forward_range}@ && @\libconcept{forward_range}@ { + constexpr auto begin() const requires @\libconcept{forward_range}@ && @\libconcept{forward_range}@ && + @\libconcept{forward_range}@ { return @\exposid{outer-iterator}@{*this, ranges::begin(@\exposid{base_}@)}; } @@ -7925,7 +8009,8 @@ } constexpr auto end() const { - if constexpr (@\libconcept{forward_range}@ && @\libconcept{forward_range}@ && @\libconcept{common_range}@) + if constexpr (@\libconcept{forward_range}@ && @\libconcept{forward_range}@ && @\libconcept{common_range}@ && + @\libconcept{forward_range}@) return @\exposid{outer-iterator}@{*this, ranges::end(@\exposid{base_}@)}; else return default_sentinel; @@ -7988,6 +8073,10 @@ // if \tcode{V} models \libconcept{forward_range} bool @\exposid{trailing_empty_}@ = false; // \expos + constexpr explicit @\exposid{outer-iterator}@(@\exposid{Parent}@& parent) // \expos + requires (!@\libconcept{forward_range}@<@\exposid{Base}@>); + constexpr @\exposid{outer-iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current) // \expos + requires @\libconcept{forward_range}@<@\exposid{Base}@>; public: using iterator_concept = @@ -8001,10 +8090,6 @@ using difference_type = range_difference_t<@\exposid{Base}@>; @\exposid{outer-iterator}@() = default; - constexpr explicit @\exposid{outer-iterator}@(@\exposid{Parent}@& parent) - requires (!@\libconcept{forward_range}@<@\exposid{Base}@>); - constexpr @\exposid{outer-iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current) - requires @\libconcept{forward_range}@<@\exposid{Base}@>; constexpr @\exposid{outer-iterator}@(@\exposid{outer-iterator}@ i) requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; @@ -8222,9 +8307,10 @@ template struct lazy_split_view::@\exposid{inner-iterator}@ { private: - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - @\exposidnc{outer-iterator}@ @\exposid{i_}@ = @\exposidnc{outer-iterator}@(); // \expos - bool @\exposid{incremented_}@ = false; // \expos + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + @\exposidnc{outer-iterator}@ @\exposid{i_}@ = @\exposidnc{outer-iterator}@(); // \expos + bool @\exposid{incremented_}@ = false; // \expos + constexpr explicit @\exposid{inner-iterator}@(@\exposidnc{outer-iterator}@ i); // \expos public: using iterator_concept = @\exposid{outer-iterator}@::iterator_concept; @@ -8235,7 +8321,6 @@ using difference_type = range_difference_t<@\exposid{Base}@>; @\exposid{inner-iterator}@() = default; - constexpr explicit @\exposid{inner-iterator}@(@\exposid{outer-iterator}@ i); constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; constexpr iterator_t<@\exposid{Base}@> base() && requires @\libconcept{forward_range}@; @@ -8546,10 +8631,12 @@ @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> class split_view::@\exposid{iterator}@ { private: - split_view* @\exposid{parent_}@ = nullptr; // \expos - iterator_t @\exposid{cur_}@ = iterator_t(); // \expos - subrange> @\exposid{next_}@ = subrange>(); // \expos - bool @\exposid{trailing_empty_}@ = false; // \expos + split_view* @\exposid{parent_}@ = nullptr; // \expos + iterator_t @\exposid{cur_}@ = iterator_t(); // \expos + subrange> @\exposid{next_}@ = subrange>(); // \expos + bool @\exposid{trailing_empty_}@ = false; // \expos + constexpr @\exposid{iterator}@(split_view& parent, iterator_t current, // \expos + subrange> next); public: using iterator_concept = forward_iterator_tag; @@ -8558,7 +8645,6 @@ using difference_type = range_difference_t; @\exposid{iterator}@() = default; - constexpr @\exposid{iterator}@(split_view& parent, iterator_t current, subrange> next); constexpr iterator_t base() const; constexpr value_type operator*() const; @@ -8673,10 +8759,10 @@ struct split_view::@\exposid{sentinel}@ { private: sentinel_t @\exposid{end_}@ = sentinel_t(); // \expos + constexpr explicit @\exposid{sentinel}@(split_view& parent); // \expos public: @\exposid{sentinel}@() = default; - constexpr explicit @\exposid{sentinel}@(split_view& parent); friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); }; @@ -8779,6 +8865,8 @@ constexpr auto size() requires (@\libconcept{sized_range}@ && ...); constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); + constexpr auto reserve_hint() requires (@\libconcept{approximately_sized_range}@ && ...); + constexpr auto reserve_hint() const requires (@\libconcept{approximately_sized_range}@ && ...); }; template @@ -8921,7 +9009,8 @@ Equivalent to: \begin{codeblock} constexpr auto N = sizeof...(Views); -if constexpr (@\libconcept{common_range}@<@\exposid{maybe-const}@<@\exposid{is-const}@, Views...[N - 1]>>) { +if constexpr (@\exposconcept{all-forward}<\exposid{is-const}, Views...>@ && + @\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 { @@ -8950,6 +9039,26 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{reserve_hint}{concat_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} +return apply( + [](auto... sizes) { + using CT = @\exposid{make-unsigned-like-t}@>; + return (CT(sizes) + ...); + }, + @\exposid{tuple-transform}@(ranges::reserve_hint, @\exposid{views_}@)); +\end{codeblock} +\end{itemdescr} + \rSec3[range.concat.iterator]{Class \tcode{concat_view::\exposid{iterator}}} \indexlibrarymember{iterator}{concat_view}% @@ -8961,7 +9070,6 @@ @\exposconcept{concatable}@ template class concat_view::@\exposid{iterator}@ { - public: using iterator_category = @\seebelow@; // not always present using iterator_concept = @\seebelow@; @@ -9067,7 +9175,7 @@ \end{itemize} \pnum -The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +The member \grammarterm{typedef-name} \tcode{iterator_category} is declared if and only if \tcode{\exposconcept{all-forward}} is modeled. In that case, @@ -9909,6 +10017,11 @@ If the type of \tcode{E} is a (possibly cv-qualified) specialization of \tcode{reverse_view}, then \tcode{E.base()}. + +\item + Otherwise, if \tcode{E} is a specialization of \tcode{optional} and \tcode{E} + models \libconcept{view}, then \tcode{\exposidnc{decay-copy}(E)}. + \item Otherwise, if the type of \tcode{E} is \cv{} \tcode{subrange, reverse_iterator, K>} for some iterator type \tcode{I} and @@ -10060,6 +10173,11 @@ 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{optional} +for some type \tcode{X}, then \tcode{optional(E)}. + \item Otherwise, if \tcode{U} denotes \tcode{span} @@ -10214,7 +10332,10 @@ namespace std::ranges { template concept @\defexposconcept{has-tuple-element}@ = // \expos - @\exposconcept{tuple-like}@ && N < tuple_size_v; + @\exposconcept{tuple-like}@ && N < tuple_size_v && + requires(T t) { + { std::get(t) } -> @\libconcept{convertible_to}@&>; + }; template concept @\defexposconcept{returnable-element}@ = // \expos @@ -10301,6 +10422,7 @@ 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 + constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); // \expos public: using iterator_concept = @\seebelow@; @@ -10309,7 +10431,6 @@ 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}@>>; @@ -10379,7 +10500,7 @@ \end{itemize} \pnum -The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +The member \grammarterm{typedef-name} \tcode{iterator_category} is declared 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 @@ -10696,12 +10817,12 @@ template class elements_view::@\exposid{sentinel}@ { private: - using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposidnc{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 explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -11944,7 +12065,7 @@ \begin{itemdecl} template requires (@\libconcept{sentinel_for}@>, - iterator_t>> && ...) + iterator_t<@\exposid{maybe-const}@>> && ...) friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} @@ -12196,7 +12317,7 @@ \pnum The member \grammarterm{typedef-name} \tcode{\exposid{iterator}::iterator_category} -is defined if and only if \exposid{Base} models \libconcept{forward_range}. +is declared if and only if \exposid{Base} models \libconcept{forward_range}. In that case, \tcode{\exposid{iterator}::iterator_category} is defined as follows: \begin{itemize} @@ -14958,8 +15079,8 @@ 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}@; + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; }; template @@ -16191,7 +16312,7 @@ \end{itemize} \pnum -The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +The member \grammarterm{typedef-name} \tcode{iterator_category} is declared if and only if \exposid{Base} models \libconcept{forward_range}. In that case, \tcode{\exposid{iterator}::iterator_category} is defined as follows: @@ -17731,12 +17852,12 @@ \tcode{x.\exposid{end_} - y.\exposid{current_}}. \end{itemdescr} -\rSec2[range.to.input]{To input view} +\rSec2[range.as.input]{As input view} -\rSec3[range.to.input.overview]{Overview} +\rSec3[range.as.input.overview]{Overview} \pnum -\tcode{to_input_view} presents a view of an underlying sequence +\tcode{as_input_view} presents a view of an underlying sequence as an input-only non-common range. \begin{note} This is useful to avoid overhead @@ -17745,10 +17866,10 @@ \end{note} \pnum -The name \tcode{views::to_input} denotes +The name \tcode{views::as_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: +The expression \tcode{views::as_input(E)} is expression-equivalent to: \begin{itemize} \item \tcode{views::all(E)} @@ -17756,25 +17877,25 @@ does not satisfy \libconcept{common_range}, and does not satisfy \libconcept{forward_range}. \item -Otherwise, \tcode{to_input_view(E)}. +Otherwise, \tcode{as_input_view(E)}. \end{itemize} -\rSec3[range.to.input.view]{Class template \tcode{to_input_view}} +\rSec3[range.as.input.view]{Class template \tcode{as_input_view}} -\indexlibraryglobal{to_input_view}% +\indexlibraryglobal{as_input_view}% \begin{codeblock} namespace std::ranges { template<@\libconcept{input_range}@ V> requires @\libconcept{view}@ - class to_input_view : public view_interface> { + class as_input_view : public view_interface> { V @\exposid{base_}@ = V(); // \expos - // \ref{range.to.input.iterator}, class template \tcode{to_input_view::\exposid{iterator}} + // \ref{range.as.input.iterator}, class template \tcode{as_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); + as_input_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit as_input_view(V base); constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } @@ -17793,13 +17914,13 @@ }; template - to_input_view(R&&) -> to_input_view>; + as_input_view(R&&) -> as_input_view>; } \end{codeblock} -\indexlibraryctor{to_input_view}% +\indexlibraryctor{as_input_view}% \begin{itemdecl} -constexpr explicit to_input_view(V base); +constexpr explicit as_input_view(V base); \end{itemdecl} \begin{itemdescr} @@ -17808,7 +17929,7 @@ Initializes \exposid{base_} with \tcode{std::move(base)}. \end{itemdescr} -\indexlibrarymember{begin}{to_input_view}% +\indexlibrarymember{begin}{as_input_view}% \begin{itemdecl} constexpr auto begin() requires (!@\exposconcept{simple-view}@); \end{itemdecl} @@ -17819,7 +17940,7 @@ Equivalent to: \tcode{return \exposid{iterator}(ranges::begin(\exposid{base_}));} \end{itemdescr} -\indexlibrarymember{begin}{to_input_view}% +\indexlibrarymember{begin}{as_input_view}% \begin{itemdecl} constexpr auto begin() const requires @\libconcept{range}@; \end{itemdecl} @@ -17830,7 +17951,7 @@ Equivalent to: \tcode{return \exposid{iterator}(ranges::begin(\exposid{base_}));} \end{itemdescr} -\indexlibrarymember{end}{to_input_view}% +\indexlibrarymember{end}{as_input_view}% \begin{itemdecl} constexpr auto end() requires (!@\exposconcept{simple-view}@); constexpr auto end() const requires @\libconcept{range}@; @@ -17842,7 +17963,7 @@ Equivalent to: \tcode{return ranges::end(\exposid{base_});} \end{itemdescr} -\indexlibrarymember{size}{to_input_view}% +\indexlibrarymember{size}{as_input_view}% \begin{itemdecl} constexpr auto size() requires @\libconcept{sized_range}@; constexpr auto size() const requires @\libconcept{sized_range}@; @@ -17854,7 +17975,7 @@ Equivalent to: \tcode{return ranges::size(\exposid{base_});} \end{itemdescr} -\indexlibrarymember{reserve_hint}{to_input_view}% +\indexlibrarymember{reserve_hint}{as_input_view}% \begin{itemdecl} constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; @@ -17866,15 +17987,15 @@ Equivalent to: \tcode{return ranges::reserve_hint(\exposid{base_});} \end{itemdescr} -\rSec3[range.to.input.iterator]{Class template \tcode{to_input_view::\exposid{iterator}}} +\rSec3[range.as.input.iterator]{Class template \tcode{as_input_view::\exposid{iterator}}} -\indexlibraryglobal{to_input_view::\exposid{iterator}}% +\indexlibraryglobal{as_input_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{input_range}@ V> requires @\libconcept{view}@ template - class to_input_view::@\exposid{iterator}@ { + class as_input_view::@\exposid{iterator}@ { using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos @@ -17919,7 +18040,7 @@ } \end{codeblock} -\indexlibraryctor{to_input_view::\exposid{iterator}}% +\indexlibraryctor{as_input_view::\exposid{iterator}}% \begin{itemdecl} constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); \end{itemdecl} @@ -17930,7 +18051,7 @@ Initializes \exposid{current_} with \tcode{std::move(current)}. \end{itemdescr} -\indexlibraryctor{to_input_view::\exposid{iterator}}% +\indexlibraryctor{as_input_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; @@ -17942,7 +18063,7 @@ Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}. \end{itemdescr} -\indexlibrarymember{base}{to_input_view::\exposid{iterator}}% +\indexlibrarymember{base}{as_input_view::\exposid{iterator}}% \begin{itemdecl} constexpr iterator_t<@\exposid{Base}@> base() &&; \end{itemdecl} @@ -17953,7 +18074,7 @@ \tcode{std::move(\exposid{current_})}. \end{itemdescr} -\indexlibrarymember{base}{to_input_view::\exposid{iterator}}% +\indexlibrarymember{base}{as_input_view::\exposid{iterator}}% \begin{itemdecl} constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; \end{itemdecl} @@ -17964,7 +18085,7 @@ \exposid{current_}. \end{itemdescr} -\indexlibrarymember{operator++}{to_input_view::\exposid{iterator}}% +\indexlibrarymember{operator++}{as_input_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -17979,7 +18100,7 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{to_input_view::\exposid{iterator}}% +\indexlibrarymember{operator++}{as_input_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -17990,7 +18111,7 @@ Equivalent to: \tcode{++*this;} \end{itemdescr} -\indexlibrarymember{operator==}{to_input_view::\exposid{iterator}}% +\indexlibrarymember{operator==}{as_input_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y); \end{itemdecl} @@ -18001,7 +18122,7 @@ \tcode{x.\exposid{current_} == y}. \end{itemdescr} -\indexlibrarymember{operator-}{to_input_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{as_input_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr difference_type operator-(const sentinel_t<@\exposid{Base}@>& y, const @\exposid{iterator}@& x) requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; @@ -18013,7 +18134,7 @@ \tcode{y - x.\exposid{current_}}. \end{itemdescr} -\indexlibrarymember{operator-}{to_input_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{as_input_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y) requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; @@ -18025,7 +18146,7 @@ \tcode{x.\exposid{current_} - y}. \end{itemdescr} -\indexlibrarymember{iter_move}{to_input_view::\exposid{iterator}}% +\indexlibrarymember{iter_move}{as_input_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i) noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); @@ -18037,7 +18158,7 @@ Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});} \end{itemdescr} -\indexlibrarymember{iter_swap}{to_input_view::\exposid{iterator}}% +\indexlibrarymember{iter_swap}{as_input_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_}@))) diff --git a/source/statements.tex b/source/statements.tex index 34018bd618..fa6944b172 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -35,6 +35,11 @@ \begin{bnf} \nontermdef{condition}\br expression\br + condition-declaration +\end{bnf} + +\begin{bnf} +\nontermdef{condition-declaration}\br \opt{attribute-specifier-seq} decl-specifier-seq declarator brace-or-equal-initializer\br structured-binding-declaration initializer \end{bnf} @@ -143,19 +148,16 @@ \pnum If a \grammarterm{condition} can be syntactically resolved -as either an expression or a declaration, +as either an \grammarterm{expression} or a \grammarterm{condition-declaration}, it is interpreted as the latter. \pnum -In the \grammarterm{decl-specifier-seq} of a \grammarterm{condition} -or of a \grammarterm{for-range-declaration}, -including that of any \grammarterm{structured-binding-declaration} of -the \grammarterm{condition}, -each -\grammarterm{decl-specifier} shall be either a \grammarterm{type-specifier} +For any \grammarterm{condition} or \grammarterm{for-range-declaration} $D$, +each \grammarterm{decl-specifier} +in the \grammarterm{decl-specifier-seq} of $D$, +including that of any \grammarterm{structured-binding-declaration} of $D$, +shall be either a \grammarterm{type-specifier} or \keyword{constexpr}. -The \grammarterm{decl-specifier-seq} of a \grammarterm{for-range-declaration} -shall not define a class or enumeration. \rSec1[stmt.label]{Label}% \indextext{statement!labeled} @@ -265,7 +267,6 @@ \pnum \begin{note} A compound statement defines a block scope\iref{basic.scope}. -A declaration is a \grammarterm{statement}\iref{stmt.dcl}. \end{note} \rSec1[stmt.select]{Selection statements}% @@ -323,7 +324,7 @@ If the \keyword{if} statement is of the form \tcode{if constexpr}, the value of the condition is contextually converted to \keyword{bool} and -the converted expression shall be a constant expression\iref{expr.const}; +the converted expression shall be a constant expression\iref{expr.const.const}; this form is called a \defn{constexpr if} statement. If the value of the converted condition is \tcode{false}, the first substatement is a @@ -408,7 +409,7 @@ \pnum If a consteval if statement is evaluated in a context -that is manifestly constant-evaluated\iref{expr.const}, +that is manifestly constant-evaluated\iref{expr.const.defns}, the first substatement is executed. \begin{note} The first substatement is an immediate function context. @@ -464,7 +465,7 @@ \keyword{case} constant-expression \terminal{:} \end{ncbnf} where the \grammarterm{constant-expression} shall be -a converted constant expression\iref{expr.const} of the +a converted constant expression\iref{expr.const.const} of the adjusted type of the switch condition. No two of the case constants in the same switch shall have the same value after conversion. @@ -587,7 +588,7 @@ (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 +when interpreted as a \grammarterm{constant-expression}\iref{expr.const.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}; @@ -807,7 +808,8 @@ \begin{bnf} \nontermdef{expansion-init-list}\br - \terminal{\{} \opt{expression-list} \terminal{\}} + \terminal{\{} expression-list \opt{\terminal{,}} \terminal{\}}\br + \terminal{\{} \terminal{\}} \end{bnf} \pnum @@ -824,7 +826,7 @@ \tcode{E.begin()} and \tcode{E.end()}, or \item argument-dependent lookups for \tcode{begin(E)} and for \tcode{end(E)} -each find at least one function or function template. +each find at least one viable candidate\iref{over.match.viable}. \end{itemize} \pnum @@ -871,10 +873,8 @@ \begin{codeblock} { @\grammarterm{init-statement}@ - static constexpr auto&& @\exposidnc{range}@ = @\grammarterm{expansion-initializer}@; - static constexpr auto @\exposidnc{begin}@ = @\exposidnc{begin-expr}@; // see \ref{stmt.ranged} - static constexpr auto @\exposidnc{end}@ = @\exposidnc{end-expr}@; // see \ref{stmt.ranged} - + @\opt{constexpr}@ decltype(auto) @\exposidnc{range}@ = (@\grammarterm{expansion-initializer}@); + @\opt{constexpr}@ auto @\exposidnc{begin}@ = @\exposidnc{begin-expr}@; // see \ref{stmt.ranged} @$S_{0}$@ @\vdots@ @$S_{N-1}$@ @@ -882,29 +882,45 @@ \end{codeblock} where $N$ is the result of evaluating the expression \begin{codeblock} -[] consteval { +[&] consteval { std::ptrdiff_t result = 0; - for (auto i = @\exposid{begin}@; i != @\exposid{end}@; ++i, ++result); + auto b = @\exposid{begin-expr}@; + auto e = @\exposid{end-expr}@; + for (; b != e; ++b) ++result; return result; // distance from \exposid{begin} to \exposid{end} }() \end{codeblock} and $S_{i}$ is \begin{codeblock} { - static constexpr auto @\exposid{iter}@ = @\exposid{begin}@ + i; + @\opt{constexpr}@ auto @\exposid{iter}@ = @\exposid{begin}@ + decltype(begin - begin){@\placeholder{i}@}; @\grammarterm{for-range-declaration}@ = *@\exposid{iter}@; @\grammarterm{compound-statement}@ } \end{codeblock} -The variables \exposid{range}, \exposid{begin}, \exposid{end}, and \exposid{iter} +The variables \exposid{range}, \exposid{begin}, and \exposid{iter} are defined for exposition only. -\begin{note} -The instantiation is ill-formed if \exposid{range} -is not a constant expression\iref{expr.const}. -\end{note} +The keyword \keyword{constexpr} is present in the declarations +of \exposid{range}, \exposid{begin}, and \exposid{iter} +if and only if +\keyword{constexpr} is one of the \grammarterm{decl-specifier}{s} of +the \grammarterm{decl-specifier-seq} of +the \grammarterm{for-range-declaration}. +The identifier \tcode{\placeholder{i}} is considered to be +a prvalue of type \tcode{std::ptrdiff_t}; +the program is ill-formed if +\tcode{\placeholder{i}} is not representable as such a value. \item -Otherwise, $S$ is a destructuring expansion statement and $S$ is equivalent to: +Otherwise, $S$ is a destructuring expansion statement and, +if $N$ is $0$, $S$ is equivalent to: +\begin{codeblock} +{ + @\grammarterm{init-statement}@ + @\opt{\keyword{constexpr}}@ auto&& @\exposid{range}@ = @\grammarterm{expansion-initializer}@; +} +\end{codeblock} +otherwise, $S$ is equivalent to: \begin{codeblock} { @\grammarterm{init-statement}@ @@ -918,11 +934,14 @@ of the \grammarterm{expansion-initializer} and $S_{i}$ is \begin{codeblock} { - @\grammarterm{for-range-declaration}@ = @$u_{i}$@; + @\grammarterm{for-range-declaration}@ = @$v_{i}$@; @\grammarterm{compound-statement}@ } \end{codeblock} -The keyword \keyword{constexpr} is present in the declaration +If the \grammarterm{expansion-initializer} is an lvalue, then +$v_{i}$ is $u_{i}$; +otherwise, $v_{i}$ is \tcode{static_cast($u_{i}$)}. +The keyword \keyword{constexpr} is present in the \grammarterm{structured-binding-declaration} of $u_{0}, u_{1}, \dotsc, u_{N-1}$ if and only if \keyword{constexpr} is one of the \grammarterm{decl-specifier}s of the \grammarterm{decl-specifier-seq} @@ -1052,8 +1071,7 @@ If the innermost enclosing such statement $X$ is an \grammarterm{iteration-statement}\iref{stmt.iter}, the \keyword{continue} statement -causes control to pass to the end of the \grammarterm{statement} -or \grammarterm{compound-statement} of $X$. +causes control to pass to the end of the \grammarterm{statement} of $X$. Otherwise, control passes to the end of the \grammarterm{compound-statement} of the current $S_{i}$\iref{stmt.expand}. @@ -1132,10 +1150,14 @@ \end{note} \pnum -In a function whose return type is a reference, +In a function 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. +a \tcode{return} statement that binds +\begin{itemize} +\item a returned reference or +\item a constituent reference\iref{intro.object} of a returned object +\end{itemize} +to a temporary expression\iref{class.temporary} is ill-formed. \begin{example} \begin{codeblock} auto&& f1() { @@ -1287,7 +1309,8 @@ after its \grammarterm{init-declarator}. \indextext{initialization!jump past}% \indextext{\idxcode{goto}!initialization and}% -Upon each transfer of control (including sequential execution of statements) +Upon each transfer of control (including sequential execution of statements, +but excluding function calls) within a function from point $P$ to point $Q$, 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. @@ -1451,7 +1474,7 @@ T1(a) = 3, T2(4), // \tcode{T2} will be declared as a variable of type \tcode{T1}, but this will not (*(*b)(T2(c)))(int(d)); // allow the last part of the declaration to parse properly, - // since it depends on \tcode{T2} being a type-name + // since it depends on \tcode{T2} being a \grammarterm{type-name} } \end{codeblock} \end{example} diff --git a/source/strings.tex b/source/strings.tex index 9e1e9481b8..b8619c9b4b 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -561,11 +561,11 @@ basic_string_view str); // hosted // \tcode{basic_string_view} \grammarterm{typedef-name}s - using string_view = basic_string_view; - using u8string_view = basic_string_view; - using u16string_view = basic_string_view; - using u32string_view = basic_string_view; - using wstring_view = basic_string_view; + using @\libglobal{string_view}@ = basic_string_view; + using @\libglobal{u8string_view}@ = basic_string_view; + using @\libglobal{u16string_view}@ = basic_string_view; + using @\libglobal{u32string_view}@ = basic_string_view; + using @\libglobal{wstring_view}@ = basic_string_view; // \ref{string.view.hash}, hash support template struct hash; @@ -665,7 +665,7 @@ 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; + constexpr const charT* data() const noexcept; // \ref{string.view.modifiers}, modifiers constexpr void remove_prefix(size_type n); @@ -734,7 +734,7 @@ constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const; private: - const_pointer @\exposid{data_}@; // \expos + const charT* @\exposid{data_}@; // \expos size_type @\exposid{size_}@; // \expos }; @@ -1110,7 +1110,7 @@ \indexlibrarymember{data}{basic_string_view}% \begin{itemdecl} -constexpr const_pointer data() const noexcept; +constexpr const charT* data() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -1927,12 +1927,12 @@ float stof(const string& str, size_t* idx = nullptr); double stod(const string& str, size_t* idx = nullptr); long double stold(const string& str, size_t* idx = nullptr); - string to_string(int val); - string to_string(unsigned val); - string to_string(long val); - string to_string(unsigned long val); - string to_string(long long val); - string to_string(unsigned long long val); + constexpr string to_string(int val); + constexpr string to_string(unsigned val); + constexpr string to_string(long val); + constexpr string to_string(unsigned long val); + constexpr string to_string(long long val); + constexpr string to_string(unsigned long long val); string to_string(float val); string to_string(double val); string to_string(long double val); @@ -1945,12 +1945,12 @@ float stof(const wstring& str, size_t* idx = nullptr); double stod(const wstring& str, size_t* idx = nullptr); long double stold(const wstring& str, size_t* idx = nullptr); - wstring to_wstring(int val); - wstring to_wstring(unsigned val); - wstring to_wstring(long val); - wstring to_wstring(unsigned long val); - wstring to_wstring(long long val); - wstring to_wstring(unsigned long long val); + constexpr wstring to_wstring(int val); + constexpr wstring to_wstring(unsigned val); + constexpr wstring to_wstring(long val); + constexpr wstring to_wstring(unsigned long val); + constexpr wstring to_wstring(long long val); + constexpr wstring to_wstring(unsigned long long val); wstring to_wstring(float val); wstring to_wstring(double val); wstring to_wstring(long double val); @@ -2014,6 +2014,8 @@ \tcode{data() + size()} points at an object with value \tcode{charT()} (a ``null terminator''\indextext{string!null terminator}), and \tcode{size() <= capacity()} is \tcode{true}. +The program has undefined behavior if +the null terminator is modified to any value other than \tcode{charT()}. \indexlibraryglobal{basic_string}% @@ -2131,10 +2133,10 @@ constexpr const_reference at(size_type n) const; constexpr reference at(size_type n); - constexpr const charT& front() const; - constexpr charT& front(); - constexpr const charT& back() const; - constexpr charT& back(); + constexpr const_reference front() const; + constexpr reference front(); + constexpr const_reference back() const; + constexpr reference back(); // \ref{string.modifiers}, modifiers constexpr basic_string& operator+=(const basic_string& str); @@ -2151,6 +2153,7 @@ constexpr basic_string& append(const T& t, size_type pos, size_type n = npos); constexpr basic_string& append(const charT* s, size_type n); constexpr basic_string& append(const charT* s); + constexpr basic_string& append(const charT* s, size_type pos, size_type n); constexpr basic_string& append(size_type n, charT c); template constexpr basic_string& append(InputIterator first, InputIterator last); @@ -2171,6 +2174,7 @@ constexpr basic_string& assign(const T& t, size_type pos, size_type n = npos); constexpr basic_string& assign(const charT* s, size_type n); constexpr basic_string& assign(const charT* s); + constexpr basic_string& assign(const charT* s, size_type pos, size_type n); constexpr basic_string& assign(size_type n, charT c); template constexpr basic_string& assign(InputIterator first, InputIterator last); @@ -2238,7 +2242,7 @@ // \ref{string.ops}, string operations constexpr const charT* c_str() const noexcept; constexpr const charT* data() const noexcept; - constexpr charT* data() noexcept; + constexpr charT* data() noexcept; constexpr operator basic_string_view() const noexcept; constexpr allocator_type get_allocator() const noexcept; @@ -2795,7 +2799,7 @@ \effects Equivalent to: \begin{codeblock} -return *this = basic_string_view(il.begin(), il.size()); +return *this = basic_string_view(il.data(), il.size()); \end{codeblock} \end{itemdescr} @@ -3101,10 +3105,7 @@ \pnum \returns -\tcode{*(begin() + pos)} if \tcode{pos < size()}. Otherwise, -returns a reference to an object of type \tcode{charT} with value -\tcode{charT()}, where modifying the object to any value other than -\tcode{charT()} leads to undefined behavior. +\tcode{data()[pos]}. \pnum \throws @@ -3135,8 +3136,8 @@ \indexlibrarymember{front}{basic_string}% \begin{itemdecl} -constexpr const charT& front() const; -constexpr charT& front(); +constexpr const_reference front() const; +constexpr reference front(); \end{itemdecl} \begin{itemdescr} @@ -3151,8 +3152,8 @@ \indexlibrarymember{back}{basic_string}% \begin{itemdecl} -constexpr const charT& back() const; -constexpr charT& back(); +constexpr const_reference back() const; +constexpr reference back(); \end{itemdecl} \begin{itemdescr} @@ -3354,6 +3355,18 @@ Equivalent to: \tcode{return append(s, traits::length(s));} \end{itemdescr} +\indexlibrarymember{append}{basic_string}% +\begin{itemdecl} +constexpr basic_string& append(const charT* s, size_type pos, size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return append(basic_string_view(s).substr(pos, n));} +\end{itemdescr} + \indexlibrarymember{append}{basic_string}% \begin{itemdecl} constexpr basic_string& append(size_type n, charT c); @@ -3406,7 +3419,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return append(il.begin(), il.size());} +Equivalent to: \tcode{return append(il.data(), il.size());} \end{itemdescr} \indexlibrarymember{push_back}{basic_string}% @@ -3547,6 +3560,18 @@ Equivalent to: \tcode{return assign(s, traits::length(s));} \end{itemdescr} +\indexlibrarymember{assign}{basic_string}% +\begin{itemdecl} +constexpr basic_string& assign(const charT* s, size_type pos, size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return assign(basic_string_view(s).substr(pos, n));} +\end{itemdescr} + \indexlibrarymember{assign}{basic_string}% \begin{itemdecl} constexpr basic_string& assign(initializer_list il); @@ -3555,7 +3580,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return assign(il.begin(), il.size());} +Equivalent to: \tcode{return assign(il.data(), il.size());} \end{itemdescr} \indexlibrarymember{assign}{basic_string}% @@ -4230,7 +4255,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return replace(i1, i2, il.begin(), il.size());} +Equivalent to: \tcode{return replace(i1, i2, il.data(), il.size());} \end{itemdescr} \rSec4[string.copy]{\tcode{basic_string::copy}} @@ -4291,42 +4316,17 @@ \begin{itemdecl} constexpr const charT* c_str() const noexcept; constexpr const charT* data() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A pointer \tcode{p} such that \tcode{p + i == addressof(operator[](i))} for each -\tcode{i} in \crange{0}{size()}. - -\pnum -\complexity -Constant time. - -\pnum -\remarks -The program shall not modify any of the values stored in the character array; otherwise, the behavior is undefined. -\end{itemdescr} - -\indexlibrarymember{data}{basic_string}% -\begin{itemdecl} constexpr charT* data() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -A pointer \tcode{p} such that \tcode{p + i == addressof(operator[](i))} for each -\tcode{i} in \crange{0}{size()}. +\tcode{to_address(begin())}. \pnum \complexity Constant time. - -\pnum -\remarks -The program shall not modify the value stored at \tcode{p + size()} -to any value other than \tcode{charT()}; otherwise, the behavior is undefined. \end{itemdescr} \indexlibrarymember{operator basic_string_view}{basic_string}% @@ -4443,7 +4443,11 @@ Equivalent to: \begin{codeblock} basic_string_view s = *this, sv = t; -return s.@\placeholder{G}@(sv, pos); +if (auto result = s.@\placeholder{G}@(sv, pos); result == s.npos) { + return npos; +} else { + return result; +} \end{codeblock} \pnum @@ -5273,12 +5277,12 @@ \indexlibraryglobal{to_string}% \begin{itemdecl} -string to_string(int val); -string to_string(unsigned val); -string to_string(long val); -string to_string(unsigned long val); -string to_string(long long val); -string to_string(unsigned long long val); +constexpr string to_string(int val); +constexpr string to_string(unsigned val); +constexpr string to_string(long val); +constexpr string to_string(unsigned long val); +constexpr string to_string(long long val); +constexpr string to_string(unsigned long long val); string to_string(float val); string to_string(double val); string to_string(long double val); @@ -5360,12 +5364,12 @@ \indexlibraryglobal{to_wstring}% \begin{itemdecl} -wstring to_wstring(int val); -wstring to_wstring(unsigned val); -wstring to_wstring(long val); -wstring to_wstring(unsigned long val); -wstring to_wstring(long long val); -wstring to_wstring(unsigned long long val); +constexpr wstring to_wstring(int val); +constexpr wstring to_wstring(unsigned val); +constexpr wstring to_wstring(long val); +constexpr wstring to_wstring(unsigned long val); +constexpr wstring to_wstring(long long val); +constexpr wstring to_wstring(unsigned long long val); wstring to_wstring(float val); wstring to_wstring(double val); wstring to_wstring(long double val); @@ -5380,6 +5384,11 @@ \rSec2[basic.string.hash]{Hash support} \indexlibrarymember{hash}{basic_string}% +\indexlibrarymember{hash}{string}% +\indexlibrarymember{hash}{u8string}% +\indexlibrarymember{hash}{u16string}% +\indexlibrarymember{hash}{u32string}% +\indexlibrarymember{hash}{wstring}% \begin{itemdecl} template struct hash, A>>; template struct hash, A>>; diff --git a/source/support.tex b/source/support.tex index c6929d58ff..70028e6719 100644 --- a/source/support.tex +++ b/source/support.tex @@ -236,7 +236,7 @@ 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 @\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 @@ -568,18 +568,20 @@ \begin{codeblock} #define @\defnlibxname{cpp_lib_adaptor_iterator_pair_constructor}@ 202106L // also in \libheader{stack}, \libheader{queue} #define @\defnlibxname{cpp_lib_addressof_constexpr}@ 201603L // freestanding, also in \libheader{memory} -#define @\defnlibxname{cpp_lib_algorithm_default_value_type}@ 202403L - // also in \libheader{algorithm}, \libheader{ranges}, \libheader{string}, \libheader{deque}, \libheader{list}, \libheader{forward_list}, \libheader{vector} +#define @\defnlibxname{cpp_lib_algorithm_default_value_type}@ 202603L + // also in \libheader{algorithm}, \libheader{ranges}, \libheader{string}, \libheader{deque}, \libheader{list}, \libheader{forward_list}, \libheader{vector}, \libheader{memory} #define @\defnlibxname{cpp_lib_algorithm_iterator_requirements}@ 202207L // also in \libheader{algorithm}, \libheader{numeric}, \libheader{memory} -#define @\defnlibxname{cpp_lib_aligned_accessor}@ 202411L // also in \libheader{mdspan} +#define @\defnlibxname{cpp_lib_aligned_accessor}@ 202411L // freestanding, also in \libheader{mdspan} #define @\defnlibxname{cpp_lib_allocate_at_least}@ 202302L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_allocator_traits_is_always_equal}@ 201411L // freestanding, also in \libheader{memory}, \libheader{scoped_allocator}, \libheader{string}, \libheader{deque}, \libheader{forward_list}, \libheader{list}, // \libheader{vector}, \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set} #define @\defnlibxname{cpp_lib_any}@ 201606L // also in \libheader{any} -#define @\defnlibxname{cpp_lib_apply}@ 202506L // freestanding, also in \libheader{tuple}, \libheader{type_traits} -#define @\defnlibxname{cpp_lib_array_constexpr}@ 201811L // also in \libheader{iterator}, \libheader{array} +#define @\defnlibxname{cpp_lib_apply}@ 202506L + // freestanding, also in \libheader{tuple}, \libheader{type_traits} +#define @\defnlibxname{cpp_lib_array_constexpr}@ 201811L + // freestanding, also in \libheader{iterator}, \libheader{array} #define @\defnlibxname{cpp_lib_as_const}@ 201510L // freestanding, also in \libheader{utility} #define @\defnlibxname{cpp_lib_associative_heterogeneous_erasure}@ 202110L // also in \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set} @@ -592,7 +594,7 @@ #define @\defnlibxname{cpp_lib_atomic_lock_free_type_aliases}@ 201907L // also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_min_max}@ 202506L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_reductions}@ 202506L // freestanding, also in \libheader{atomic} -#define @\defnlibxname{cpp_lib_atomic_ref}@ 202411L // freestanding, also in \libheader{atomic} +#define @\defnlibxname{cpp_lib_atomic_ref}@ 202603L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_shared_ptr}@ 201711L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_atomic_value_initialization}@ 201911L // freestanding, also in \libheader{atomic}, \libheader{memory} #define @\defnlibxname{cpp_lib_atomic_wait}@ 201907L // freestanding, also in \libheader{atomic} @@ -608,17 +610,17 @@ #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 - // freestanding, also in \libheader{atomic}, \libheader{filesystem}, \libheader{istream}, \libheader{limits}, \libheader{locale}, \libheader{ostream}, \libheader{string}, - // \libheader{string_view} + // freestanding, also in \libheader{atomic}, \libheader{filesystem}, \libheader{iosfwd}, \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_clamp}@ 201603L // freestanding, 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 // freestanding, also in \libheader{concepts}, \libheader{compare} -#define @\defnlibxname{cpp_lib_constant_wrapper}@ 202506L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_constant_wrapper}@ 202603L // freestanding, also in \libheader{utility} #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} @@ -631,6 +633,7 @@ // 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_format}@ 202511L // also in \libheader{format} #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} @@ -639,7 +642,7 @@ #define @\defnlibxname{cpp_lib_constexpr_map}@ 202502L // also in \libheader{map} #define @\defnlibxname{cpp_lib_constexpr_memory}@ 202506L // freestanding, also in \libheader{memory} #define @\defnlibxname{cpp_lib_constexpr_new}@ 202406L // freestanding, also in \libheader{new} -#define @\defnlibxname{cpp_lib_constexpr_numeric}@ 201911L // also in \libheader{numeric} +#define @\defnlibxname{cpp_lib_constexpr_numeric}@ 201911L // freestanding, 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} @@ -668,14 +671,14 @@ #define @\defnlibxname{cpp_lib_erase_if}@ 202002L // also in \libheader{string}, \libheader{deque}, \libheader{forward_list}, \libheader{list}, \libheader{vector}, \libheader{map}, \libheader{set}, \libheader{unordered_map}, // \libheader{unordered_set} -#define @\defnlibxname{cpp_lib_exception_ptr_cast}@ 202506L // also in \libheader{exception} +#define @\defnlibxname{cpp_lib_exception_ptr_cast}@ 202603L // also in \libheader{exception} #define @\defnlibxname{cpp_lib_exchange_function}@ 201304L // freestanding, also in \libheader{utility} #define @\defnlibxname{cpp_lib_execution}@ 201902L // also in \libheader{execution} #define @\defnlibxname{cpp_lib_expected}@ 202211L // also in \libheader{expected} #define @\defnlibxname{cpp_lib_filesystem}@ 201703L // also in \libheader{filesystem} -#define @\defnlibxname{cpp_lib_flat_map}@ 202207L // also in \libheader{flat_map} -#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_flat_map}@ 202511L // also in \libheader{flat_map} +#define @\defnlibxname{cpp_lib_flat_set}@ 202511L // also in \libheader{flat_set} +#define @\defnlibxname{cpp_lib_format}@ 202603L // also in \libheader{format} #define @\defnlibxname{cpp_lib_format_path}@ 202506L // also in \libheader{filesystem} #define @\defnlibxname{cpp_lib_format_ranges}@ 202207L // also in \libheader{format} #define @\defnlibxname{cpp_lib_format_uchar}@ 202311L // also in \libheader{format} @@ -708,8 +711,8 @@ #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_function_ref}@ 202604L // freestanding, also in \libheader{functional} +#define @\defnlibxname{cpp_lib_gcd_lcm}@ 201606L // freestanding, 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 @@ -722,10 +725,12 @@ #define @\defnlibxname{cpp_lib_incomplete_container_elements}@ 201505L // also in \libheader{forward_list}, \libheader{list}, \libheader{vector} #define @\defnlibxname{cpp_lib_indirect}@ 202502L // also in \libheader{memory} -#define @\defnlibxname{cpp_lib_inplace_vector}@ 202406L // also in \libheader{inplace_vector} +#define @\defnlibxname{cpp_lib_initializer_list}@ 202511L + // freestanding, also in \libheader{initializer_list} +#define @\defnlibxname{cpp_lib_inplace_vector}@ 202603L // also in \libheader{inplace_vector} #define @\defnlibxname{cpp_lib_int_pow2}@ 202002L // freestanding, also in \libheader{bit} -#define @\defnlibxname{cpp_lib_integer_comparison_functions}@ 202002L // also in \libheader{utility} -#define @\defnlibxname{cpp_lib_integer_sequence}@ 201304L // freestanding, also in \libheader{utility} +#define @\defnlibxname{cpp_lib_integer_comparison_functions}@ 202002L // freestanding, also in \libheader{utility} +#define @\defnlibxname{cpp_lib_integer_sequence}@ 202511L // 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 // freestanding, also in \libheader{functional} @@ -741,14 +746,16 @@ #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_structural}@ 202603L + // freestanding, also in \libheader{meta} and \libheader{type_traits} +#define @\defnlibxname{cpp_lib_is_sufficiently_aligned}@ 202411L // freestanding, 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_is_within_lifetime}@ 202603L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_jthread}@ 201911L // also in \libheader{stop_token}, \libheader{thread} #define @\defnlibxname{cpp_lib_latch}@ 201907L // also in \libheader{latch} #define @\defnlibxname{cpp_lib_launder}@ 201606L // freestanding, also in \libheader{new} -#define @\defnlibxname{cpp_lib_linalg}@ 202412L // also in \libheader{linalg} +#define @\defnlibxname{cpp_lib_linalg}@ 202511L // also in \libheader{linalg} #define @\defnlibxname{cpp_lib_list_remove_return_type}@ 201806L // also in \libheader{forward_list}, \libheader{list} #define @\defnlibxname{cpp_lib_logical_traits}@ 201510L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_make_from_tuple}@ 201606L // freestanding, also in \libheader{tuple} @@ -784,27 +791,28 @@ #define @\defnlibxname{cpp_lib_ranges}@ 202406L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_as_const}@ 202311L // freestanding, also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_as_input}@ 202502L // 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_contains}@ 202207L // freestanding, also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_ranges_enumerate}@ 202302L // freestanding, also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_filter}@ 202603L // freestanding, also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_find_last}@ 202207L // freestanding, also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_ranges_fold}@ 202207L // freestanding, also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_generate_random}@ 202403L // also in \libheader{random} #define @\defnlibxname{cpp_lib_ranges_indices}@ 202506L // also in \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_iota}@ 202202L // also in \libheader{numeric} +#define @\defnlibxname{cpp_lib_ranges_iota}@ 202202L // freestanding, also in \libheader{numeric} #define @\defnlibxname{cpp_lib_ranges_join_with}@ 202202L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_repeat}@ 202207L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_reserve_hint}@ 202502L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_slide}@ 202202L // freestanding, also in \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_starts_ends_with}@ 202106L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_ranges_starts_ends_with}@ 202106L // freestanding, also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_stride}@ 202207L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // freestanding, also in \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_to_input}@ 202502L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // freestanding, also in \libheader{ranges}, \libheader{tuple}, \libheader{utility} #define @\defnlibxname{cpp_lib_ratio}@ 202306L // freestanding, also in \libheader{ratio} @@ -812,13 +820,15 @@ #define @\defnlibxname{cpp_lib_rcu}@ 202306L // also in \libheader{rcu} #define @\defnlibxname{cpp_lib_reference_from_temporary}@ 202202L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_reference_wrapper}@ 202403L // freestanding, also in \libheader{functional} -#define @\defnlibxname{cpp_lib_reflection}@ 202506L // also in \libheader{meta} +#define @\defnlibxname{cpp_lib_reflection}@ 202603L // also in \libheader{meta} #define @\defnlibxname{cpp_lib_remove_cvref}@ 201711L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_replaceable_contract_violation_handler}@ @\seebelow@ + // freestanding, also in \libheader{contracts} #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_robust_nonmodifying_seq_ops}@ 201304L // freestanding, also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_sample}@ 201603L // freestanding, also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_saturation_arithmetic}@ 202603L // freestanding, also in \libheader{numeric} #define @\defnlibxname{cpp_lib_scoped_lock}@ 201703L // also in \libheader{mutex} #define @\defnlibxname{cpp_lib_semaphore}@ 201907L // also in \libheader{semaphore} #define @\defnlibxname{cpp_lib_senders}@ 202506L // also in \libheader{execution} @@ -827,28 +837,30 @@ #define @\defnlibxname{cpp_lib_shared_ptr_weak_type}@ 201606L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_shared_timed_mutex}@ 201402L // also in \libheader{shared_mutex} #define @\defnlibxname{cpp_lib_shift}@ 202202L // also in \libheader{algorithm} -#define @\defnlibxname{cpp_lib_simd}@ 202506L // also in \libheader{simd} +#define @\defnlibxname{cpp_lib_simd}@ 202603L // also in \libheader{simd} #define @\defnlibxname{cpp_lib_simd_complex}@ 202502L // also in \libheader{simd} #define @\defnlibxname{cpp_lib_simd_permutations}@ 202506L // also in \libheader{simd} #define @\defnlibxname{cpp_lib_smart_ptr_for_overwrite}@ 202002L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_smart_ptr_owner_equality}@ 202306L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_source_location}@ 201907L // freestanding, also in \libheader{source_location} #define @\defnlibxname{cpp_lib_span}@ 202311L // freestanding, also in \libheader{span} -#define @\defnlibxname{cpp_lib_span_initializer_list}@ 202311L // freestanding, also in \libheader{span} -#define @\defnlibxname{cpp_lib_spanstream}@ 202106L // also in \libheader{spanstream} +#define @\defnlibxname{cpp_lib_spanstream}@ 202106L // also in \libheader{iosfwd}, \libheader{spanstream} #define @\defnlibxname{cpp_lib_ssize}@ 201902L // freestanding, also in \libheader{iterator} #define @\defnlibxname{cpp_lib_sstream_from_string_view}@ 202306L // also in \libheader{sstream} #define @\defnlibxname{cpp_lib_stacktrace}@ 202011L // also in \libheader{stacktrace} +#define @\defnlibxname{cpp_lib_start_lifetime}@ 202603L // freestanding, 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_stdbit_h}@ 202603L // also in \libheader{stdbit.h} +#define @\defnlibxname{cpp_lib_stdckdint_h}@ 202603L // also in \libheader{stdckdint.h} #define @\defnlibxname{cpp_lib_string_contains}@ 202011L // also in \libheader{string}, \libheader{string_view} #define @\defnlibxname{cpp_lib_string_resize_and_overwrite}@ 202110L // also in \libheader{string} #define @\defnlibxname{cpp_lib_string_subview}@ 202506L // also in \libheader{string}, \libheader{string_view} #define @\defnlibxname{cpp_lib_string_udls}@ 201304L // also in \libheader{string} #define @\defnlibxname{cpp_lib_string_view}@ 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_submdspan}@ 202603L // freestanding, also in \libheader{mdspan} +#define @\defnlibxname{cpp_lib_syncbuf}@ 201803L // also in \libheader{iosfwd}, \libheader{syncstream} #define @\defnlibxname{cpp_lib_task}@ 202506L // also in \libheader{execution} #define @\defnlibxname{cpp_lib_text_encoding}@ 202306L // also in \libheader{text_encoding} #define @\defnlibxname{cpp_lib_three_way_comparison}@ 201907L // freestanding, also in \libheader{compare} @@ -860,8 +872,6 @@ #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} @@ -873,6 +883,7 @@ #define @\defnlibxname{cpp_lib_unordered_map_try_emplace}@ 201411L // also in \libheader{unordered_map} #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_valarray}@ 202511L // also in \libheader{valarray} #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} @@ -908,6 +919,12 @@ the requirements of a hosted implementation, and to the integer literal \tcode{0} otherwise\iref{new.delete}. +\pnum +The macro \xname{cpp_lib_replaceable_contract_violation_handler} is defined to +the integer literal \tcode{202603L} +if the contract-violation handler is replaceable, and +to the integer literal \tcode{0} otherwise\iref{basic.contract.handler}. + \pnum \recommended Freestanding implementations should only define a macro from \libheader{version} @@ -993,7 +1010,9 @@ \item \indexlibraryglobal{round_to_nearest}% \tcode{round_to_nearest} -if the rounding style is to the nearest representable value +if the rounding style is to the nearest representable value; +if there are two equally near such values, +the one with an even least significant digit is chosen \item \indexlibraryglobal{round_toward_infinity}% \tcode{round_toward_infinity} @@ -1106,11 +1125,6 @@ \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} @@ -1320,10 +1334,6 @@ \begin{itemdescr} \pnum Measure of the maximum rounding error. -\begin{footnote} -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}% @@ -1430,9 +1440,6 @@ \pnum \tcode{true} if the type has a representation for a quiet (non-signaling) ``Not a Number''. -\begin{footnote} -Required by ISO/IEC 10967-1:2012. -\end{footnote} \pnum Meaningful for all floating-point types. @@ -1452,9 +1459,6 @@ \begin{itemdescr} \pnum \tcode{true} if the type has a representation for a signaling ``Not a Number''. -\begin{footnote} -Required by ISO/IEC 10967-1:2012. -\end{footnote} \pnum Meaningful for all floating-point types. @@ -1474,9 +1478,6 @@ \begin{itemdescr} \pnum Representation of positive infinity, if available. -\begin{footnote} -Required by ISO/IEC 10967-1:2012. -\end{footnote} \pnum Meaningful for all specializations for which @@ -1493,9 +1494,6 @@ \begin{itemdescr} \pnum Representation of a quiet ``Not a Number'', if available. -\begin{footnote} -Required by ISO/IEC 10967-1:2012. -\end{footnote} \pnum Meaningful for all specializations for which @@ -1512,9 +1510,6 @@ \begin{itemdescr} \pnum Representation of a signaling ``Not a Number'', if available. -\begin{footnote} -Required by ISO/IEC 10967-1:2012. -\end{footnote} \pnum Meaningful for all specializations for which @@ -1532,9 +1527,6 @@ \indextext{number!subnormal}% \pnum Minimum positive subnormal value, if available. -\begin{footnote} -Required by ISO/IEC 10967-1:2012. -\end{footnote} Otherwise, minimum positive normalized value. \pnum @@ -1570,9 +1562,6 @@ \begin{itemdescr} \pnum \tcode{true} if the set of values representable by the type is finite. -\begin{footnote} -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 precision types. @@ -1590,9 +1579,6 @@ \begin{itemdescr} \pnum \tcode{true} if the type is modulo. -\begin{footnote} -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 \crange{min()}{max()}, the value returned differs from the true value by an @@ -1619,9 +1605,6 @@ \tcode{true} 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 ISO/IEC 10967-1:2012. -\end{footnote} \pnum Meaningful for all specializations. @@ -1639,7 +1622,6 @@ \begin{footnote} Refer to \IsoFloatUndated{}. -Required by ISO/IEC 10967-1:2012. \end{footnote} \pnum @@ -1656,7 +1638,6 @@ The rounding style for the type. \begin{footnote} Equivalent to \tcode{FLT_ROUNDS}. -Required by ISO/IEC 10967-1:2012. \end{footnote} \pnum @@ -2073,10 +2054,10 @@ are also optional; however, if an implementation defines integer types with the corresponding width and no padding bits, -it defines the corresponding \grammarterm{typedef-name}s. +it declares the corresponding \grammarterm{typedef-name}s. Each of the macros listed in this subclause is defined if and only if -the implementation defines the corresponding \grammarterm{typedef-name}. +the implementation declares the corresponding \grammarterm{typedef-name}. \begin{note} The macros \tcode{INT\placeholdernc{N}_C} and \tcode{UINT\placeholdernc{N}_C} correspond to the \grammarterm{typedef-name}s @@ -2087,7 +2068,7 @@ \rSec2[stdfloat.syn]{Header \tcode{} synopsis} \pnum -The header \libheader{stdfloat} defines type aliases for +The header \libheader{stdfloat} declares type aliases for the optional extended floating-point types that are specified in \ref{basic.extended.fp}. @@ -2403,8 +2384,8 @@ 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; +constexpr void operator delete (void* ptr, void*) noexcept; +constexpr void operator delete[](void* ptr, void*) noexcept; \end{codeblock} \rSec2[new.delete]{Storage allocation and deallocation} @@ -2974,7 +2955,7 @@ \indexlibrarymember{delete}{operator}% \begin{itemdecl} -void operator delete(void* ptr, void*) noexcept; +constexpr void operator delete(void* ptr, void*) noexcept; \end{itemdecl} \begin{itemdescr} @@ -2992,7 +2973,7 @@ \indexlibrarymember{delete}{operator}% \begin{itemdecl} -void operator delete[](void* ptr, void*) noexcept; +constexpr void operator delete[](void* ptr, void*) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3177,9 +3158,12 @@ \pnum \expects \tcode{p} represents the address \placeholder{A} of a byte in memory. -An object \placeholder{X} that is within its lifetime\iref{basic.life} -and whose type is similar\iref{conv.qual} to \tcode{T} -is located at the address \placeholder{A}. +An object \placeholder{X} +whose type is similar\iref{conv.qual} to \tcode{T} +is located at the address \placeholder{A}, and +is either within its lifetime\iref{basic.life} or +is an array element subobject +whose containing array object is within its lifetime. All bytes of storage that would be reachable through\iref{basic.compound} the result are reachable through \tcode{p}. @@ -3469,6 +3453,7 @@ \indexheader{typeindex}% \begin{codeblock} #include // see \ref{compare.syn} +#include // see \ref{typeinfo.syn} namespace std { class type_index; @@ -3652,6 +3637,9 @@ static consteval source_location current() noexcept; constexpr source_location() noexcept; + constexpr source_location(const source_location&) noexcept = default; + constexpr source_location& operator=(const source_location&) noexcept = default; + // source location field access constexpr uint_least32_t line() const noexcept; constexpr uint_least32_t column() const noexcept; @@ -3668,25 +3656,14 @@ \end{codeblock} \pnum -The type \tcode{source_location} meets the -\oldconcept{DefaultConstructible}, -\oldconcept{CopyConstructible}, -\oldconcept{Copy\-Assignable}, -\oldconcept{Swappable}, and -\oldconcept{Destructible} -requirements\iref{utility.arg.requirements,swappable.requirements}. -All of the following conditions are \tcode{true}: -\begin{itemize} -\item \tcode{is_nothrow_move_constructible_v} -\item \tcode{is_nothrow_move_assignable_v} -\item \tcode{is_nothrow_swappable_v} -\end{itemize} +The type \tcode{source_location} models \libconcept{semiregular}. +\tcode{is_nothrow_swappable_v} is \tcode{true}. \begin{note} The intent of \tcode{source_location} is to have a small size and efficient copying. It is unspecified whether the copy/move constructors and the copy/move assignment operators -are trivial and/or constexpr. +are trivial. \end{note} \pnum @@ -3870,18 +3847,20 @@ terminate_handler set_terminate(terminate_handler f) noexcept; [[noreturn]] void terminate() noexcept; - constexpr int uncaught_exceptions() noexcept; + int uncaught_exceptions() noexcept; using exception_ptr = @\unspec@; - constexpr exception_ptr current_exception() noexcept; + constexpr exception_ptr @\exposid{current-exception}@() noexcept; // \expos + exception_ptr current_exception() noexcept; [[noreturn]] constexpr void rethrow_exception(exception_ptr p); template constexpr exception_ptr make_exception_ptr(E e) noexcept; - template constexpr const E* exception_ptr_cast(const exception_ptr& p) noexcept; + template + constexpr optional exception_ptr_cast(const exception_ptr& p) noexcept; template void exception_ptr_cast(const exception_ptr&&) = delete; - template [[noreturn]] constexpr void throw_with_nested(T&& t); - template constexpr void rethrow_if_nested(const E& e); + template [[noreturn]] void throw_with_nested(T&& t); + template void rethrow_if_nested(const E& e); } \end{codeblock} @@ -4106,7 +4085,7 @@ \indexlibraryglobal{uncaught_exceptions}% \begin{itemdecl} -constexpr int uncaught_exceptions() noexcept; +int uncaught_exceptions() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4175,7 +4154,8 @@ \indexlibraryglobal{current_exception}% \begin{itemdecl} -constexpr exception_ptr current_exception() noexcept; +constexpr exception_ptr @\exposid{current-exception}@() noexcept; +exception_ptr current_exception() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4245,20 +4225,15 @@ try { throw e; } catch(...) { - return current_exception(); + return @\exposid{current-exception}@(); } \end{codeblock} - -\pnum -\begin{note} -This function is provided for convenience and -efficiency reasons. -\end{note} \end{itemdescr} \indexlibraryglobal{exception_ptr_cast}% \begin{itemdecl} -template constexpr const E* exception_ptr_cast(const exception_ptr& p) noexcept; +template + constexpr optional exception_ptr_cast(const exception_ptr& p) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4275,11 +4250,12 @@ \pnum \returns -A pointer to the exception object referred to by \tcode{p}, +An \tcode{optional} containing a reference +to the exception object referred to by \tcode{p}, if \tcode{p} is not null and a handler of type \tcode{const E\&} would be a match\iref{except.handle} for that exception object. -Otherwise, \tcode{nullptr}. +Otherwise, \tcode{nullopt}. \end{itemdescr} \rSec2[except.nested]{\tcode{nested_exception}} @@ -4289,18 +4265,18 @@ namespace std { class nested_exception { public: - 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; + nested_exception() noexcept; + nested_exception(const nested_exception&) noexcept = default; + nested_exception& operator=(const nested_exception&) noexcept = default; + virtual ~nested_exception() = default; // access functions - [[noreturn]] constexpr void rethrow_nested() const; - constexpr exception_ptr nested_ptr() const noexcept; + [[noreturn]] void rethrow_nested() const; + exception_ptr nested_ptr() const noexcept; }; - template [[noreturn]] constexpr void throw_with_nested(T&& t); - template constexpr void rethrow_if_nested(const E& e); + template [[noreturn]] void throw_with_nested(T&& t); + template void rethrow_if_nested(const E& e); } \end{codeblock} @@ -4317,7 +4293,7 @@ \indexlibraryctor{nested_exception}% \begin{itemdecl} -constexpr nested_exception() noexcept; +nested_exception() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4328,7 +4304,7 @@ \indexlibrarymember{rethrow_nested}{nested_exception}% \begin{itemdecl} -[[noreturn]] constexpr void rethrow_nested() const; +[[noreturn]] void rethrow_nested() const; \end{itemdecl} \begin{itemdescr} @@ -4340,7 +4316,7 @@ \indexlibrarymember{nested_ptr}{nested_exception}% \begin{itemdecl} -constexpr exception_ptr nested_ptr() const noexcept; +exception_ptr nested_ptr() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4351,7 +4327,7 @@ \indexlibrarymember{throw_with_nested}{nested_exception}% \begin{itemdecl} -template [[noreturn]] constexpr void throw_with_nested(T&& t); +template [[noreturn]] void throw_with_nested(T&& t); \end{itemdecl} \begin{itemdescr} @@ -4374,7 +4350,7 @@ \indexlibrarymember{rethrow_if_nested}{nested_exception}% \begin{itemdecl} -template constexpr void rethrow_if_nested(const E& e); +template void rethrow_if_nested(const E& e); \end{itemdecl} \begin{itemdescr} @@ -4432,7 +4408,6 @@ 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; @@ -4551,22 +4526,6 @@ \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} @@ -4682,14 +4641,12 @@ constexpr initializer_list() noexcept; - constexpr size_t size() const noexcept; // number of elements - constexpr const E* begin() const noexcept; // first element - constexpr const E* end() const noexcept; // one past the last element + constexpr const E* data() const noexcept; + constexpr size_t size() const noexcept; + constexpr bool empty() const noexcept; + constexpr const E* begin() const noexcept; + constexpr const E* end() const noexcept; }; - - // \ref{support.initlist.range}, initializer list range access - template constexpr const E* begin(initializer_list il) noexcept; - template constexpr const E* end(initializer_list il) noexcept; } \end{codeblock} @@ -4747,43 +4704,41 @@ \tcode{begin() + size()}. \end{itemdescr} -\indexlibrarymember{size}{initializer_list}% +\indexlibrarymember{data}{initializer_list}% \begin{itemdecl} -constexpr size_t size() const noexcept; +constexpr const E* data() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -The number of elements in the array. - -\pnum -\complexity -Constant time. +\tcode{begin()}. \end{itemdescr} -\rSec2[support.initlist.range]{Initializer list range access} - -\indexlibrary{\idxcode{begin(initializer_list)}}% +\indexlibrarymember{size}{initializer_list}% \begin{itemdecl} -template constexpr const E* begin(initializer_list il) noexcept; +constexpr size_t size() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{il.begin()}. +The number of elements in the array. + +\pnum +\complexity +Constant. \end{itemdescr} -\indexlibrary{\idxcode{end(initializer_list)}}% +\indexlibrarymember{empty}{initializer_list}% \begin{itemdecl} -template constexpr const E* end(initializer_list il) noexcept; +constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{il.end()}. +\tcode{size() == 0}. \end{itemdescr} \rSec1[cmp]{Comparisons} @@ -5719,7 +5674,7 @@ \pnum There is an \impldef{total ordering of all types} total ordering of all types. For any (possibly incomplete) types \tcode{X} and \tcode{Y}, -the expression \tcode{\exposid{TYPE-ORDER}(X, Y)} is a constant expression\iref{expr.const} +the expression \tcode{\exposid{TYPE-ORDER}(X, Y)} is a constant expression\iref{expr.const.const} of type \tcode{strong_ordering}\iref{cmp.strongord}. Its value is \tcode{strong_ordering::less} if \tcode{X} precedes \tcode{Y} in this implementation-defined total order, @@ -5738,15 +5693,24 @@ \indexlibraryglobal{type_order}% \begin{itemdecl} -template - struct type_order; +template struct type_order { + static constexpr strong_ordering @\libmember{value}{type_order}@ = @\exposid{TYPE-ORDER}@(T, U); + + using @\libmember{value_type}{type_order}@ = strong_ordering; + + constexpr @\libmember{operator value_type}{type_order}@() const noexcept { return value; } + constexpr value_type @\libmember{operator()}{type_order}@() const noexcept { return value; } +}; \end{itemdecl} \begin{itemdescr} \pnum -The name \tcode{type_order} denotes a \oldconcept{BinaryTypeTrait}\iref{meta.rqmts} -with a base characteristic of -\tcode{inte\-gral_constant}. +If an explicit specialization or partial specialization of \tcode{type_order} is declared, +the program is ill-formed. + +\pnum +The templates \tcode{type_order} and \tcode{type_order_v} +may be instantiated with incomplete types as arguments. \pnum \recommended @@ -5843,8 +5807,7 @@ \begin{codeblock} namespace std { template<> - struct coroutine_handle - { + struct coroutine_handle { // \ref{coroutine.handle.con}, construct/reset constexpr coroutine_handle() noexcept; constexpr coroutine_handle(nullptr_t) noexcept; @@ -5868,8 +5831,7 @@ }; template - struct coroutine_handle - { + struct coroutine_handle { // \ref{coroutine.handle.con}, construct/reset constexpr coroutine_handle() noexcept; constexpr coroutine_handle(nullptr_t) noexcept; @@ -6181,8 +6143,7 @@ \begin{codeblock} namespace std { template<> - struct coroutine_handle - { + struct coroutine_handle { // \ref{coroutine.handle.noop.conv}, conversion constexpr operator coroutine_handle<>() const noexcept; @@ -6413,6 +6374,11 @@ In lieu of the default argument promotions specified in \IsoC{} 6.5.3.3, the definition in~\ref{expr.call} applies. \item +If more than one argument is present for \tcode{va_start} and +any of the second or subsequent arguments +expands to include unbalanced parentheses, or +a preprocessing token that does not convert to a token, +the program is ill-formed, no diagnostic required. The preprocessing tokens comprising the second and subsequent arguments to \tcode{va_start} (if any) are discarded. diff --git a/source/templates.tex b/source/templates.tex index 1cc78289d7..369755465d 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -126,6 +126,27 @@ in the declaration shall contain at most one declarator. When such a declaration is used to declare a class template, no declarator is permitted. +In a \grammarterm{template-declaration} +whose \grammarterm{declaration} is a \grammarterm{friend-type-declaration}, +the \grammarterm{friend-type-declaration} shall be of the form +\begin{ncsimplebnf} +\keyword{friend} friend-type-specifier \terminal{;} +\end{ncsimplebnf} +\begin{example} +\begin{codeblock} +template +struct C { + struct Nested { }; +}; + +template +struct S { + template + friend class C::Nested...; // error: pack expansion is not a \grammarterm{friend-type-specifier} + friend class C::Nested...; // OK, not a \grammarterm{template-declaration} +}; +\end{codeblock} +\end{example} \pnum \indextext{template name!linkage of}% @@ -172,7 +193,8 @@ \begin{itemize} \item a template, \item an entity defined\iref{basic.def} or created\iref{class.temporary} - within the \grammarterm{compound-statement} + within the + \grammarterm{for-range-declaration} or \grammarterm{compound-statement} of an \grammarterm{expansion-statement}\iref{stmt.expand}, \item an entity defined or created in a templated entity, \item a member of a templated entity, @@ -496,15 +518,23 @@ \end{itemize} \pnum +Certain constructs refer to template parameter objects, +which are distinct objects with static storage duration and non-volatile const type. +No two such objects have template-argument-equivalent values\iref{temp.type}. An \grammarterm{id-expression} naming a constant template parameter of class type \tcode{T} -denotes a static storage duration object of type \tcode{const T}, -known as a \defn{template parameter object}, -which is template-argument-equivalent\iref{temp.type} to +denotes the template parameter object of type \tcode{const T}, +which is template-argument-equivalent to the corresponding template argument after it has been converted to the type of the template parameter\iref{temp.arg.nontype}. -No two template parameter objects are template-argument-equivalent. +\begin{note} +There can be template parameter objects of array type\iref{meta.define.static}, +but such an object is never denoted by an \grammarterm{id-expression} +that names a constant template parameter. +Such an object can have an address that +is not unique among all other in-lifetime objects\iref{intro.object}. +\end{note} \begin{note} If an \grammarterm{id-expression} names a non-reference constant template parameter, @@ -572,9 +602,8 @@ 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 template argument shall not be specified for +a template parameter pack\iref{temp.variadic}. A default template argument may be specified in a template declaration. A default template argument shall not be specified in the \grammarterm{template-parameter-list}{s} @@ -715,13 +744,18 @@ \begin{bnf} \nontermdef{template-argument}\br + template-argument-name\br constant-expression\br type-id\br - \opt{nested-name-specifier} template-name\br - nested-name-specifier \terminal{template} template-name\br braced-init-list \end{bnf} +\begin{bnf} +\nontermdef{template-argument-name}\br + \opt{nested-name-specifier} identifier\br + nested-name-specifier \terminal{template} identifier +\end{bnf} + \pnum \indextext{component name}% The component name of a @@ -889,6 +923,11 @@ \end{codeblock} \end{example} +\pnum +The component names of a \grammarterm{template-argument-name} are +those of its \grammarterm{nested-name-specifier} (if any) and +its \grammarterm{identifier}. + \pnum A \grammarterm{template-id} or \grammarterm{splice-specialization-specifier} is \defnx{valid}{\idxgram{template-id}!valid} if @@ -918,7 +957,7 @@ \grammarterm{splice-specialization-specifier} shall be valid unless its respective \grammarterm{template-name} or \grammarterm{splice-specifier} -names or designates a function template\iref{temp.deduct}. +designates a function template\iref{temp.deduct}. \begin{example} \begin{codeblock} template class X; @@ -1052,6 +1091,32 @@ the $n^\text{th}$ template argument is a pack expansion whose pattern is the name of the template parameter pack. +\pnum +If a \grammarterm{template-argument} $A$ +matches the form \grammarterm{template-argument-name}, +it is interpreted as such; +the \grammarterm{identifier} is looked up +and its meaning is determined as follows: +\begin{itemize} +\item +If lookup finds an injected-class-name\iref{temp.local}, then: +\begin{itemize} +\item +When $A$ is for a type template template parameter, +$A$ denotes the corresponding class template. +\item +Otherwise, it denotes a \grammarterm{type-name}. +\end{itemize} +\item +Otherwise, if lookup finds a template, +$A$ denotes that template. +\item +Otherwise, if lookup finds a type alias or a type, +$A$ denotes the underlying type and is interpreted as a \grammarterm{type-id}. +\item +Otherwise, $A$ is interpreted as an expression. +\end{itemize} + \pnum In a \grammarterm{template-argument}, @@ -1075,7 +1140,7 @@ template void f(); void g() { - f(); // \tcode{int()} is a type-id: call the first \tcode{f()} + f(); // \tcode{int()} is a \grammarterm{type-id}: call the first \tcode{f()} } \end{codeblock} \end{example} @@ -1258,7 +1323,7 @@ is determined from its template argument $A$ as follows. If \tcode{T} is not a class type and $A$ is not a \grammarterm{braced-init-list}, -$A$ shall be a converted constant expression\iref{expr.const} +$A$ shall be a converted constant expression\iref{expr.const.const} of type \tcode{T}; the value of $P$ is $A$ (as converted). \pnum @@ -1287,7 +1352,7 @@ \item the full-expression of an invented \grammarterm{init-declarator} for the initialization would not be a constant expression -when interpreted as a \grammarterm{constant-expression}\iref{expr.const}, or +when interpreted as a \grammarterm{constant-expression}\iref{expr.const.const}, or \item the initialization would cause $P$ to not be template-argument-equivalent\iref{temp.type} to \tcode{v}, \end{itemize} @@ -1430,11 +1495,14 @@ template parameter shall be the name of a template. For a \grammarterm{type-tt-parameter}, -the name shall denote a class template or alias template. +the name shall denote a class template, alias template, or +type template template parameter. For a \grammarterm{variable-tt-parameter}, -the name shall denote a variable template. +the name shall denote a variable template or +variable template template parameter. For a \grammarterm{concept-tt-parameter}, -the name shall denote a concept. +the name shall denote a concept or +concept template parameter. Only primary templates are considered when matching the template template argument with the corresponding parameter; partial specializations are not considered even if their parameter lists match that of the template template @@ -1874,7 +1942,7 @@ the normal form\iref{temp.constr.normal} of the concept-id after substitution of \tcode{C}. \begin{note} -Normalization of \tcode{CI} might be ill-formed; no diagnostics is required. +Normalization of \tcode{CI} can be ill-formed with no diagnostic required. \end{note} \pnum @@ -2128,7 +2196,7 @@ in the normal form \tcode{N} of \tcode{CE}, appearances of \tcode{C}{'s} template parameters in the parameter mappings of the atomic constraints in \tcode{N} -with their respective arguments from \tcode{C}. +with their respective arguments from \tcode{CI}. If any such substitution results in an invalid type or expression, the program is ill-formed; no diagnostic is required. \end{itemize} @@ -2508,7 +2576,9 @@ they are of reference type and they refer to the same object or function, or \item -they are of array type and their corresponding elements are template-argument-equivalent, +they are of array type and their corresponding elements are either +both within their lifetimes and template-argument-equivalent or +both not within their lifetimes, \begin{footnote} An array as a \grammarterm{template-parameter} decays to a pointer. \end{footnote} @@ -2612,31 +2682,30 @@ which shall be a class or variable template. \pnum +A \defnadj{separately instantiated}{construct} +of a templated function \tcode{F} is a +\begin{itemize} +\item default argument, +\item \grammarterm{noexcept-specifier}, or +\item \grammarterm{function-contract-specifier} +\end{itemize} +of \tcode{F}. For purposes of name lookup and instantiation, -default arguments, -\grammarterm{type-constraint}{s}, -\grammarterm{requires-clause}{s}\iref{temp.pre}, -and -\grammarterm{noexcept-specifier}{s} -of function templates -and -of member functions of class templates +separately instantiated constructs, +\grammarterm{type-constraint}{s}, and +\grammarterm{requires-clause}{s}\iref{temp.pre} are considered definitions; each -default argument, -\grammarterm{type-constraint}, -\grammarterm{requires-clause}, -or -\grammarterm{noexcept-specifier} +separately instantiated construct, +\grammarterm{type-constraint}, or +\grammarterm{requires-clause} is a separate definition which is unrelated to the templated function definition or to any other -default arguments, -\grammarterm{type-constraint}{s}, -\grammarterm{requires-clause}{s}, -or -\grammarterm{noexcept-specifier}{s}. +separately instantiated constructs, +\grammarterm{type-constraint}{s}, or +\grammarterm{requires-clause}{s}. For the purpose of instantiation, the substatements of a constexpr if statement\iref{stmt.if} are considered definitions. For the purpose of name lookup and instantiation, @@ -4223,7 +4292,7 @@ \end{codeblock} \end{example} \indextext{expression!functionally equivalent|see{functionally equivalent, expressions}}% -Two potentially-evaluated expressions involving template parameters that are not equivalent are +Two potentially evaluated expressions involving template parameters that are not equivalent are \defnx{functionally equivalent}{functionally equivalent!expressions} if, for any given set of template arguments, the evaluation of the expression results in the same value. @@ -4339,10 +4408,10 @@ \item when the address of a function template specialization is taken; \item -when a placement operator delete that is a +when a placement deallocation function that is a function template specialization -is selected to match a placement operator new\iref{basic.stc.dynamic.deallocation,expr.new}; +is selected to match a placement allocation function\iref{basic.stc.dynamic.deallocation,expr.new}; \item when a friend function declaration\iref{temp.friend}, an explicit instantiation\iref{temp.explicit} or an explicit specialization\iref{temp.expl.spec} refers to @@ -4373,11 +4442,9 @@ variable template, or concept, respectively, and substitute it for each occurrence of that parameter in the function type of the template. -\begin{note} -The type replacing the placeholder +The type replacing a placeholder in the type of the value synthesized for a constant template parameter -is also a unique synthesized type. -\end{note} +is a unique synthesized type. \pnum %FIXME: What's a "synthesized template"? Do we mean the synthesized @@ -4626,9 +4693,11 @@ the alias template. Any other \grammarterm{template-id} that names a specialization of an alias template is -a \grammarterm{typedef-name} for a type alias. +a \grammarterm{typedef-name} for a type alias; +such a \grammarterm{template-id} is ill-formed if +forming the associated type results in substitution failure. \begin{note} -An alias template name is never deduced. +The alias template name is not deduced from such a type\iref{temp.deduct.type}. \end{note} \begin{example} \begin{codeblock} @@ -5065,7 +5134,7 @@ \item an instantiation uses a default argument or default template argument that had not been defined at the point at which the template was defined, or -\item constant expression evaluation\iref{expr.const} within the template +\item constant expression evaluation\iref{expr.const.core} within the template instantiation uses \begin{itemize} \item the value of a const object of integral or unscoped enumeration type or @@ -5296,7 +5365,7 @@ \defnx{type-dependent}{expression!type-dependent} (that is, its type may depend on a template parameter) or \defnx{value-dependent}{expression!value-dependent} -(that is, its value when evaluated as a constant expression\iref{expr.const} +(that is, its value when evaluated as a constant expression\iref{expr.const.const} may depend on a template parameter) as described below. @@ -5492,7 +5561,7 @@ its lookup context, if it is a qualified name, is the current instantiation, and \item -lookup for it finds any member of a class that is the current instantiation +lookup for it finds any member of a class that is the current instantiation. \end{itemize} \begin{example} \begin{codeblock} @@ -5595,7 +5664,9 @@ is dependent if \begin{itemize} \item -it has a dependent initializer, or +it has a dependent initializer, +\item +it refers to a type template template parameter, or \item it refers to an alias template that is a member of the current instantiation and @@ -5709,7 +5780,7 @@ a structured binding declaration\iref{dcl.struct.bind} whose \grammarterm{brace-or-equal-initializer} is type-dependent, \item -associated by name lookup with a pack, +associated by name lookup with a structured binding pack, \begin{example} \begin{codeblock} struct C { }; @@ -5751,8 +5822,8 @@ of an \grammarterm{expansion-statement} $S$ if the type specified for $N$ contains a placeholder type and either \begin{itemize} -\item the \grammarterm{expansion-initializer} of $S$ is type-dependent or -\item $S$ is not an iterating expansion statement, or +\item $S$ is not an iterating expansion statement or +\item the \grammarterm{expansion-initializer} of $S$ is type-dependent, or \end{itemize} \item dependent @@ -5811,9 +5882,15 @@ \pnum A class member access expression\iref{expr.ref} is type-dependent if -the terminal name of its \grammarterm{id-expression}, if any, is dependent or +\begin{itemize} +\item +the terminal name of its \grammarterm{id-expression}, if any, is dependent, +\item +its \grammarterm{splice-expression}, if any, is type-dependent, or +\item the expression refers to a member of the current instantiation and the type of the referenced member is dependent. +\end{itemize} \begin{note} In an expression of the form \tcode{x.y} @@ -5882,7 +5959,7 @@ it names a static member function that is a dependent member of the current instantiation, or \item -it names a potentially-constant variable\iref{expr.const} +it names a potentially-constant variable\iref{expr.const.init} that is initialized with an expression that is value-dependent. \end{itemize} @@ -5939,8 +6016,6 @@ \keyword{sizeof} \terminal{...} \terminal{(} identifier \terminal{)}\br fold-expression \end{ncsimplebnf} -unless the \grammarterm{identifier} is a structured binding pack -whose initializer is not dependent. \pnum A \grammarterm{noexcept-expression}\iref{expr.unary.noexcept} @@ -5953,7 +6028,7 @@ instantiation is value-dependent. An expression of the form \tcode{\&}\grammarterm{cast-expression} is also value-dependent if evaluating \grammarterm{cast-expression} -as a core constant expression\iref{expr.const} succeeds and +as a core constant expression\iref{expr.const.core} succeeds and the result of the evaluation refers to a templated entity that is an object with static or thread storage duration or a member function. @@ -5962,12 +6037,13 @@ \begin{itemize} \item it is of the form \tcode{\caret\caret \grammarterm{reflection-name}} and -the \grammarterm{reflection-name} +either lookup for the \grammarterm{reflection-name} finds a declaration that +inhabits a scope corresponding to a templated entity or +the \grammarterm{reflection-name} is \begin{itemize} -\item is a dependent qualified name, -\item is a dependent \grammarterm{namespace-name}, -\item is the name of a template parameter, or -\item names a dependent member of the current instantiation\iref{temp.dep.type}, +\item a dependent qualified name, +\item a dependent \grammarterm{namespace-name}, or +\item the name of a template parameter, \end{itemize} \item it is of the form \tcode{\caret\caret \grammarterm{type-id}} and @@ -6084,7 +6160,7 @@ A template argument is also dependent if it is a pack expansion. \pnum -A template template parameter is dependent if +A template template argument is dependent if it names a template parameter or its terminal name is dependent. @@ -6096,11 +6172,13 @@ For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, -if the specialization is implicitly instantiated because it is referenced -from within another template specialization and -the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation -of the enclosing specialization. +of the enclosing specialization if +\begin{itemize} +\item the specialization is implicitly instantiated +because it is referenced from within another template specialization and +\item the context from which it is referenced depends on a template parameter. +\end{itemize} Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization. @@ -6114,12 +6192,16 @@ \pnum For a \grammarterm{noexcept-specifier} of a function template -specialization or specialization of a member function of a class template, if -the \grammarterm{noexcept-specifier} is implicitly instantiated because -it is needed by another template specialization and the context that requires -it depends on a template parameter, the point of instantiation of the +specialization or specialization of a member function of a class template, +the point of instantiation of the \grammarterm{noexcept-specifier} is the point of instantiation of the -specialization that requires it. Otherwise, the point of instantiation for such +specialization that requires it if +\begin{itemize} +\item the \grammarterm{noexcept-specifier} is implicitly instantiated +because it is needed by another template specialization and +\item the context that requires it depends on a template parameter. +\end{itemize} +Otherwise, the point of instantiation for such a \grammarterm{noexcept-specifier} immediately follows the namespace scope declaration or definition that requires the \grammarterm{noexcept-specifier}. @@ -6127,14 +6209,16 @@ \pnum For a class template specialization, a class member template specialization, or a specialization for a class member of a class template, -if the specialization is implicitly instantiated because it is referenced -from within another template specialization, -if the context from which the specialization is referenced depends on a -template parameter, -and if the specialization is not instantiated previous to the instantiation of -the enclosing template, the point of instantiation is immediately before the point of instantiation of -the enclosing template. +the enclosing template if +\begin{itemize} +\item the specialization is implicitly instantiated +because it is referenced from within another template specialization, +\item the context from which the specialization is referenced +depends on a template parameter, and +\item the specialization is not instantiated +previous to the instantiation of the enclosing template. +\end{itemize} Otherwise, the point of instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization. @@ -6516,7 +6600,7 @@ declared with a type deduced from its initializer or return value\iref{dcl.spec.auto}, \item -a potentially-constant variable\iref{expr.const}, or +a potentially-constant variable\iref{expr.const.init}, or \item a specialization of a templated class. \end{itemize} @@ -6566,19 +6650,6 @@ X ch; // error: incomplete type \tcode{X} \end{codeblock} \end{example} -\begin{note} -Within a template declaration, -a local class\iref{class.local} or enumeration and the members of -a local class are never considered to be entities that can be separately -instantiated (this includes their default arguments, -\grammarterm{noexcept-specifier}{s}, and non-static data member -initializers, if any, -but not their \grammarterm{type-constraint}{s} or \grammarterm{requires-clause}{s}). -As a result, the dependent names are looked up, the -semantic constraints are checked, and any templates used are instantiated as -part of the instantiation of the entity within which the local class or -enumeration is declared. -\end{note} \pnum The implicit instantiation of a class template specialization causes @@ -6598,10 +6669,6 @@ unscoped member enumerations, and member anonymous unions. \end{itemize} -The implicit instantiation of a class template specialization -does not cause the implicit instantiation of -default arguments or \grammarterm{noexcept-specifier}{s} -of the class member functions. \begin{example} \begin{codeblock} template @@ -6665,11 +6732,6 @@ implicitly instantiated when it is referenced in a context that requires a function definition to exist or if the existence of the definition affects the semantics of the program. -Unless a call is to a function template explicit specialization or -to a member function of an explicitly specialized class template, -a default argument for a function template or a member function of a -class template is implicitly instantiated when the function is -called in a context that requires the value of the default argument. \begin{note} An inline function that is the subject of an explicit instantiation declaration @@ -6726,7 +6788,7 @@ The existence of a definition of a variable or function is considered to affect the semantics of the program if the variable or function -is needed for constant evaluation by an expression\iref{expr.const}, +is needed for constant evaluation by an expression\iref{expr.const.defns}, even if constant evaluation of the expression is not required or if constant expression evaluation does not use the definition. @@ -6800,7 +6862,25 @@ causes specializations in the default member initializer to be instantiated. \pnum -If a templated function +The separately instantiated constructs\iref{temp.decls.general} +of a templated function \tcode{F} that is either +\begin{itemize} +\item +a member of a local class or +\item +the function call operator of the closure type +of a non-generic \grammarterm{lambda-expression} +\end{itemize} +are instantiated when the declaration of \tcode{F} is instantiated. +\begin{note} +For the purposes of instantiation, +these constructs are still considered separately +from the function to which they belong. +\end{note} + +\pnum +Other than as specified above, +when a templated function \tcode{f} is called in a way that requires a default argument to be used, the dependent names are looked up, the semantics constraints are checked, @@ -6819,7 +6899,9 @@ \tcode{f}. \pnum +\begin{note} Each default argument is instantiated independently. +\end{note} \begin{example} \begin{codeblock} template void f(T x, T y = ydef(T()), T z = zdef(T())); @@ -6837,16 +6919,16 @@ \end{example} \pnum -The \grammarterm{noexcept-specifier} and \grammarterm{function-contract-specifier}s -of a function template specialization -are not instantiated along with the function declaration; -they are instantiated -when needed\iref{except.spec,dcl.contract.func}. If such a -specifier is needed but has not yet been -instantiated, the dependent names are looked up, the semantics constraints are -checked, and the instantiation of any template used in the -specifier is done as if it were being done as part -of instantiating the declaration of the specialization at that point. +Other than as specified above, +the separately instantiated constructs +of a specialization of a templated function +are instantiated only when needed\iref{except.spec,dcl.contract.func}. +When such a construct is instantiated, +the dependent names are looked up, +the semantics constraints are checked, and +the instantiation of any template used in the construct +is done as if it were being done as part of instantiating the declaration +of the specialization at that point. \pnum \begin{note} @@ -7657,7 +7739,7 @@ int j = f(5.6); // error: \tcode{X} cannot be deduced f(f); // \tcode{Y} for outer \tcode{f} deduced as \tcode{int (*)(bool)} f(f); // error: \tcode{f} does not denote a single function template specialization - int k = g(5.6); // \tcode{Y} deduced as double; \tcode{Z} deduced as an empty sequence + int k = g(5.6); // \tcode{Y} deduced as \tcode{double}; \tcode{Z} deduced as an empty sequence f(g); // \tcode{Y} for outer \tcode{f} deduced as \tcode{int (*)(bool)}, // \tcode{Z} deduced as an empty sequence } @@ -7970,20 +8052,40 @@ \end{note} Invalid types and expressions can result in a deduction failure only in the immediate context of the deduction substitution loci. +The \defnadj{immediate}{context} of a deduction substitution locus +is that deduction substitution locus, +excluding bodies of \grammarterm{lambda-expression}s and separately instantiated constructs. +\begin{example} +\begin{codeblock} +template +T* fun(T&& v); // \#1: the deduction substitution locus is the function type + // ``function of (rvalue reference to \tcode{T}) returning pointer to \tcode{T}'' + +void fun(...); // \#2 + +void test() +{ + int i; + fun(i); // selects \#2 (forming the type ``pointer to reference to \tcode{int}'' fails in \#1) +} +\end{codeblock} +\end{example} +\begin{note} +Separately instantiated constructs are excluded from the immediate contexts +even if they are instantiated at the same time. +\end{note} \begin{note} The substitution into types and expressions can result -in effects such as the instantiation of class template specializations and/or -function template specializations, the generation of implicitly-defined functions, -etc. Such effects are not in the ``immediate context'' and can result in the -program being ill-formed. +in effects such as the instantiation of template specializations, +the generation of implicitly-defined functions, etc. +Such effects are not in the immediate context +and can result in the program being ill-formed. \end{note} \pnum -When substituting into a \grammarterm{lambda-expression}, -substitution into its body is not in the immediate context. \begin{note} -The intent is to avoid requiring implementations to deal with -substitution failure involving arbitrary statements. +No \grammarterm{statement} is ever in the immediate context +of a deduction substitution locus. \begin{example} \begin{codeblock} template @@ -7999,17 +8101,17 @@ template auto h(T) -> decltype([x = T::invalid]() { }); void h(...); -h(0); // error: invalid expression not part of the immediate context +h(0); // OK, calls \tcode{h(...)} template auto i(T) -> decltype([]() -> typename T::invalid { }); void i(...); -i(0); // error: invalid expression not part of the immediate context +i(0); // OK, calls \tcode{i(...)} template - auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t)); // \#1 -void j(...); // \#2 -j(0); // deduction fails on \#1, calls \#2 + auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t)); +void j(...); +j(0); // OK, calls \tcode{j(...)} \end{codeblock} \end{example} \end{note} @@ -8523,7 +8625,7 @@ \tcode{P}) with the type specified by the \grammarterm{conversion-type-id} of the \grammarterm{conversion-function-id} being looked up -(call it \tcode{A}) as described in~\ref{temp.deduct.type}. +(call it \tcode{A}), as described in~\ref{temp.deduct.type}. If the \grammarterm{conversion-function-id} is constructed during overload resolution\iref{over.match.funcs}, the rules in the remainder of this subclause apply. @@ -8703,18 +8805,16 @@ \end{itemize} \pnum -Using the resulting types -\tcode{P} -and -\tcode{A}, +If \tcode{A} was transformed from a function parameter pack and +\tcode{P} is not a parameter pack, +type deduction fails. +Otherwise, using the resulting types \tcode{P} and \tcode{A}, the deduction is then done as described in~\ref{temp.deduct.type}. If \tcode{P} is a function parameter pack, the type \tcode{A} of each remaining parameter type of the argument template is compared with the type \tcode{P} of the \grammarterm{declarator-id} of the function parameter pack. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. -Similarly, if \tcode{A} was transformed from a function parameter pack, -it is compared with each remaining parameter type of the parameter template. If deduction succeeds for a given type, the type from the argument template is considered to be at least as specialized as the type from the parameter template. @@ -9391,11 +9491,16 @@ \end{note} \pnum -If \tcode{P} has a form that contains \tcode{}, and -if the type of \tcode{i} differs from the type +If \tcode{P} has a form that contains \tcode{}, +deduction fails unless the type of \tcode{i} is the same as that of the corresponding template parameter +\tcode{p} in the specialization (from \tcode{A}) of the template named by the enclosing \grammarterm{simple-template-id} or -\grammarterm{splice-specialization-specifier}, deduction fails. +\grammarterm{splice-specialization-specifier}; +if the declared type of \tcode{i} contains a placeholder type, +the corresponding template argument for the purposes of +placeholder type deduction\iref{dcl.type.auto.deduct} +is an \grammarterm{id-expression} for \tcode{p}. If \tcode{P} has a form that contains \tcode{[i]}, and if the type of \tcode{i} is not an integral type, deduction fails. \begin{footnote} @@ -9415,15 +9520,54 @@ template void f(A); void k1() { A<1> a; - f(a); // error: deduction fails for conversion from \tcode{int} to \tcode{short} - f<1>(a); // OK + f(a); // error: deduction fails for conversion from \tcode{int} to \tcode{short} + f<1>(a); // OK } template class B { }; template void g(B); void k2() { B<1> b; - g(b); // OK, cv-qualifiers are ignored on template parameter types + g(b); // OK, cv-qualifiers are ignored on template parameter types +} + +template struct C; +template void f(C *); +void g(C<0LL> *ap) { + f(ap); // OK, deduces \tcode{long long} value from \tcode{0LL} +} + +template struct D; +template void f(D *); +void g(D<0LL> *ap) { + f(ap); // OK, deduces \tcode{x} as an \tcode{int} value +} + +template struct E; +template void f(E *); +int v; +void g(E *bp) { + f(bp); // error: type \tcode{int} of \tcode{x} does not match the \tcode{int \&} type +} // of the template parameter in the \tcode{E} specialization of \tcode{E} + +template struct F; +template void f(F *); +int i; +void g(F *ap) { + f(ap); // OK, deduces \tcode{x} as a constant template parameter of type \tcode{const int \&} +} + +template struct G; +template long *f(G *); // \#1 +template short *f(G *); // \#2 + +const int j = 0; +short *g(G<(j)> *ap) { // OK, \tcode{q} has type \tcode{const int \&} + return f(ap); // OK, only \#2 matches +} + +long *g(G *ap) { // OK, \tcode{q} has type \tcode{int} + return f(ap); // OK, \#1 is more specialized } \end{codeblock} \end{example} @@ -9518,12 +9662,12 @@ for explicit instantiations\iref{temp.explicit}, explicit specializations\iref{temp.expl.spec}, and certain friend declarations\iref{temp.friend}. This is also done to determine whether a deallocation function template specialization matches a placement -\tcode{operator new}\iref{basic.stc.dynamic.deallocation,expr.new}. +allocation function\iref{basic.stc.dynamic.deallocation,expr.new}. In all these cases, \tcode{P} is the type of the function template being considered as a potential match and \tcode{A} is either the function type from the declaration or the type of the deallocation function that would match the placement -\tcode{operator new} as described in~\ref{expr.new}. The +allocation function as described in~\ref{expr.new}. The deduction is done as described in~\ref{temp.deduct.type}. \pnum diff --git a/source/text.tex b/source/text.tex index f8e942ea4c..b862e007c3 100644 --- a/source/text.tex +++ b/source/text.tex @@ -10,8 +10,8 @@ \begin{libsumtab}{Text library summary}{text.summary} \ref{charconv} & Primitive numeric conversions & \tcode{} \\ \rowsep \ref{localization} & Localization library & \tcode{}, \tcode{} \\ \rowsep -\ref{format} & Formatting & \tcode{} \\ \rowsep \ref{text.encoding} & Text encodings identification & \tcode{} \\ \rowsep +\ref{format} & Formatting & \tcode{} \\ \rowsep \ref{re} & Regular expressions library & \tcode{} \\ \rowsep \ref{text.c.strings} & Null-terminated sequence utilities & \tcode{}, \tcode{}, \tcode{}, \tcode{}, \tcode{} \\ @@ -25,7 +25,7 @@ When a function is specified with a type placeholder of \tcode{\placeholder{integer-type}}, the implementation provides overloads -for \tcode{char} and all cv-unqualified signed and unsigned integer types +for \tcode{char} and all signed and unsigned integer types in lieu of \tcode{\placeholder{integer-type}}. When a function is specified with a type placeholder of \tcode{\placeholder{floating-point-type}}, @@ -289,7 +289,10 @@ in the \tcode{"C"} locale for the given nonzero base, as described for \tcode{strtol}, -except that no \tcode{"0x"} or \tcode{"0X"} prefix shall appear +except that +no \tcode{"0b"} or \tcode{"0B"} prefix shall appear +if the value of \tcode{base} is 2, +no \tcode{"0x"} or \tcode{"0X"} prefix shall appear if the value of \tcode{base} is 16, and except that \tcode{'-'} is the only sign that may appear, @@ -1302,7 +1305,7 @@ \pnum The \tcode{put()} members make no provision for error reporting. -(Any failures of the OutputIterator argument can be extracted from +(Any failures of the \tcode{OutputIterator} argument can be extracted from the returned iterator.) The \tcode{get()} members take an \tcode{ios_base::iostate\&} argument whose value they ignore, @@ -1351,44 +1354,44 @@ \begin{codeblock} namespace std { template - class ctype : public locale::facet, public ctype_base { - public: - using @\libmember{char_type}{ctype}@ = charT; + class ctype : public locale::facet, public ctype_base { + public: + using @\libmember{char_type}{ctype}@ = charT; - explicit ctype(size_t refs = 0); + 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; + 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; + 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 @\libmember{id}{ctype}@; + static locale::id @\libmember{id}{ctype}@; - 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; - }; + 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} @@ -1682,15 +1685,15 @@ \begin{codeblock} namespace std { template - class ctype_byname : public ctype { - public: - using @\libmember{mask}{ctype_byname}@ = ctype::mask; - explicit ctype_byname(const char*, size_t refs = 0); - explicit ctype_byname(const string&, size_t refs = 0); + class ctype_byname : public ctype { + public: + using @\libmember{mask}{ctype_byname}@ = ctype::mask; + explicit ctype_byname(const char*, size_t refs = 0); + explicit ctype_byname(const string&, size_t refs = 0); - protected: - ~ctype_byname(); - }; + protected: + ~ctype_byname(); + }; } \end{codeblock} @@ -1702,46 +1705,46 @@ \begin{codeblock} namespace std { template<> - class ctype : public locale::facet, public ctype_base { - public: - using @\libmember{char_type}{ctype}@ = char; + class ctype : public locale::facet, public ctype_base { + public: + using @\libmember{char_type}{ctype}@ = char; - explicit ctype(const mask* tab = nullptr, bool del = false, size_t refs = 0); + 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; + 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 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; + 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 @\libmember{id}{ctype}@; - static const size_t @\libmember{table_size}{ctype}@ = @\impdef@; + static locale::id @\libmember{id}{ctype}@; + static const size_t @\libmember{table_size}{ctype}@ = @\impdef@; - const mask* table() const noexcept; - static const mask* classic_table() noexcept; + 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; - }; + 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} @@ -1964,54 +1967,54 @@ }; template - class codecvt : public locale::facet, public codecvt_base { - public: - using @\libmember{intern_type}{codecvt}@ = internT; - using @\libmember{extern_type}{codecvt}@ = externT; - using @\libmember{state_type}{codecvt}@ = stateT; + class codecvt : public locale::facet, public codecvt_base { + public: + using @\libmember{intern_type}{codecvt}@ = internT; + using @\libmember{extern_type}{codecvt}@ = externT; + using @\libmember{state_type}{codecvt}@ = stateT; - explicit codecvt(size_t refs = 0); + 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 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 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; + 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; + 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 @\libmember{id}{codecvt}@; + static locale::id @\libmember{id}{codecvt}@; - 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; - }; + 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} @@ -2370,14 +2373,14 @@ \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); + 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(); - }; + protected: + ~codecvt_byname(); + }; } \end{codeblock} @@ -5023,7 +5026,7 @@ \begin{codeblock} namespace std { struct text_encoding { - static constexpr size_t max_name_length = 63; + static constexpr size_t @\libmember{max_name_length}{text_encoding}@ = 63; // \ref{text.encoding.id}, enumeration \tcode{text_encoding::id} enum class id : int_least32_t { @@ -5429,264 +5432,264 @@ \begin{codeblock} namespace std { enum class text_encoding::id : int_least32_t { - other = 1, - unknown = 2, - ASCII = 3, - ISOLatin1 = 4, - ISOLatin2 = 5, - ISOLatin3 = 6, - ISOLatin4 = 7, - ISOLatinCyrillic = 8, - ISOLatinArabic = 9, - ISOLatinGreek = 10, - ISOLatinHebrew = 11, - ISOLatin5 = 12, - ISOLatin6 = 13, - ISOTextComm = 14, - HalfWidthKatakana = 15, - JISEncoding = 16, - ShiftJIS = 17, - EUCPkdFmtJapanese = 18, - EUCFixWidJapanese = 19, - ISO4UnitedKingdom = 20, - ISO11SwedishForNames = 21, - ISO15Italian = 22, - ISO17Spanish = 23, - ISO21German = 24, - ISO60DanishNorwegian = 25, - ISO69French = 26, - ISO10646UTF1 = 27, - ISO646basic1983 = 28, - INVARIANT = 29, - ISO2IntlRefVersion = 30, - NATSSEFI = 31, - NATSSEFIADD = 32, - ISO10Swedish = 35, - KSC56011987 = 36, - ISO2022KR = 37, - EUCKR = 38, - ISO2022JP = 39, - ISO2022JP2 = 40, - ISO13JISC6220jp = 41, - ISO14JISC6220ro = 42, - ISO16Portuguese = 43, - ISO18Greek7Old = 44, - ISO19LatinGreek = 45, - ISO25French = 46, - ISO27LatinGreek1 = 47, - ISO5427Cyrillic = 48, - ISO42JISC62261978 = 49, - ISO47BSViewdata = 50, - ISO49INIS = 51, - ISO50INIS8 = 52, - ISO51INISCyrillic = 53, - ISO54271981 = 54, - ISO5428Greek = 55, - ISO57GB1988 = 56, - ISO58GB231280 = 57, - ISO61Norwegian2 = 58, - ISO70VideotexSupp1 = 59, - ISO84Portuguese2 = 60, - ISO85Spanish2 = 61, - ISO86Hungarian = 62, - ISO87JISX0208 = 63, - ISO88Greek7 = 64, - ISO89ASMO449 = 65, - ISO90 = 66, - ISO91JISC62291984a = 67, - ISO92JISC62991984b = 68, - ISO93JIS62291984badd = 69, - ISO94JIS62291984hand = 70, - ISO95JIS62291984handadd = 71, - ISO96JISC62291984kana = 72, - ISO2033 = 73, - ISO99NAPLPS = 74, - ISO102T617bit = 75, - ISO103T618bit = 76, - ISO111ECMACyrillic = 77, - ISO121Canadian1 = 78, - ISO122Canadian2 = 79, - ISO123CSAZ24341985gr = 80, - ISO88596E = 81, - ISO88596I = 82, - ISO128T101G2 = 83, - ISO88598E = 84, - ISO88598I = 85, - ISO139CSN369103 = 86, - ISO141JUSIB1002 = 87, - ISO143IECP271 = 88, - ISO146Serbian = 89, - ISO147Macedonian = 90, - ISO150 = 91, - ISO151Cuba = 92, - ISO6937Add = 93, - ISO153GOST1976874 = 94, - ISO8859Supp = 95, - ISO10367Box = 96, - ISO158Lap = 97, - ISO159JISX02121990 = 98, - ISO646Danish = 99, - USDK = 100, - DKUS = 101, - KSC5636 = 102, - Unicode11UTF7 = 103, - ISO2022CN = 104, - ISO2022CNEXT = 105, - UTF8 = 106, - ISO885913 = 109, - ISO885914 = 110, - ISO885915 = 111, - ISO885916 = 112, - GBK = 113, - GB18030 = 114, - OSDEBCDICDF0415 = 115, - OSDEBCDICDF03IRV = 116, - OSDEBCDICDF041 = 117, - ISO115481 = 118, - KZ1048 = 119, - UCS2 = 1000, - UCS4 = 1001, - UnicodeASCII = 1002, - UnicodeLatin1 = 1003, - UnicodeJapanese = 1004, - UnicodeIBM1261 = 1005, - UnicodeIBM1268 = 1006, - UnicodeIBM1276 = 1007, - UnicodeIBM1264 = 1008, - UnicodeIBM1265 = 1009, - Unicode11 = 1010, - SCSU = 1011, - UTF7 = 1012, - UTF16BE = 1013, - UTF16LE = 1014, - UTF16 = 1015, - CESU8 = 1016, - UTF32 = 1017, - UTF32BE = 1018, - UTF32LE = 1019, - BOCU1 = 1020, - UTF7IMAP = 1021, - Windows30Latin1 = 2000, - Windows31Latin1 = 2001, - Windows31Latin2 = 2002, - Windows31Latin5 = 2003, - HPRoman8 = 2004, - AdobeStandardEncoding = 2005, - VenturaUS = 2006, - VenturaInternational = 2007, - DECMCS = 2008, - PC850Multilingual = 2009, - PCp852 = 2010, - PC8CodePage437 = 2011, - PC8DanishNorwegian = 2012, - PC862LatinHebrew = 2013, - PC8Turkish = 2014, - IBMSymbols = 2015, - IBMThai = 2016, - HPLegal = 2017, - HPPiFont = 2018, - HPMath8 = 2019, - HPPSMath = 2020, - HPDesktop = 2021, - VenturaMath = 2022, - MicrosoftPublishing = 2023, - Windows31J = 2024, - GB2312 = 2025, - Big5 = 2026, - Macintosh = 2027, - IBM037 = 2028, - IBM038 = 2029, - IBM273 = 2030, - IBM274 = 2031, - IBM275 = 2032, - IBM277 = 2033, - IBM278 = 2034, - IBM280 = 2035, - IBM281 = 2036, - IBM284 = 2037, - IBM285 = 2038, - IBM290 = 2039, - IBM297 = 2040, - IBM420 = 2041, - IBM423 = 2042, - IBM424 = 2043, - IBM500 = 2044, - IBM851 = 2045, - IBM855 = 2046, - IBM857 = 2047, - IBM860 = 2048, - IBM861 = 2049, - IBM863 = 2050, - IBM864 = 2051, - IBM865 = 2052, - IBM868 = 2053, - IBM869 = 2054, - IBM870 = 2055, - IBM871 = 2056, - IBM880 = 2057, - IBM891 = 2058, - IBM903 = 2059, - IBM904 = 2060, - IBM905 = 2061, - IBM918 = 2062, - IBM1026 = 2063, - IBMEBCDICATDE = 2064, - EBCDICATDEA = 2065, - EBCDICCAFR = 2066, - EBCDICDKNO = 2067, - EBCDICDKNOA = 2068, - EBCDICFISE = 2069, - EBCDICFISEA = 2070, - EBCDICFR = 2071, - EBCDICIT = 2072, - EBCDICPT = 2073, - EBCDICES = 2074, - EBCDICESA = 2075, - EBCDICESS = 2076, - EBCDICUK = 2077, - EBCDICUS = 2078, - Unknown8BiT = 2079, - Mnemonic = 2080, - Mnem = 2081, - VISCII = 2082, - VIQR = 2083, - KOI8R = 2084, - HZGB2312 = 2085, - IBM866 = 2086, - PC775Baltic = 2087, - KOI8U = 2088, - IBM00858 = 2089, - IBM00924 = 2090, - IBM01140 = 2091, - IBM01141 = 2092, - IBM01142 = 2093, - IBM01143 = 2094, - IBM01144 = 2095, - IBM01145 = 2096, - IBM01146 = 2097, - IBM01147 = 2098, - IBM01148 = 2099, - IBM01149 = 2100, - Big5HKSCS = 2101, - IBM1047 = 2102, - PTCP154 = 2103, - Amiga1251 = 2104, - KOI7switched = 2105, - BRF = 2106, - TSCII = 2107, - CP51932 = 2108, - windows874 = 2109, - windows1250 = 2250, - windows1251 = 2251, - windows1252 = 2252, - windows1253 = 2253, - windows1254 = 2254, - windows1255 = 2255, - windows1256 = 2256, - windows1257 = 2257, - windows1258 = 2258, - TIS620 = 2259, - CP50220 = 2260 + @\libmember{other}{text_encoding}@ = 1, + @\libmember{unknown}{text_encoding}@ = 2, + @\libmember{ASCII}{text_encoding}@ = 3, + @\libmember{ISOLatin1}{text_encoding}@ = 4, + @\libmember{ISOLatin2}{text_encoding}@ = 5, + @\libmember{ISOLatin3}{text_encoding}@ = 6, + @\libmember{ISOLatin4}{text_encoding}@ = 7, + @\libmember{ISOLatinCyrillic}{text_encoding}@ = 8, + @\libmember{ISOLatinArabic}{text_encoding}@ = 9, + @\libmember{ISOLatinGreek}{text_encoding}@ = 10, + @\libmember{ISOLatinHebrew}{text_encoding}@ = 11, + @\libmember{ISOLatin5}{text_encoding}@ = 12, + @\libmember{ISOLatin6}{text_encoding}@ = 13, + @\libmember{ISOTextComm}{text_encoding}@ = 14, + @\libmember{HalfWidthKatakana}{text_encoding}@ = 15, + @\libmember{JISEncoding}{text_encoding}@ = 16, + @\libmember{ShiftJIS}{text_encoding}@ = 17, + @\libmember{EUCPkdFmtJapanese}{text_encoding}@ = 18, + @\libmember{EUCFixWidJapanese}{text_encoding}@ = 19, + @\libmember{ISO4UnitedKingdom}{text_encoding}@ = 20, + @\libmember{ISO11SwedishForNames}{text_encoding}@ = 21, + @\libmember{ISO15Italian}{text_encoding}@ = 22, + @\libmember{ISO17Spanish}{text_encoding}@ = 23, + @\libmember{ISO21German}{text_encoding}@ = 24, + @\libmember{ISO60DanishNorwegian}{text_encoding}@ = 25, + @\libmember{ISO69French}{text_encoding}@ = 26, + @\libmember{ISO10646UTF1}{text_encoding}@ = 27, + @\libmember{ISO646basic1983}{text_encoding}@ = 28, + @\libmember{INVARIANT}{text_encoding}@ = 29, + @\libmember{ISO2IntlRefVersion}{text_encoding}@ = 30, + @\libmember{NATSSEFI}{text_encoding}@ = 31, + @\libmember{NATSSEFIADD}{text_encoding}@ = 32, + @\libmember{ISO10Swedish}{text_encoding}@ = 35, + @\libmember{KSC56011987}{text_encoding}@ = 36, + @\libmember{ISO2022KR}{text_encoding}@ = 37, + @\libmember{EUCKR}{text_encoding}@ = 38, + @\libmember{ISO2022JP}{text_encoding}@ = 39, + @\libmember{ISO2022JP2}{text_encoding}@ = 40, + @\libmember{ISO13JISC6220jp}{text_encoding}@ = 41, + @\libmember{ISO14JISC6220ro}{text_encoding}@ = 42, + @\libmember{ISO16Portuguese}{text_encoding}@ = 43, + @\libmember{ISO18Greek7Old}{text_encoding}@ = 44, + @\libmember{ISO19LatinGreek}{text_encoding}@ = 45, + @\libmember{ISO25French}{text_encoding}@ = 46, + @\libmember{ISO27LatinGreek1}{text_encoding}@ = 47, + @\libmember{ISO5427Cyrillic}{text_encoding}@ = 48, + @\libmember{ISO42JISC62261978}{text_encoding}@ = 49, + @\libmember{ISO47BSViewdata}{text_encoding}@ = 50, + @\libmember{ISO49INIS}{text_encoding}@ = 51, + @\libmember{ISO50INIS8}{text_encoding}@ = 52, + @\libmember{ISO51INISCyrillic}{text_encoding}@ = 53, + @\libmember{ISO54271981}{text_encoding}@ = 54, + @\libmember{ISO5428Greek}{text_encoding}@ = 55, + @\libmember{ISO57GB1988}{text_encoding}@ = 56, + @\libmember{ISO58GB231280}{text_encoding}@ = 57, + @\libmember{ISO61Norwegian2}{text_encoding}@ = 58, + @\libmember{ISO70VideotexSupp1}{text_encoding}@ = 59, + @\libmember{ISO84Portuguese2}{text_encoding}@ = 60, + @\libmember{ISO85Spanish2}{text_encoding}@ = 61, + @\libmember{ISO86Hungarian}{text_encoding}@ = 62, + @\libmember{ISO87JISX0208}{text_encoding}@ = 63, + @\libmember{ISO88Greek7}{text_encoding}@ = 64, + @\libmember{ISO89ASMO449}{text_encoding}@ = 65, + @\libmember{ISO90}{text_encoding}@ = 66, + @\libmember{ISO91JISC62291984a}{text_encoding}@ = 67, + @\libmember{ISO92JISC62991984b}{text_encoding}@ = 68, + @\libmember{ISO93JIS62291984badd}{text_encoding}@ = 69, + @\libmember{ISO94JIS62291984hand}{text_encoding}@ = 70, + @\libmember{ISO95JIS62291984handadd}{text_encoding}@ = 71, + @\libmember{ISO96JISC62291984kana}{text_encoding}@ = 72, + @\libmember{ISO2033}{text_encoding}@ = 73, + @\libmember{ISO99NAPLPS}{text_encoding}@ = 74, + @\libmember{ISO102T617bit}{text_encoding}@ = 75, + @\libmember{ISO103T618bit}{text_encoding}@ = 76, + @\libmember{ISO111ECMACyrillic}{text_encoding}@ = 77, + @\libmember{ISO121Canadian1}{text_encoding}@ = 78, + @\libmember{ISO122Canadian2}{text_encoding}@ = 79, + @\libmember{ISO123CSAZ24341985gr}{text_encoding}@ = 80, + @\libmember{ISO88596E}{text_encoding}@ = 81, + @\libmember{ISO88596I}{text_encoding}@ = 82, + @\libmember{ISO128T101G2}{text_encoding}@ = 83, + @\libmember{ISO88598E}{text_encoding}@ = 84, + @\libmember{ISO88598I}{text_encoding}@ = 85, + @\libmember{ISO139CSN369103}{text_encoding}@ = 86, + @\libmember{ISO141JUSIB1002}{text_encoding}@ = 87, + @\libmember{ISO143IECP271}{text_encoding}@ = 88, + @\libmember{ISO146Serbian}{text_encoding}@ = 89, + @\libmember{ISO147Macedonian}{text_encoding}@ = 90, + @\libmember{ISO150}{text_encoding}@ = 91, + @\libmember{ISO151Cuba}{text_encoding}@ = 92, + @\libmember{ISO6937Add}{text_encoding}@ = 93, + @\libmember{ISO153GOST1976874}{text_encoding}@ = 94, + @\libmember{ISO8859Supp}{text_encoding}@ = 95, + @\libmember{ISO10367Box}{text_encoding}@ = 96, + @\libmember{ISO158Lap}{text_encoding}@ = 97, + @\libmember{ISO159JISX02121990}{text_encoding}@ = 98, + @\libmember{ISO646Danish}{text_encoding}@ = 99, + @\libmember{USDK}{text_encoding}@ = 100, + @\libmember{DKUS}{text_encoding}@ = 101, + @\libmember{KSC5636}{text_encoding}@ = 102, + @\libmember{Unicode11UTF7}{text_encoding}@ = 103, + @\libmember{ISO2022CN}{text_encoding}@ = 104, + @\libmember{ISO2022CNEXT}{text_encoding}@ = 105, + @\libmember{UTF8}{text_encoding}@ = 106, + @\libmember{ISO885913}{text_encoding}@ = 109, + @\libmember{ISO885914}{text_encoding}@ = 110, + @\libmember{ISO885915}{text_encoding}@ = 111, + @\libmember{ISO885916}{text_encoding}@ = 112, + @\libmember{GBK}{text_encoding}@ = 113, + @\libmember{GB18030}{text_encoding}@ = 114, + @\libmember{OSDEBCDICDF0415}{text_encoding}@ = 115, + @\libmember{OSDEBCDICDF03IRV}{text_encoding}@ = 116, + @\libmember{OSDEBCDICDF041}{text_encoding}@ = 117, + @\libmember{ISO115481}{text_encoding}@ = 118, + @\libmember{KZ1048}{text_encoding}@ = 119, + @\libmember{UCS2}{text_encoding}@ = 1000, + @\libmember{UCS4}{text_encoding}@ = 1001, + @\libmember{UnicodeASCII}{text_encoding}@ = 1002, + @\libmember{UnicodeLatin1}{text_encoding}@ = 1003, + @\libmember{UnicodeJapanese}{text_encoding}@ = 1004, + @\libmember{UnicodeIBM1261}{text_encoding}@ = 1005, + @\libmember{UnicodeIBM1268}{text_encoding}@ = 1006, + @\libmember{UnicodeIBM1276}{text_encoding}@ = 1007, + @\libmember{UnicodeIBM1264}{text_encoding}@ = 1008, + @\libmember{UnicodeIBM1265}{text_encoding}@ = 1009, + @\libmember{Unicode11}{text_encoding}@ = 1010, + @\libmember{SCSU}{text_encoding}@ = 1011, + @\libmember{UTF7}{text_encoding}@ = 1012, + @\libmember{UTF16BE}{text_encoding}@ = 1013, + @\libmember{UTF16LE}{text_encoding}@ = 1014, + @\libmember{UTF16}{text_encoding}@ = 1015, + @\libmember{CESU8}{text_encoding}@ = 1016, + @\libmember{UTF32}{text_encoding}@ = 1017, + @\libmember{UTF32BE}{text_encoding}@ = 1018, + @\libmember{UTF32LE}{text_encoding}@ = 1019, + @\libmember{BOCU1}{text_encoding}@ = 1020, + @\libmember{UTF7IMAP}{text_encoding}@ = 1021, + @\libmember{Windows30Latin1}{text_encoding}@ = 2000, + @\libmember{Windows31Latin1}{text_encoding}@ = 2001, + @\libmember{Windows31Latin2}{text_encoding}@ = 2002, + @\libmember{Windows31Latin5}{text_encoding}@ = 2003, + @\libmember{HPRoman8}{text_encoding}@ = 2004, + @\libmember{AdobeStandardEncoding}{text_encoding}@ = 2005, + @\libmember{VenturaUS}{text_encoding}@ = 2006, + @\libmember{VenturaInternational}{text_encoding}@ = 2007, + @\libmember{DECMCS}{text_encoding}@ = 2008, + @\libmember{PC850Multilingual}{text_encoding}@ = 2009, + @\libmember{PCp852}{text_encoding}@ = 2010, + @\libmember{PC8CodePage437}{text_encoding}@ = 2011, + @\libmember{PC8DanishNorwegian}{text_encoding}@ = 2012, + @\libmember{PC862LatinHebrew}{text_encoding}@ = 2013, + @\libmember{PC8Turkish}{text_encoding}@ = 2014, + @\libmember{IBMSymbols}{text_encoding}@ = 2015, + @\libmember{IBMThai}{text_encoding}@ = 2016, + @\libmember{HPLegal}{text_encoding}@ = 2017, + @\libmember{HPPiFont}{text_encoding}@ = 2018, + @\libmember{HPMath8}{text_encoding}@ = 2019, + @\libmember{HPPSMath}{text_encoding}@ = 2020, + @\libmember{HPDesktop}{text_encoding}@ = 2021, + @\libmember{VenturaMath}{text_encoding}@ = 2022, + @\libmember{MicrosoftPublishing}{text_encoding}@ = 2023, + @\libmember{Windows31J}{text_encoding}@ = 2024, + @\libmember{GB2312}{text_encoding}@ = 2025, + @\libmember{Big5}{text_encoding}@ = 2026, + @\libmember{Macintosh}{text_encoding}@ = 2027, + @\libmember{IBM037}{text_encoding}@ = 2028, + @\libmember{IBM038}{text_encoding}@ = 2029, + @\libmember{IBM273}{text_encoding}@ = 2030, + @\libmember{IBM274}{text_encoding}@ = 2031, + @\libmember{IBM275}{text_encoding}@ = 2032, + @\libmember{IBM277}{text_encoding}@ = 2033, + @\libmember{IBM278}{text_encoding}@ = 2034, + @\libmember{IBM280}{text_encoding}@ = 2035, + @\libmember{IBM281}{text_encoding}@ = 2036, + @\libmember{IBM284}{text_encoding}@ = 2037, + @\libmember{IBM285}{text_encoding}@ = 2038, + @\libmember{IBM290}{text_encoding}@ = 2039, + @\libmember{IBM297}{text_encoding}@ = 2040, + @\libmember{IBM420}{text_encoding}@ = 2041, + @\libmember{IBM423}{text_encoding}@ = 2042, + @\libmember{IBM424}{text_encoding}@ = 2043, + @\libmember{IBM500}{text_encoding}@ = 2044, + @\libmember{IBM851}{text_encoding}@ = 2045, + @\libmember{IBM855}{text_encoding}@ = 2046, + @\libmember{IBM857}{text_encoding}@ = 2047, + @\libmember{IBM860}{text_encoding}@ = 2048, + @\libmember{IBM861}{text_encoding}@ = 2049, + @\libmember{IBM863}{text_encoding}@ = 2050, + @\libmember{IBM864}{text_encoding}@ = 2051, + @\libmember{IBM865}{text_encoding}@ = 2052, + @\libmember{IBM868}{text_encoding}@ = 2053, + @\libmember{IBM869}{text_encoding}@ = 2054, + @\libmember{IBM870}{text_encoding}@ = 2055, + @\libmember{IBM871}{text_encoding}@ = 2056, + @\libmember{IBM880}{text_encoding}@ = 2057, + @\libmember{IBM891}{text_encoding}@ = 2058, + @\libmember{IBM903}{text_encoding}@ = 2059, + @\libmember{IBM904}{text_encoding}@ = 2060, + @\libmember{IBM905}{text_encoding}@ = 2061, + @\libmember{IBM918}{text_encoding}@ = 2062, + @\libmember{IBM1026}{text_encoding}@ = 2063, + @\libmember{IBMEBCDICATDE}{text_encoding}@ = 2064, + @\libmember{EBCDICATDEA}{text_encoding}@ = 2065, + @\libmember{EBCDICCAFR}{text_encoding}@ = 2066, + @\libmember{EBCDICDKNO}{text_encoding}@ = 2067, + @\libmember{EBCDICDKNOA}{text_encoding}@ = 2068, + @\libmember{EBCDICFISE}{text_encoding}@ = 2069, + @\libmember{EBCDICFISEA}{text_encoding}@ = 2070, + @\libmember{EBCDICFR}{text_encoding}@ = 2071, + @\libmember{EBCDICIT}{text_encoding}@ = 2072, + @\libmember{EBCDICPT}{text_encoding}@ = 2073, + @\libmember{EBCDICES}{text_encoding}@ = 2074, + @\libmember{EBCDICESA}{text_encoding}@ = 2075, + @\libmember{EBCDICESS}{text_encoding}@ = 2076, + @\libmember{EBCDICUK}{text_encoding}@ = 2077, + @\libmember{EBCDICUS}{text_encoding}@ = 2078, + @\libmember{Unknown8BiT}{text_encoding}@ = 2079, + @\libmember{Mnemonic}{text_encoding}@ = 2080, + @\libmember{Mnem}{text_encoding}@ = 2081, + @\libmember{VISCII}{text_encoding}@ = 2082, + @\libmember{VIQR}{text_encoding}@ = 2083, + @\libmember{KOI8R}{text_encoding}@ = 2084, + @\libmember{HZGB2312}{text_encoding}@ = 2085, + @\libmember{IBM866}{text_encoding}@ = 2086, + @\libmember{PC775Baltic}{text_encoding}@ = 2087, + @\libmember{KOI8U}{text_encoding}@ = 2088, + @\libmember{IBM00858}{text_encoding}@ = 2089, + @\libmember{IBM00924}{text_encoding}@ = 2090, + @\libmember{IBM01140}{text_encoding}@ = 2091, + @\libmember{IBM01141}{text_encoding}@ = 2092, + @\libmember{IBM01142}{text_encoding}@ = 2093, + @\libmember{IBM01143}{text_encoding}@ = 2094, + @\libmember{IBM01144}{text_encoding}@ = 2095, + @\libmember{IBM01145}{text_encoding}@ = 2096, + @\libmember{IBM01146}{text_encoding}@ = 2097, + @\libmember{IBM01147}{text_encoding}@ = 2098, + @\libmember{IBM01148}{text_encoding}@ = 2099, + @\libmember{IBM01149}{text_encoding}@ = 2100, + @\libmember{Big5HKSCS}{text_encoding}@ = 2101, + @\libmember{IBM1047}{text_encoding}@ = 2102, + @\libmember{PTCP154}{text_encoding}@ = 2103, + @\libmember{Amiga1251}{text_encoding}@ = 2104, + @\libmember{KOI7switched}{text_encoding}@ = 2105, + @\libmember{BRF}{text_encoding}@ = 2106, + @\libmember{TSCII}{text_encoding}@ = 2107, + @\libmember{CP51932}{text_encoding}@ = 2108, + @\libmember{windows874}{text_encoding}@ = 2109, + @\libmember{windows1250}{text_encoding}@ = 2250, + @\libmember{windows1251}{text_encoding}@ = 2251, + @\libmember{windows1252}{text_encoding}@ = 2252, + @\libmember{windows1253}{text_encoding}@ = 2253, + @\libmember{windows1254}{text_encoding}@ = 2254, + @\libmember{windows1255}{text_encoding}@ = 2255, + @\libmember{windows1256}{text_encoding}@ = 2256, + @\libmember{windows1257}{text_encoding}@ = 2257, + @\libmember{windows1258}{text_encoding}@ = 2258, + @\libmember{TIS620}{text_encoding}@ = 2259, + @\libmember{CP50220}{text_encoding}@ = 2260 }; } \end{codeblock} @@ -5695,7 +5698,7 @@ The \tcode{text_encoding::id} enumeration contains an enumerator for each known registered character encoding. For each encoding, the corresponding enumerator is derived from -the alias beginning with ``\tcode{cs}'', as follows +the alias beginning with ``\tcode{cs}'', as follows: \begin{itemize} \item \tcode{csUnicode} is mapped to \tcode{text_encoding::id::UCS2}, @@ -5748,16 +5751,18 @@ template struct basic_format_string; - template struct @\exposid{runtime-format-string}@ { // \expos + template struct @\exposid{dynamic-format-string}@ { // \expos private: basic_string_view @\exposid{str}@; // \expos public: - @\exposid{runtime-format-string}@(basic_string_view s) noexcept : @\exposid{str}@(s) {} - @\exposid{runtime-format-string}@(const @\exposid{runtime-format-string}@&) = delete; - @\exposid{runtime-format-string}@& operator=(const @\exposid{runtime-format-string}@&) = delete; + constexpr @\exposid{dynamic-format-string}@(basic_string_view s) noexcept : @\exposid{str}@(s) {} + @\exposid{dynamic-format-string}@(const @\exposid{dynamic-format-string}@&) = delete; + @\exposid{dynamic-format-string}@& operator=(const @\exposid{dynamic-format-string}@&) = delete; }; - @\exposid{runtime-format-string}@ runtime_format(string_view fmt) noexcept { return fmt; } - @\exposid{runtime-format-string}@ runtime_format(wstring_view fmt) noexcept { return fmt; } + constexpr @\exposid{dynamic-format-string}@ + dynamic_format(string_view fmt) noexcept { return fmt; } + constexpr @\exposid{dynamic-format-string}@ + dynamic_format(wstring_view fmt) noexcept { return fmt; } template using @\libglobal{format_string}@ = basic_format_string...>; @@ -5766,32 +5771,32 @@ // \ref{format.functions}, formatting functions template - string format(format_string fmt, Args&&... args); + constexpr string format(format_string fmt, Args&&... args); template - wstring format(wformat_string fmt, Args&&... args); + constexpr wstring format(wformat_string fmt, Args&&... args); template string format(const locale& loc, format_string fmt, Args&&... args); template wstring format(const locale& loc, wformat_string fmt, Args&&... args); - string vformat(string_view fmt, format_args args); - wstring vformat(wstring_view fmt, wformat_args args); + constexpr string vformat(string_view fmt, format_args args); + constexpr wstring vformat(wstring_view fmt, wformat_args args); string vformat(const locale& loc, string_view fmt, format_args args); wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); template - Out format_to(Out out, format_string fmt, Args&&... args); + constexpr Out format_to(Out out, format_string fmt, Args&&... args); template - Out format_to(Out out, wformat_string fmt, Args&&... args); + constexpr Out format_to(Out out, wformat_string fmt, Args&&... args); template Out format_to(Out out, const locale& loc, format_string fmt, Args&&... args); template Out format_to(Out out, const locale& loc, wformat_string fmt, Args&&... args); template - Out vformat_to(Out out, string_view fmt, format_args args); + constexpr Out vformat_to(Out out, string_view fmt, format_args args); template - Out vformat_to(Out out, wstring_view fmt, wformat_args args); + constexpr Out vformat_to(Out out, wstring_view fmt, wformat_args args); template Out vformat_to(Out out, const locale& loc, string_view fmt, format_args args); template @@ -5802,11 +5807,13 @@ iter_difference_t size; }; template - format_to_n_result format_to_n(Out out, iter_difference_t n, - format_string fmt, Args&&... args); + constexpr format_to_n_result format_to_n(Out out, iter_difference_t n, + format_string fmt, + Args&&... args); template - format_to_n_result format_to_n(Out out, iter_difference_t n, - wformat_string fmt, Args&&... args); + constexpr format_to_n_result format_to_n(Out out, iter_difference_t n, + wformat_string fmt, + Args&&... args); template format_to_n_result format_to_n(Out out, iter_difference_t n, const locale& loc, format_string fmt, @@ -5817,9 +5824,9 @@ Args&&... args); template - size_t formatted_size(format_string fmt, Args&&... args); + constexpr size_t formatted_size(format_string fmt, Args&&... args); template - size_t formatted_size(wformat_string fmt, Args&&... args); + constexpr size_t formatted_size(wformat_string fmt, Args&&... args); template size_t formatted_size(const locale& loc, format_string fmt, Args&&... args); template @@ -5895,10 +5902,10 @@ template class @\exposidnc{format-arg-store}@; // \expos template - @\exposid{format-arg-store}@ + constexpr @\exposid{format-arg-store}@ make_format_args(Args&... fmt_args); template - @\exposid{format-arg-store}@ + constexpr @\exposid{format-arg-store}@ make_wformat_args(Args&... args); // \ref{format.error}, class \tcode{format_error} @@ -6381,23 +6388,37 @@ the \defnx{locale-specific form}{locale-specific form!format string}. The \tcode{L} option is only valid for arithmetic types, and its effect depends upon the type. +A call to \tcode{format} on a given formatter specialization +is not a constant subexpression if the locale-specific form is specified. \begin{itemize} \item For integral types, the locale-specific form causes the context's locale to be used -to insert the appropriate digit group separator characters. +to insert the appropriate digit group separator characters +as if obtained with +\tcode{numpunct::grouping} and +\tcode{numpunct::thousands_sep}. \item For floating-point types, the locale-specific form causes the context's locale to be used -to insert the appropriate digit group and radix separator characters. +to insert the appropriate digit group and radix separator characters +as if obtained with +\tcode{numpunct::grouping}, +\tcode{numpunct::thousands_sep}, and +\tcode{numpunct::decimal_point}. \item For the textual representation of \tcode{bool}, the locale-specific form causes the context's locale to be used to insert the appropriate string as if obtained -with \tcode{numpunct::truename} or \tcode{numpunct::falsename}. +with \tcode{numpunct::truename} or \tcode{numpunct::\brk{}falsename}. \end{itemize} +If the string literal encoding is a Unicode encoding form and +the locale is among an implementation-defined set of locales, +each replacement that depends on the locale is performed as if +the replacement character sequence is converted to +the string literal encoding. \pnum The \fmtgrammarterm{type} determines how the data should be presented. @@ -6425,7 +6446,9 @@ let \range{first}{last} be a range large enough to hold the \tcode{to_chars} output and \tcode{value} be the formatting argument value. -Formatting is done as if by calling \tcode{to_chars} as specified +Formatting is done as if by calling \tcode{to_chars} as specified, +transcoding the \tcode{to_chars} output to the wide literal encoding if +\tcode{charT} is \tcode{wchar_t}, and copying the output through the output iterator of the format context. \begin{note} Additional padding and adjustments are performed @@ -6633,7 +6656,7 @@ \topline \lhdr{Type} & \rhdr{Meaning} \\ \rowsep none, \tcode{p} & -If \tcode{uintptr_t} is defined, +If \tcode{uintptr_t} is declared, \begin{codeblock} to_chars(first, last, reinterpret_cast(value), 16) \end{codeblock} @@ -6669,7 +6692,7 @@ public: template consteval basic_format_string(const T& s); - basic_format_string(@\exposid{runtime-format-string}@ s) noexcept : str(s.@\exposid{str}@) {} + constexpr basic_format_string(@\exposid{dynamic-format-string}@ s) noexcept : str(s.@\exposid{str}@) {} constexpr basic_string_view get() const noexcept { return @\exposid{str}@; } }; @@ -6691,13 +6714,19 @@ \pnum \remarks -A call to this function is not a core constant expression\iref{expr.const} +A call to this function is not a core constant expression\iref{expr.const.core} unless there exist \tcode{args} of types \tcode{Args} such that \exposid{str} is a format string for \tcode{args}. \end{itemdescr} \rSec2[format.functions]{Formatting functions} +\pnum +A call to any of the functions defined in this subclause +is a constant subexpression only if +each of the used \tcode{formatter} specializations +is a constexpr-enabled specialization\iref{format.formatter.spec}. + \pnum In the description of the functions, operator \tcode{+} is used for some of the iterator categories for which it does not have to be defined. @@ -6707,7 +6736,7 @@ \indexlibraryglobal{format}% \begin{itemdecl} template - string format(format_string fmt, Args&&... args); + constexpr string format(format_string fmt, Args&&... args); \end{itemdecl} \begin{itemdescr} @@ -6722,7 +6751,7 @@ \indexlibraryglobal{format}% \begin{itemdecl} template - wstring format(wformat_string fmt, Args&&... args); + constexpr wstring format(wformat_string fmt, Args&&... args); \end{itemdecl} \begin{itemdescr} @@ -6766,8 +6795,8 @@ \indexlibraryglobal{vformat}% \begin{itemdecl} -string vformat(string_view fmt, format_args args); -wstring vformat(wstring_view fmt, wformat_args args); +constexpr string vformat(string_view fmt, format_args args); +constexpr wstring vformat(wstring_view fmt, wformat_args args); string vformat(const locale& loc, string_view fmt, format_args args); wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); \end{itemdecl} @@ -6788,7 +6817,7 @@ \indexlibraryglobal{format_to}% \begin{itemdecl} template - Out format_to(Out out, format_string fmt, Args&&... args); + constexpr Out format_to(Out out, format_string fmt, Args&&... args); \end{itemdecl} \begin{itemdescr} @@ -6803,7 +6832,7 @@ \indexlibraryglobal{format_to}% \begin{itemdecl} template - Out format_to(Out out, wformat_string fmt, Args&&... args); + constexpr Out format_to(Out out, wformat_string fmt, Args&&... args); \end{itemdecl} \begin{itemdescr} @@ -6848,9 +6877,9 @@ \indexlibraryglobal{vformat_to}% \begin{itemdecl} template - Out vformat_to(Out out, string_view fmt, format_args args); + constexpr Out vformat_to(Out out, string_view fmt, format_args args); template - Out vformat_to(Out out, wstring_view fmt, wformat_args args); + constexpr Out vformat_to(Out out, wstring_view fmt, wformat_args args); template Out vformat_to(Out out, const locale& loc, string_view fmt, format_args args); template @@ -6890,11 +6919,13 @@ \indexlibraryglobal{format_to_n}% \begin{itemdecl} template - format_to_n_result format_to_n(Out out, iter_difference_t n, - format_string fmt, Args&&... args); + constexpr format_to_n_result format_to_n(Out out, iter_difference_t n, + format_string fmt, + Args&&... args); template - format_to_n_result format_to_n(Out out, iter_difference_t n, - wformat_string fmt, Args&&... args); + constexpr format_to_n_result format_to_n(Out out, iter_difference_t n, + wformat_string fmt, + Args&&... args); template format_to_n_result format_to_n(Out out, iter_difference_t n, const locale& loc, format_string fmt, @@ -6947,9 +6978,9 @@ \indexlibraryglobal{formatted_size}% \begin{itemdecl} template - size_t formatted_size(format_string fmt, Args&&... args); + constexpr size_t formatted_size(format_string fmt, Args&&... args); template - size_t formatted_size(wformat_string fmt, Args&&... args); + constexpr size_t formatted_size(wformat_string fmt, Args&&... args); template size_t formatted_size(const locale& loc, format_string fmt, Args&&... args); template @@ -7092,7 +7123,7 @@ Pursuant to \ref{namespace.std}, users may specialize \tcode{enable_nonlocking_formatter_optimization} for cv-unqualified program-defined types. -Such specializations shall be usable in constant expressions\iref{expr.const} +Such specializations shall be usable in constant expressions\iref{expr.const.init} and have type \tcode{const bool}. \end{itemdescr} @@ -7148,12 +7179,14 @@ which modifies the state of the \tcode{formatter} to be as if the type of the \fmtgrammarterm{std-format-spec} parsed by the last call to \tcode{parse} were \tcode{?}. +A \defn{constexpr-enabled} specialization of \tcode{formatter} +has its \tcode{format} member function declared \tcode{constexpr}. Each header that declares the template \tcode{formatter} provides the following enabled specializations: \begin{itemize} \item \indexlibrary{\idxcode{formatter}!specializations!character types}% -The debug-enabled specializations +The debug-enabled and constexpr-enabled specializations \begin{codeblock} template<> struct formatter; template<> struct formatter; @@ -7163,7 +7196,7 @@ \item \indexlibrary{\idxcode{formatter}!specializations!string types}% For each \tcode{charT}, -the debug-enabled string type specializations +the debug-enabled and constexpr-enabled string type specializations \begin{codeblock} template<> struct formatter; template<> struct formatter; @@ -7175,27 +7208,37 @@ \end{codeblock} \item -\indexlibrary{\idxcode{formatter}!specializations!arithmetic types}% +\indexlibrary{\idxcode{formatter}!specializations!integer types}% +For each \tcode{charT}, +for each \tcode{IntegerT} that is either +a signed or unsigned integer type or \tcode{bool}, +a constexpr-enabled specialization +\begin{codeblock} +template<> struct formatter; +\end{codeblock} + +\item +\indexlibrary{\idxcode{formatter}!specializations!floating-point types}% For each \tcode{charT}, -for each cv-unqualified arithmetic type \tcode{ArithmeticT} -other than -\tcode{char}, -\keyword{wchar_t}, -\keyword{char8_t}, -\keyword{char16_t}, or -\keyword{char32_t}, +for each \tcode{FloatingT} that is a cv-unqualified floating-point type, a specialization \begin{codeblock} -template<> struct formatter; +template<> struct formatter; \end{codeblock} \item \indexlibrary{\idxcode{formatter}!specializations!pointer types}% \indexlibrary{\idxcode{formatter}!specializations!\idxcode{nullptr_t}}% For each \tcode{charT}, -the pointer type specializations +the constexpr-enabled pointer type specialization \begin{codeblock} template<> struct formatter; +\end{codeblock} + +\item +For each \tcode{charT}, +the pointer type specializations +\begin{codeblock} template<> struct formatter; template<> struct formatter; \end{codeblock} @@ -7579,7 +7622,7 @@ \remarks Let \tcode{\placeholder{cur-arg-id}} be the value of \tcode{next_arg_id_} prior to this call. Call expressions where \tcode{\placeholder{cur-arg-id} >= num_args_} is \tcode{true} -are not core constant expressions\iref{expr.const}. +are not core constant expressions\iref{expr.const.core}. \end{itemdescr} \indexlibrarymember{check_arg_id}{basic_format_parse_context}% @@ -7606,7 +7649,7 @@ \pnum \remarks -A call to this function is a core constant expression\iref{expr.const} only if +A call to this function is a core constant expression\iref{expr.const.core} only if \tcode{id < num_args_} is \tcode{true}. \end{itemdescr} @@ -7696,11 +7739,11 @@ using char_type = charT; template using formatter_type = formatter; - basic_format_arg arg(size_t id) const noexcept; + constexpr basic_format_arg arg(size_t id) const noexcept; std::locale locale(); - iterator out(); - void advance_to(iterator it); + constexpr iterator out(); + constexpr void advance_to(iterator it); }; } \end{codeblock} @@ -7734,7 +7777,7 @@ \recommended For a given type \tcode{charT}, implementations should provide -a single instantiation of \tcode{basic_format_context} +a single specialization of \tcode{basic_format_context} for appending to \tcode{basic_string}, \tcode{vector}, @@ -7744,7 +7787,7 @@ \indexlibrarymember{arg}{basic_format_context}% \begin{itemdecl} -basic_format_arg arg(size_t id) const noexcept; +constexpr basic_format_arg arg(size_t id) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -7768,7 +7811,7 @@ \indexlibrarymember{out}{basic_format_context}% \begin{itemdecl} -iterator out(); +constexpr iterator out(); \end{itemdecl} \begin{itemdescr} @@ -7779,7 +7822,7 @@ \indexlibrarymember{advance_to}{basic_format_context}% \begin{itemdecl} -void advance_to(iterator it); +constexpr void advance_to(iterator it); \end{itemdecl} \begin{itemdescr} @@ -7837,7 +7880,7 @@ \indexlibraryglobal{format_kind} \begin{itemdecl} template - requires @\libconcept{same_as}@> + requires @\libconcept{same_as}@> constexpr range_format format_kind = @\seebelow@; \end{itemdecl} @@ -7885,7 +7928,7 @@ Pursuant to \ref{namespace.std}, users may specialize \tcode{format_kind} for cv-unqualified program-defined types that model \tcode{ranges::\libconcept{input_range}}. -Such specializations shall be usable in constant expressions\iref{expr.const} +Such specializations shall be usable in constant expressions\iref{expr.const.init} and have type \tcode{const range_format}. \end{itemdescr} @@ -7916,7 +7959,7 @@ template requires @\libconcept{formattable}@, charT> && @\libconcept{same_as}@>, T> - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(R&& r, FormatContext& ctx) const; }; } @@ -8087,7 +8130,7 @@ template requires @\libconcept{formattable}@, charT> && @\libconcept{same_as}@>, T> - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(R&& r, FormatContext& ctx) const; \end{itemdecl} @@ -8150,7 +8193,7 @@ parse(ParseContext& ctx); template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(@\exposid{maybe-const-r}@& elems, FormatContext& ctx) const; }; } @@ -8195,7 +8238,7 @@ \indexlibrarymemberexpos{format}{range-default-formatter}% \begin{itemdecl} template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(@\exposid{maybe-const-r}@& elems, FormatContext& ctx) const; \end{itemdecl} @@ -8226,7 +8269,7 @@ parse(ParseContext& ctx); template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(@\exposid{maybe-const-map}@& r, FormatContext& ctx) const; }; } @@ -8275,7 +8318,7 @@ \indexlibrarymemberexpos{format}{range-default-formatter}% \begin{itemdecl} template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(@\exposid{maybe-const-map}@& r, FormatContext& ctx) const; \end{itemdecl} @@ -8305,7 +8348,7 @@ parse(ParseContext& ctx); template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(@\exposid{maybe-const-set}@& r, FormatContext& ctx) const; }; } @@ -8341,7 +8384,7 @@ \indexlibrarymemberexpos{format}{range-default-formatter}% \begin{itemdecl} template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(@\exposid{maybe-const-set}@& r, FormatContext& ctx) const; \end{itemdecl} @@ -8368,7 +8411,7 @@ parse(ParseContext& ctx); template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(@\seebelow@& str, FormatContext& ctx) const; }; } @@ -8432,25 +8475,25 @@ class handle; private: - using char_type = Context::char_type; // \expos + using @\exposid{char-type}@ = Context::char_type; // \expos - variant, - const void*, handle> value; // \expos + const @\exposid{char-type}@*, basic_string_view<@\exposid{char-type}@>, + const void*, handle> @\exposid{value_}@; // \expos - template explicit basic_format_arg(T& v) noexcept; // \expos + template constexpr explicit basic_format_arg(T& v) noexcept; // \expos public: - basic_format_arg() noexcept; + constexpr basic_format_arg() noexcept; - explicit operator bool() const noexcept; + constexpr explicit operator bool() const noexcept; template - decltype(auto) visit(this basic_format_arg arg, Visitor&& vis); + constexpr decltype(auto) visit(this basic_format_arg arg, Visitor&& vis); template - R visit(this basic_format_arg arg, Visitor&& vis); + constexpr R visit(this basic_format_arg arg, Visitor&& vis); }; } \end{codeblock} @@ -8465,7 +8508,7 @@ \indexlibrary{\idxcode{basic_format_arg}!constructor|(}% \begin{itemdecl} -basic_format_arg() noexcept; +constexpr basic_format_arg() noexcept; \end{itemdecl} \begin{itemdescr} @@ -8475,7 +8518,7 @@ \end{itemdescr} \begin{itemdecl} -template explicit basic_format_arg(T& v) noexcept; +template constexpr explicit basic_format_arg(T& v) noexcept; \end{itemdecl} \begin{itemdescr} @@ -8485,56 +8528,56 @@ \pnum \expects -If \tcode{decay_t} is \tcode{char_type*} or \tcode{const char_type*}, -\tcode{static_cast(v)} points to an NTCTS\iref{defns.ntcts}. +If \tcode{decay_t} is \tcode{\exposid{char-type}*} or \tcode{const \exposid{char-type}*}, +\tcode{static_cast(v)} points to an NTCTS\iref{defns.ntcts}. \pnum \effects Let \tcode{TD} be \tcode{remove_const_t}. \begin{itemize} \item -If \tcode{TD} is \tcode{bool} or \tcode{char_type}, -initializes \tcode{value} with \tcode{v}; +If \tcode{TD} is \tcode{bool} or \exposid{char-type}, +initializes \exposid{value_} with \tcode{v}; \item -otherwise, if \tcode{TD} is \tcode{char} and \tcode{char_type} is -\keyword{wchar_t}, initializes \tcode{value} with +otherwise, if \tcode{TD} is \tcode{char} and \exposid{char-type} is +\keyword{wchar_t}, initializes \exposid{value_} with \tcode{static_cast(static_cast(v))}; \item otherwise, if \tcode{TD} is a signed integer type\iref{basic.fundamental} and \tcode{sizeof(TD) <= sizeof(int)}, -initializes \tcode{value} with \tcode{static_cast(v)}; +initializes \exposid{value_} with \tcode{static_cast(v)}; \item otherwise, if \tcode{TD} is an unsigned integer type and \tcode{sizeof(TD) <= sizeof(unsigned int)}, initializes -\tcode{value} with \tcode{static_cast(v)}; +\exposid{value_} with \tcode{static_cast(v)}; \item otherwise, if \tcode{TD} is a signed integer type and \tcode{sizeof(TD) <= sizeof(long long int)}, initializes -\tcode{value} with \tcode{static_cast(v)}; +\exposid{value_} with \tcode{static_cast(v)}; \item otherwise, if \tcode{TD} is an unsigned integer type and \tcode{sizeof(TD) <= sizeof(unsigned long long int)}, initializes -\tcode{value} with +\exposid{value_} with \tcode{static_cast(v)}; \item otherwise, if \tcode{TD} is a standard floating-point type, -initializes \tcode{value} with \tcode{v}; +initializes \exposid{value_} with \tcode{v}; \item otherwise, if \tcode{TD} is a specialization of \tcode{basic_string_view} or \tcode{basic_string} and -\tcode{TD::value_type} is \tcode{char_type}, -initializes \tcode{value} with -\tcode{basic_string_view(v.data(), v.size())}; +\tcode{TD::value_type} is \exposid{char-type}, +initializes \exposid{value_} with +\tcode{basic_string_view<\exposid{char-type}>(v.data(), v.size())}; \item otherwise, if \tcode{decay_t} is -\tcode{char_type*} or \tcode{const char_type*}, -initializes \tcode{value} with \tcode{static_cast(v)}; +\tcode{\exposid{char-type}*} or \tcode{const \exposid{char-type}*}, +initializes \exposid{value_} with \tcode{static_cast(v)}; \item otherwise, if \tcode{is_void_v>} is \tcode{true} or \tcode{is_null_pointer_v} is \tcode{true}, -initializes \tcode{value} with \tcode{static_cast(v)}; +initializes \exposid{value_} with \tcode{static_cast(v)}; \item -otherwise, initializes \tcode{value} with \tcode{handle(v)}. +otherwise, initializes \exposid{value_} with \tcode{handle(v)}. \end{itemize} \begin{note} Constructing \tcode{basic_format_arg} from a pointer to a member is ill-formed @@ -8547,37 +8590,37 @@ \indexlibrarymember{operator bool}{basic_format_arg}% \begin{itemdecl} -explicit operator bool() const noexcept; +constexpr explicit operator bool() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{!holds_alternative(value)}. +\tcode{!holds_alternative(\exposid{value_})}. \end{itemdescr} \indexlibrarymember{visit}{basic_format_arg}% \begin{itemdecl} template - decltype(auto) visit(this basic_format_arg arg, Visitor&& vis); + constexpr decltype(auto) visit(this basic_format_arg arg, Visitor&& vis); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return arg.value.visit(std::forward(vis));} +Equivalent to: \tcode{return arg.\exposid{value_}.visit(std::forward(vis));} \end{itemdescr} \indexlibrarymember{visit}{basic_format_arg}% \begin{itemdecl} template - R visit(this basic_format_arg arg, Visitor&& vis); + constexpr R visit(this basic_format_arg arg, Visitor&& vis); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return arg.value.visit(std::forward(vis));} +Equivalent to: \tcode{return arg.\exposid{value_}.visit(std::forward(vis));} \end{itemdescr} \pnum @@ -8589,21 +8632,21 @@ namespace std { template class basic_format_arg::handle { - const void* ptr_; // \expos - void (*format_)(basic_format_parse_context&, - Context&, const void*); // \expos + const void* @\exposid{ptr_}@; // \expos + void (*@\exposid{format_}@)(basic_format_parse_context<@\exposid{char-type}@>&, + Context&, const void*); // \expos - template explicit handle(T& val) noexcept; // \expos + template constexpr explicit handle(T& val) noexcept; // \expos public: - void format(basic_format_parse_context&, Context& ctx) const; + constexpr void format(basic_format_parse_context<@\exposid{char-type}@>&, Context& ctx) const; }; } \end{codeblock} \indexlibraryctor{basic_format_arg::handle}% \begin{itemdecl} -template explicit handle(T& val) noexcept; +template constexpr explicit handle(T& val) noexcept; \end{itemdecl} \begin{itemdescr} @@ -8625,10 +8668,10 @@ \pnum \effects Initializes -\tcode{ptr_} with \tcode{addressof(val)} and -\tcode{format_} with +\exposid{ptr_} with \tcode{addressof(val)} and +\exposid{format_} with \begin{codeblock} -[](basic_format_parse_context& parse_ctx, +[](basic_format_parse_context<@\exposid{char-type}@>& parse_ctx, Context& format_ctx, const void* ptr) { typename Context::template formatter_type f; parse_ctx.advance_to(f.parse(parse_ctx)); @@ -8640,13 +8683,13 @@ \indexlibrarymember{format}{basic_format_arg::handle}% \begin{itemdecl} -void format(basic_format_parse_context& parse_ctx, Context& format_ctx) const; +constexpr void format(basic_format_parse_context<@\exposid{char-type}@>& parse_ctx, Context& format_ctx) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{format_(parse_ctx, format_ctx, ptr_);} +Equivalent to: \tcode{\exposid{format_}(parse_ctx, format_ctx, \exposid{ptr_});} \end{itemdescr} \rSec3[format.arg.store]{Class template \exposid{format-arg-store}} @@ -8666,7 +8709,8 @@ \indexlibraryglobal{make_format_args}% \begin{itemdecl} template - @\exposid{format-arg-store}@ make_format_args(Args&... fmt_args); + constexpr @\exposid{format-arg-store}@ + make_format_args(Args&... fmt_args); \end{itemdecl} \begin{itemdescr} @@ -8687,7 +8731,8 @@ \indexlibraryglobal{make_wformat_args}% \begin{itemdecl} template - @\exposid{format-arg-store}@ make_wformat_args(Args&... args); + constexpr @\exposid{format-arg-store}@ + make_wformat_args(Args&... args); \end{itemdecl} \begin{itemdescr} @@ -8703,14 +8748,14 @@ namespace std { template class basic_format_args { - size_t size_; // \expos - const basic_format_arg* data_; // \expos + size_t @\exposid{size_}@; // \expos + const basic_format_arg* @\exposid{data_}@; // \expos public: template - basic_format_args(const @\exposid{format-arg-store}@& store) noexcept; + constexpr basic_format_args(const @\exposid{format-arg-store}@& store) noexcept; - basic_format_arg get(size_t i) const noexcept; + constexpr basic_format_arg get(size_t i) const noexcept; }; template @@ -8735,26 +8780,26 @@ \indexlibraryctor{basic_format_args}% \begin{itemdecl} template - basic_format_args(const @\exposid{format-arg-store}@& store) noexcept; + constexpr basic_format_args(const @\exposid{format-arg-store}@& store) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects Initializes -\tcode{size_} with \tcode{sizeof...(Args)} and -\tcode{data_} with \tcode{store.args.data()}. +\exposid{size_} with \tcode{sizeof...(Args)} and +\exposid{data_} with \tcode{store.\exposid{args}.data()}. \end{itemdescr} \indexlibrarymember{get}{basic_format_args}% \begin{itemdecl} -basic_format_arg get(size_t i) const noexcept; +constexpr basic_format_arg get(size_t i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{i < size_ ?\ data_[i] :\ basic_format_arg()}. +\tcode{i < \exposid{size_} ?\ \exposid{data_}[i] :\ basic_format_arg()}. \end{itemdescr} \rSec2[format.tuple]{Tuple formatter} @@ -8785,13 +8830,13 @@ parse(ParseContext& ctx); template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(@\seebelow@& elems, FormatContext& ctx) const; }; template constexpr bool enable_nonlocking_formatter_optimization<@\placeholder{pair-or-tuple}@> = - (enable_nonlocking_formatter_optimization && ...); + (enable_nonlocking_formatter_optimization> && ...); } \end{codeblock} @@ -8918,7 +8963,7 @@ \indexlibrarymember{format}{formatter}% \begin{itemdecl} template - typename FormatContext::iterator + constexpr typename FormatContext::iterator format(@\seebelow@& elems, FormatContext& ctx) const; \end{itemdecl} @@ -12606,7 +12651,7 @@ 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} +member \tcode{suffix}, the value of the member \tcode{suffix.matched} 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. diff --git a/source/threads.tex b/source/threads.tex index 44a5619aee..53bec75486 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -293,9 +293,9 @@ \pnum A type \tcode{L} meets the \defnoldconcept{TimedLockable} requirements if it meets the \oldconcept{Lockable} requirements and the following expressions are well-formed and have the specified semantics -(\tcode{m} denotes a value of type \tcode{L}, \tcode{rel_time} denotes a value of an -instantiation of \tcode{duration}\iref{time.duration}, and \tcode{abs_time} denotes a value -of an instantiation of \tcode{time_point}\iref{time.point}). +(\tcode{m} denotes a value of type \tcode{L}, \tcode{rel_time} denotes a value of a +specialization of \tcode{duration}\iref{time.duration}, and \tcode{abs_time} denotes a value +of a specialization of \tcode{time_point}\iref{time.point}). \begin{itemdecl} m.try_lock_for(rel_time) @@ -631,7 +631,6 @@ If the callback invocation was added to stop state's list of callbacks, \tcode{scb} shall be associated with the stop state. \end{itemize} -\item \begin{note} If \tcode{t.stop_possible()} is \tcode{false}, there is no requirement @@ -1981,7 +1980,7 @@ static unsigned int hardware_concurrency() noexcept; private: - stop_source ssource; // \expos + stop_source @\exposid{ssource}@; // \expos }; } \end{codeblock} @@ -2002,7 +2001,7 @@ \pnum \ensures \tcode{get_id() == id()} is \tcode{true} -and \tcode{ssource.stop_possible()} is \tcode{false}. +and \tcode{\exposid{ssource}.stop_possible()} is \tcode{false}. \end{itemdescr} \indexlibraryctor{jthread}% @@ -2026,7 +2025,7 @@ \pnum \effects -Initializes \tcode{ssource}. +Initializes \exposid{ssource}. The new thread of execution executes \begin{codeblock} invoke(auto(std::forward(f)), get_stop_token(), // for \tcode{invoke}, see \ref{func.invoke} @@ -2055,7 +2054,7 @@ \pnum \ensures \tcode{get_id() != id()} is \tcode{true} -and \tcode{ssource.stop_possible()} is \tcode{true} +and \tcode{\exposid{ssource}.stop_possible()} is \tcode{true} and \tcode{*this} represents the newly started thread. \begin{note} The calling thread can make a stop request only once, @@ -2087,9 +2086,9 @@ \tcode{x.get_id() == id()} and \tcode{get_id()} returns the value of \tcode{x.get_id()} prior to the start of construction. -\tcode{ssource} has the value of \tcode{x.ssource} +\exposid{ssource} has the value of \tcode{x.\exposid{ssource}} prior to the start of construction -and \tcode{x.ssource.stop_possible()} is \tcode{false}. +and \tcode{x.\exposid{ssource}.stop_possible()} is \tcode{false}. \end{itemdescr} \indexlibrarydtor{jthread}% @@ -2125,7 +2124,7 @@ \ensures \tcode{get_id()} returns the value of \tcode{x.get_id()} prior to the assignment. -\tcode{ssource} has the value of \tcode{x.ssource} +\exposid{ssource} has the value of \tcode{x.\exposid{ssource}} prior to the assignment. \pnum @@ -2253,7 +2252,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return ssource;} +Equivalent to: \tcode{return \exposid{ssource};} \end{itemdescr} \indexlibrarymember{get_stop_token}{jthread}% @@ -2264,7 +2263,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return ssource.get_token();} +Equivalent to: \tcode{return \exposid{ssource}.get_token();} \end{itemdescr} \indexlibrarymember{request_stop}{jthread}% @@ -2275,7 +2274,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return ssource.request_stop();} +Equivalent to: \tcode{return \exposid{ssource}.request_stop();} \end{itemdescr} @@ -2398,6 +2397,10 @@ \rSec2[atomics.general]{General} +\pnum +Let \tcode{\placeholdernc{COPYCV}(FROM, TO)} be an alias for type \tcode{TO} +with the addition of \tcode{FROM}'s top-level cv-qualifiers. + \pnum Subclause \ref{atomics} describes components for fine-grained atomic access. This access is provided via operations on atomic objects. @@ -2807,10 +2810,10 @@ \pnum The type aliases \tcode{atomic_int$N$_t}, \tcode{atomic_uint$N$_t}, \tcode{atomic_intptr_t}, and \tcode{atomic_uintptr_t} -are defined if and only if +are declared if and only if \tcode{int$N$_t}, \tcode{uint$N$_t}, \tcode{intptr_t}, and \tcode{uintptr_t} -are defined, respectively. +are declared, respectively. \pnum \indexlibraryglobal{atomic_signed_lock_free}% @@ -3150,17 +3153,21 @@ namespace std { template struct atomic_ref { private: - T* ptr; // \expos + T* @\exposid{ptr}@; // \expos public: using value_type = remove_cv_t; + using @\exposid{address-return-type}@ = @\placeholdernc{COPYCV}@(T, void)*; // \expos static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(T&); + explicit atomic_ref(T&&) = delete; constexpr atomic_ref(const atomic_ref&) noexcept; + template + constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; @@ -3182,25 +3189,25 @@ constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; - constexpr T* address() const noexcept; + constexpr @\exposid{address-return-type}@ address() const noexcept; }; } \end{codeblock} \pnum An \tcode{atomic_ref} object applies atomic operations\iref{atomics.general} to -the object referenced by \tcode{*ptr} such that, +the object referenced by \tcode{*\exposid{ptr}} such that, for the lifetime\iref{basic.life} of the \tcode{atomic_ref} object, -the object referenced by \tcode{*ptr} is an atomic object\iref{intro.races}. +the object referenced by \tcode{*\exposid{ptr}} is an atomic object\iref{intro.races}. \pnum The program is ill-formed if \tcode{is_trivially_copyable_v} is \tcode{false}. \pnum -The lifetime\iref{basic.life} of an object referenced by \tcode{*ptr} +The lifetime\iref{basic.life} of an object referenced by \tcode{*\exposid{ptr}} shall exceed the lifetime of all \tcode{atomic_ref}s that reference the object. While any \tcode{atomic_ref} instances exist -that reference the \tcode{*ptr} object, +that reference the \tcode{*\exposid{ptr}} object, all accesses to that object shall exclusively occur through those \tcode{atomic_ref} instances. No subobject of the object referenced by \tcode{atomic_ref} @@ -3236,17 +3243,16 @@ \pnum The alignment required for an object to be referenced by an atomic reference, which is at least \tcode{alignof(T)}. +For any type \tcode{U} similar to \tcode{T}, +the value of \tcode{required_alignment} +is the same as \tcode{atomic_ref>::required_alignment}. \pnum \begin{note} -Hardware could require an object -referenced by an \tcode{atomic_ref} -to have stricter alignment\iref{basic.align} -than other objects of type \tcode{T}. -Further, whether operations on an \tcode{atomic_ref} -are lock-free could depend on the alignment of the referenced object. -For example, lock-free operations on \tcode{std::complex} -could be supported only if aligned to \tcode{2*alignof(double)}. +An implementation can choose to define +\tcode{atomic_ref::required_alignment} +to a value greater than \tcode{alignof(T)} in order to ensure that +operations on all objects of type \tcode{atomic_ref} are lock-free. \end{note} \end{itemdescr} @@ -3263,6 +3269,9 @@ The static data member \tcode{is_always_lock_free} is \tcode{true} if the \tcode{atomic_ref} type's operations are always lock-free, and \tcode{false} otherwise. +For any type \tcode{U} similar to \tcode{T}, +the value of \tcode{is_always_lock_free} +is the same as \tcode{atomic_ref>::is_always_lock_free}. \end{itemdescr} \indexlibrarymember{is_lock_free}{atomic_ref}% @@ -3317,6 +3326,24 @@ \tcode{*this} references the object referenced by \tcode{ref}. \end{itemdescr} +\begin{itemdecl} +template + constexpr atomic_ref(const atomic_ref&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{T} and \tcode{U} are similar types\iref{conv.qual}, and +\item \tcode{is_convertible_v} is \tcode{true}. +\end{itemize} + +\pnum +\ensures +\tcode{*this} references the object referenced by \tcode{ref}. +\end{itemdescr} + \indexlibrarymember{store}{atomic_ref}% \indexlibrarymember{store}{atomic_ref<\placeholder{pointer-type}>}% \indexlibrarymember{store}{atomic_ref<\placeholder{integral-type}>}% @@ -3340,7 +3367,7 @@ \pnum \effects -Atomically replaces the value referenced by \tcode{*ptr} +Atomically replaces the value referenced by \tcode{*\exposid{ptr}} with the value of \tcode{desired}. Memory is affected according to the value of \tcode{order}. \end{itemdescr} @@ -3389,7 +3416,7 @@ \pnum \returns -Atomically returns the value referenced by \tcode{*ptr}. +Atomically returns the value referenced by \tcode{*\exposid{ptr}}. \end{itemdescr} \indexlibrarymember{operator \placeholder{type}}{atomic_ref}% @@ -3422,14 +3449,14 @@ \pnum \effects -Atomically replaces the value referenced by \tcode{*ptr} +Atomically replaces the value referenced by \tcode{*\exposid{ptr}} with \tcode{desired}. Memory is affected according to the value of \tcode{order}. This operation is an atomic read-modify-write operation\iref{intro.multithread}. \pnum \returns -Atomically returns the value referenced by \tcode{*ptr} +Atomically returns the value referenced by \tcode{*\exposid{ptr}} immediately before the effects. \end{itemdescr} @@ -3443,16 +3470,16 @@ \indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} constexpr bool compare_exchange_weak(value_type& expected, value_type desired, - memory_order success, memory_order failure) const noexcept; + memory_order success, memory_order failure) const noexcept; constexpr bool compare_exchange_strong(value_type& expected, value_type desired, - memory_order success, memory_order failure) const noexcept; + memory_order success, memory_order failure) const noexcept; constexpr bool compare_exchange_weak(value_type& expected, value_type desired, - memory_order order = memory_order::seq_cst) const noexcept; + memory_order order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type& expected, value_type desired, - memory_order order = memory_order::seq_cst) const noexcept; + memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3471,9 +3498,9 @@ \effects Retrieves the value in \tcode{expected}. It then atomically compares the value representation of -the value referenced by \tcode{*ptr} for equality +the value referenced by \tcode{*\exposid{ptr}} for equality with that previously retrieved from \tcode{expected}, -and if \tcode{true}, replaces the value referenced by \tcode{*ptr} +and if \tcode{true}, replaces the value referenced by \tcode{*\exposid{ptr}} with that in \tcode{desired}. If and only if the comparison is \tcode{true}, memory is affected according to the value of \tcode{success}, and @@ -3489,11 +3516,11 @@ If and only if the comparison is \tcode{false} then, after the atomic operation, the value in \tcode{expected} is replaced by -the value read from the value referenced by \tcode{*ptr} +the value read from the value referenced by \tcode{*\exposid{ptr}} during the atomic comparison. If the operation returns \tcode{true}, these operations are atomic read-modify-write operations\iref{intro.races} -on the value referenced by \tcode{*ptr}. +on the value referenced by \tcode{*\exposid{ptr}}. Otherwise, these operations are atomic load operations on that memory. \pnum @@ -3503,11 +3530,11 @@ \pnum \remarks A weak compare-and-exchange operation may fail spuriously. -That is, even when the contents of memory referred to -by \tcode{expected} and \tcode{ptr} are equal, +That is, even when the value representations referred to +by \tcode{expected} and \exposid{ptr} compare equal, it may return \tcode{false} and -store back to \tcode{expected} the same memory contents -that were originally there. +store back to \tcode{expected} +the same value representation that was originally there. \begin{note} This spurious failure enables implementation of compare-and-exchange on a broader class of machines, e.g., load-locked store-conditional machines. @@ -3550,7 +3577,7 @@ \pnum \remarks This function is an atomic waiting operation\iref{atomics.wait} -on atomic object \tcode{*ptr}. +on atomic object \tcode{*\exposid{ptr}}. \end{itemdescr} \indexlibrarymember{notify_one}{atomic_ref}% @@ -3565,14 +3592,14 @@ \pnum \effects -Unblocks the execution of at least one atomic waiting operation on \tcode{*ptr} +Unblocks the execution of at least one atomic waiting operation on \tcode{*\exposid{ptr}} that is eligible to be unblocked\iref{atomics.wait} by this call, if any such atomic waiting operations exist. \pnum \remarks This function is an atomic notifying operation\iref{atomics.wait} -on atomic object \tcode{*ptr}. +on atomic object \tcode{*\exposid{ptr}}. \end{itemdescr} \indexlibrarymember{notify_all}{atomic_ref}% @@ -3587,24 +3614,24 @@ \pnum \effects -Unblocks the execution of all atomic waiting operations on \tcode{*ptr} +Unblocks the execution of all atomic waiting operations on \tcode{*\exposid{ptr}} that are eligible to be unblocked\iref{atomics.wait} by this call. \pnum \remarks This function is an atomic notifying operation\iref{atomics.wait} -on atomic object \tcode{*ptr}. +on atomic object \tcode{*\exposid{ptr}}. \end{itemdescr} \indexlibrarymember{address}{atomic_ref}% \begin{itemdecl} -constexpr T* address() const noexcept; +constexpr @\exposid{address-return-type}@ address() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{ptr}. +\exposid{ptr}. \end{itemdescr} \rSec3[atomics.ref.int]{Specializations for integral types} @@ -3630,18 +3657,22 @@ namespace std { template<> struct atomic_ref<@\placeholder{integral-type}@> { private: - @\placeholder{integral-type}@* ptr; // \expos + @\placeholder{integral-type}@* @\exposid{ptr}@; // \expos public: using value_type = remove_cv_t<@\placeholder{integral-type}@>; using difference_type = value_type; + using @\exposid{address-return-type}@ = @\placeholdernc{COPYCV}@(@\placeholder{integral-type}@, void)*; // \expos static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(@\placeholder{integral-type}@&); + explicit atomic_ref(@\placeholder{integral-type}@&&) = delete; constexpr atomic_ref(const atomic_ref&) noexcept; + template + constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; @@ -3703,7 +3734,7 @@ constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; - constexpr @\placeholder{integral-type}@* address() const noexcept; + constexpr @\exposid{address-return-type}@ address() const noexcept; }; } \end{codeblock} @@ -3736,15 +3767,15 @@ \pnum \effects -Atomically replaces the value referenced by \tcode{*ptr} with -the result of the computation applied to the value referenced by \tcode{*ptr} +Atomically replaces the value referenced by \tcode{*\exposid{ptr}} with +the result of the computation applied to the value referenced by \tcode{*\exposid{ptr}} and the given operand. Memory is affected according to the value of \tcode{order}. These operations are atomic read-modify-write operations\iref{intro.races}. \pnum \returns -Atomically, the value referenced by \tcode{*ptr} +Atomically, the value referenced by \tcode{*\exposid{ptr}} immediately before the effects. \pnum @@ -3778,6 +3809,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{integral-type}>} is \tcode{false}. + \pnum \expects \tcode{order} is \tcode{memory_order::relaxed}, @@ -3786,9 +3821,9 @@ \pnum \effects -Atomically replaces the value referenced by \tcode{*ptr} +Atomically replaces the value referenced by \tcode{*\exposid{ptr}} with the result of the computation applied to -the value referenced by \tcode{*ptr} and the given \tcode{operand}. +the value referenced by \tcode{*\exposid{ptr}} and the given \tcode{operand}. Memory is affected according to the value of \tcode{order}. These operations are atomic modify-write operations\iref{atomics.order}. @@ -3796,7 +3831,7 @@ \remarks Except for \tcode{store_max} and \tcode{store_min}, for signed integer types, -the result is as if \tcode{*ptr} and parameters +the result is as if \tcode{*\exposid{ptr}} and parameters were converted to their corresponding unsigned types, the computation performed on those types, and the result converted back to the signed type. @@ -3806,7 +3841,7 @@ For \tcode{store_max} and \tcode{store_min}, the maximum and minimum computation is performed as if by \tcode{max} and \tcode{min} algorithms\iref{alg.min.max}, respectively, -with \tcode{*ptr} and the first parameter as the arguments. +with \tcode{*\exposid{ptr}} and the first parameter as the arguments. \end{itemdescr} \indexlibrarymember{operator+=}{atomic_ref<\placeholder{integral-type}>}% @@ -3848,18 +3883,22 @@ namespace std { template<> struct atomic_ref<@\placeholder{floating-point-type}@> { private: - @\placeholder{floating-point-type}@* ptr; // \expos + @\placeholder{floating-point-type}@* @\exposid{ptr}@; // \expos public: using value_type = remove_cv_t<@\placeholder{floating-point-type}@>; using difference_type = value_type; + using @\exposid{address-return-type}@ = @\placeholdernc{COPYCV}@(@\placeholder{floating-point-type}@, void)*; // \expos static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(@\placeholder{floating-point-type}@&); + explicit atomic_ref(@\placeholder{floating-point-type}@&&) = delete; constexpr atomic_ref(const atomic_ref&) noexcept; + template + constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, @@ -3917,7 +3956,7 @@ memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; - constexpr @\placeholder{floating-point-type}@* address() const noexcept; + constexpr @\exposid{address-return-type}@ address() const noexcept; }; } \end{codeblock} @@ -3949,25 +3988,25 @@ \indexlibrarymember{fetch_min}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} constexpr value_type fetch_@\placeholdernc{key}@(value_type operand, - memory_order order = memory_order::seq_cst) const noexcept; + memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_const_v<\exposid{floating-point-type}>} is \tcode{false}. +\tcode{is_const_v<\placeholder{floating-point-type}>} is \tcode{false}. \pnum \effects -Atomically replaces the value referenced by \tcode{*ptr} with -the result of the computation applied to the value referenced by \tcode{*ptr} +Atomically replaces the value referenced by \tcode{*\exposid{ptr}} with +the result of the computation applied to the value referenced by \tcode{*\exposid{ptr}} and the given operand. Memory is affected according to the value of \tcode{order}. These operations are atomic read-modify-write operations\iref{intro.races}. \pnum \returns -Atomically, the value referenced by \tcode{*ptr} +Atomically, the value referenced by \tcode{*\exposid{ptr}} immediately before the effects. \pnum @@ -3988,27 +4027,27 @@ For \tcode{fetch_fmaximum} and \tcode{fetch_fminimum}, the maximum and minimum computation is performed as if by \tcode{fmaximum} and \tcode{fminimum}, respectively, -with \tcode{*ptr} and the first parameter as the arguments. +with \tcode{*\exposid{ptr}} and the first parameter as the arguments. \item For \tcode{fetch_fmaximum_num} and \tcode{fetch_fminimum_num}, the maximum and minimum computation is performed as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, -with \tcode{*ptr} and the first parameter as the arguments. +with \tcode{*\exposid{ptr}} and the first parameter as the arguments. \item For \tcode{fetch_max} and \tcode{fetch_min}, the maximum and minimum computation is performed as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, -with \tcode{*ptr} and the first parameter as the arguments, except that: +with \tcode{*\exposid{ptr}} and the first parameter as the arguments, except that: \begin{itemize} \item -If both arguments are NaN, an unspecified NaN value is stored at \tcode{*ptr}. +If both arguments are NaN, an unspecified NaN value is stored at \tcode{*\exposid{ptr}}. \item If exactly one argument is a NaN, -either the other argument or an unspecified NaN value is stored at \tcode{*ptr}; +either the other argument or an unspecified NaN value is stored at \tcode{*\exposid{ptr}}; it is unspecified which. \item If the arguments are differently signed zeros, -which of these values is stored at \tcode{*ptr} is unspecified. +which of these values is stored at \tcode{*\exposid{ptr}} is unspecified. \end{itemize} \end{itemize} @@ -4028,10 +4067,14 @@ \indexlibrarymember{store_fmaximum_num}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} constexpr void store_@\placeholdernc{key}@(value_type operand, - memory_order order = memory_order::seq_cst) const noexcept; + memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{floating-point-type}>} is \tcode{false}. + \pnum \expects \tcode{order} is \tcode{memory_order::relaxed}, @@ -4040,9 +4083,9 @@ \pnum \effects -Atomically replaces the value referenced by \tcode{*ptr} +Atomically replaces the value referenced by \tcode{*\exposid{ptr}} with the result of the computation applied to -the value referenced by \tcode{*ptr} and the given \tcode{operand}. +the value referenced by \tcode{*\exposid{ptr}} and the given \tcode{operand}. Memory is affected according to the value of \tcode{order}. These operations are atomic modify-write operations\iref{atomics.order}. @@ -4070,23 +4113,23 @@ For \tcode{store_fmaximum} and \tcode{store_fminimum}, the maximum and minimum computation is performed as if by \tcode{fmaximum} and \tcode{fminimum}, respectively, -with \tcode{*ptr} and the first parameter as the arguments. +with \tcode{*\exposid{ptr}} and the first parameter as the arguments. \item For \tcode{store_fmaximum_num} and \tcode{store_fminimum_num}, the maximum and minimum computation is performed as if by \tcode{fmaximum_num }and \tcode{fminimum_num}, respectively, -with \tcode{*ptr} and the first parameter as the arguments. +with \tcode{*\exposid{ptr}} and the first parameter as the arguments. \item For \tcode{store_max} and \tcode{store_min}, the maximum and minimum computation is performed as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, -with \tcode{*ptr} and the first parameter as the arguments, except that: +with \tcode{*\exposid{ptr}} and the first parameter as the arguments, except that: \begin{itemize} \item -If both arguments are NaN, an unspecified NaN value is stored at \tcode{*ptr}. +If both arguments are NaN, an unspecified NaN value is stored at \tcode{*\exposid{ptr}}. \item If exactly one argument is a NaN, -either the other argument or an unspecified NaN value is stored at \tcode{*ptr}, +either the other argument or an unspecified NaN value is stored at \tcode{*\exposid{ptr}}, it is unspecified which. \item If the arguments are differently signed zeros, @@ -4109,7 +4152,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{is_const_v<\exposid{floating-point-type}>} is \tcode{false}. +\tcode{is_const_v<\placeholder{floating-point-type}>} is \tcode{false}. \pnum \effects @@ -4136,18 +4179,22 @@ namespace std { template<> struct atomic_ref<@\placeholder{pointer-type}@> { private: - @\placeholder{pointer-type}@* ptr; // \expos + @\placeholder{pointer-type}@* @\exposid{ptr}@; // \expos public: using value_type = remove_cv_t<@\placeholder{pointer-type}@>; using difference_type = ptrdiff_t; + using @\exposid{address-return-type}@ = @\placeholdernc{COPYCV}@(@\placeholder{pointer-type}@, void)*; // \expos static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(@\placeholder{pointer-type}@&); + explicit atomic_ref(@\placeholder{pointer-type}@&&) = delete; constexpr atomic_ref(const atomic_ref&) noexcept; + template + constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; @@ -4194,7 +4241,7 @@ constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; - constexpr @\placeholder{pointer-type}@* address() const noexcept; + constexpr @\placeholder{address-return-type}@ address() const noexcept; }; } \end{codeblock} @@ -4228,15 +4275,15 @@ \pnum \effects -Atomically replaces the value referenced by \tcode{*ptr} with -the result of the computation applied to the value referenced by \tcode{*ptr} +Atomically replaces the value referenced by \tcode{*\exposid{ptr}} with +the result of the computation applied to the value referenced by \tcode{*\exposid{ptr}} and the given operand. Memory is affected according to the value of \tcode{order}. These operations are atomic read-modify-write operations\iref{intro.races}. \pnum \returns -Atomically, the value referenced by \tcode{*ptr} +Atomically, the value referenced by \tcode{*\exposid{ptr}} immediately before the effects. \pnum @@ -4267,6 +4314,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{pointer-type}>} is \tcode{false}. + \pnum \mandates \tcode{remove_pointer_t<\placeholder{pointer-type}>} is a complete object type. @@ -4279,9 +4330,9 @@ \pnum \effects -Atomically replaces the value referenced by \tcode{*ptr} +Atomically replaces the value referenced by \tcode{*\exposid{ptr}} with the result of the computation applied to -the value referenced by \tcode{*ptr} and the given \tcode{operand}. +the value referenced by \tcode{*\exposid{ptr}} and the given \tcode{operand}. Memory is affected according to the value of \tcode{order}. These operations are atomic modify-write operations\iref{atomics.order}. @@ -4292,7 +4343,7 @@ For \tcode{store_max} and \tcode{store_min}, the \tcode{maximum} and \tcode{minimum} computation is performed as if by \tcode{max} and \tcode{min} algorithms\iref{alg.min.max}, respectively, -with \tcode{*ptr} and the first parameter as the arguments. +with \tcode{*\exposid{ptr}} and the first parameter as the arguments. \begin{note} If the pointers point to different complete objects (or subobjects thereof), the \tcode{<} operator does not establish @@ -4714,19 +4765,19 @@ bool compare_exchange_weak(T& expected, T desired, memory_order success, memory_order failure) volatile noexcept; constexpr bool compare_exchange_weak(T& expected, T desired, - memory_order success, memory_order failure) noexcept; + memory_order success, memory_order failure) noexcept; bool compare_exchange_strong(T& expected, T desired, memory_order success, memory_order failure) volatile noexcept; constexpr bool compare_exchange_strong(T& expected, T desired, - memory_order success, memory_order failure) noexcept; + memory_order success, memory_order failure) noexcept; bool compare_exchange_weak(T& expected, T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(T& expected, T desired, - memory_order order = memory_order::seq_cst) noexcept; + memory_order order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(T& expected, T desired, - memory_order order = memory_order::seq_cst) noexcept; + memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4762,7 +4813,7 @@ pointed to by \keyword{this} during the atomic comparison. If the operation returns \tcode{true}, these operations are atomic read-modify-write -operations\iref{intro.multithread} on the memory +operations\iref{intro.races} on the memory pointed to by \keyword{this}. Otherwise, these operations are atomic load operations on that memory. @@ -4806,6 +4857,7 @@ \end{example} \pnum +\recommended Implementations should ensure that weak compare-and-exchange operations do not consistently return \tcode{false} unless either the atomic object has value different from \tcode{expected} or there are concurrent modifications to the @@ -4814,9 +4866,11 @@ \pnum \remarks A weak compare-and-exchange operation may fail spuriously. That is, even when -the contents of memory referred to by \tcode{expected} and \keyword{this} are -equal, it may return \tcode{false} and store back to \tcode{expected} the same memory -contents that were originally there. +the value representations referred to by \tcode{expected} and \keyword{this} +compare equal, +it may return \tcode{false} and +store back to \tcode{expected} +the same value representation that was originally there. \begin{note} This spurious failure enables implementation of compare-and-exchange on a broader class of @@ -4961,23 +5015,10 @@ \indexlibrary{\idxcode{atomic<\placeholder{integral-type}>}}% \pnum There are specializations of the \tcode{atomic} -class template for the integral types -\tcode{char}, -\tcode{signed char}, -\tcode{unsigned char}, -\tcode{short}, -\tcode{unsigned short}, -\tcode{int}, -\tcode{unsigned int}, -\tcode{long}, -\tcode{unsigned long}, -\tcode{long long}, -\tcode{unsigned long long}, -\keyword{char8_t}, -\keyword{char16_t}, -\keyword{char32_t}, -\keyword{wchar_t}, -and any other types needed by the typedefs in the header \libheaderref{cstdint}. +class template for +each character type\iref{basic.fundamental}, +each standard integer type, and +any other types needed by the typedefs in the header \libheaderref{cstdint}. For each such type \tcode{\placeholder{integral-type}}, the specialization \tcode{atomic<\placeholder{integral-type}>} provides additional atomic operations appropriate to integral types. \begin{note} @@ -5013,52 +5054,52 @@ @\placeholdernc{integral-type}@ exchange(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; constexpr @\placeholdernc{integral-type}@ exchange(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, - memory_order, memory_order) noexcept; + memory_order, memory_order) noexcept; bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, - memory_order, memory_order) noexcept; + memory_order, memory_order) noexcept; bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_add(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; constexpr @\placeholdernc{integral-type}@ fetch_add(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_sub(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; constexpr @\placeholdernc{integral-type}@ fetch_sub(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_and(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; constexpr @\placeholdernc{integral-type}@ fetch_and(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_or(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) volatile noexcept; + memory_order = memory_order::seq_cst) volatile noexcept; constexpr @\placeholdernc{integral-type}@ fetch_or(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; constexpr @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_max(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; constexpr @\placeholdernc{integral-type}@ fetch_max(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_min(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; constexpr @\placeholdernc{integral-type}@ fetch_min(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; void store_add(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; @@ -5385,7 +5426,7 @@ memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{floating-point-type}@ fetch_min(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - constexpr @\placeholdernc{floating-poin-type}@t fetch_min(@\placeholdernc{floating-point-type}@, + constexpr @\placeholdernc{floating-point-type}@ fetch_min(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{floating-point-type}@ fetch_fmaximum(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; @@ -5724,11 +5765,11 @@ bool compare_exchange_weak(T*&, T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(T*&, T*, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T*&, T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(T*&, T*, - memory_order = memory_order::seq_cst) noexcept; + memory_order = memory_order::seq_cst) noexcept; T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; @@ -6117,7 +6158,7 @@ constexpr void notify_all() noexcept; private: - shared_ptr p; // \expos + shared_ptr @\exposid{p}@; // \expos }; } \end{codeblock} @@ -6130,7 +6171,7 @@ \begin{itemdescr} \pnum \effects -Value-initializes \tcode{p}. +Value-initializes \exposid{p}. \end{itemdescr} \indexlibraryctor{atomic>}% @@ -6171,7 +6212,7 @@ \pnum \effects Atomically replaces the value pointed to by \keyword{this} with -the value of \tcode{desired} as if by \tcode{p.swap(desired)}. +the value of \tcode{desired} as if by \tcode{\exposid{p}.swap(desired)}. Memory is affected according to the value of \tcode{order}. \end{itemdescr} @@ -6216,7 +6257,7 @@ \pnum \returns -Atomically returns \tcode{p}. +Atomically returns \exposid{p}. \end{itemdescr} \indexlibrarymember{operator shared_ptr}{atomic>}% @@ -6239,14 +6280,14 @@ \begin{itemdescr} \pnum \effects -Atomically replaces \tcode{p} with \tcode{desired} -as if by \tcode{p.swap(desired)}. +Atomically replaces \exposid{p} with \tcode{desired} +as if by \tcode{\exposid{p}.swap(desired)}. Memory is affected according to the value of \tcode{order}. This is an atomic read-modify-write operation\iref{intro.races}. \pnum \returns -Atomically returns the value of \tcode{p} immediately before the effects. +Atomically returns the value of \exposid{p} immediately before the effects. \end{itemdescr} \indexlibrarymember{compare_exchange_weak}{atomic>}% @@ -6268,15 +6309,15 @@ \pnum \effects -If \tcode{p} is equivalent to \tcode{expected}, -assigns \tcode{desired} to \tcode{p} and +If \exposid{p} is equivalent to \tcode{expected}, +assigns \tcode{desired} to \exposid{p} and has synchronization semantics corresponding to the value of \tcode{success}, -otherwise assigns \tcode{p} to \tcode{expected} and +otherwise assigns \exposid{p} to \tcode{expected} and has synchronization semantics corresponding to the value of \tcode{failure}. \pnum \returns -\tcode{true} if \tcode{p} was equivalent to \tcode{expected}, +\tcode{true} if \exposid{p} was equivalent to \tcode{expected}, \tcode{false} otherwise. \pnum @@ -6445,7 +6486,7 @@ constexpr void notify_all() noexcept; private: - weak_ptr p; // \expos + weak_ptr @\exposid{p}@; // \expos }; } \end{codeblock} @@ -6458,7 +6499,7 @@ \begin{itemdescr} \pnum \effects -Value-initializes \tcode{p}. +Value-initializes \exposid{p}. \end{itemdescr} \indexlibraryctor{atomic>}% @@ -6499,7 +6540,7 @@ \pnum \effects Atomically replaces the value pointed to by \keyword{this} with -the value of \tcode{desired} as if by \tcode{p.swap(desired)}. +the value of \tcode{desired} as if by \tcode{\exposid{p}.swap(desired)}. Memory is affected according to the value of \tcode{order}. \end{itemdescr} @@ -6533,7 +6574,7 @@ \pnum \returns -Atomically returns \tcode{p}. +Atomically returns \exposid{p}. \end{itemdescr} \indexlibrarymember{operator weak_ptr}{atomic>}% @@ -6556,14 +6597,14 @@ \begin{itemdescr} \pnum \effects -Atomically replaces \tcode{p} with \tcode{desired} -as if by \tcode{p.swap(desired)}. +Atomically replaces \exposid{p} with \tcode{desired} +as if by \tcode{\exposid{p}.swap(desired)}. Memory is affected according to the value of \tcode{order}. This is an atomic read-modify-write operation\iref{intro.races}. \pnum \returns -Atomically returns the value of \tcode{p} immediately before the effects. +Atomically returns the value of \exposid{p} immediately before the effects. \end{itemdescr} \indexlibrarymember{compare_exchange_weak}{atomic>}% @@ -6584,15 +6625,15 @@ \pnum \effects -If \tcode{p} is equivalent to \tcode{expected}, -assigns \tcode{desired} to \tcode{p} and +If \exposid{p} is equivalent to \tcode{expected}, +assigns \tcode{desired} to \exposid{p} and has synchronization semantics corresponding to the value of \tcode{success}, -otherwise assigns \tcode{p} to \tcode{expected} and +otherwise assigns \exposid{p} to \tcode{expected} and has synchronization semantics corresponding to the value of \tcode{failure}. \pnum \returns -\tcode{true} if \tcode{p} was equivalent to \tcode{expected}, +\tcode{true} if \exposid{p} was equivalent to \tcode{expected}, \tcode{false} otherwise. \pnum @@ -7067,6 +7108,7 @@ #define @\libmacro{ATOMIC_BOOL_LOCK_FREE}@ @\seebelow@ #define @\libmacro{ATOMIC_CHAR_LOCK_FREE}@ @\seebelow@ +#define @\libmacro{ATOMIC_CHAR8_T_LOCK_FREE}@ @\seebelow@ #define @\libmacro{ATOMIC_CHAR16_T_LOCK_FREE}@ @\seebelow@ #define @\libmacro{ATOMIC_CHAR32_T_LOCK_FREE}@ @\seebelow@ #define @\libmacro{ATOMIC_WCHAR_T_LOCK_FREE}@ @\seebelow@ @@ -7176,7 +7218,7 @@ \pnum Each of the \grammarterm{using-declaration}s for \tcode{int$N$_t}, \tcode{uint$N$_t}, \tcode{intptr_t}, and \tcode{uintptr_t} -listed above is defined if and only if the implementation defines +listed above is declared if and only if the implementation declares the corresponding \grammarterm{typedef-name} in \ref{atomics.syn}. \pnum @@ -7308,7 +7350,7 @@ The implementation provides lock and unlock operations, as described below. For purposes of determining the existence of a data race, these behave as atomic operations\iref{intro.multithread}. The lock and unlock operations on -a single mutex appears to occur in a single total order. +a single mutex appear to occur in a single total order. \begin{note} This can be viewed as the modification order\iref{intro.multithread} of the @@ -7555,10 +7597,10 @@ \tcode{recursive_timed_mutex}, and \tcode{shared_timed_mutex}. They meet the requirements set out below. In this description, \tcode{m} denotes an object of a mutex type, -\tcode{rel_time} denotes an object of an -instantiation of \tcode{duration}\iref{time.duration}, and \tcode{abs_time} denotes an -object of an -instantiation of \tcode{time_point}\iref{time.point}. +\tcode{rel_time} denotes an object of a +specialization of \tcode{duration}\iref{time.duration}, and \tcode{abs_time} denotes an +object of a +specialization of \tcode{time_point}\iref{time.point}. \begin{note} The timed mutex types meet the \oldconcept{TimedLockable} requirements\iref{thread.req.lockable.timed}. @@ -7949,9 +7991,9 @@ shared mutex types\iref{thread.sharedmutex.requirements}, and additionally meet the requirements set out below. In this description, \tcode{m} denotes an object of a shared timed mutex type, -\tcode{rel_time} denotes an object of an instantiation of +\tcode{rel_time} denotes an object of a specialization of \tcode{duration}\iref{time.duration}, and -\tcode{abs_time} denotes an object of an instantiation of +\tcode{abs_time} denotes an object of a specialization of \tcode{time_point}\iref{time.point}. \begin{note} The shared timed mutex types meet the \oldconcept{SharedTimedLockable} @@ -8131,9 +8173,9 @@ struct adopt_lock_t { }; // assume the calling thread has already // obtained mutex ownership and manage it - inline constexpr defer_lock_t defer_lock { }; - inline constexpr try_to_lock_t try_to_lock { }; - inline constexpr adopt_lock_t adopt_lock { }; + inline constexpr defer_lock_t defer_lock { }; + inline constexpr try_to_lock_t try_to_lock { }; + inline constexpr adopt_lock_t adopt_lock { }; } \end{codeblock} @@ -8155,7 +8197,7 @@ lock_guard& operator=(const lock_guard&) = delete; private: - mutex_type& pm; // \expos + mutex_type& @\exposid{pm}@; // \expos }; } \end{codeblock} @@ -8165,7 +8207,7 @@ within a scope. A \tcode{lock_guard} object maintains ownership of a lockable object throughout the \tcode{lock_guard} object's lifetime\iref{basic.life}. The behavior of a program is undefined if the lockable object referenced by -\tcode{pm} does not exist for the entire lifetime of the \tcode{lock_guard} +\exposid{pm} does not exist for the entire lifetime of the \tcode{lock_guard} object. The supplied \tcode{Mutex} type shall meet the \oldconcept{BasicLockable} requirements\iref{thread.req.lockable.basic}. @@ -8177,7 +8219,7 @@ \begin{itemdescr} \pnum \effects -Initializes \tcode{pm} with \tcode{m}. Calls \tcode{m.lock()}. +Initializes \exposid{pm} with \tcode{m}. Calls \tcode{m.lock()}. \end{itemdescr} \indexlibraryctor{lock_guard}% @@ -8192,7 +8234,7 @@ \pnum \effects -Initializes \tcode{pm} with \tcode{m}. +Initializes \exposid{pm} with \tcode{m}. \pnum \throws @@ -8207,7 +8249,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{pm.unlock()} +Equivalent to: \tcode{\exposid{pm}.unlock()} \end{itemdescr} \rSec3[thread.lock.scoped]{Class template \tcode{scoped_lock}} @@ -8228,7 +8270,7 @@ scoped_lock& operator=(const scoped_lock&) = delete; private: - tuple pm; // \expos + tuple @\exposid{pm}@; // \expos }; } \end{codeblock} @@ -8238,7 +8280,7 @@ within a scope. A \tcode{scoped_lock} object maintains ownership of lockable objects throughout the \tcode{scoped_lock} object's lifetime\iref{basic.life}. The behavior of a program is undefined if the lockable objects referenced by -\tcode{pm} do not exist for the entire lifetime of the \tcode{scoped_lock} +\exposid{pm} do not exist for the entire lifetime of the \tcode{scoped_lock} object. \begin{itemize} \item @@ -8262,7 +8304,7 @@ \begin{itemdescr} \pnum \effects -Initializes \tcode{pm} with \tcode{tie(m...)}. +Initializes \exposid{pm} with \tcode{tie(m...)}. Then if \tcode{sizeof...(MutexTypes)} is \tcode{0}, no effects. Otherwise if \tcode{sizeof...(MutexTypes)} is \tcode{1}, then \tcode{m.lock()}. Otherwise, \tcode{lock(m...)}. @@ -8280,7 +8322,7 @@ \pnum \effects -Initializes \tcode{pm} with \tcode{tie(m...)}. +Initializes \exposid{pm} with \tcode{tie(m...)}. \pnum \throws @@ -8296,7 +8338,7 @@ \pnum \effects For all \tcode{i} in \range{0}{sizeof...(MutexTypes)}, -\tcode{get(pm).unlock()}. +\tcode{get(\exposid{pm}).unlock()}. \end{itemdescr} \rSec3[thread.lock.unique]{Class template \tcode{unique_lock}} @@ -8350,8 +8392,8 @@ mutex_type* mutex() const noexcept; private: - mutex_type* pm; // \expos - bool owns; // \expos + mutex_type* @\exposid{pm}@; // \expos + bool @\exposid{owns}@; // \expos }; } \end{codeblock} @@ -8362,8 +8404,8 @@ construction or after construction, and may be transferred, after acquisition, to another \tcode{unique_lock} object. Objects of type \tcode{unique_lock} are not copyable but are movable. The behavior of a program is undefined if the contained pointer -\tcode{pm} is not null and the lockable object pointed -to by \tcode{pm} does not exist for the entire remaining +\exposid{pm} is not null and the lockable object pointed +to by \exposid{pm} does not exist for the entire remaining lifetime\iref{basic.life} of the \tcode{unique_lock} object. The supplied \tcode{Mutex} type shall meet the \oldconcept{BasicLockable} requirements\iref{thread.req.lockable.basic}. @@ -8388,7 +8430,7 @@ \begin{itemdescr} \pnum \ensures -\tcode{pm == nullptr} and \tcode{owns == false}. +\tcode{\exposid{pm} == nullptr} and \tcode{\exposid{owns} == false}. \end{itemdescr} \indexlibraryctor{unique_lock}% @@ -8403,7 +8445,7 @@ \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == true}. +\tcode{\exposid{pm} == addressof(m)} and \tcode{\exposid{owns} == true}. \end{itemdescr} \indexlibraryctor{unique_lock}% @@ -8414,7 +8456,7 @@ \begin{itemdescr} \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == false}. +\tcode{\exposid{pm} == addressof(m)} and \tcode{\exposid{owns} == false}. \end{itemdescr} \indexlibraryctor{unique_lock}% @@ -8434,7 +8476,7 @@ \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == res}, +\tcode{\exposid{pm} == addressof(m)} and \tcode{o\exposid{owns}wns == res}, where \tcode{res} is the value returned by the call to \tcode{m.try_lock()}. \end{itemdescr} @@ -8450,7 +8492,7 @@ \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == true}. +\tcode{\exposid{pm} == addressof(m)} and \tcode{\exposid{owns} == true}. \pnum \throws @@ -8475,7 +8517,7 @@ \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == res}, +\tcode{\exposid{pm} == addressof(m)} and \tcode{\exposid{owns} == res}, where \tcode{res} is the value returned by the call to \tcode{m.try_lock_until(abs_time)}. \end{itemdescr} @@ -8497,7 +8539,7 @@ \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == res}, +\tcode{\exposid{pm} == addressof(m)} and \tcode{\exposid{owns} == res}, where \tcode{res} is the value returned by the call to \tcode{m.try_lock_for(rel_time)}. \end{itemdescr} @@ -8509,7 +8551,7 @@ \begin{itemdescr} \pnum \ensures -\tcode{pm == u_p.pm} and \tcode{owns == u_p.owns} (where \tcode{u_p} is the state of \tcode{u} just prior to this construction), \tcode{u.pm == 0} and \tcode{u.owns == false}. +\tcode{\exposid{pm} == u_p.\exposid{pm}} and \tcode{\exposid{owns} == u_p.\exposid{owns}} (where \tcode{u_p} is the state of \tcode{u} just prior to this construction), \tcode{u.\exposid{pm} == 0} and \tcode{u.\exposid{owns} == false}. \end{itemdescr} \indexlibrarymember{operator=}{unique_lock}% @@ -8535,7 +8577,7 @@ \begin{itemdescr} \pnum \effects -If \tcode{owns} calls \tcode{pm->unlock()}. +If \exposid{owns} calls \tcode{\exposid{pm}->unlock()}. \end{itemdescr} \rSec4[thread.lock.unique.locking]{Locking} @@ -8548,22 +8590,22 @@ \begin{itemdescr} \pnum \effects -As if by \tcode{pm->lock()}. +As if by \tcode{\exposid{pm}->lock()}. \pnum \ensures -\tcode{owns == true}. +\tcode{\exposid{owns} == true}. \pnum \throws -Any exception thrown by \tcode{pm->lock()}. \tcode{system_error} when an exception +Any exception thrown by \tcode{\exposid{pm}->lock()}. \tcode{system_error} when an exception is required\iref{thread.req.exception}. \pnum \errors \begin{itemize} -\item \tcode{operation_not_permitted} --- if \tcode{pm} is \keyword{nullptr}. -\item \tcode{resource_deadlock_would_occur} --- if on entry \tcode{owns} +\item \tcode{operation_not_permitted} --- if \exposid{pm} is \keyword{nullptr}. +\item \tcode{resource_deadlock_would_occur} --- if on entry \exposid{owns} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -8581,27 +8623,27 @@ \pnum \effects -As if by \tcode{pm->try_lock()}. +As if by \tcode{\exposid{pm}->try_lock()}. \pnum \ensures -\tcode{owns == res}, where \tcode{res} is the value returned by -\tcode{pm->try_lock()}. +\tcode{\exposid{owns} == res}, where \tcode{res} is the value returned by +\tcode{\exposid{pm}->try_lock()}. \pnum \returns -The value returned by \tcode{pm->try_lock()}. +The value returned by \tcode{\exposid{pm}->try_lock()}. \pnum \throws -Any exception thrown by \tcode{pm->try_lock()}. \tcode{system_error} when an exception +Any exception thrown by \tcode{\exposid{pm}->try_lock()}. \tcode{system_error} when an exception is required\iref{thread.req.exception}. \pnum \errors \begin{itemize} -\item \tcode{operation_not_permitted} --- if \tcode{pm} is \keyword{nullptr}. -\item \tcode{resource_deadlock_would_occur} --- if on entry \tcode{owns} +\item \tcode{operation_not_permitted} --- if \exposid{pm} is \keyword{nullptr}. +\item \tcode{resource_deadlock_would_occur} --- if on entry \exposid{owns} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -8620,27 +8662,27 @@ \pnum \effects -As if by \tcode{pm->try_lock_until(abs_time)}. +As if by \tcode{\exposid{pm}->try_lock_until(abs_time)}. \pnum \ensures -\tcode{owns == res}, where \tcode{res} is the value returned by -\tcode{pm->try_lock_until(abs_time)}. +\tcode{\exposid{owns} == res}, where \tcode{res} is the value returned by +\tcode{\exposid{pm}->try_lock_until(abs_time)}. \pnum \returns -The value returned by \tcode{pm->try_lock_until(abs_time)}. +The value returned by \tcode{\exposid{pm}->try_lock_until(abs_time)}. \pnum \throws -Any exception thrown by \tcode{pm->try_lock_until(abstime)}. \tcode{system_error} when an +Any exception thrown by \tcode{\exposid{pm}->try_lock_until(abstime)}. \tcode{system_error} when an exception is required\iref{thread.req.exception}. \pnum \errors \begin{itemize} -\item \tcode{operation_not_permitted} --- if \tcode{pm} is \keyword{nullptr}. -\item \tcode{resource_deadlock_would_occur} --- if on entry \tcode{owns} is +\item \tcode{operation_not_permitted} --- if \exposid{pm} is \keyword{nullptr}. +\item \tcode{resource_deadlock_would_occur} --- if on entry \exposid{owns} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -8658,26 +8700,26 @@ \pnum \effects -As if by \tcode{pm->try_lock_for(rel_time)}. +As if by \tcode{\exposid{pm}->try_lock_for(rel_time)}. \pnum \ensures -\tcode{owns == res}, where \tcode{res} is the value returned by \tcode{pm->try_lock_for(rel_time)}. +\tcode{\exposid{owns} == res}, where \tcode{res} is the value returned by \tcode{\exposid{pm}->try_lock_for(rel_time)}. \pnum \returns -The value returned by \tcode{pm->try_lock_for(rel_time)}. +The value returned by \tcode{\exposid{pm}->try_lock_for(rel_time)}. \pnum \throws -Any exception thrown by \tcode{pm->try_lock_for(rel_time)}. \tcode{system_error} when an +Any exception thrown by \tcode{\exposid{pm}->try_lock_for(rel_time)}. \tcode{system_error} when an exception is required\iref{thread.req.exception}. \pnum \errors \begin{itemize} -\item \tcode{operation_not_permitted} --- if \tcode{pm} is \keyword{nullptr}. -\item \tcode{resource_deadlock_would_occur} --- if on entry \tcode{owns} is +\item \tcode{operation_not_permitted} --- if \exposid{pm} is \keyword{nullptr}. +\item \tcode{resource_deadlock_would_occur} --- if on entry \exposid{owns} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -8690,11 +8732,11 @@ \begin{itemdescr} \pnum \effects -As if by \tcode{pm->unlock()}. +As if by \tcode{\exposid{pm}->unlock()}. \pnum \ensures -\tcode{owns == false}. +\tcode{\exposid{owns} == false}. \pnum \throws @@ -8704,7 +8746,7 @@ \pnum \errors \begin{itemize} -\item \tcode{operation_not_permitted} --- if on entry \tcode{owns} is \tcode{false}. +\item \tcode{operation_not_permitted} --- if on entry \exposid{owns} is \tcode{false}. \end{itemize} \end{itemdescr} @@ -8729,11 +8771,11 @@ \begin{itemdescr} \pnum \ensures -\tcode{pm == 0} and \tcode{owns == false}. +\tcode{\exposid{pm} == 0} and \tcode{\exposid{owns} == false}. \pnum \returns -The previous value of \tcode{pm}. +The previous value of \exposid{pm}. \end{itemdescr} \indexlibrarymember{swap}{unique_lock}% @@ -8758,7 +8800,7 @@ \begin{itemdescr} \pnum \returns -\tcode{owns}. +\exposid{owns}. \end{itemdescr} \indexlibrarymember{operator bool}{unique_lock}% @@ -8780,7 +8822,7 @@ \begin{itemdescr} \pnum \returns -\tcode{pm}. +\exposid{pm}. \end{itemdescr} \rSec3[thread.lock.shared]{Class template \tcode{shared_lock}} @@ -8832,8 +8874,8 @@ mutex_type* mutex() const noexcept; private: - mutex_type* pm; // \expos - bool owns; // \expos + mutex_type* @\exposid{pm}@; // \expos + bool @\exposid{owns}@; // \expos }; } \end{codeblock} @@ -8844,8 +8886,8 @@ acquired at construction or after construction, and may be transferred, after acquisition, to another \tcode{shared_lock} object. Objects of type \tcode{shared_lock} are not copyable but are movable. The behavior of a program -is undefined if the contained pointer \tcode{pm} is not null and the lockable -object pointed to by \tcode{pm} does not exist for the entire remaining +is undefined if the contained pointer \exposid{pm} is not null and the lockable +object pointed to by \exposid{pm} does not exist for the entire remaining lifetime\iref{basic.life} of the \tcode{shared_lock} object. The supplied \tcode{Mutex} type shall meet the \oldconcept{SharedLockable} requirements\iref{thread.req.lockable.shared}. @@ -8870,7 +8912,7 @@ \begin{itemdescr} \pnum \ensures -\tcode{pm == nullptr} and \tcode{owns == false}. +\tcode{\exposid{pm} == nullptr} and \tcode{\exposid{owns} == false}. \end{itemdescr} \indexlibraryctor{shared_lock}% @@ -8885,7 +8927,7 @@ \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == true}. +\tcode{\exposid{pm} == addressof(m)} and \tcode{\exposid{owns} == true}. \end{itemdescr} \indexlibraryctor{shared_lock}% @@ -8896,7 +8938,7 @@ \begin{itemdescr} \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == false}. +\tcode{pm == addressof(m)} and \tcode{\exposid{owns} == false}. \end{itemdescr} \indexlibraryctor{shared_lock}% @@ -8911,7 +8953,7 @@ \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == res} +\tcode{\exposid{pm} == addressof(m)} and \tcode{\exposid{owns} == res} where \tcode{res} is the value returned by the call to \tcode{m.try_lock_shared()}. \end{itemdescr} @@ -8928,7 +8970,7 @@ \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == true}. +\tcode{\exposid{pm} == addressof(m)} and \tcode{\exposid{owns} == true}. \end{itemdescr} \indexlibraryctor{shared_lock}% @@ -8950,7 +8992,7 @@ \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == res} +\tcode{\exposid{pm} == addressof(m)} and \tcode{\exposid{owns} == res} where \tcode{res} is the value returned by the call to \tcode{m.try_lock_shared_until(abs_time)}. \end{itemdescr} @@ -8974,7 +9016,7 @@ \pnum \ensures -\tcode{pm == addressof(m)} and \tcode{owns == res} +\tcode{\exposid{pm} == addressof(m)} and \tcode{\exposid{owns} == res} where \tcode{res} is the value returned by the call to \tcode{m.try_lock_shared_for(rel_time)}. \end{itemdescr} @@ -8987,7 +9029,7 @@ \begin{itemdescr} \pnum \effects -If \tcode{owns} calls \tcode{pm->unlock_shared()}. +If \exposid{owns} calls \tcode{\exposid{pm}->unlock_shared()}. \end{itemdescr} \indexlibraryctor{shared_lock}% @@ -8998,9 +9040,9 @@ \begin{itemdescr} \pnum \ensures -\tcode{pm == sl_p.pm} and \tcode{owns == sl_p.owns} (where +\tcode{\exposid{pm} == sl_p.\exposid{pm}} and \tcode{\exposid{owns} == sl_p.\exposid{owns}} (where \tcode{sl_p} is the state of \tcode{sl} just prior to this construction), -\tcode{sl.pm == nullptr} and \tcode{sl.owns == false}. +\tcode{sl.\exposid{pm} == nullptr} and \tcode{sl.\exposid{owns} == false}. \end{itemdescr} \indexlibrarymember{operator=}{shared_lock}% @@ -9028,22 +9070,22 @@ \begin{itemdescr} \pnum \effects -As if by \tcode{pm->lock_shared()}. +As if by \tcode{\exposid{pm}->lock_shared()}. \pnum \ensures -\tcode{owns == true}. +\tcode{\exposid{owns} == true}. \pnum \throws -Any exception thrown by \tcode{pm->lock_shared()}. +Any exception thrown by \tcode{\exposid{pm}->lock_shared()}. \tcode{system_error} when an exception is required\iref{thread.req.exception}. \pnum \errors \begin{itemize} -\item \tcode{operation_not_permitted} --- if \tcode{pm} is \keyword{nullptr}. -\item \tcode{resource_deadlock_would_occur} --- if on entry \tcode{owns} is +\item \tcode{operation_not_permitted} --- if \exposid{pm} is \keyword{nullptr}. +\item \tcode{resource_deadlock_would_occur} --- if on entry \exposid{owns} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -9056,27 +9098,27 @@ \begin{itemdescr} \pnum \effects -As if by \tcode{pm->try_lock_shared()}. +As if by \tcode{\exposid{pm}->try_lock_shared()}. \pnum \ensures -\tcode{owns == res}, where \tcode{res} is the value returned by -the call to \tcode{pm->try_lock_shared()}. +\tcode{\exposid{owns} == res}, where \tcode{res} is the value returned by +the call to \tcode{\exposid{pm}->try_lock_shared()}. \pnum \returns -The value returned by the call to \tcode{pm->try_lock_shared()}. +The value returned by the call to \tcode{\exposid{pm}->try_lock_shared()}. \pnum \throws -Any exception thrown by \tcode{pm->try_lock_shared()}. +Any exception thrown by \tcode{\exposid{pm}->try_lock_shared()}. \tcode{system_error} when an exception is required\iref{thread.req.exception}. \pnum \errors \begin{itemize} -\item \tcode{operation_not_permitted} --- if \tcode{pm} is \keyword{nullptr}. -\item \tcode{resource_deadlock_would_occur} --- if on entry \tcode{owns} is +\item \tcode{operation_not_permitted} --- if \exposid{pm} is \keyword{nullptr}. +\item \tcode{resource_deadlock_would_occur} --- if on entry \exposid{owns} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -9095,28 +9137,28 @@ \pnum \effects -As if by \tcode{pm->try_lock_shared_until(abs_time)}. +As if by \tcode{\exposid{pm}->try_lock_shared_until(abs_time)}. \pnum \ensures -\tcode{owns == res}, where \tcode{res} is the value returned by -the call to \tcode{pm->try_lock_shared_until(abs_time)}. +\tcode{\exposid{owns} == res}, where \tcode{res} is the value returned by +the call to \tcode{\exposid{pm}->try_lock_shared_until(abs_time)}. \pnum \returns The value returned by the call to -\tcode{pm->try_lock_shared_until(abs_time)}. +\tcode{\exposid{pm}->try_lock_shared_until(abs_time)}. \pnum \throws -Any exception thrown by \tcode{pm->try_lock_shared_until(abs_time)}. +Any exception thrown by \tcode{\exposid{pm}->try_lock_shared_until(abs_time)}. \tcode{system_error} when an exception is required\iref{thread.req.exception}. \pnum \errors \begin{itemize} -\item \tcode{operation_not_permitted} --- if \tcode{pm} is \keyword{nullptr}. -\item \tcode{resource_deadlock_would_occur} --- if on entry \tcode{owns} is +\item \tcode{operation_not_permitted} --- if \exposid{pm} is \keyword{nullptr}. +\item \tcode{resource_deadlock_would_occur} --- if on entry \exposid{owns} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -9135,25 +9177,25 @@ \pnum \effects -As if by \tcode{pm->try_lock_shared_for(rel_time)}. +As if by \tcode{\exposid{pm}->try_lock_shared_for(rel_time)}. \pnum \ensures -\tcode{owns == res}, where \tcode{res} is the value returned by the call to \tcode{pm->try_lock_shared_for(rel_time)}. +\tcode{\exposid{owns} == res}, where \tcode{res} is the value returned by the call to \tcode{\exposid{pm}->try_lock_shared_for(rel_time)}. \pnum \returns -The value returned by the call to \tcode{pm->try_lock_shared_for(rel_time)}. +The value returned by the call to \tcode{\exposid{pm}->try_lock_shared_for(rel_time)}. \pnum \throws -Any exception thrown by \tcode{pm->try_lock_shared_for(rel_time)}. \tcode{system_error} when an exception is required\iref{thread.req.exception}. +Any exception thrown by \tcode{\exposid{pm}->try_lock_shared_for(rel_time)}. \tcode{system_error} when an exception is required\iref{thread.req.exception}. \pnum \errors \begin{itemize} -\item \tcode{operation_not_permitted} --- if \tcode{pm} is \keyword{nullptr}. -\item \tcode{resource_deadlock_would_occur} --- if on entry \tcode{owns} is +\item \tcode{operation_not_permitted} --- if \exposid{pm} is \keyword{nullptr}. +\item \tcode{resource_deadlock_would_occur} --- if on entry \exposid{owns} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -9166,11 +9208,11 @@ \begin{itemdescr} \pnum \effects -As if by \tcode{pm->unlock_shared()}. +As if by \tcode{\exposid{pm}->unlock_shared()}. \pnum \ensures -\tcode{owns == false}. +\tcode{\exposid{owns} == false}. \pnum \throws @@ -9179,7 +9221,7 @@ \pnum \errors \begin{itemize} -\item \tcode{operation_not_permitted} --- if on entry \tcode{owns} is +\item \tcode{operation_not_permitted} --- if on entry \exposid{owns} is \tcode{false}. \end{itemize} \end{itemdescr} @@ -9205,11 +9247,11 @@ \begin{itemdescr} \pnum \ensures -\tcode{pm == nullptr} and \tcode{owns == false}. +\tcode{\exposid{pm} == nullptr} and \tcode{\exposid{owns} == false}. \pnum \returns -The previous value of \tcode{pm}. +The previous value of \exposid{pm}. \end{itemdescr} \indexlibrarymember{swap}{shared_lock}% @@ -9234,7 +9276,7 @@ \begin{itemdescr} \pnum \returns -\tcode{owns}. +\exposid{owns}. \end{itemdescr} \indexlibrarymember{operator bool}{shared_lock}% @@ -9245,7 +9287,7 @@ \begin{itemdescr} \pnum \returns -\tcode{owns}. +\exposid{owns}. \end{itemdescr} \indexlibrarymember{mutex}{shared_lock}% @@ -9256,7 +9298,7 @@ \begin{itemdescr} \pnum \returns -\tcode{pm}. +\exposid{pm}. \end{itemdescr} \rSec2[thread.lock.algorithm]{Generic locking algorithms} @@ -9470,6 +9512,16 @@ \pnum Condition variable construction and destruction need not be synchronized. +\pnum +The definitions in \ref{thread.condition} +make use of the following exposition-only function: +\begin{codeblock} +template + chrono::steady_clock::time_point @\exposid{rel-to-abs}@(const Dur& rel_time) { + return chrono::steady_clock::now() + chrono::ceil(rel_time); + } +\end{codeblock} + \rSec2[condition.variable.syn]{Header \tcode{} synopsis} \indexheader{condition_variable}% @@ -9508,11 +9560,14 @@ \effects Transfers ownership of the lock associated with \tcode{lk} into internal storage and schedules \tcode{cond} to be notified when the current -thread exits, after all objects with thread storage duration associated with -the current thread have been destroyed. This notification is equivalent to: +thread exits. +This notification is sequenced after +all objects with thread storage duration associated with +the current thread have been destroyed and +is equivalent to: \begin{codeblock} -lk.unlock(); cond.notify_all(); +lk.unlock(); \end{codeblock} \pnum @@ -9556,17 +9611,17 @@ void wait(unique_lock& lock, Predicate pred); template cv_status wait_until(unique_lock& lock, - const chrono::time_point& abs_time); + chrono::time_point abs_time); template bool wait_until(unique_lock& lock, - const chrono::time_point& abs_time, + chrono::time_point abs_time, Predicate pred); template cv_status wait_for(unique_lock& lock, - const chrono::duration& rel_time); + chrono::duration rel_time); template bool wait_for(unique_lock& lock, - const chrono::duration& rel_time, + chrono::duration rel_time, Predicate pred); using native_handle_type = @\impdefnc@; // see~\ref{thread.req.native} @@ -9732,7 +9787,7 @@ \begin{itemdecl} template cv_status wait_until(unique_lock& lock, - const chrono::time_point& abs_time); + chrono::time_point abs_time); \end{itemdecl} \begin{itemdescr} @@ -9794,7 +9849,7 @@ \begin{itemdecl} template cv_status wait_for(unique_lock& lock, - const chrono::duration& rel_time); + chrono::duration rel_time); \end{itemdecl} \begin{itemdescr} @@ -9813,7 +9868,7 @@ \effects Equivalent to: \begin{codeblock} -return wait_until(lock, chrono::steady_clock::now() + rel_time); +return wait_until(lock, @\exposid{rel-to-abs}@(rel_time)); \end{codeblock} \pnum @@ -9845,7 +9900,7 @@ \begin{itemdecl} template bool wait_until(unique_lock& lock, - const chrono::time_point& abs_time, + chrono::time_point abs_time, Predicate pred); \end{itemdecl} @@ -9900,7 +9955,7 @@ \begin{itemdecl} template bool wait_for(unique_lock& lock, - const chrono::duration& rel_time, + chrono::duration rel_time, Predicate pred); \end{itemdecl} @@ -9923,7 +9978,7 @@ \effects Equivalent to: \begin{codeblock} -return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred)); +return wait_until(lock, @\exposid{rel-to-abs}@(rel_time), std::move(pred)); \end{codeblock} \pnum @@ -9996,24 +10051,24 @@ void wait(Lock& lock, Predicate pred); template - cv_status wait_until(Lock& lock, const chrono::time_point& abs_time); + cv_status wait_until(Lock& lock, chrono::time_point abs_time); template - bool wait_until(Lock& lock, const chrono::time_point& abs_time, + bool wait_until(Lock& lock, chrono::time_point abs_time, Predicate pred); template - cv_status wait_for(Lock& lock, const chrono::duration& rel_time); + cv_status wait_for(Lock& lock, chrono::duration rel_time); template - bool wait_for(Lock& lock, const chrono::duration& rel_time, Predicate pred); + bool wait_for(Lock& lock, chrono::duration rel_time, Predicate pred); // \ref{thread.condvarany.intwait}, interruptible waits template bool wait(Lock& lock, stop_token stoken, Predicate pred); template bool wait_until(Lock& lock, stop_token stoken, - const chrono::time_point& abs_time, Predicate pred); + chrono::time_point abs_time, Predicate pred); template bool wait_for(Lock& lock, stop_token stoken, - const chrono::duration& rel_time, Predicate pred); + chrono::duration rel_time, Predicate pred); }; } \end{codeblock} @@ -10138,7 +10193,7 @@ \indexlibrarymember{wait_until}{condition_variable_any}% \begin{itemdecl} template - cv_status wait_until(Lock& lock, const chrono::time_point& abs_time); + cv_status wait_until(Lock& lock, chrono::time_point abs_time); \end{itemdecl} \begin{itemdescr} @@ -10189,7 +10244,7 @@ \indexlibrarymember{wait_for}{condition_variable_any}% \begin{itemdecl} template - cv_status wait_for(Lock& lock, const chrono::duration& rel_time); + cv_status wait_for(Lock& lock, chrono::duration rel_time); \end{itemdecl} \begin{itemdescr} @@ -10197,7 +10252,7 @@ \effects Equivalent to: \begin{codeblock} -return wait_until(lock, chrono::steady_clock::now() + rel_time); +return wait_until(lock, @\exposid{rel-to-abs}@(rel_time)); \end{codeblock} \pnum @@ -10227,7 +10282,7 @@ \indexlibrarymember{wait_until}{condition_variable_any}% \begin{itemdecl} template - bool wait_until(Lock& lock, const chrono::time_point& abs_time, Predicate pred); + bool wait_until(Lock& lock, chrono::time_point abs_time, Predicate pred); \end{itemdecl} \begin{itemdescr} @@ -10257,7 +10312,7 @@ \indexlibrarymember{wait_for}{condition_variable_any}% \begin{itemdecl} template - bool wait_for(Lock& lock, const chrono::duration& rel_time, Predicate pred); + bool wait_for(Lock& lock, chrono::duration rel_time, Predicate pred); \end{itemdecl} \begin{itemdescr} @@ -10265,7 +10320,7 @@ \effects Equivalent to: \begin{codeblock} -return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred)); +return wait_until(lock, @\exposid{rel-to-abs}@(rel_time), std::move(pred)); \end{codeblock} \end{itemdescr} @@ -10323,7 +10378,7 @@ \begin{itemdecl} template bool wait_until(Lock& lock, stop_token stoken, - const chrono::time_point& abs_time, Predicate pred); + chrono::time_point abs_time, Predicate pred); \end{itemdecl} \begin{itemdescr} @@ -10376,7 +10431,7 @@ \begin{itemdecl} template bool wait_for(Lock& lock, stop_token stoken, - const chrono::duration& rel_time, Predicate pred); + chrono::duration rel_time, Predicate pred); \end{itemdecl} \begin{itemdescr} @@ -10384,8 +10439,7 @@ \effects Equivalent to: \begin{codeblock} -return wait_until(lock, std::move(stoken), chrono::steady_clock::now() + rel_time, - std::move(pred)); +return wait_until(lock, std::move(stoken), @\exposid{rel-to-abs}@(rel_time), std::move(pred)); \end{codeblock} \end{itemdescr} @@ -10443,7 +10497,7 @@ bool try_acquire_until(const chrono::time_point& abs_time); private: - ptrdiff_t counter; // \expos + ptrdiff_t @\exposid{counter}@; // \expos }; } \end{codeblock} @@ -10473,7 +10527,7 @@ \begin{itemdescr} \pnum \returns -The maximum value of \tcode{counter}. +The maximum value of \exposid{counter}. This value is greater than or equal to \tcode{least_max_value}. \end{itemdescr} @@ -10490,7 +10544,7 @@ \pnum \effects -Initializes \tcode{counter} with \tcode{desired}. +Initializes \exposid{counter} with \tcode{desired}. \pnum \throws @@ -10506,13 +10560,13 @@ \pnum \expects \tcode{update >= 0} is \tcode{true}, and -\tcode{update <= max() - counter} is \tcode{true}. +\tcode{update <= max() - \exposid{counter}} is \tcode{true}. \pnum \effects -Atomically execute \tcode{counter += update}. +Atomically execute \tcode{\exposid{counter} += update}. Then, unblocks any threads -that are waiting for \tcode{counter} to be greater than zero. +that are waiting for \exposid{counter} to be greater than zero. \pnum \sync @@ -10537,11 +10591,11 @@ \begin{itemdescr} \pnum \effects -Attempts to atomically decrement \tcode{counter} if it is positive, +Attempts to atomically decrement \exposid{counter} if it is positive, without blocking. -If \tcode{counter} is not decremented, there is no effect and +If \exposid{counter} is not decremented, there is no effect and \tcode{try_acquire} immediately returns. -An implementation may fail to decrement \tcode{counter} +An implementation may fail to decrement \exposid{counter} even if it is positive. \begin{note} This spurious failure is normally uncommon, but @@ -10554,7 +10608,7 @@ \pnum \returns -\tcode{true} if \tcode{counter} was decremented, otherwise \tcode{false}. +\tcode{true} if \exposid{counter} was decremented, otherwise \tcode{false}. \end{itemdescr} \indexlibrarymember{acquire}{counting_semaphore}% @@ -10570,7 +10624,7 @@ \item Evaluates \tcode{try_acquire()}. If the result is \tcode{true}, returns. \item \indextext{block (execution)}% -Blocks on \tcode{*this} until \tcode{counter} is greater than zero. +Blocks on \tcode{*this} until \exposid{counter} is greater than zero. \end{itemize} \pnum @@ -10603,7 +10657,7 @@ \item \indextext{block (execution)}% Blocks on \tcode{*this} - until \tcode{counter} is greater than zero or until the timeout expires. + until \exposid{counter} is greater than zero or until the timeout expires. If it is unblocked by the timeout expiring, returns \tcode{false}. \end{itemize} The timeout expires\iref{thread.req.timing} @@ -10673,7 +10727,7 @@ void arrive_and_wait(ptrdiff_t update = 1); private: - ptrdiff_t counter; // \expos + ptrdiff_t @\exposid{counter}@; // \expos }; } \end{codeblock} @@ -10696,7 +10750,7 @@ \begin{itemdescr} \pnum \returns -The maximum value of \tcode{counter} that the implementation supports. +The maximum value of \exposid{counter} that the implementation supports. \end{itemdescr} \indexlibraryctor{latch}% @@ -10712,7 +10766,7 @@ \pnum \effects -Initializes \tcode{counter} with \tcode{expected}. +Initializes \exposid{counter} with \tcode{expected}. \pnum \throws @@ -10728,12 +10782,12 @@ \pnum \expects \tcode{update >= 0} is \tcode{true}, and -\tcode{update <= counter} is \tcode{true}. +\tcode{update <= \exposid{counter}} is \tcode{true}. \pnum \effects -Atomically decrements \tcode{counter} by \tcode{update}. -If \tcode{counter} is equal to zero, +Atomically decrements \exposid{counter} by \tcode{update}. +If \exposid{counter} is equal to zero, unblocks all threads blocked on \tcode{*this}. \pnum @@ -10758,7 +10812,7 @@ \begin{itemdescr} \pnum \returns -With very low probability \tcode{false}. Otherwise \tcode{counter == 0}. +With very low probability \tcode{false}. Otherwise \tcode{\exposid{counter} == 0}. \end{itemdescr} \indexlibrarymember{wait}{latch}% @@ -10770,9 +10824,9 @@ \pnum \indextext{block (execution)}% \effects -If \tcode{counter} equals zero, returns immediately. +If \exposid{counter} equals zero, returns immediately. Otherwise, blocks on \tcode{*this} -until a call to \tcode{count_down} that decrements \tcode{counter} to zero. +until a call to \tcode{count_down} that decrements \exposid{counter} to zero. \pnum \throws @@ -10848,7 +10902,7 @@ void arrive_and_drop(); private: - CompletionFunction completion; // \expos + CompletionFunction @\exposid{completion}@; // \expos }; } \end{codeblock} @@ -10885,7 +10939,7 @@ The \defn{phase completion step} that is executed at the end of each phase has the following effects: \begin{itemize} -\item Invokes the completion function, equivalent to \tcode{completion()}. +\item Invokes the completion function, equivalent to \tcode{\exposid{completion}()}. \item Unblocks all threads that are blocked on the phase synchronization point. \end{itemize} The end of the completion step strongly happens before @@ -10913,7 +10967,7 @@ in addition to satisfying the requirements of \tcode{CompletionFunction}, it meets the \oldconcept{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}) and -\tcode{completion()} has no effects. +\tcode{\exposid{completion}()} has no effects. \pnum \tcode{barrier::arrival_token} is an unspecified type, @@ -10949,7 +11003,7 @@ \effects Sets both the initial expected count for each barrier phase and the current expected count for the first phase to \tcode{expected}. -Initializes \tcode{completion} with \tcode{std::move(f)}. +Initializes \exposid{completion} with \tcode{std::move(f)}. Starts the first phase. \begin{note} If \tcode{expected} is 0 this object can only be destroyed. @@ -11229,7 +11283,7 @@ const char* what() const noexcept; private: - error_code ec_; // \expos + error_code @\exposid{ec_}@; // \expos }; } \end{codeblock} @@ -11242,7 +11296,7 @@ \begin{itemdescr} \pnum \effects -Initializes \tcode{ec_} with \tcode{make_error_code(e)}. +Initializes \exposid{ec_} with \tcode{make_error_code(e)}. \end{itemdescr} \indexlibrarymember{code}{future_error}% @@ -11253,7 +11307,7 @@ \begin{itemdescr} \pnum \returns -\tcode{ec_}. +\exposid{ec_}. \end{itemdescr} \indexlibrarymember{what}{future_error}% @@ -13193,7 +13247,7 @@ \indexlibraryglobal{rcu_retire}% \begin{itemdecl} template> -void rcu_retire(T* p, D d = D(), rcu_domain& dom = rcu_default_domain()); + void rcu_retire(T* p, D d = D(), rcu_domain& dom = rcu_default_domain()); \end{itemdecl} \begin{itemdescr} diff --git a/source/time.tex b/source/time.tex index 67b1b06b47..a29b08edf7 100644 --- a/source/time.tex +++ b/source/time.tex @@ -160,19 +160,19 @@ minutes* offset = nullptr); // convenience typedefs - using nanoseconds = duration<@\term{signed integer type of at least 64 bits}@, nano>; - using microseconds = duration<@\term{signed integer type of at least 55 bits}@, micro>; - using milliseconds = duration<@\term{signed integer type of at least 45 bits}@, milli>; - using seconds = duration<@\term{signed integer type of at least 35 bits}@>; - using minutes = duration<@\term{signed integer type of at least 29 bits}@, ratio< 60>>; - using hours = duration<@\term{signed integer type of at least 23 bits}@, ratio<3600>>; - using days = duration<@\term{signed integer type of at least 25 bits}@, + using nanoseconds = duration<@\placeholder{signed integer type of at least 64 bits}@, nano>; + using microseconds = duration<@\placeholder{signed integer type of at least 55 bits}@, micro>; + using milliseconds = duration<@\placeholder{signed integer type of at least 45 bits}@, milli>; + using seconds = duration<@\placeholder{signed integer type of at least 35 bits}@>; + using minutes = duration<@\placeholder{signed integer type of at least 29 bits}@, ratio< 60>>; + using hours = duration<@\placeholder{signed integer type of at least 23 bits}@, ratio<3600>>; + using days = duration<@\placeholder{signed integer type of at least 25 bits}@, ratio_multiply, hours::period>>; - using weeks = duration<@\term{signed integer type of at least 22 bits}@, + using weeks = duration<@\placeholder{signed integer type of at least 22 bits}@, ratio_multiply, days::period>>; - using years = duration<@\term{signed integer type of at least 17 bits}@, + using years = duration<@\placeholder{signed integer type of at least 17 bits}@, ratio_multiply, days::period>>; - using months = duration<@\term{signed integer type of at least 20 bits}@, + using months = duration<@\placeholder{signed integer type of at least 20 bits}@, ratio_divide>>; // \ref{time.point.nonmember}, \tcode{time_point} arithmetic @@ -840,7 +840,7 @@ template struct formatter; template struct formatter; template - struct formatter>, charT>; + struct formatter>, charT>; template struct formatter; template struct formatter; template @@ -1287,7 +1287,10 @@ \pnum \tcode{Rep} shall be an arithmetic type or a class emulating an arithmetic type. -If \tcode{duration} is instantiated with a \tcode{duration} type as the argument for the template +If a specialization of \tcode{duration} +is instantiated with +a cv-qualified type or a specialization of \tcode{duration} +as the argument for the template parameter \tcode{Rep}, the program is ill-formed. \pnum @@ -1351,13 +1354,17 @@ \begin{itemdescr} \pnum \constraints -No overflow is induced in the conversion and -\tcode{treat_as_floating_point_v} is \tcode{true} or both -\tcode{ratio_divide::den} is \tcode{1} and +\tcode{is_convertible_v} is \tcode{true}. +\tcode{ratio_divide} is a valid ratio specialization. +Either: +\begin{itemize} +\item \tcode{treat_as_floating_point_v} is \tcode{true}; or +\item \tcode{ratio_divide::den} is \tcode{1} and \tcode{treat_as_floating_point_v} is \tcode{false}. +\end{itemize} \begin{note} This -requirement prevents implicit truncation error when converting between +requirement prevents implicit truncation errors when converting between integral-based \tcode{duration} types. Such a construction could easily lead to confusion about the value of the \tcode{duration}. \end{note} @@ -3529,6 +3536,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{os << sys_time{lt.time_since_epoch()}} is a valid expression. + \pnum \effects \begin{codeblock} @@ -8523,19 +8534,22 @@ \begin{itemize} \item Initializes \tcode{is_neg} with \tcode{d < Duration::zero()}. + Let \tcode{\placeholder{ABS_D}} represent + \tcode{-d} if \tcode{is_neg} is \tcode{true} and + \tcode{d} otherwise. \item - Initializes \tcode{h} with \tcode{duration_cast(abs(d))}. + Initializes \tcode{h} with \tcode{duration_cast(\placeholder{ABS_D})}. \item Initializes \tcode{m} - with \tcode{duration_cast(abs(d) - hours())}. + with \tcode{duration_cast(\placeholder{ABS_D} - hours())}. \item Initializes \tcode{s} - with \tcode{duration_cast(abs(d) - hours() - minutes())}. + with \tcode{duration_cast(\placeholder{ABS_D} - hours() - minutes())}. \item If \tcode{treat_as_floating_point_v} is \tcode{true}, - initializes \tcode{ss} with \tcode{abs(d) - hours() - minutes() - seconds()}. + initializes \tcode{ss} with \tcode{\placeholder{ABS_D} - hours() - minutes() - seconds()}. Otherwise, initializes \tcode{ss} - with \tcode{duration_cast(abs(d) - hours() - minutes() - seconds())}. + with \tcode{duration_cast(\placeholder{ABS_D} - hours() - minutes() - seconds())}. \end{itemize} \begin{note} When \tcode{precision::rep} is integral and @@ -9240,11 +9254,11 @@ \begin{codeblock} namespace std::chrono { struct sys_info { - sys_seconds begin; - sys_seconds end; - seconds offset; - minutes save; - string abbrev; + sys_seconds begin; + sys_seconds end; + seconds offset; + minutes save; + string abbrev; }; } \end{codeblock} @@ -10777,11 +10791,17 @@ the locale's alternate time representation. \\ \rowsep \tcode{\%y} & -The last two decimal digits of the year. +The last two decimal digits of the year, +regardless of the sign of the year. If the result is a single digit, it is prefixed by \tcode{0}. The modified command \tcode{\%Oy} produces the locale's alternative representation. The modified command \tcode{\%Ey} produces the locale's alternative representation of offset from \tcode{\%EC} (year only). +\begin{tailexample} +\begin{codeblock} +cout << format("{:%C %y}", -1976y); // prints \tcode{-20 76} +\end{codeblock} +\end{tailexample} \\ \rowsep \tcode{\%Y} & The year as a decimal number. @@ -11454,7 +11474,8 @@ The modified command \tcode{\%EX} interprets the locale's alternate time representation. \\ \rowsep \tcode{\%y} & -The last two decimal digits of the year. +The last two decimal digits of the year, +regardless of the sign of the year. If the century is not otherwise specified (e.g., with \tcode{\%C}), values in the range \crange{69}{99} @@ -11467,6 +11488,12 @@ Leading zeroes are permitted but not required. The modified commands \tcode{\%Ey} and \tcode{\%Oy} interpret the locale's alternative representation. +\begin{tailexample} +\begin{codeblock} +year y; +istringstream{"-20 76"} >> parse("%3C %y", y); // \tcode{y == -1976y} is \tcode{true} +\end{codeblock} +\end{tailexample} \\ \rowsep \tcode{\%Y} & The year as a decimal number. diff --git a/source/utilities.tex b/source/utilities.tex index 5e93b63c63..87993d46ac 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -97,6 +97,22 @@ [[noreturn]] void unreachable(); void observable_checkpoint() noexcept; + // \ref{const.wrap.class}, class template \tcode{constant_wrapper} + template + struct @\exposidnc{cw-fixed-value}@; // \expos + + template<@\exposidnc{cw-fixed-value}@ X, class = typename decltype(X)::@\exposid{type}@> + struct constant_wrapper; + + template + concept @\defexposconceptnc{constexpr-param}@ = // \expos + requires { typename constant_wrapper; }; + + struct @\exposidnc{cw-operators}@; // \expos + + template<@\exposid{cw-fixed-value}@ X> + constexpr auto @\libglobal{cw}@ = constant_wrapper{}; + // \ref{intseq}, compile-time integer sequences% \indexlibraryglobal{index_sequence}% \indexlibraryglobal{make_index_sequence}% @@ -114,6 +130,21 @@ template using index_sequence_for = make_index_sequence; + // \ref{intseq.binding}, structured binding support + template struct tuple_size; + template struct tuple_element; + + template + struct tuple_size>; + + template + struct tuple_element>; + template + struct tuple_element>; + + template + constexpr T get(integer_sequence) noexcept; + // \ref{pairs}, class template \tcode{pair} template struct pair; @@ -151,9 +182,6 @@ constexpr @\seebelow@ make_pair(T1&&, T2&&); // \ref{pair.astuple}, tuple-like access to pair - template struct tuple_size; - template struct tuple_element; - template struct tuple_size>; template struct tuple_element>; @@ -213,15 +241,6 @@ }; template constexpr in_place_index_t in_place_index{}; - // \tcode{nontype} argument tag% -\indexlibraryglobal{nontype_t}% -\indexlibraryglobal{nontype} - template - struct nontype_t { - explicit nontype_t() = default; - }; - template constexpr nontype_t nontype{}; - // \ref{variant.monostate}, class \tcode{monostate}% \indexlibraryglobal{monostate} struct monostate; @@ -364,19 +383,19 @@ }; void g() { - shared_ptr sp1 = factory(2, 1.414); // error: 2 will not bind to \tcode{int\&} + shared_ptr sp1 = factory(2, 1.414); // error: \tcode{2} will not bind to \tcode{int\&} int i = 2; shared_ptr sp2 = factory(i, 1.414); // OK } \end{codeblock} In the first call to \tcode{factory}, -\tcode{A1} is deduced as \tcode{int}, so 2 is forwarded +\tcode{A1} is deduced as \tcode{int}, so \tcode{2} is forwarded to \tcode{A}'s constructor as an rvalue. In the second call to \tcode{factory}, \tcode{A1} is deduced as \tcode{int\&}, so \tcode{i} is forwarded to \tcode{A}'s constructor as an lvalue. In both cases, \tcode{A2} is deduced as \tcode{double}, so -1.414 is forwarded to \tcode{A}'s constructor as an rvalue. +\tcode{1.414} is forwarded to \tcode{A}'s constructor as an rvalue. \end{example} \end{itemdescr} @@ -546,8 +565,8 @@ \begin{itemdescr} \pnum \mandates -Both \tcode{T} and \tcode{U} are standard integer types or -extended integer types\iref{basic.fundamental}. +Each of \tcode{T} and \tcode{U} is +a signed or unsigned integer type\iref{basic.fundamental}. \pnum \effects @@ -585,8 +604,8 @@ \begin{itemdescr} \pnum \mandates -Both \tcode{T} and \tcode{U} are standard integer types or -extended integer types\iref{basic.fundamental}. +Each of \tcode{T} and \tcode{U} is +a signed or unsigned integer type\iref{basic.fundamental}. \pnum \effects @@ -648,8 +667,8 @@ \begin{itemdescr} \pnum \mandates -Both \tcode{T} and \tcode{R} are standard integer types or -extended integer types\iref{basic.fundamental}. +Each of \tcode{T} and \tcode{R} is +a signed or unsigned integer type\iref{basic.fundamental}. \pnum \effects @@ -731,6 +750,302 @@ Establishes an observable checkpoint\iref{intro.abstract}. \end{itemdescr} +\rSec2[const.wrap.class]{Class template \tcode{constant_wrapper}} + +\begin{codeblock} +namespace std { + template + struct @\exposidnc{cw-fixed-value}@ { // \expos + using @\exposidnc{type}@ = T; // \expos + constexpr @\exposidnc{cw-fixed-value}@(@\exposidnc{type}@ v) noexcept : @\exposidnc{data}@(v) {} + T @\exposidnc{data}@; // \expos + }; + + template + struct @\exposidnc{cw-fixed-value}@ { // \expos + using @\exposidnc{type}@ = T[Extent]; // \expos + constexpr @\exposidnc{cw-fixed-value}@(T (&arr)[Extent]) noexcept; + T @\exposidnc{data}@[Extent]; // \expos + }; + + template + @\exposidnc{cw-fixed-value}@(T (&)[Extent]) -> @\exposidnc{cw-fixed-value}@; // \expos + + struct @\exposidnc{cw-operators}@ { // \expos + // unary operators + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator+(T) noexcept -> constant_wrapper<(+T::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator-(T) noexcept -> constant_wrapper<(-T::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator~(T) noexcept -> constant_wrapper<(~T::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator!(T) noexcept -> constant_wrapper<(!T::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator&(T) noexcept -> constant_wrapper<(&T::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator*(T) noexcept -> constant_wrapper<(*T::value)> + { return {}; } + + // binary operators + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator+(L, R) noexcept -> constant_wrapper<(L::value + R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator-(L, R) noexcept -> constant_wrapper<(L::value - R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator*(L, R) noexcept -> constant_wrapper<(L::value * R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator/(L, R) noexcept -> constant_wrapper<(L::value / R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator%(L, R) noexcept -> constant_wrapper<(L::value % R::value)> + { return {}; } + + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator<<(L, R) noexcept -> constant_wrapper<(L::value << R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator>>(L, R) noexcept -> constant_wrapper<(L::value >> R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator&(L, R) noexcept -> constant_wrapper<(L::value & R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator|(L, R) noexcept -> constant_wrapper<(L::value | R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator^(L, R) noexcept -> constant_wrapper<(L::value ^ R::value)> + { return {}; } + + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + requires (!is_constructible_v || + !is_constructible_v) + friend constexpr auto operator&&(L, R) noexcept + -> constant_wrapper<(L::value && R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + requires (!is_constructible_v || + !is_constructible_v) + friend constexpr auto operator||(L, R) noexcept + -> constant_wrapper<(L::value || R::value)> + { return {}; } + + // comparisons + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator<=>(L, R) noexcept + -> constant_wrapper<(L::value <=> R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator<(L, R) noexcept -> constant_wrapper<(L::value < R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator<=(L, R) noexcept -> constant_wrapper<(L::value <= R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator==(L, R) noexcept -> constant_wrapper<(L::value == R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator!=(L, R) noexcept -> constant_wrapper<(L::value != R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator>(L, R) noexcept -> constant_wrapper<(L::value > R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator>=(L, R) noexcept -> constant_wrapper<(L::value >= R::value)> + { return {}; } + + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator,(L, R) noexcept = delete; + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator->*(L, R) noexcept -> constant_wrapper*(R::value)> + { return {}; } + + // pseudo-mutators + template<@\exposconcept{constexpr-param}@ T> + constexpr auto operator++(this T) noexcept + -> constant_wrapper<(++T::value)> { return {}; } + template<@\exposconcept{constexpr-param}@ T> + constexpr auto operator++(this T, int) noexcept + -> constant_wrapper<(T::value++)> { return {}; } + template<@\exposconcept{constexpr-param}@ T> + constexpr auto operator--(this T) noexcept + -> constant_wrapper<(--T::value)> { return {}; } + template<@\exposconcept{constexpr-param}@ T> + constexpr auto operator--(this T, int) noexcept + -> constant_wrapper<(T::value--)> { return {}; } + + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator+=(this T, R) noexcept + -> constant_wrapper<(T::value += R::value)> { return {}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator-=(this T, R) noexcept + -> constant_wrapper<(T::value -= R::value)> { return {}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator*=(this T, R) noexcept + -> constant_wrapper<(T::value *= R::value)> { return {}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator/=(this T, R) noexcept + -> constant_wrapper<(T::value /= R::value)> { return {}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator%=(this T, R) noexcept + -> constant_wrapper<(T::value %= R::value)> { return {}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator&=(this T, R) noexcept + -> constant_wrapper<(T::value &= R::value)> { return {}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator|=(this T, R) noexcept + -> constant_wrapper<(T::value |= R::value)> { return {}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator^=(this T, R) noexcept + -> constant_wrapper<(T::value ^= R::value)> { return {}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator<<=(this T, R) noexcept + -> constant_wrapper<(T::value <<= R::value)> { return {}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator>>=(this T, R) noexcept + -> constant_wrapper<(T::value >>= R::value)> { return {}; } + }; + + template<@\exposid{cw-fixed-value}@ X, class> + struct @\libglobal{constant_wrapper}@ : @\exposid{cw-operators}@ { + static constexpr const auto & value = X.@\exposid{data}@; + using type = constant_wrapper; + using value_type = decltype(X)::@\exposid{type}@; + + template<@\exposconcept{constexpr-param}@ R> + constexpr auto operator=(R) const noexcept + -> constant_wrapper<(value = R::value)> { return {}; } + + constexpr operator decltype(value)() const noexcept { return value; } + + template + static constexpr decltype(auto) operator()(Args&&... args) noexcept(@\seebelow@); + template + static constexpr decltype(auto) operator[](Args&&... args) noexcept(@\seebelow@); + }; +} +\end{codeblock} + +\pnum +The class template \tcode{constant_wrapper} aids in metaprogramming by ensuring +that the evaluation of expressions comprised entirely of \tcode{constant_wrapper} +are core constant expressions\iref{expr.const.core}, +regardless of the context in which they appear. +In particular, this enables use of \tcode{constant_wrapper} values +that are passed as arguments to constexpr functions to be used in constant expressions. + +\pnum +\begin{note} +The unnamed second template parameter to \tcode{constant_wrapper} is present +to aid argument-dependent lookup\iref{basic.lookup.argdep} +in finding overloads for which \tcode{constant_wrapper}'s wrapped value is a suitable argument, +but for which the \tcode{constant_wrapper} itself is not. +\end{note} + +\pnum +\begin{example} +\begin{codeblock} + constexpr auto initial_phase(auto quantity_1, auto quantity_2) { + return quantity_1 + quantity_2; + } + + constexpr auto middle_phase(auto tbd) { + return tbd; + } + + void final_phase(auto gathered, auto available) { + if constexpr (gathered == available) + std::cout << "Profit!\n"; + } + + void impeccable_underground_planning() { + auto gathered_quantity = middle_phase(initial_phase(std::cw<42>, std::cw<13>)); + static_assert(gathered_quantity == 55); + auto all_available = std::cw<55>; + final_phase(gathered_quantity, all_available); + } + + void deeply_flawed_underground_planning() { + constexpr auto gathered_quantity = middle_phase(initial_phase(42, 13)); + constexpr auto all_available = 55; + final_phase(gathered_quantity, all_available); // error: \tcode{gathered == available} + // is not a constant expression + } +\end{codeblock} +\end{example} + +\begin{itemdecl} +constexpr @\exposid{cw-fixed-value}@(T (&arr)[Extent]) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initialize elements of \exposid{data} with corresponding elements of \tcode{arr}. +\end{itemdescr} + +\indexlibrarymember{operator()}{constant_wrapper}% +\begin{itemdecl} +template + static constexpr decltype(auto) operator()(Args&&... args) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{\placeholder{call-expr}} be +\tcode{constant_wrapper<\placeholder{INVOKE}(value, remove_cvref_t::value...)>\{\}} +if all types in \tcode{remove_cvref_t...} satisfy \exposconcept{constexpr-param} and +\tcode{constant_wrapper<\placeholder{INVOKE}(val\-ue, remove_cvref_t::value...)>} is a valid type, +otherwise let \tcode{\placeholder{call-expr}} be \tcode{\placeholder{INVOKE}(value, std::forward(args)...)}. + +\pnum +\constraints +\tcode{\placeholder{call-expr}} is a valid expression. + +\pnum +\effects +Equivalent to: \tcode{return \placeholder{call-expr};} + +\pnum +\remarks +The exception specification is equivalent to \tcode{noexcept(\placeholder{call-expr})}. +\end{itemdescr} + +\indexlibrarymember{operator[]}{constant_wrapper}% +\begin{itemdecl} +template + static constexpr decltype(auto) operator[](Args&&... args) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{\placeholder{subscr-expr}} be +\tcode{constant_wrapper::value...]>\{\}} +if all types in \tcode{remove_cvref_t...} satisfy \exposconcept{constexpr-param} and +\tcode{constant_wrapper::value...]>} is a valid type, +otherwise let \tcode{\placeholder{subscr-expr}} be \tcode{value[std::forward(args)...]}. + +\pnum +\constraints +\tcode{\placeholder{subscr-expr}} is a valid expression. + +\pnum +\effects +Equivalent to: \tcode{return \placeholder{subscr-expr};} + +\pnum +\remarks +The exception specification is equivalent to \tcode{noexcept(\placeholder{subscr-expr})}. +\end{itemdescr} + \rSec1[pairs]{Pairs} \rSec2[pairs.general]{General} @@ -1512,8 +1827,8 @@ the class template \tcode{tuple} that can be instantiated with any number of arguments. Each template argument specifies the type of an element in the \tcode{tuple}. Consequently, tuples are -heterogeneous, fixed-size collections of values. An instantiation of \tcode{tuple} with -two arguments is similar to an instantiation of \tcode{pair} with the same two arguments. +heterogeneous, fixed-size collections of values. A specialization of \tcode{tuple} with +two arguments behaves similarly to a specialization of \tcode{pair} with the same two arguments. See~\ref{pairs}. \pnum @@ -1662,9 +1977,11 @@ public: // \ref{tuple.cnstr}, \tcode{tuple} construction constexpr explicit(@\seebelow@) tuple(); - constexpr explicit(@\seebelow@) tuple(const Types&...); // only if \tcode{sizeof...(Types) >= 1} + constexpr explicit(@\seebelow@) tuple(const Types&...) // only if \tcode{sizeof...(Types) >= 1} + noexcept(@\seebelow@); template - constexpr explicit(@\seebelow@) tuple(UTypes&&...); // only if \tcode{sizeof...(Types) >= 1} + constexpr explicit(@\seebelow@) tuple(UTypes&&...) // only if \tcode{sizeof...(Types) >= 1} + noexcept(@\seebelow@); tuple(const tuple&) = default; tuple(tuple&&) = default; @@ -1840,7 +2157,8 @@ \indexlibraryctor{tuple}% \begin{itemdecl} -constexpr explicit(@\seebelow@) tuple(const Types&...); +constexpr explicit(@\seebelow@) tuple(const Types&...) + noexcept((is_nothrow_copy_constructible_v && ...)); \end{itemdecl} \begin{itemdescr} @@ -1864,7 +2182,8 @@ \indexlibraryctor{tuple}% \begin{itemdecl} -template constexpr explicit(@\seebelow@) tuple(UTypes&&... u); +template constexpr explicit(@\seebelow@) tuple(UTypes&&... u) + noexcept((is_nothrow_constructible_v && ...)); \end{itemdecl} \begin{itemdescr} @@ -2828,6 +3147,7 @@ the template is available when any of the headers \libheaderref{array}, +\libheaderref{complex}, \libheaderref{ranges}, or \libheaderref{utility} are included. @@ -2842,13 +3162,14 @@ \pnum Let \tcode{TE} denote \tcode{tuple_element_t} of the cv-unqualified type \tcode{T}. Then each specialization of the template meets the \oldconcept{TransformationTrait} requirements\iref{meta.rqmts} -with a member typedef \tcode{type} that names the type \tcode{add_const_t}. +with a member typedef \tcode{type} that names the type \tcode{const TE}. \pnum In addition to being available via inclusion of the \libheader{tuple} header, the template is available when any of the headers \libheaderref{array}, +\libheaderref{complex}, \libheaderref{ranges}, or \libheaderref{utility} are included. @@ -3256,7 +3577,7 @@ template constexpr bool operator>=(const optional&, const U&); template constexpr bool operator>=(const T&, const optional&); template - requires (!@\exposconcept{is-derived-from-optional}@) && @\libconcept{three_way_comparable_with}@ + requires (!@\exposconcept{is-derived-from-optional}@) && @\libconcept{three_way_comparable_with}@ constexpr compare_three_way_result_t operator<=>(const optional&, const U&); @@ -3362,7 +3683,9 @@ constexpr void reset() noexcept; private: - T* @\exposidnc{val}@; // \expos + union { + remove_cv_t @\exposidnc{val}@; // \expos + }; }; template @@ -3371,19 +3694,14 @@ \end{codeblock} \pnum -An object of type \tcode{optional} at any given time -either contains a value or does not contain a value. -When an object of type \tcode{optional} -\defnx{contains a value}{contains a value!\idxcode{optional}}, -it means that an object of type \tcode{T}, referred to as the optional object's \defnx{contained value}{contained value!\idxcode{optional}}, +An instance of \tcode{optional} is said to +\defnx{contain a value}{contain a value!\idxcode{optional}} +when and only when +its member \exposid{val} is active\iref{class.union.general}; +\exposid{val} is referred to as its +\defnx{contained value}{contained value!\idxcode{optional}}. +An optional object's contained value is nested within\iref{intro.object} the optional object. -When an object of type \tcode{optional} is contextually converted to \tcode{bool}, -the conversion returns \tcode{true} if the object contains a value; -otherwise the conversion returns \tcode{false}. - -\pnum -When an object of type \tcode{optional} contains a value, -member \tcode{val} points to the contained value. \pnum A type \tcode{X} is a @@ -3434,8 +3752,8 @@ \begin{itemdescr} \pnum \effects -If \tcode{rhs} contains a value, direct-non-list-initializes the contained value -with \tcode{*rhs}. +If \tcode{rhs} contains a value, direct-non-list-initializes \exposid{val} +with \tcode{rhs.\exposid{val}}. \pnum \ensures @@ -3465,8 +3783,8 @@ \pnum \effects -If \tcode{rhs} contains a value, direct-non-list-initializes the contained value -with \tcode{*std::move(rhs)}. +If \tcode{rhs} contains a value, direct-non-list-initializes \exposid{val} +with \tcode{std::move(rhs.\exposid{val})}. \tcode{rhs.has_value()} is unchanged. \pnum @@ -3497,7 +3815,8 @@ \pnum \effects -Direct-non-list-initializes the contained value with \tcode{std::forward(args)...}. +Direct-non-list-initializes \exposid{val} +with \tcode{std::forward(args)...}. \pnum \ensures @@ -3525,7 +3844,8 @@ \pnum \effects -Direct-non-list-initializes the contained value with \tcode{il, std::forward(args)...}. +Direct-non-list-initializes \exposid{val} +with \tcode{il, std::forward(args)...}. \pnum \ensures @@ -3558,7 +3878,8 @@ \pnum \effects -Direct-non-list-initializes the contained value with \tcode{std::forward(v)}. +Direct-non-list-initializes \exposid{val} +with \tcode{std::forward(v)}. \pnum \ensures @@ -3595,7 +3916,8 @@ \pnum \effects If \tcode{rhs} contains a value, -direct-non-list-initializes the contained value with \tcode{*rhs}. +direct-non-list-initializes \exposid{val} +with \tcode{rhs.operator*()}. \pnum \ensures @@ -3630,7 +3952,8 @@ \pnum \effects If \tcode{rhs} contains a value, -direct-non-list-initializes the contained value with \tcode{*std::move(rhs)}. +direct-non-list-initializes \exposid{val} +with \tcode{std::move(rhs).operator*()}. \tcode{rhs.has_value()} is unchanged. \pnum @@ -3659,10 +3982,9 @@ \begin{itemdescr} \pnum \effects -If \tcode{is_trivially_destructible_v != true} and \tcode{*this} contains a value, calls -\begin{codeblock} -val->T::~T() -\end{codeblock} +If \tcode{is_trivially_destructible_v} is \tcode{false} +and \tcode{*this} contains a value, +calls \tcode{\exposid{val}.T::\~T()}. \pnum \remarks @@ -3679,7 +4001,7 @@ \begin{itemdescr} \pnum \effects -If \tcode{*this} contains a value, calls \tcode{val->T::\~T()} to destroy the contained value; otherwise no effect. +If \tcode{*this} contains a value, calls \tcode{\exposid{val}.T::\~T()} to destroy the contained value; otherwise no effect. \pnum \ensures @@ -3704,12 +4026,12 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -assigns \tcode{*rhs} to the contained value & -direct-non-list-initializes the contained value with \tcode{*rhs} \\ +assigns \tcode{rhs.\exposid{val}} to \exposid{val} & +direct-non-list-initializes \exposid{val} with \tcode{rhs.\exposid{val}} \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & -destroys the contained value by calling \tcode{val->T::\~T()} & +destroys the contained value by calling \tcode{\exposid{val}.T::\~T()} & no effect \\ \end{lib2dtab2} @@ -3756,12 +4078,12 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -assigns \tcode{*std::move(rhs)} to the contained value & -direct-non-list-initializes the contained value with \tcode{*std::move(rhs)} \\ +assigns \tcode{std::move(rhs.\exposid{val})} to \exposid{val} & +direct-non-list-initializes \exposid{val} with \tcode{std::move(rhs.\exposid{val})} \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & -destroys the contained value by calling \tcode{val->T::\~T()} & +destroys the contained value by calling \tcode{\exposid{val}.T::\~T()} & no effect \\ \end{lib2dtab2} @@ -3783,9 +4105,9 @@ \pnum If any exception is thrown, the result of the expression \tcode{this->has_value()} remains unchanged. If an exception is thrown during the call to \tcode{T}'s move constructor, -the state of \tcode{*rhs.val} is determined by the exception safety guarantee of \tcode{T}'s move constructor. +the state of \tcode{rhs.\exposid{val}} is determined by the exception safety guarantee of \tcode{T}'s move constructor. If an exception is thrown during the call to \tcode{T}'s move assignment, -the state of \tcode{*val} and \tcode{*rhs.val} is determined by the exception safety guarantee of \tcode{T}'s move assignment. +the states of \exposid{val} and \tcode{rhs.\exposid{val}} are determined by the exception safety guarantee of \tcode{T}'s move assignment. If \tcode{is_trivially_move_constructible_v \&\&} \tcode{is_trivially_move_assignable_v \&\&} \tcode{is_trivially_destructible_v} is \tcode{true}, @@ -3809,7 +4131,10 @@ \pnum \effects -If \tcode{*this} contains a value, assigns \tcode{std::forward(v)} to the contained value; otherwise direct-non-list-initializes the contained value with \tcode{std::forward(v)}. +If \tcode{*this} contains a value, +assigns \tcode{std::forward(v)} to \exposid{val}; +otherwise direct-non-list-initializes \exposid{val} +with \tcode{std::forward(v)}. \pnum \ensures @@ -3821,7 +4146,9 @@ \pnum \remarks -If any exception is thrown, the result of the expression \tcode{this->has_value()} remains unchanged. If an exception is thrown during the call to \tcode{T}'s constructor, the state of \tcode{v} is determined by the exception safety guarantee of \tcode{T}'s constructor. If an exception is thrown during the call to \tcode{T}'s assignment, the state of \tcode{*val} and \tcode{v} is determined by the exception safety guarantee of \tcode{T}'s assignment. +If any exception is thrown, the result of the expression \tcode{this->has_value()} remains unchanged. If an exception is thrown during the call to \tcode{T}'s constructor, the state of \tcode{v} is determined by the exception safety guarantee of \tcode{T}'s constructor. If an exception is thrown during the call to \tcode{T}'s assignment, +the states of \exposid{val} and \tcode{v} are +determined by the exception safety guarantee of \tcode{T}'s assignment. \end{itemdescr} \indexlibrarymember{operator=}{optional}% @@ -3850,12 +4177,12 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -assigns \tcode{*rhs} to the contained value & -direct-non-list-initializes the contained value with \tcode{*rhs} \\ +assigns \tcode{rhs.operator*()} to \exposid{val} & +direct-non-list-initializes \exposid{val} with \tcode{rhs.operator*()} \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & -destroys the contained value by calling \tcode{val->T::\~T()} & +destroys the contained value by calling \tcode{\exposid{val}.T::\~T()} & no effect \\ \end{lib2dtab2} @@ -3872,10 +4199,10 @@ If any exception is thrown, the result of the expression \tcode{this->has_value()} remains unchanged. If an exception is thrown during the call to \tcode{T}'s constructor, -the state of \tcode{*rhs.val} is determined by +the state of \tcode{rhs.\exposid{val}} is determined by the exception safety guarantee of \tcode{T}'s constructor. If an exception is thrown during the call to \tcode{T}'s assignment, -the state of \tcode{*val} and \tcode{*rhs.val} is determined by +the states of \exposid{val} and \tcode{rhs.\exposid{val}} are determined by the exception safety guarantee of \tcode{T}'s assignment. \end{itemdescr} @@ -3906,12 +4233,12 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -assigns \tcode{*std::move(rhs)} to the contained value & -direct-non-list-initializes the contained value with \tcode{*std::move(rhs)} \\ +assigns \tcode{std::move(rhs).op\-erator*()} to \exposid{val} & +direct-non-list-initializes \exposid{val} with \tcode{std::move(rhs).opera\-tor*()} \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & -destroys the contained value by calling \tcode{val->T::\~T()} & +destroys the contained value by calling \tcode{\exposid{val}.T::\~T()} & no effect \\ \end{lib2dtab2} @@ -3928,10 +4255,10 @@ If any exception is thrown, the result of the expression \tcode{this->has_value()} remains unchanged. If an exception is thrown during the call to \tcode{T}'s constructor, -the state of \tcode{*rhs.val} is determined by +the state of \tcode{rhs.\exposid{val}} is determined by the exception safety guarantee of \tcode{T}'s constructor. If an exception is thrown during the call to \tcode{T}'s assignment, -the state of \tcode{*val} and \tcode{*rhs.val} is determined by +the states of \exposid{val} and \tcode{rhs.\exposid{val}} are determined by the exception safety guarantee of \tcode{T}'s assignment. \end{itemdescr} @@ -3942,13 +4269,13 @@ \begin{itemdescr} \pnum -\mandates +\constraints \tcode{is_constructible_v} is \tcode{true}. \pnum \effects -Calls \tcode{*this = nullopt}. Then direct-non-list-initializes the contained value -with \tcode{std::forward\brk{}(args)...}. +Calls \tcode{*this = nullopt}. Then direct-non-list-initializes \exposid{val} +with \tcode{std::forward(args\brk{})...}. \pnum \ensures @@ -3956,7 +4283,7 @@ \pnum \returns -A reference to the new contained value. +\exposid{val}. \pnum \throws @@ -3964,7 +4291,9 @@ \pnum \remarks -If an exception is thrown during the call to \tcode{T}'s constructor, \tcode{*this} does not contain a value, and the previous \tcode{*val} (if any) has been destroyed. +If an exception is thrown during the call to \tcode{T}'s constructor, +\tcode{*this} does not contain a value, and +the previous \exposid{val} (if any) has been destroyed. \end{itemdescr} \indexlibrarymember{emplace}{optional}% @@ -3979,8 +4308,8 @@ \pnum \effects -Calls \tcode{*this = nullopt}. Then direct-non-list-initializes the contained value with -\tcode{il, std::\brk{}forward(args)...}. +Calls \tcode{*this = nullopt}. Then direct-non-list-initializes \exposid{val} with +\tcode{il, std::forward(\brk{}args)...}. \pnum \ensures @@ -3988,7 +4317,7 @@ \pnum \returns -A reference to the new contained value. +\exposid{val}. \pnum \throws @@ -3996,7 +4325,9 @@ \pnum \remarks -If an exception is thrown during the call to \tcode{T}'s constructor, \tcode{*this} does not contain a value, and the previous \tcode{*val} (if any) has been destroyed. +If an exception is thrown during the call to \tcode{T}'s constructor, +\tcode{*this} does not contain a value, and +the previous \exposid{val} (if any) has been destroyed. \end{itemdescr} \rSec3[optional.swap]{Swap} @@ -4023,17 +4354,17 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -calls \tcode{swap(*(*this), *rhs)} & -direct-non-list-initializes the contained value of \tcode{*this} -with \tcode{std::move(*rhs)}, -followed by \tcode{rhs.val->T::\~T()}; +calls \tcode{swap(\exposid{val}, rhs.\exposid{val})} & +direct-non-list-initializes \exposid{val} +with \tcode{std::move(rhs.\exposid{val})}, +followed by \tcode{rhs.\exposid{val}.T::\~T()}; postcondition is that \tcode{*this} contains a value and \tcode{rhs} does not contain a value \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & -direct-non-list-initializes the contained value of \tcode{rhs} -with \tcode{std::move(*(*this))}, -followed by \tcode{val->T::\~T()}; +direct-non-list-initializes \tcode{rhs.\exposid{val}} +with \tcode{std::move(\exposid{val})}, +followed by \tcode{\exposid{val}.T::\~T()}; postcondition is that \tcode{*this} does not contain a value and \tcode{rhs} contains a value & no effect \\ \end{lib2dtab2} @@ -4052,9 +4383,9 @@ \pnum If any exception is thrown, the results of the expressions \tcode{this->has_value()} and \tcode{rhs.has_value()} remain unchanged. If an exception is thrown during the call to function \tcode{swap}, -the state of \tcode{*val} and \tcode{*rhs.val} is determined by the exception safety guarantee of \tcode{swap} for lvalues of \tcode{T}. +the states of \exposid{val} and \tcode{rhs.\exposid{val}} are determined by the exception safety guarantee of \tcode{swap} for lvalues of \tcode{T}. If an exception is thrown during the call to \tcode{T}'s move constructor, -the state of \tcode{*val} and \tcode{*rhs.val} is determined by the exception safety guarantee of \tcode{T}'s move constructor. +the states of \exposid{val} and \tcode{rhs.\exposid{val}} are determined by the exception safety guarantee of \tcode{T}'s move constructor. \end{itemdescr} \rSec3[optional.iterators]{Iterator support} @@ -4125,7 +4456,7 @@ \pnum \returns -\tcode{val}. +\tcode{addressof(\exposid{val})}. \pnum \remarks @@ -4145,7 +4476,7 @@ \pnum \returns -\tcode{*val}. +\exposid{val}. \pnum \remarks @@ -4165,7 +4496,7 @@ \pnum \effects -Equivalent to: \tcode{return std::move(*val);} +Equivalent to: \tcode{return std::move(\exposid{val});} \end{itemdescr} \indexlibrarymember{operator bool}{optional}% @@ -4209,7 +4540,7 @@ \effects Equivalent to: \begin{codeblock} -return has_value() ? *val : throw bad_optional_access(); +return has_value() ? @\exposid{val}@ : throw bad_optional_access(); \end{codeblock} \end{itemdescr} @@ -4225,7 +4556,7 @@ \effects Equivalent to: \begin{codeblock} -return has_value() ? std::move(*val) : throw bad_optional_access(); +return has_value() ? std::move(@\exposid{val}@) : throw bad_optional_access(); \end{codeblock} \end{itemdescr} @@ -4243,7 +4574,7 @@ \effects Equivalent to: \begin{codeblock} -return has_value() ? **this : static_cast(std::forward(v)); +return has_value() ? @\exposid{val}@ : static_cast(std::forward(v)); \end{codeblock} \end{itemdescr} @@ -4261,7 +4592,7 @@ \effects Equivalent to: \begin{codeblock} -return has_value() ? std::move(**this) : static_cast(std::forward(v)); +return has_value() ? std::move(@\exposid{val}@) : static_cast(std::forward(v)); \end{codeblock} \end{itemdescr} @@ -4275,7 +4606,7 @@ \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{invoke_result_t}. +Let \tcode{U} be \tcode{invoke_result_t}. \pnum \mandates @@ -4286,7 +4617,7 @@ Equivalent to: \begin{codeblock} if (*this) { - return invoke(std::forward(f), *@\exposid{val}@); + return invoke(std::forward(f), @\exposid{val}@); } else { return remove_cvref_t(); } @@ -4301,7 +4632,7 @@ \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{invoke_result_t}. +Let \tcode{U} be \tcode{invoke_result_t}. \pnum \mandates @@ -4312,7 +4643,7 @@ Equivalent to: \begin{codeblock} if (*this) { - return invoke(std::forward(f), std::move(*@\exposid{val}@)); + return invoke(std::forward(f), std::move(@\exposid{val}@)); } else { return remove_cvref_t(); } @@ -4327,14 +4658,14 @@ \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{remove_cv_t>}. +Let \tcode{U} be \tcode{remove_cv_t>}. \pnum \mandates \tcode{U} is a valid contained type for \tcode{optional}. The declaration \begin{codeblock} -U u(invoke(std::forward(f), *@\exposid{val}@)); +U u(invoke(std::forward(f), @\exposid{val}@)); \end{codeblock} is well-formed for some invented variable \tcode{u}. \begin{note} @@ -4345,7 +4676,7 @@ \returns If \tcode{*this} contains a value, an \tcode{optional} object whose contained value is direct-non-list-initialized with -\tcode{invoke(std::forward(f), *\exposid{val})}; +\tcode{invoke(std::forward(f), \exposid{val})}; otherwise, \tcode{optional()}. \end{itemdescr} @@ -4358,14 +4689,14 @@ \begin{itemdescr} \pnum Let \tcode{U} be -\tcode{remove_cv_t>}. +\tcode{remove_cv_t>}. \pnum \mandates \tcode{U} is a valid contained type for \tcode{optional}. The declaration \begin{codeblock} -U u(invoke(std::forward(f), std::move(*@\exposid{val}@))); +U u(invoke(std::forward(f), std::move(@\exposid{val}@))); \end{codeblock} is well-formed for some invented variable \tcode{u}. \begin{note} @@ -4376,7 +4707,7 @@ \returns If \tcode{*this} contains a value, an \tcode{optional} object whose contained value is direct-non-list-initialized with -\tcode{invoke(std::forward(f), std::move(*\exposid{val}))}; +\tcode{invoke(std::forward(f), std::move(\exposid{val}))}; otherwise, \tcode{optional()}. \end{itemdescr} @@ -4444,7 +4775,7 @@ \begin{itemdescr} \pnum \effects -If \tcode{*this} contains a value, calls \tcode{val->T::\~T()} to destroy the contained value; +If \tcode{*this} contains a value, calls \tcode{\exposid{val}.T::\~T()} to destroy the contained value; otherwise no effect. \pnum @@ -4460,10 +4791,10 @@ template class optional { public: - using value_type = T; - using iterator = @\impdefnc@; // see~\ref{optional.ref.iterators} + using value_type = T; + using iterator = @\impdefnc@; // present only if \tcode{T} is an object type other than an array + // of unknown bound; see~\ref{optional.ref.iterators} - public: // \ref{optional.ref.ctor}, constructors constexpr optional() noexcept = default; constexpr optional(nullopt_t) noexcept : optional() {} @@ -4494,8 +4825,8 @@ constexpr void swap(optional& rhs) noexcept; // \ref{optional.ref.iterators}, iterator support - constexpr iterator begin() const noexcept; - constexpr iterator end() const noexcept; + constexpr auto begin() const noexcept; + constexpr auto end() const noexcept; // \ref{optional.ref.observe}, observers constexpr T* operator->() const noexcept; @@ -4532,6 +4863,9 @@ the \defnx{contained value}{contained value!\idxcode{optional.ref}} is a reference to \tcode{*\exposid{val}}. +\pnum +Each type \tcode{optional} is a trivially copyable class\iref{class.prop}. + \rSec3[optional.ref.ctor]{Constructors} \begin{itemdecl} @@ -4607,7 +4941,7 @@ \effects Equivalent to: \begin{codeblock} -if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*rhs); +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(rhs.operator*()); \end{codeblock} \pnum @@ -4638,7 +4972,7 @@ \effects Equivalent to: \begin{codeblock} -if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*rhs); +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(rhs.operator*()); \end{codeblock} \pnum @@ -4669,7 +5003,7 @@ \effects Equivalent to: \begin{codeblock} -if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*std::move(rhs)); +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(std::move(rhs).operator*()); \end{codeblock} \pnum @@ -4700,7 +5034,7 @@ \effects Equivalent to: \begin{codeblock} -if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*std::move(rhs)); +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(std::move(rhs).operator*()); \end{codeblock} \pnum @@ -4763,13 +5097,14 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{swap(\exposid{val}, rhs.\exposid{val})}. +Equivalent to: \tcode{std::swap(\exposid{val}, rhs.\exposid{val})}. \end{itemdescr} \rSec3[optional.ref.iterators]{Iterator support} \begin{itemdecl} -using iterator = @\impdef@; +using iterator = @\impdefnc@; // present only if \tcode{T} is an object type other than an array + // of unknown bound \end{itemdecl} \begin{itemdescr} @@ -4787,22 +5122,31 @@ \end{itemdescr} \begin{itemdecl} -constexpr iterator begin() const noexcept; +constexpr auto begin() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{T} is an object type other than an array of unknown bound. + \pnum \returns - If \tcode{has_value()} is \tcode{true}, - an iterator referring to \tcode{*\exposid{val}}. - Otherwise, a past-the-end iterator value. + An object \tcode{i} of type \tcode{iterator}, such that + \tcode{i} is an iterator referring to \tcode{*\exposid{val}} + if \tcode{has_value()} is \tcode{true}, and + a past-the-end iterator value otherwise. \end{itemdescr} \begin{itemdecl} -constexpr iterator end() const noexcept; +constexpr auto end() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{T} is an object type other than an array of unknown bound. + \pnum \returns \tcode{begin() + has_value()}. @@ -4877,6 +5221,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{T} is a non-array object type. + \pnum Let \tcode{X} be \tcode{remove_cv_t}. @@ -4890,6 +5238,14 @@ \begin{codeblock} return has_value() ? *@\exposid{val}@ : static_cast(std::forward(u)); \end{codeblock} + +\pnum +\remarks +The return type is unspecified if +\tcode{T} is an array type or a non-object type. +\begin{note} +This is to avoid the declaration being ill-formed. +\end{note} \end{itemdescr} \rSec3[optional.ref.monadic]{Monadic operations} @@ -4929,6 +5285,7 @@ \pnum \mandates +\tcode{U} is a valid contained type for \tcode{optional}. The declaration \begin{codeblock} U u(invoke(std::forward(f), *@\exposid{val}@)); @@ -5016,7 +5373,11 @@ this indicates that an optional object not containing a value shall be constructed. \pnum -Type \tcode{nullopt_t} shall not have a default constructor or an initializer-list constructor, and shall not be an aggregate. +Type \tcode{nullopt_t} does not have +a default constructor or an initializer-list constructor, and +is not an aggregate. +\tcode{nullopt_t} models \libconcept{copyable} and +\tcode{\libconcept{three_way_comparable}}. \rSec2[optional.bad.access]{Class \tcode{bad_optional_access}} @@ -5255,7 +5616,12 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? *x == v : false;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return *x == v; +return false; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator==}{optional}% @@ -5272,7 +5638,12 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? v == *x : false;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return v == *x; +return false; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator"!=}{optional}% @@ -5289,7 +5660,12 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? *x != v : true;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return *x != v; +return true; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator"!=}{optional}% @@ -5306,7 +5682,12 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? v != *x : true;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return v != *x; +return true; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator<}{optional}% @@ -5323,7 +5704,12 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? *x < v : true;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return *x < v; +return true; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator<}{optional}% @@ -5340,7 +5726,12 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? v < *x : false;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return v < *x; +return false; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator>}{optional}% @@ -5357,7 +5748,12 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? *x > v : false;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return *x > v; +return false; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator>}{optional}% @@ -5374,7 +5770,12 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? v > *x : true;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return v > *x; +return true; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator<=}{optional}% @@ -5391,7 +5792,12 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? *x <= v : true;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return *x <= v; +return true; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator<=}{optional}% @@ -5408,7 +5814,12 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? v <= *x : false;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return v <= *x; +return false; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator>=}{optional}% @@ -5425,7 +5836,12 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? *x >= v : false;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return *x >= v; +return false; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator>=}{optional}% @@ -5442,13 +5858,18 @@ \pnum \effects -Equivalent to: \tcode{return x.has_value() ? v >= *x : true;} +Equivalent to: +\begin{codeblock} +if (x.has_value()) + return v >= *x; +return true; +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator<=>}{optional}% \begin{itemdecl} template - requires (!@\exposconcept{is-derived-from-optional}@) && @\libconcept{three_way_comparable_with}@ + requires (!@\exposconcept{is-derived-from-optional}@) && @\libconcept{three_way_comparable_with}@ constexpr compare_three_way_result_t operator<=>(const optional& x, const U& v); \end{itemdecl} @@ -5493,8 +5914,8 @@ begins with a type \grammarterm{template-argument}. \pnum -\returns -\tcode{optional>(std::forward(v))}. +\effects +Equivalent to: \tcode{return optional>(std::forward(v));} \end{itemdescr} \indexlibraryglobal{make_optional}% @@ -5682,7 +6103,7 @@ public: // \ref{variant.ctor}, constructors constexpr variant() noexcept(@\seebelow@); - constexpr variant(const variant&); + constexpr variant(const variant&) noexcept(@\seebelow@); constexpr variant(variant&&) noexcept(@\seebelow@); template @@ -5797,7 +6218,7 @@ \indexlibraryctor{variant}% \begin{itemdecl} -constexpr variant(const variant& w); +constexpr variant(const variant& w) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} @@ -5810,7 +6231,8 @@ \pnum \throws -Any exception thrown by direct-initializing any $\tcode{T}_i$ for all $i$. +Any exception thrown by +the initialization of the contained value. \pnum \remarks @@ -5818,6 +6240,8 @@ \tcode{is_copy_constructible_v<$\tcode{T}_i$>} is \tcode{true} for all $i$. If \tcode{is_trivially_copy_constructible_v<$\tcode{T}_i$>} is \tcode{true} for all $i$, this constructor is trivial. +The exception specification is equivalent to the logical \logop{and} of +\tcode{is_nothrow_copy_constructible_v<$\tcode{T}_i$>} for all $i$. \end{itemdescr} \indexlibraryctor{variant}% @@ -5839,7 +6263,8 @@ \pnum \throws -Any exception thrown by move-constructing any $\tcode{T}_i$ for all $i$. +Any exception thrown by +the initialization of the contained value. \pnum \remarks @@ -5907,7 +6332,8 @@ \pnum \throws -Any exception thrown by the initialization of the selected alternative $\tcode{T}_j$. +Any exception thrown by +the initialization of the contained value. \pnum \remarks @@ -5941,7 +6367,8 @@ \pnum \throws -Any exception thrown by calling the selected constructor of \tcode{T}. +Any exception thrown by +the initialization of the contained value. \pnum \remarks @@ -5974,7 +6401,8 @@ \pnum \throws -Any exception thrown by calling the selected constructor of \tcode{T}. +Any exception thrown by +the initialization of the contained value. \pnum \remarks @@ -6008,7 +6436,8 @@ \pnum \throws -Any exception thrown by calling the selected constructor of $\tcode{T}_I$. +Any exception thrown by +the initialization of the contained value. \pnum \remarks @@ -6041,6 +6470,11 @@ \ensures \tcode{index()} is \tcode{I}. +\pnum +\throws +Any exception thrown by +the initialization of the contained value. + \pnum \remarks If $\tcode{T}_I$'s selected constructor is a constexpr constructor, this @@ -6504,7 +6938,7 @@ Let \tcode{VA} denote \tcode{variant_alternative} of the cv-unqualified type \tcode{T}. Then each specialization of the template meets the \oldconcept{TransformationTrait} requirements\iref{meta.rqmts} with a -member typedef \tcode{type} that names the type \tcode{add_const_t}. +member typedef \tcode{type} that names the type \tcode{const VA::type}. \end{itemdescr} \indexlibraryglobal{variant_alternative}% @@ -7046,6 +7480,9 @@ \indexheader{any}% \begin{codeblock} +#include // see \ref{initializer.list.syn} +#include // see \ref{typeinfo.syn} + namespace std { // \ref{any.bad.any.cast}, class \tcode{bad_any_cast} class bad_any_cast; @@ -8127,10 +8564,10 @@ friend constexpr bool operator==(const expected&, const unexpected&); private: - bool @\exposid{has_val}@; // \expos + bool @\exposid{has_val}@; // \expos union { - T @\exposid{val}@; // \expos - E @\exposid{unex}@; // \expos + remove_cv_t @\exposid{val}@; // \expos + E @\exposid{unex}@; // \expos }; }; } @@ -8605,6 +9042,17 @@ \tcode{is_nothrow_move_constructible_v || is_nothrow_move_constructible_v} is \tcode{true}. \end{itemize} + +\pnum +This operator is trivial if: +\begin{itemize} +\item \tcode{is_trivially_copy_constructible_v} is \tcode{true}, and +\item \tcode{is_trivially_copy_assignable_v} is \tcode{true}, and +\item \tcode{is_trivially_destructible_v} is \tcode{true}, and +\item \tcode{is_trivially_copy_constructible_v} is \tcode{true}, and +\item \tcode{is_trivially_copy_assignable_v} is \tcode{true}, and +\item \tcode{is_trivially_destructible_v} is \tcode{true}. +\end{itemize} \end{itemdescr} \indexlibrarymember{operator=}{expected}% @@ -8662,6 +9110,17 @@ is_nothrow_move_assignable_v && is_nothrow_move_constructible_v && is_nothrow_move_assignable_v && is_nothrow_move_constructible_v \end{codeblock} + +\pnum +This operator is trivial if: +\begin{itemize} +\item \tcode{is_trivially_move_constructible_v} is \tcode{true}, and +\item \tcode{is_trivially_move_assignable_v} is \tcode{true}, and +\item \tcode{is_trivially_destructible_v} is \tcode{true}, and +\item \tcode{is_trivially_move_constructible_v} is \tcode{true}, and +\item \tcode{is_trivially_move_assignable_v} is \tcode{true}, and +\item \tcode{is_trivially_destructible_v} is \tcode{true}. +\end{itemize} \end{itemdescr} \indexlibrarymember{operator=}{expected}% @@ -8856,7 +9315,7 @@ throw; } } else { - T tmp(std::move(@\exposid{val}@)); + remove_cv_t tmp(std::move(@\exposid{val}@)); destroy_at(addressof(@\exposid{val}@)); try { construct_at(addressof(@\exposid{unex}@), std::move(rhs.@\exposid{unex}@)); @@ -9407,7 +9866,9 @@ \pnum \returns -\tcode{x.has_value() \&\& static_cast(*x == v)}. +If \tcode{x.has_value()} is \tcode{true}, +\tcode{*x == v}; +otherwise \tcode{false}. \end{itemdescr} \indexlibrarymember{operator==}{expected}% @@ -9423,7 +9884,9 @@ \pnum \returns -\tcode{!x.has_value() \&\& static_cast(x.error() == e.error())}. +If \tcode{!x.has_value()} is \tcode{true}, +\tcode{x.error() == e.error()}; +otherwise \tcode{false}. \end{itemdescr} \rSec2[expected.void]{Partial specialization of \tcode{expected} for \tcode{void} types} @@ -9805,6 +10268,13 @@ This operator is defined as deleted unless \tcode{is_copy_assignable_v} is \tcode{true} and \tcode{is_copy_constructible_v} is \tcode{true}. + +\pnum +This operator is trivial if +\tcode{is_trivially_copy_constructible_v}, +\tcode{is_trivially_copy_assigna\-ble_v}, and +\tcode{is_trivially_destructible_v} +are all \tcode{true}. \end{itemdescr} \indexlibrarymember{operator=}{expected}% @@ -9844,6 +10314,13 @@ \remarks The exception specification is equivalent to \tcode{is_nothrow_move_constructible_v \&\& is_nothrow_move_assignable_v}. + +\pnum +This operator is trivial if +\tcode{is_trivially_move_constructible_v}, +\tcode{is_trivially_move_assigna\-ble_v}, and +\tcode{is_trivially_destructible_v} +are all \tcode{true}. \end{itemdescr} \indexlibrarymember{operator=}{expected}% @@ -10345,7 +10822,8 @@ \pnum \returns If \tcode{x.has_value()} does not equal \tcode{y.has_value()}, \tcode{false}; -otherwise \tcode{x.has_value() || static_cast(x.error() == y.error())}. +otherwise if \tcode{x.has_value()} is \tcode{true}, \tcode{true}; +otherwise \tcode{x.error() == y.error()}. \end{itemdescr} \indexlibrarymember{operator==}{expected}% @@ -10362,7 +10840,9 @@ \pnum \returns -\tcode{!x.has_value() \&\& static_cast(x.error() == e.error())}. +If \tcode{!x.has_value()} is \tcode{true}, +\tcode{x.error() == e.error()}; +otherwise \tcode{false}. \end{itemdescr} \rSec1[bitset]{Bitsets} @@ -10409,13 +10889,18 @@ // bit reference class reference { public: - constexpr reference(const reference&) = default; + constexpr reference(const reference& x) noexcept; constexpr ~reference(); constexpr reference& operator=(bool x) noexcept; // for \tcode{b[i] = x;} - constexpr reference& operator=(const reference&) noexcept; // for \tcode{b[i] = b[j];} - constexpr bool operator~() const noexcept; // flips the bit + constexpr reference& operator=(const reference& x) noexcept; // for \tcode{b[i] = b[j];} + constexpr const reference& operator=(bool x) const noexcept; constexpr operator bool() const noexcept; // for \tcode{x = b[i];} + constexpr bool operator~() const noexcept; constexpr reference& flip() noexcept; // for \tcode{b[i].flip();} + + friend constexpr void swap(reference x, reference y) noexcept; + friend constexpr void swap(reference x, bool& y) noexcept; + friend constexpr void swap(bool& x, reference y) noexcept; }; // \ref{bitset.cons}, constructors @@ -10502,7 +10987,7 @@ zero. Each bit has a non-negative position \tcode{pos}. When converting -between an object of class +between an object of type \tcode{bitset} and a value of some integral type, bit position \tcode{pos} corresponds to the @@ -10511,6 +10996,107 @@ The integral value corresponding to two or more bits is the sum of their bit values. +\pnum +\tcode{reference} +is a class that simulates a reference to a single bit in the sequence. + +\indexlibraryctor{bitset::reference}% +\begin{itemdecl} +constexpr reference::reference(const reference& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{*this} to refer to the same bit as \tcode{x}. +\end{itemdescr} + +\indexlibrarydtor{bitset::reference}% +\begin{itemdecl} +constexpr reference::~reference(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +None. +\end{itemdescr} + +\indexlibrarymember{operator=}{bitset::reference}% +\begin{itemdecl} +constexpr reference& reference::operator=(bool x) noexcept; +constexpr reference& reference::operator=(const reference& x) noexcept; +constexpr const reference& reference::operator=(bool x) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Sets the bit referred to by \tcode{*this} if \tcode{bool(x)} is \tcode{true}, +and clears it otherwise. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{operator bool}{bitset::reference}% +\begin{itemdecl} +constexpr reference::operator bool() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if the value of the bit referred to by \tcode{*this} is one, +\tcode{false} otherwise. +\end{itemdescr} + +\indexlibrarymember{operator\~{}}{bitset::reference}% +\begin{itemdecl} +constexpr bool reference::operator~() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!bool(*this)}. +\end{itemdescr} + +\indexlibrarymember{swap}{bitset::reference}% +\begin{itemdecl} +constexpr void swap(reference x, reference y) noexcept; +constexpr void swap(reference x, bool& y) noexcept; +constexpr void swap(bool& x, reference y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Exchanges the values denoted by \tcode{x} and \tcode{y} as if by: + +\begin{codeblock} +bool b = x; +x = y; +y = b; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{flip}{bitset::reference}% +\begin{itemdecl} +constexpr reference& reference::flip() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{*this = !*this}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \pnum The functions described in \ref{template.bitset} can report three kinds of errors, each associated with a distinct exception: @@ -10633,6 +11219,15 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{is_array_v} is \tcode{false}, +\item \tcode{is_trivially_copyable_v} is \tcode{true}, +\item \tcode{is_standard_layout_v} is \tcode{true}, and +\item \tcode{is_trivially_default_constructible_v} is \tcode{true}. +\end{itemize} + \pnum \effects As if by: @@ -11250,6 +11845,9 @@ \indexlibraryglobal{unwrap_ref_decay}% \indexlibraryglobal{unwrap_ref_decay_t}% \begin{codeblock} +#include // see \ref{initializer.list.syn} +#include // see \ref{typeinfo.syn} + namespace std { // \ref{func.invoke}, invoke template @@ -11492,19 +12090,20 @@ A \defnadj{callable}{object} is an object of a callable type. \pnum -A \defnx{call wrapper type}{call wrapper!type} is a type that holds a callable object -and supports a call operation that forwards to that object. +A \defnx{call wrapper type}{call wrapper!type} is a type that holds +a \defnadj{target}{object}, +which is either +a callable object or +an object representing a callable object, +and supports a call operation that forwards to that callable object. \pnum A \defn{call wrapper} is an object of a call wrapper type. -\pnum -A \defn{target object} is the callable object held by a call wrapper. - \pnum A call wrapper type may additionally hold a sequence of objects and references -that may be passed as arguments to the target object. +that may be passed as arguments to the callable object. These entities are collectively referred to as \defnx{bound argument entities}{bound argument entity}. @@ -12049,7 +12648,7 @@ \indexlibrarymember{operator()}{plus<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) + std::forward(u)); + -> decltype(std::forward(t) + std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12091,7 +12690,7 @@ \indexlibrarymember{operator()}{minus<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) - std::forward(u)); + -> decltype(std::forward(t) - std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12133,7 +12732,7 @@ \indexlibrarymember{operator()}{multiplies<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) * std::forward(u)); + -> decltype(std::forward(t) * std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12175,7 +12774,7 @@ \indexlibrarymember{operator()}{divides<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) / std::forward(u)); + -> decltype(std::forward(t) / std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12217,7 +12816,7 @@ \indexlibrarymember{operator()}{modulus<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) % std::forward(u)); + -> decltype(std::forward(t) % std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12259,7 +12858,7 @@ \indexlibrarymember{operator()}{negate<>}% \begin{itemdecl} template constexpr auto operator()(T&& t) const - -> decltype(-std::forward(t)); + -> decltype(-std::forward(t)); \end{itemdecl} \begin{itemdescr} @@ -12327,7 +12926,7 @@ \indexlibrarymember{operator()}{equal_to<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) == std::forward(u)); + -> decltype(std::forward(t) == std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12369,7 +12968,7 @@ \indexlibrarymember{operator()}{not_equal_to<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) != std::forward(u)); + -> decltype(std::forward(t) != std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12411,7 +13010,7 @@ \indexlibrarymember{operator()}{greater<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) > std::forward(u)); + -> decltype(std::forward(t) > std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12453,7 +13052,7 @@ \indexlibrarymember{operator()}{less<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) < std::forward(u)); + -> decltype(std::forward(t) < std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12495,7 +13094,7 @@ \indexlibrarymember{operator()}{greater_equal<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) >= std::forward(u)); + -> decltype(std::forward(t) >= std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12537,7 +13136,7 @@ \indexlibrarymember{operator()}{less_equal<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) <= std::forward(u)); + -> decltype(std::forward(t) <= std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12846,7 +13445,7 @@ \indexlibrarymember{operator()}{logical_and<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) && std::forward(u)); + -> decltype(std::forward(t) && std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12888,7 +13487,7 @@ \indexlibrarymember{operator()}{logical_or<>}% \begin{itemdecl} template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) || std::forward(u)); + -> decltype(std::forward(t) || std::forward(u)); \end{itemdecl} \begin{itemdescr} @@ -12930,7 +13529,7 @@ \indexlibrarymember{operator()}{logical_not<>}% \begin{itemdecl} template constexpr auto operator()(T&& t) const - -> decltype(!std::forward(t)); + -> decltype(!std::forward(t)); \end{itemdecl} \begin{itemdescr} @@ -13202,9 +13801,9 @@ \pnum \returns -A perfect forwarding call wrapper\iref{func.require} \tcode{g} that -does not have state entities, and -has the call pattern \tcode{!invoke(f, call_args...)}. +A perfect forwarding call wrapper\iref{func.require} \tcode{g} +whose target object is a copy of \tcode{cw}, and +whose call pattern is \tcode{!invoke(f, call_args...)}. \end{itemdescr} \rSec2[func.bind.partial]{Function templates \tcode{bind_front} and \tcode{bind_back}} @@ -13324,8 +13923,9 @@ \pnum \returns -A perfect forwarding call wrapper\iref{func.require} \tcode{g} that -does not have a target object, and has the call pattern: +A perfect forwarding call wrapper\iref{func.require} \tcode{g} +whose target object is a copy of \tcode{cw}, and +whose call pattern is: \begin{itemize} \item \tcode{invoke(f, bound_args..., call_args...)} @@ -13613,10 +14213,12 @@ \pnum Let \tcode{t} be an object of a type that is a specialization of -\tcode{function}, \tcode{copyable_function}, or \tcode{move_only_function}, +\tcode{function}, \tcode{copyable_function}, \tcode{move_only_function}, +or \tcode{function_ref}, such that the target object \tcode{x} of \tcode{t} has a type that is a specialization of -\tcode{function}, \tcode{copyable_function}, or \tcode{move_only_function}. +\tcode{function}, \tcode{copyable_function}, \tcode{move_only_function}, +or \tcode{function_ref}. Each argument of the invocation of \tcode{x} evaluated as part of the invocation of \tcode{t} may alias an argument in the same position in the invocation of \tcode{t} that @@ -14265,12 +14867,12 @@ \tcode{*this} has no target object if any of the following hold: \begin{itemize} \item -\tcode{f} is a null function pointer value, or +\tcode{f} is a null function pointer value, \item \tcode{f} is a null member pointer value, or \item \tcode{remove_cvref_t} is a specialization of -the \tcode{move_only_function} class template, +the \tcode{move_only_function} or \tcode{copyable_function} class template, and \tcode{f} has no target object. \end{itemize} Otherwise, \tcode{*this} has a target object of type \tcode{VT} @@ -14956,9 +15558,11 @@ // \ref{func.wrap.ref.ctor}, constructors and assignment operators template function_ref(F*) noexcept; template constexpr function_ref(F&&) noexcept; - template constexpr function_ref(nontype_t) noexcept; - template constexpr function_ref(nontype_t, U&&) noexcept; - template constexpr function_ref(nontype_t, @\cv{}@ T*) noexcept; + template constexpr function_ref(constant_wrapper) noexcept; + template + constexpr function_ref(constant_wrapper, U&&) noexcept; + template + constexpr function_ref(constant_wrapper, @\cv{}@ T*) noexcept; constexpr function_ref(const function_ref&) noexcept = default; constexpr function_ref& operator=(const function_ref&) noexcept = default; @@ -14978,10 +15582,10 @@ // \ref{func.wrap.ref.deduct}, deduction guides template function_ref(F*) -> function_ref; - template - function_ref(nontype_t) -> function_ref<@\seebelow@>; - template - function_ref(nontype_t, T&&) -> function_ref<@\seebelow@>; + template + function_ref(constant_wrapper) -> function_ref<@\seebelow@>; + template + function_ref(constant_wrapper, T&&) -> function_ref<@\seebelow@>; } \end{codeblock} @@ -15031,6 +15635,25 @@ \end{codeblock} \end{itemdescr} +\indextext{function_ref::is-convertible-from-specialization@\tcode{function_ref::\exposid{is-convertible-from-\brk{}specialization}}}% +\begin{itemdecl} +template + static constexpr bool @\exposid{is-convertible-from-specialization}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +If \tcode{F} denotes a specialization +\tcode{function_ref} +for some placeholders \cvqual{cv2} and \placeholder{noex2}, +\tcode{\exposid{is-convertible-from-specialization}} is equal to: +\begin{codeblock} +is_convertible_v && +is_convertible_v. +\end{codeblock} +Otherwise, \tcode{\exposid{is-convertible-from-specialization}} is \tcode{false}. +\end{itemdescr} + \indexlibraryctor{function_ref}% \begin{itemdecl} template function_ref(F* f) noexcept; @@ -15078,32 +15701,62 @@ \pnum \effects -Initializes -\exposid{bound-entity} with \tcode{addressof(f)}, and +If \tcode{\exposid{is-convertible-from-specialization}>} +is \tcode{false}, +initializes +\exposid{bound-en\-tity} with \tcode{addressof(f)}, and \exposid{thunk-ptr} with the address of a function \tcode{\placeholder{thunk}} such that -\tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} +\tcode{\placeholder{thunk}(\exposid{bound-\brk{}entity}, \placeholder{call-args}...)} is expression-equivalent\iref{defns.expression.equivalent} to \tcode{invoke_r(static_cast<\cv{} T\&>(f), \placeholder{call-args}...)}. +Otherwise, initializes \exposid{bound-entity} +with the value of \tcode{f.\exposid{bound-entity}} and +\exposid{thunk-\brk{}ptr} with the value of \tcode{f.\exposid{thunk-ptr}}. + +\pnum +\remarks +If \tcode{remove_cvref_t} is a specialization of \tcode{function_ref}, +an implementation may initialize \exposid{bound-entity} +with the value of \tcode{f.\exposid{bound-entity}} and \exposid{thunk-ptr} +with the value of \tcode{f.\exposid{thunk-ptr}}. +\begin{example} +\begin{codeblock} +void f1(std::string); +void f2(std::string); + +function_ref r1(&f1); +function_ref r2(r1); +r2(""); // \tcode{f1} is invoked +r1 = &f2; +r2(""); // it is unspecified if \tcode{f1} or \tcode{f2} is invoked +\end{codeblock} +\end{example} \end{itemdescr} \indexlibraryctor{function_ref}% \begin{itemdecl} -template constexpr function_ref(nontype_t) noexcept; +template constexpr function_ref(constant_wrapper f) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{F} be \tcode{decltype(f)}. - \pnum \constraints -\tcode{\exposid{is-invocable-using}} is \tcode{true}. +\tcode{\exposid{is-invocable-using}} is \tcode{true}. \pnum \mandates +\begin{itemize} +\item If \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, -then \tcode{f != nullptr} is \tcode{true}. +then \tcode{f.value != nullptr} is \tcode{true}, and +\item +if \tcode{ArgTypes} is not an empty pack and +all types in \tcode{remove_cvref_t...} +satisfy \exposconcept{constexpr-param} then +\tcode{constant_wrapper<\placeholdernc{INVOKE}(f.value, remove_cvref_t::\newline value...)>} +is not a valid type. +\end{itemize} \pnum \effects @@ -15114,31 +15767,30 @@ such that \tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} is expression-equivalent\iref{defns.expression.equivalent} to -\tcode{invoke_r(f, \placeholder{call-args}...)}. +\tcode{invoke_r(f.value, \placeholder{call-args}...)}. \end{itemdescr} \indexlibraryctor{function_ref}% \begin{itemdecl} -template - constexpr function_ref(nontype_t, U&& obj) noexcept; +template + constexpr function_ref(constant_wrapper f, U&& obj) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{T} be \tcode{remove_reference_t} and -\tcode{F} be \tcode{decltype(f)}. +Let \tcode{T} be \tcode{remove_reference_t}. \pnum \constraints \begin{itemize} \item \tcode{is_rvalue_reference_v} is \tcode{false}, and -\item \tcode{\exposid{is-invocable-using}} is \tcode{true}. +\item \tcode{\exposid{is-invocable-using}} is \tcode{true}. \end{itemize} \pnum \mandates If \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, -then \tcode{f != nullptr} is \tcode{true}. +then \tcode{f.value != nullptr} is \tcode{true}. \pnum \effects @@ -15148,27 +15800,24 @@ such that \tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} is expression-equivalent\iref{defns.expression.equivalent} to -\tcode{invoke_r(f, static_cast<\cv{} T\&>(obj), \placeholder{call-args}...)}. +\tcode{invoke_r(f.value, static_cast<\cv{} T\&>(obj), \placeholder{call-args}...)}. \end{itemdescr} \indexlibraryctor{function_ref}% \begin{itemdecl} -template - constexpr function_ref(nontype_t, @\cv{}@ T* obj) noexcept; +template + constexpr function_ref(constant_wrapper f, @\cv{}@ T* obj) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{F} be \tcode{decltype(f)}. - \pnum \constraints -\tcode{\exposid{is-invocable-using}} is \tcode{true}. +\tcode{\exposid{is-invocable-using}} is \tcode{true}. \pnum \mandates If \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, -then \tcode{f != nullptr} is \tcode{true}. +then \tcode{f.value != nullptr} is \tcode{true}. \pnum \expects @@ -15183,7 +15832,7 @@ such that \tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} is expression-equivalent\iref{defns.expression.equivalent} to -\tcode{invoke_r(f, obj, \placeholder{call-args}...)}. +\tcode{invoke_r(f.value, obj, \placeholder{call-args}...)}. \end{itemdescr} \indexlibrarymember{operator=}{function_ref}% @@ -15195,9 +15844,9 @@ \pnum \constraints \begin{itemize} -\item \tcode{T} is not the same type as \tcode{function_ref}, +\item \tcode{\exposid{is-convertible-from-specialization}} is \tcode{false}, \item \tcode{is_pointer_v} is \tcode{false}, and -\item \tcode{T} is not a specialization of \tcode{nontype_t}. +\item \tcode{T} is not a specialization of \tcode{constant_wrapper}. \end{itemize} \end{itemdescr} @@ -15229,13 +15878,13 @@ \end{itemdescr} \begin{itemdecl} -template - function_ref(nontype_t) -> function_ref<@\seebelow@>; +template + function_ref(constant_wrapper) -> function_ref<@\seebelow@>; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{F} be \tcode{remove_pointer_t}. +Let \tcode{F} be \tcode{remove_pointer_t}. \pnum \constraints @@ -15247,14 +15896,11 @@ \end{itemdescr} \begin{itemdecl} -template - function_ref(nontype_t, T&&) -> function_ref<@\seebelow@>; +template + function_ref(constant_wrapper, T&&) -> function_ref<@\seebelow@>; \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{F} be \tcode{decltype(f)}. - \pnum \constraints %FIXME: R and E should be defined outside of these constraints. @@ -15269,7 +15915,7 @@ in which case let \tcode{R} be \tcode{invoke_result_t}, \tcode{A...} be an empty pack, and -\tcode{E} be \tcode{false}, or +\tcode{E} be \tcode{true}, or \item \tcode{F} is of the form \tcode{R(*)(G, A...) noexcept(E)} for a type \tcode{G}. @@ -15721,15 +16367,8 @@ \pnum \constantwhen -\tcode{To}, \tcode{From}, and the types of all subobjects -of \tcode{To} and \tcode{From} are types \tcode{T} such that: -\begin{itemize} -\item \tcode{is_union_v} is \tcode{false}; -\item \tcode{is_pointer_v} is \tcode{false}; -\item \tcode{is_member_pointer_v} is \tcode{false}; -\item \tcode{is_volatile_v} is \tcode{false}; and -\item \tcode{T} has no non-static data members of reference type. -\end{itemize} +Neither \tcode{To} nor \tcode{From} +has constexpr-unknown representation\iref{expr.const.core}. \pnum \returns @@ -15845,7 +16484,7 @@ \remarks A function call expression that violates the precondition in the \expects element -is not a core constant expression\iref{expr.const}. +is not a core constant expression\iref{expr.const.core}. \end{itemdescr} \indexlibraryglobal{bit_floor}% diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index e1c6be970c..b0ed29aaaf 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -454,6 +454,9 @@ % CWG 2843 removed [uaxid.def.rfmt] \removedxref{uaxid.def.rfmt} +% P3016R6 Resolve inconsistencies in begin/end for valarray and braced intializers +\removedxref{support.initlist.range} + %%% Renamed sections. %%% Examples: % diff --git a/tools/check-output.sh b/tools/check-output.sh index a28d236e0c..8b23f65141 100755 --- a/tools/check-output.sh +++ b/tools/check-output.sh @@ -43,27 +43,27 @@ grep newlabel `ls *.aux | grep -v std.aux` | awk -F '{' '{ print $2 }' | # Find grammar index entries missing a definition cat std-grammarindex.ind | - awk 'BEGIN { def=1 } /^ .item/ { if (def==0) { gsub("[{},]", "", item); print item } item=$NF; def=0; next } /hyperindexformat/ { def=1 }' | + awk 'BEGIN { def=1 } /^ .item/ { if (def==0) { gsub("[{},]", "", item); print item } item=$NF; def=0; next } /hyper(x{0,1})indexformat/ { def=1 }' | grep -v -- '-keyword$' | # xxx-keyword is special sed 's/^\(.*\)$/grammar non-terminal \1 has no definition/' | fail || failed=1 # Find header index entries missing a definition cat std-headerindex.ind | - awk 'BEGIN { def=1 } /^ .item/ { if (def==0) { gsub("[{},]", "", item); print item } i=NF; while (i > 0 && $i !~ "<[a-z_.]*>") { --i; } item=$i; def=0; next } /hyperindexformat/ { def=1 }' | + awk 'BEGIN { def=1 } /^ .item/ { if (def==0) { gsub("[{},]", "", item); print item } i=NF; while (i > 0 && $i !~ "<[a-z_.]*>") { --i; } item=$i; def=0; next } /hyper(x{0,1})indexformat/ { def=1 }' | sed 's/^\(.*\)$/header \1 has no definition/' | fail || failed=1 # Find concept index entries missing a definition cat std-conceptindex.ind | - sed 's/.hyperindexformat/\nhyperindexformat/;s/.hyperpage/\nhyperpage/g' | + sed 's/.hyper\(x\{0,1\}\)indexformat/\nhyperindexformat/;s/.hyperpage/\nhyperpage/g' | awk 'BEGIN { def=1 } /^ .item/ { if (def==0) { gsub("[{},]", "", item); print item } item=$NF; def=0; next } /hyperindexformat/ { def=1 }' | sed 's/^\(.*\)$/concept \1 has no definition/' | fail || failed=1 # Find undecorated concept names in code blocks patt="`cat std-conceptindex.ind | - sed 's/.hyperindexformat/\nhyperindexformat/;s/.hyperpage/\nhyperpage/' | + sed 's/.hyper\(x\{0,1\}\)indexformat/\nhyperindexformat/;s/.hyperpage/\nhyperpage/' | sed -n 's/^ .item.*{\([-a-z_]*\)}.*$/\1/p;s/^ .item.*frenchspacing \([a-z_]*\)}.*$/\1/p'`" patt="`echo $patt | sed 's/ /\\\\|/g'`"