diff --git a/.gitorder b/.gitorder index abebabaa77..edc39fbf98 100644 --- a/.gitorder +++ b/.gitorder @@ -5,6 +5,7 @@ source/macros.tex source/tables.tex source/cover-*.tex source/front.tex +source/preface.tex source/intro.tex source/lex.tex source/basic.tex @@ -21,22 +22,24 @@ source/lib-intro.tex source/support.tex source/concepts.tex source/diagnostics.tex +source/memory.tex +source/meta.tex source/utilities.tex -source/strings.tex source/containers.tex source/iterators.tex source/ranges.tex source/algorithms.tex +source/strings.tex +source/text.tex source/numerics.tex source/time.tex -source/locales.tex source/iostreams.tex -source/regex.tex -source/atomics.tex source/threads.tex +source/exec.tex source/grammar.tex source/limits.tex source/compatibility.tex source/future.tex +source/uax31.tex source/back.tex source/xrefdelta.tex diff --git a/papers/n5002.html b/papers/n5002.html new file mode 100644 index 0000000000..0c4835ed67 --- /dev/null +++ b/papers/n5002.html @@ -0,0 +1,839 @@ + + + + + +Codestin Search App + + +

N5002 Editors’ Report:
Programming Languages — C++

+ +

Date: 2024-12-17

+ +

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

+ +

Email: cxxeditor@gmail.com

+ +

Acknowledgements

+ +

Thanks to all those who have submitted editorial +issues +and to those who have provided pull requests with fixes. +Special thanks to Andreas Krug for many timely editorial fixes.

+ +

New papers

+ + + +

Motions incorporated into working draft

+ +

Notes on motions

+ +

CWG Poll 9 was retracted.

+ +

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

+ + + +

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

+ +

Core working group polls

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

CWG Poll 9 was retracted.

+ +

Library working group polls

+ +

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

+ +

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

+ +

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

+ +

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

+ +

LWG Poll 5 was sent back (see above).

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

LWG Poll 17 was sent back (see above).

+ +

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

+ +

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

+ +

Editorial changes

+ +

Major editorial changes

+ +

There have not been any major editorial changes.

+ +

Minor editorial changes

+ +

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

+ +
commit e9604bcd3d8325860a4db9d02c4f90d0ae70162e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 21:12:40 2024 +0100
+
+    [depr.format.syn] Fix header reference
+
+commit 0b296da823e7af4a987a0a870ae299420b9ae502
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Oct 17 00:39:04 2024 +0100
+
+    [{localization,re}.general] Change "This Clause" to "Subclause".
+
+    These subclauses are no longer top-level clauses.
+
+commit 629e10e2f4177dd24d513be71f2203de325a7e8a
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Oct 17 08:57:39 2024 +0200
+
+    [inplace.vector.overview] Add missing ',' in comment
+
+commit 726e07a3a99a87f5e89dd40a064f4a6bc84ed3ce
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Oct 17 08:25:55 2024 +0200
+
+    [cpp.subst] Fix typo
+
+commit 88b2b8dcbd145782cfab61e6dad9296c9294593d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Oct 16 22:58:07 2024 +0200
+
+    [exec.domain.default] Add missing \pnum
+
+commit 8698ea48e40acc2e18630e799bbb23c41b9344e6
+Author: James Touton <bekenn@gmail.com>
+Date:   Mon Sep 16 21:47:30 2024 -0700
+
+    [over.match.best.general] Minor formatting fixes
+
+commit 7ad39cbf374764a4e232f967e01541419230fedc
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Oct 17 11:16:28 2024 -0400
+
+    [lex.comment] Move the subclause earlier, to where it better fits
+
+    Comments should fit betweem character sets (to define the basic source
+    character set) and preprocessor tokens, that must already understand
+    comments in order to treat them as whitespace.
+
+commit 7f7170cc9b96e9cc76bc0b765837978856936ab1
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Oct 5 16:21:15 2024 -0400
+
+    [depr] Reorder clauses by origin of deprecation
+
+    Reorders the deprecated features annex to follow the order
+    of the main clauses that the deprecates feature refers to.
+    Where multiple clauses are references, use the one named by
+    the [depr.XXX] stable label.
+
+commit cd21b72788d9066f79f31fb6c4516481dfbb4925
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Fri Oct 18 03:55:20 2024 +0800
+
+    [range.concat.iterator] Remove redundant \expos comments (#6942)
+
+commit 801fb2c0aaf6693a06a9a9e38871bae9536dc194
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Oct 17 17:05:47 2024 -0400
+
+    [lex] Reorder subclauses to better follow phases of translation
+
+    This PR purely moves existing words around, and does not create any new content.
+
+    The proposed subclause ordering is now:
+
+    * 5 Lexical convensions
+      - 5.1 Separate translation
+      - 5.2 Phases of translation
+      - 5.3 Characters
+        - 5.3.1 Character sets
+        - 5.3.2 Universal character names
+      - 5.4 Comments
+      - 5.5 Preprocessing tokens
+      - 5.6 Header names
+      - 5.7 Preprocessing numbers
+      - 5.8 Operators and punctuators
+      - 5.9 Alternative tokens
+      - 5.10 Tokens
+      - 5.11 Identifiers
+      - 5.12 Keywords
+      - 5.13 Literals
+        - 5.13.1 Kinds of literals
+        - 5.13.2 ...
+
+commit 49113a4a577b8d6aed7e5321f0c1fe68d0bd6480
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Oct 18 08:28:28 2024 +0200
+
+    [library.general] Adjust library overview for recent clause restructuring
+
+commit a470ff890be232b9e2a15e44c406ef72c7d816c2
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Oct 19 11:31:59 2024 +0200
+
+    [lex.pptoken] Fix indefinitive article for consistency (#7324)
+
+commit 92594a81f021e76dce6acf7ea5d8176350a1e3fb
+Author: Eelis van der Weegen <eelis@eelis.net>
+Date:   Wed Mar 13 21:04:43 2019 +0100
+
+    [temp.deduct.call] Include surrounding code in math formula
+
+commit 0451d08aefd5318254d7d204ad45700aa4d5a2e7
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Oct 21 19:45:10 2024 +0800
+
+    [specialized.algorithms.general] Restore the note for potentially-overlapping objects and undefined behavior (#7326)
+
+    The original note was incorrect and removed (see #6157). But it turns out
+    that _some_ note is still helpful. This PR tries to find the right way to
+    describe storage reusing and potential subsequent undefined behavior.
+
+commit f6b7ef3f1c6e483d97ad5a4f86b3efed38b74c99
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Oct 19 11:41:35 2024 -0400
+
+    [lex.phases] Add crossreferences from phases 3 and 4
+
+    The phases of translation use forward references to the rest
+    of the standard well, but phases 3 and 4 almost entirely lack
+    such crossreferences, despite doing significant work in the
+    process of translating a file.
+
+commit a69507a54e67ae91424d9c621a9cb57ef3ba1512
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 21 17:48:09 2024 +0200
+
+    [locale.codecvt.virtuals] Fix garbled sentence
+
+commit e0576ed2411f36b0ba648afbf6953a0c72c9effb
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Oct 21 13:09:51 2024 -0400
+
+    [compliance] Sort the freestanding headers after clause reorganization
+
+commit b0135f256e40d45faf1d1ac2aaa3abbda36a17c3
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Tue Oct 22 02:14:47 2024 -0500
+
+    [exec.awaitables] Add missing word (#7340)
+
+commit eb9872aedc581e82e804c0fe8ca7d478ba066b17
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Tue Oct 22 12:09:22 2024 +0200
+
+    [func.wrap.func.con] Fix ill-formed postcondition (#7341)
+
+commit ced2c3866cb3d410c812fa3c359058d185aec329
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Oct 23 13:47:18 2024 -0400
+
+    [allocator.requirements.general] Remove redundant template syntax (#5872)
+
+commit e70d9d6b901457cae9f4f596393f4bf7cee4591a
+Author: Eisenwave <me@eisenwave.net>
+Date:   Mon Oct 21 20:29:10 2024 +0200
+
+    [intro.races] Clarify conflicts for the case where no bits are changed
+
+commit 6ba0dc9b2bf4c3cebc51154e4d543eafb41a8064
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Aug 20 00:52:57 2023 +0200
+
+    [intro.memory] remove stray definitions
+
+commit 9dc7b3f30d2971ccb3bb38483a7cdb62065a2c3c
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Oct 22 17:12:25 2024 -0400
+
+    [basic.stc.inherit] Dissolve paragraph into [...general]
+
+    The whole subclause [basic.stc.inherit] is a single sentence that
+    belongs adjacent to the material in [basic.std.general] that
+    specifies how entities acquire a storage duration, wheras all the
+    remaining subclauses below [basic.stc] describe specific storage
+    durations.  Folding that sentence directly into the general clause
+    is even clearer.
+
+commit d5174d561b61304118cdf1042c5697ec6083c181
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Oct 24 09:03:57 2024 +0200
+
+    [basic.link] Add commas between coordinate subclauses (#7342)
+
+commit 8ab0745b6099fd56288763e57ca47dee099db7cb
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Oct 25 10:53:22 2024 +0200
+
+    [bit.cast] change "behaviour" to "behavior" (#7353)
+
+commit 95d491ed6ca7817423855be4f90b61094a1b4312
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Oct 26 15:52:55 2024 +0200
+
+    [associative.reqmts.general] Fix punctuation (#7354)
+
+commit 3eb8c47d8f2fe050e221b5d4c36189d965273b37
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sat Oct 26 16:00:12 2024 +0200
+
+    [basic.compound] Add comma to run-on sentence (#7348)
+
+commit 84af20dcd1976a8982d4418756d1ec9728306580
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sun Oct 27 13:27:34 2024 +0100
+
+    [mdspan.layout.left.cons] Remove duplicate "Effects:" (#7355)
+
+commit ac5b25027266917de3fbb220fc9ecfa4470672f9
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Oct 27 22:46:10 2024 +0100
+
+    [expr.prim.lambda.capture, expr.const, ostream.formatted.print] Reword "automatic variable" (#7358)
+
+commit 324f56439e951773e6ce7437e703fb3aafd5a90c
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Oct 28 07:42:45 2024 -0400
+
+    [lex.pptoken] Reorder paragraphs to define terms before they are used (#7346)
+
+    First move p1 below p2, so that we do not refer to preprocessing tokens before they are defined.
+    Then move p4 up, as it is splitting some unrelated examples, neither of which use its contents.
+
+commit bf43925ff0d9e80997918e98989892b4c7bf15f7
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Oct 29 11:52:02 2024 +0100
+
+    [mdspan.layout.left.cons] Fix typo (#7360)
+
+commit a42d1246936f6376acf6188c1b2053886cdaf3c2
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sat Nov 2 14:38:54 2024 +0100
+
+    [lib.types.movedfrom] Add cross-reference to [defns.valid] (#7365)
+
+commit 6bfbb59e48b6bde05a78d257cbb943acdb2b6781
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Fri Apr 7 17:09:40 2023 +0800
+
+    [format.string.std] Replace "Derived Extracted Property" with simply "property"
+
+commit aa53618e39f16a6fbf147a8ac2d95a33cb8c5cbc
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Fri Aug 9 17:39:07 2024 +0800
+
+    [lex.name] Strike "Derived Core Properties"
+
+commit cb15975d133869eb18a8b7878343a990e63415e2
+Author: Ilya Burylov <burylov@gmail.com>
+Date:   Wed Nov 6 01:44:54 2024 -0800
+
+    [linalg.helpers.mandates] Fix typos (#7372)
+
+commit fcf95f0f1cb3ae11274f1c3477447aadb76b54ca
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Nov 6 13:27:56 2024 +0100
+
+    [exec.opstate.general] Fix typo (#7370)
+
+commit efa0bec63a2718967f7033217a757d536eba3c18
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed Nov 6 12:55:52 2024 +0000
+
+    [linalg.reqs.val] Fix use of \defnadjx for value types (#7374)
+
+commit 693835ad625acfdf2d610240b99d6d8fecdb8a6a
+Author: Casey Carter <Casey@Carter.net>
+Date:   Sat Nov 16 06:21:27 2024 -0800
+
+    [fs.op.remove] Clarify "Returns" element (#7387)
+
+    To avoid confusion as in microsoft/STL#5088.
+
+commit 1788b3fcd8f3dbe7b31e6bbfbb968ad43d7ecec3
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Nov 17 20:05:57 2024 +0000
+
+    [over.ics.ref] Fix formatting of 'cv T' (#7389)
+
+commit 16df53c4ab9a17942f5bf994031c98105959a5d5
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Nov 18 17:37:02 2024 +0000
+
+    [defns.regex.primary.equivalence.class] Hyphenate 'locale-specific' (#7395)
+
+commit 4f0facdcd57b922510212ddf44ef39f46dcbe44d
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Nov 18 17:38:09 2024 +0000
+
+    [temp.param] Fix typos (#7394)
+
+commit 99deb7022614be47cfcce4f003d8eb57c02b6926
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Nov 19 05:21:45 2024 +0000
+
+    [over.ics.ref] Capitalize 'Exact Match' (#7392)
+
+commit fb8036b6dfe5ce4a99cd85fddac3f115a7fd96af
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Nov 19 05:25:41 2024 +0000
+
+    [class] Avoid hyphenation for 'multidimensional' (#7391)
+
+commit 3f41cf86547b77854abddde7dcaddf2ff00405bf
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Nov 19 05:26:53 2024 +0000
+
+    [lex.phases] Move cross-reference to the first use of the referenced term (#7393)
+
+commit a05b963e9fe12a8589502b4fbc951c119ae1b3b2
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Jul 30 16:51:21 2024 -0400
+
+    [basic.life] Move definition of before and after from bottom to top of subclause
+
+    The last paragraph of this subclause changes the definition of English words
+    used throughout the preceding paragraphs.  While it might be preferable
+    to replace all such usage with the new definitions, that would be a Core issue,
+    see paragraph 6 for an example of awkward usage.  Hence, we move the
+    redefinition to the start of the subclause so we know how to read this text
+    from the start.
+
+commit 2981bd94f25ea2199fd6b8af7aa76e03cf427697
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Oct 19 08:31:08 2024 -0400
+
+    [basic.align] Move the Alignment subclause adjacent to "Object model"
+
+    Alignment puts additional restrictions on object placement.
+
+commit eac0893a9a90a5704deef6db3deecae026f04271
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Oct 2 14:59:41 2024 -0400
+
+    [except.terminate] Better describe the  function
+
+    While 'std:terminate' was originally conceived as the way to
+    report failures in the exception handling machinery, it has
+    evolved to become a more general tool for reporting unrecoverable
+    failures in the C++ runtime.  This rewording attempts to address
+    that evolving design, and in doing so addresses the outstanding
+    %FIXME% that the current text is not adequately descriptive in
+    the first place.
+
+commit f4c4c7cdfb7fba0a6ffbf8e55f2ea6debdf13e87
+Author: xmh0511 <970252187@qq.com>
+Date:   Wed Nov 20 08:17:02 2024 +0800
+
+    [dcl.link] Change "objects" to "entities"
+
+    "Entities" is more appropriate since it includes functions.
+
+commit 38461e17588aff3c6851de6ffc7f3e89418e0e65
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Nov 7 18:50:10 2024 +0800
+
+    [reverse.iter.cons] Removed redundant wording
+
+commit 8caa49a8266d7ef6b4ef3132588d154de07bbabd
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Mar 1 20:49:37 2024 +0100
+
+    [rand.req.seedseq] Remove 'compile-time' complexity for typedefs
+
+commit e2ddc7ab689bdaf91d2b2aa6424cef2510d3677a
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Mar 1 20:50:27 2024 +0100
+
+    [rand.req.dist] Remove 'compile-time' complexity for typedefs
+
+commit c9155b214a51d069cf4a575f10af2b4c4caca5d7
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Mar 1 20:52:39 2024 +0100
+
+    [char.traits.require] Remove 'compile-time' complexity for typedefs
+
+commit 2cd11c5503e78251c0c0fb4147e2d8ccb0947727
+Author: Vlad Serebrennikov <serebrennikov.vladislav@gmail.com>
+Date:   Tue Oct 8 15:30:13 2024 +0400
+
+    [temp.pre] Fix note about uniqueness of a template name in a scope
+
+commit 2edf50afeec8cf200504718646b2b12492dac8ec
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Oct 21 08:33:19 2024 -0400
+
+    [lex.header] Modernize text around header names
+
+    The footnote better belongs in the main text as a regular note.
+    To make the notes flow consistently, switch the order of the
+    note and normative text in the first paragraph to lead with the
+    normative text.
+
+commit 4a5d988a24f6c9737ca076e790b05e22ba169a7a
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Nov 22 12:55:43 2024 +0100
+
+    [refwrap.invoke] Place period at end (#7402)
+
+commit aed97568c63ad5c3c200eff34799413f3ad842f4
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Nov 23 07:53:16 2024 +0100
+
+    [lex.ccon, except.spec] Remove extraneous trailing linebreaks (#7403)
+
+commit 219b959258b6314a3c96bee86b8a18b0f4a7c37e
+Author: mrussoLuxoft <117848841+mrussoLuxoft@users.noreply.github.com>
+Date:   Sat Nov 30 19:36:56 2024 +0100
+
+    [dcl.spec.auto.general] Clarify sentence structure by adding bullets (#7450)
+
+commit 861071a824419b955c4efb2d07980e78c9fc62c7
+Author: Daniel Krügler <daniel.kruegler@gmail.com>
+Date:   Wed Dec 4 15:05:03 2024 +0100
+
+    [iterator.requirements.general] Revert `indirectly_writable` to "writable" definition (#7471)
+
+    This fixes a misapplication of the 2019 Belfast meeting LWG motion 9 (P1878R1), which erroneously replaced the "writable" definition by the `indirectly_writable` concept.
+
+commit c530fd8e0f80029e88b0977bebbf70252d38795e
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Fri Dec 6 21:52:45 2024 +0800
+
+    [text.encoding.overview] Add cross-reference text_encoding​::​aliases_view (#7476)
+
+commit 10668dceb8186d7990ff4966a6808bb20ba3eed7
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Dec 12 18:47:14 2024 +0000
+
+    [vector.overview,vector.bool.pspc] Move`at() const` to after `at()` (#7484)
+
+    This is consistent with the ordering for operator[].
+
+commit 0b1256638ebf4f1c611c3ca6182bad69be4837ce
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Dec 16 19:53:51 2024 +0100
+
+    [unique.ptr.single.general] Fix typo
+
+commit 76465d7e42f56f763901e3f6a79ae6d77162a510
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Dec 16 12:17:46 2024 +0100
+
+    [expr.type] Fix typo
+
+commit c7fbd5974f4b5e8881d1dc3e8fdf0b59ecba3bab
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Sun Dec 8 07:34:44 2024 +0800
+
+    [locale.ctype.virtuals] Fix a decade-old typo
+
+commit f9c835be8299556ae5943dbb340b4929a6100b15
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Dec 6 16:51:49 2024 +0100
+
+    [except.spec] Remove misleading restriction in list of examples
+
+commit e99e78d67b631fbb328770fbcd4882e683360cb1
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Dec 6 10:57:01 2024 +0100
+
+    [basic.pre,basic.lookup.general] Cleanup definition of term 'name lookup'
+
+commit 57ba5a5f4095ec3df6292cfdc371f554e8b684ef
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Dec 17 12:25:26 2024 -0500
+
+    [lex.phases] Reorder the first two sentences of phase 7 (#7432)
+
+    Currently, the first sentence refers to "tokens" that do not exist until after the second sentence.
+
+commit 55a58f9206e41a831c664747dbacebd25c01b034
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Tue Dec 17 19:34:54 2024 +0100
+
+    [class.conv.ctor] Turn last paragraph into a note (#6505)
+
+commit 3443cd8af21845e5a4fda6246c4c1bbc74cd007b
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Dec 17 19:18:25 2024 +0100
+
+    [exec.envs] Fix typo
+
+commit 14199aed5adb4baaef28245b4de88e7ffe73a365
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Dec 17 20:02:55 2024 +0100
+
+    [atomics.ref.int, atomics.ref.float] Minor \tcode fixes (#7499)
+
+commit daae8f9a9b959c099e99f248324af95bbaf11779
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Dec 18 03:09:10 2024 +0800
+
+    [flat.{map,multimap,set,multiset}] Exposition-only formatting (#6404)
+
+commit 7cbd07c13063b9730d51385198e13bb036d40377
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Dec 16 11:08:10 2024 +0100
+
+    [depr.meta.types] Remove superfluous period
+
+commit 7fe908fa11ad69138975bfec2cf376c66a536d08
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Dec 17 14:13:02 2024 -0500
+
+    [cpp] Distinguish "preprocessing token" from "token" (#7482)
+
+commit 9c9d19f6aef145cf2c074dcdd343e7a2446417a9
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Dec 6 17:37:05 2024 +0000
+
+    [sequence.reqmts] Remove unnecessary qualification of which new element
+
+    There is only one new element, and this avoids having to decide whether it should say args....
+
+ + diff --git a/papers/n5002.md b/papers/n5002.md new file mode 100644 index 0000000000..f5c5e576b1 --- /dev/null +++ b/papers/n5002.md @@ -0,0 +1,697 @@ +# N5002 Editors' Report -- Programming Languages -- C++ + +Date: 2024-12-17 + +Thomas Köppe (editor, Google DeepMind) +Jens Maurer (co-editor) +Dawn Perchik (co-editor, Bright Side Computing, LLC) +Richard Smith (co-editor, Google Inc) + +Email: `cxxeditor@gmail.com` + +## Acknowledgements + +Thanks to all those who have [submitted editorial +issues](https://github.com/cplusplus/draft/wiki/How-to-submit-an-editorial-issue) +and to those who have provided pull requests with fixes. +Special thanks to Andreas Krug for many timely editorial fixes. + +## New papers + + * [N5001](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n5001.pdf) is the + current working draft for C++26. It replaces + [N4993](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4993.pdf). + * N5002 is this Editors' Report. + + +## Motions incorporated into working draft + +### Notes on motions + +CWG Poll 9 was retracted. + +Two LWG Polls, Poll 5 (P0472R2) and Poll 17 (P3019R11) have not been applied and +are being sent back to WG21 for clarification. We expect to see revisions to be +approved at the next meeting: + +* LWG Poll 5 accidentally polled for the obsolete revision P0472R2 instead of the + intended P0472R3. It is sent back due to unclear intentions, with a request for + WG21 to clarify, and the expectation that R3 will be approved. + +* LWG Poll 17 caused technical discussion after the meeting, in which some + oversights were observed. The paper authors and the LWG chair agreed that + further LWG review would be in everybody's best interest. The poll is sent back + due to unclear specification, with a request for WG21 to produce a revision, + which we expect to be approved at the next meeting. + +In CWG Poll 1, issue CWG1965 contains no wording changes since it is subsumed by CWG2879. + +### Core working group polls +CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues in +[P3524R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3524r0.html) +(Core Language Working Group "ready" Issues for the November, 2024 meeting) to the C++ Working Paper. + +CWG Poll 2. Apply the changes in +[P3340R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3340r0.pdf) +(A Consistent Grammar for Sequences) to the C++ Working Paper. + +CWG Poll 3. Apply the changes in +[P2686R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2686r5.pdf) +(constexpr structured bindings and references to constexpr variables) to the C++ Working Paper. + +CWG Poll 4. Apply the changes in +[P3068R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3068r6.html) +(Allowing exception throwing in constant-evaluation) to the C++ Working Paper. + +CWG Poll 5. Apply the changes in +[P3247R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3247r2.html) +(Deprecate the notion of trivial types) to the C++ Working Paper. + +CWG Poll 6. Apply the changes in +[P2865R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2865r6.pdf) +(Remove Deprecated Array Comparisons from C++26) to the C++ Working Paper. + +CWG Poll 7. Apply the changes in +[P1061R10](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p1061r10.html) +(Structured Bindings can introduce a Pack) to the C++ Working Paper. + +CWG Poll 8. Apply the changes in +[P3176R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3176r1.html) +(The Oxford variadic comma) to the C++ Working Paper. + +CWG Poll 9 was retracted. + +### Library working group polls + +LWG Poll 1. Apply the changes for all Ready and Tentatively Ready issues in +[P3504R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3504r0.html) +(C++ Standard Library Ready Issues to be moved in Wrocław, Nov. 2024) to the C++ working paper. + +LWG Poll 2. Apply the changes in +[P3136R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3136r1.html) +(Retiring niebloids) to the C++ working paper. + +LWG Poll 3. Apply the changes in +[P3138R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3138r5.html) +(`views::cache_latest`) to the C++ working paper. + +LWG Poll 4. Apply the changes in +[P3379R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3379r0.html) +(Constrain `std::expected` equality operators) to the C++ working paper. + +LWG Poll 5 was sent back (see above). + +LWG Poll 6. Apply the changes in +[P2862R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2862r1.html) +(`text_encoding::name()` should never return null values) to the C++ working paper. + +LWG Poll 7. Apply the changes in +[P2897R7](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2897r7.html) +(`aligned_accessor`: An `mdspan` accessor expressing pointer over-alignment) to the C++ working paper. + +LWG Poll 8. Apply the changes in +[P3355R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3355r1.html) +(Fix `submdspan` for C++26) to the C++ working paper. + +LWG Poll 9. Apply the changes in +[P3222R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3222r0.html) +(Fix C++26 by adding transposed special cases for P2642 layouts) to the C++ working paper. + +LWG Poll 10. Apply the changes in +[P3050R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3050r2.html) +(Fix C++26 by optimizing `linalg::conjugated` for noncomplex value types) to the C++ working paper. + +LWG Poll 11. Apply the changes in +[P3396R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3396r1.html) +(`std::execution` wording fixes) to the C++ working paper. + +LWG Poll 12. Apply the changes in +[P2835R7](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2835r7.html) +(Expose `std::atomic_ref`'s object address) to the C++ working paper. + +LWG Poll 13. Apply the changes in +[P3323R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3323r1.html) +(cv-qualified types in `atomic` and `atomic_ref`) to the C++ working paper. + +LWG Poll 14. Apply the changes in +[P3508R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3508r0.html) +(Wording for "constexpr for specialized memory algorithms") and +[P3369R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3369r0.html) +(`constexpr` for `uninitialized_default_construct`) to the C++ working paper. + +LWG Poll 15. Apply the changes in +[P3370R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3370r1.html) +(Add new library headers from C23) to the C++ working paper. + +LWG Poll 16. Apply the changes in +[P3309R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3309r3.html) +(constexpr `atomic` and `atomic_ref`) to the C++ working paper. + +LWG Poll 17 was sent back (see above). + +LWG Poll 18. Apply the changes in +[P1928R15](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p1928r15.pdf) +(`std::simd` — merge data-parallel types from the Parallelism TS 2) to the C++ working paper. + +LWG Poll 19. Apply the changes in +[P3325R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3325r5.html) +(A Utility for Creating Execution Environments) to the C++ working paper. + +## Editorial changes + +### Major editorial changes + +There have not been any major editorial changes. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4993 is below. This +list excludes changes that do not affect the body text or only affect whitespace +or typeface. For a complete list including such changes (or for the actual +deltas applied by these changes), consult the +[draft sources on GitHub](https://github.com/cplusplus/draft/compare/n4993...n5001). + + commit e9604bcd3d8325860a4db9d02c4f90d0ae70162e + Author: Thomas Köppe + Date: Wed Oct 16 21:12:40 2024 +0100 + + [depr.format.syn] Fix header reference + + commit 0b296da823e7af4a987a0a870ae299420b9ae502 + Author: Thomas Köppe + Date: Thu Oct 17 00:39:04 2024 +0100 + + [{localization,re}.general] Change "This Clause" to "Subclause". + + These subclauses are no longer top-level clauses. + + commit 629e10e2f4177dd24d513be71f2203de325a7e8a + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Oct 17 08:57:39 2024 +0200 + + [inplace.vector.overview] Add missing ',' in comment + + commit 726e07a3a99a87f5e89dd40a064f4a6bc84ed3ce + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Oct 17 08:25:55 2024 +0200 + + [cpp.subst] Fix typo + + commit 88b2b8dcbd145782cfab61e6dad9296c9294593d + Author: Jens Maurer + Date: Wed Oct 16 22:58:07 2024 +0200 + + [exec.domain.default] Add missing \pnum + + commit 8698ea48e40acc2e18630e799bbb23c41b9344e6 + Author: James Touton + Date: Mon Sep 16 21:47:30 2024 -0700 + + [over.match.best.general] Minor formatting fixes + + commit 7ad39cbf374764a4e232f967e01541419230fedc + Author: Alisdair Meredith + Date: Thu Oct 17 11:16:28 2024 -0400 + + [lex.comment] Move the subclause earlier, to where it better fits + + Comments should fit betweem character sets (to define the basic source + character set) and preprocessor tokens, that must already understand + comments in order to treat them as whitespace. + + commit 7f7170cc9b96e9cc76bc0b765837978856936ab1 + Author: Alisdair Meredith + Date: Sat Oct 5 16:21:15 2024 -0400 + + [depr] Reorder clauses by origin of deprecation + + Reorders the deprecated features annex to follow the order + of the main clauses that the deprecates feature refers to. + Where multiple clauses are references, use the one named by + the [depr.XXX] stable label. + + commit cd21b72788d9066f79f31fb6c4516481dfbb4925 + Author: Hewill Kang + Date: Fri Oct 18 03:55:20 2024 +0800 + + [range.concat.iterator] Remove redundant \expos comments (#6942) + + commit 801fb2c0aaf6693a06a9a9e38871bae9536dc194 + Author: Alisdair Meredith + Date: Thu Oct 17 17:05:47 2024 -0400 + + [lex] Reorder subclauses to better follow phases of translation + + This PR purely moves existing words around, and does not create any new content. + + The proposed subclause ordering is now: + + * 5 Lexical convensions + - 5.1 Separate translation + - 5.2 Phases of translation + - 5.3 Characters + - 5.3.1 Character sets + - 5.3.2 Universal character names + - 5.4 Comments + - 5.5 Preprocessing tokens + - 5.6 Header names + - 5.7 Preprocessing numbers + - 5.8 Operators and punctuators + - 5.9 Alternative tokens + - 5.10 Tokens + - 5.11 Identifiers + - 5.12 Keywords + - 5.13 Literals + - 5.13.1 Kinds of literals + - 5.13.2 ... + + commit 49113a4a577b8d6aed7e5321f0c1fe68d0bd6480 + Author: Jens Maurer + Date: Fri Oct 18 08:28:28 2024 +0200 + + [library.general] Adjust library overview for recent clause restructuring + + commit a470ff890be232b9e2a15e44c406ef72c7d816c2 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Oct 19 11:31:59 2024 +0200 + + [lex.pptoken] Fix indefinitive article for consistency (#7324) + + commit 92594a81f021e76dce6acf7ea5d8176350a1e3fb + Author: Eelis van der Weegen + Date: Wed Mar 13 21:04:43 2019 +0100 + + [temp.deduct.call] Include surrounding code in math formula + + commit 0451d08aefd5318254d7d204ad45700aa4d5a2e7 + Author: A. Jiang + Date: Mon Oct 21 19:45:10 2024 +0800 + + [specialized.algorithms.general] Restore the note for potentially-overlapping objects and undefined behavior (#7326) + + The original note was incorrect and removed (see #6157). But it turns out + that _some_ note is still helpful. This PR tries to find the right way to + describe storage reusing and potential subsequent undefined behavior. + + commit f6b7ef3f1c6e483d97ad5a4f86b3efed38b74c99 + Author: Alisdair Meredith + Date: Sat Oct 19 11:41:35 2024 -0400 + + [lex.phases] Add crossreferences from phases 3 and 4 + + The phases of translation use forward references to the rest + of the standard well, but phases 3 and 4 almost entirely lack + such crossreferences, despite doing significant work in the + process of translating a file. + + commit a69507a54e67ae91424d9c621a9cb57ef3ba1512 + Author: Jens Maurer + Date: Mon Oct 21 17:48:09 2024 +0200 + + [locale.codecvt.virtuals] Fix garbled sentence + + commit e0576ed2411f36b0ba648afbf6953a0c72c9effb + Author: Alisdair Meredith + Date: Mon Oct 21 13:09:51 2024 -0400 + + [compliance] Sort the freestanding headers after clause reorganization + + commit b0135f256e40d45faf1d1ac2aaa3abbda36a17c3 + Author: timsong-cpp + Date: Tue Oct 22 02:14:47 2024 -0500 + + [exec.awaitables] Add missing word (#7340) + + commit eb9872aedc581e82e804c0fe8ca7d478ba066b17 + Author: Jan Schultke + Date: Tue Oct 22 12:09:22 2024 +0200 + + [func.wrap.func.con] Fix ill-formed postcondition (#7341) + + commit ced2c3866cb3d410c812fa3c359058d185aec329 + Author: Alisdair Meredith + Date: Wed Oct 23 13:47:18 2024 -0400 + + [allocator.requirements.general] Remove redundant template syntax (#5872) + + commit e70d9d6b901457cae9f4f596393f4bf7cee4591a + Author: Eisenwave + Date: Mon Oct 21 20:29:10 2024 +0200 + + [intro.races] Clarify conflicts for the case where no bits are changed + + commit 6ba0dc9b2bf4c3cebc51154e4d543eafb41a8064 + Author: Eisenwave + Date: Sun Aug 20 00:52:57 2023 +0200 + + [intro.memory] remove stray definitions + + commit 9dc7b3f30d2971ccb3bb38483a7cdb62065a2c3c + Author: Alisdair Meredith + Date: Tue Oct 22 17:12:25 2024 -0400 + + [basic.stc.inherit] Dissolve paragraph into [...general] + + The whole subclause [basic.stc.inherit] is a single sentence that + belongs adjacent to the material in [basic.std.general] that + specifies how entities acquire a storage duration, wheras all the + remaining subclauses below [basic.stc] describe specific storage + durations. Folding that sentence directly into the general clause + is even clearer. + + commit d5174d561b61304118cdf1042c5697ec6083c181 + Author: Jan Schultke + Date: Thu Oct 24 09:03:57 2024 +0200 + + [basic.link] Add commas between coordinate subclauses (#7342) + + commit 8ab0745b6099fd56288763e57ca47dee099db7cb + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Oct 25 10:53:22 2024 +0200 + + [bit.cast] change "behaviour" to "behavior" (#7353) + + commit 95d491ed6ca7817423855be4f90b61094a1b4312 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Oct 26 15:52:55 2024 +0200 + + [associative.reqmts.general] Fix punctuation (#7354) + + commit 3eb8c47d8f2fe050e221b5d4c36189d965273b37 + Author: Jan Schultke + Date: Sat Oct 26 16:00:12 2024 +0200 + + [basic.compound] Add comma to run-on sentence (#7348) + + commit 84af20dcd1976a8982d4418756d1ec9728306580 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sun Oct 27 13:27:34 2024 +0100 + + [mdspan.layout.left.cons] Remove duplicate "Effects:" (#7355) + + commit ac5b25027266917de3fbb220fc9ecfa4470672f9 + Author: Jan Schultke + Date: Sun Oct 27 22:46:10 2024 +0100 + + [expr.prim.lambda.capture, expr.const, ostream.formatted.print] Reword "automatic variable" (#7358) + + commit 324f56439e951773e6ce7437e703fb3aafd5a90c + Author: Alisdair Meredith + Date: Mon Oct 28 07:42:45 2024 -0400 + + [lex.pptoken] Reorder paragraphs to define terms before they are used (#7346) + + First move p1 below p2, so that we do not refer to preprocessing tokens before they are defined. + Then move p4 up, as it is splitting some unrelated examples, neither of which use its contents. + + commit bf43925ff0d9e80997918e98989892b4c7bf15f7 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Oct 29 11:52:02 2024 +0100 + + [mdspan.layout.left.cons] Fix typo (#7360) + + commit a42d1246936f6376acf6188c1b2053886cdaf3c2 + Author: Jan Schultke + Date: Sat Nov 2 14:38:54 2024 +0100 + + [lib.types.movedfrom] Add cross-reference to [defns.valid] (#7365) + + commit 6bfbb59e48b6bde05a78d257cbb943acdb2b6781 + Author: S. B. Tam + Date: Fri Apr 7 17:09:40 2023 +0800 + + [format.string.std] Replace "Derived Extracted Property" with simply "property" + + commit aa53618e39f16a6fbf147a8ac2d95a33cb8c5cbc + Author: S. B. Tam + Date: Fri Aug 9 17:39:07 2024 +0800 + + [lex.name] Strike "Derived Core Properties" + + commit cb15975d133869eb18a8b7878343a990e63415e2 + Author: Ilya Burylov + Date: Wed Nov 6 01:44:54 2024 -0800 + + [linalg.helpers.mandates] Fix typos (#7372) + + commit fcf95f0f1cb3ae11274f1c3477447aadb76b54ca + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Nov 6 13:27:56 2024 +0100 + + [exec.opstate.general] Fix typo (#7370) + + commit efa0bec63a2718967f7033217a757d536eba3c18 + Author: Jonathan Wakely + Date: Wed Nov 6 12:55:52 2024 +0000 + + [linalg.reqs.val] Fix use of \defnadjx for value types (#7374) + + commit 693835ad625acfdf2d610240b99d6d8fecdb8a6a + Author: Casey Carter + Date: Sat Nov 16 06:21:27 2024 -0800 + + [fs.op.remove] Clarify "Returns" element (#7387) + + To avoid confusion as in microsoft/STL#5088. + + commit 1788b3fcd8f3dbe7b31e6bbfbb968ad43d7ecec3 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Nov 17 20:05:57 2024 +0000 + + [over.ics.ref] Fix formatting of 'cv T' (#7389) + + commit 16df53c4ab9a17942f5bf994031c98105959a5d5 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Nov 18 17:37:02 2024 +0000 + + [defns.regex.primary.equivalence.class] Hyphenate 'locale-specific' (#7395) + + commit 4f0facdcd57b922510212ddf44ef39f46dcbe44d + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Nov 18 17:38:09 2024 +0000 + + [temp.param] Fix typos (#7394) + + commit 99deb7022614be47cfcce4f003d8eb57c02b6926 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Nov 19 05:21:45 2024 +0000 + + [over.ics.ref] Capitalize 'Exact Match' (#7392) + + commit fb8036b6dfe5ce4a99cd85fddac3f115a7fd96af + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Nov 19 05:25:41 2024 +0000 + + [class] Avoid hyphenation for 'multidimensional' (#7391) + + commit 3f41cf86547b77854abddde7dcaddf2ff00405bf + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Nov 19 05:26:53 2024 +0000 + + [lex.phases] Move cross-reference to the first use of the referenced term (#7393) + + commit a05b963e9fe12a8589502b4fbc951c119ae1b3b2 + Author: Alisdair Meredith + Date: Tue Jul 30 16:51:21 2024 -0400 + + [basic.life] Move definition of before and after from bottom to top of subclause + + The last paragraph of this subclause changes the definition of English words + used throughout the preceding paragraphs. While it might be preferable + to replace all such usage with the new definitions, that would be a Core issue, + see paragraph 6 for an example of awkward usage. Hence, we move the + redefinition to the start of the subclause so we know how to read this text + from the start. + + commit 2981bd94f25ea2199fd6b8af7aa76e03cf427697 + Author: Alisdair Meredith + Date: Sat Oct 19 08:31:08 2024 -0400 + + [basic.align] Move the Alignment subclause adjacent to "Object model" + + Alignment puts additional restrictions on object placement. + + commit eac0893a9a90a5704deef6db3deecae026f04271 + Author: Alisdair Meredith + Date: Wed Oct 2 14:59:41 2024 -0400 + + [except.terminate] Better describe the function + + While 'std:terminate' was originally conceived as the way to + report failures in the exception handling machinery, it has + evolved to become a more general tool for reporting unrecoverable + failures in the C++ runtime. This rewording attempts to address + that evolving design, and in doing so addresses the outstanding + %FIXME% that the current text is not adequately descriptive in + the first place. + + commit f4c4c7cdfb7fba0a6ffbf8e55f2ea6debdf13e87 + Author: xmh0511 <970252187@qq.com> + Date: Wed Nov 20 08:17:02 2024 +0800 + + [dcl.link] Change "objects" to "entities" + + "Entities" is more appropriate since it includes functions. + + commit 38461e17588aff3c6851de6ffc7f3e89418e0e65 + Author: A. Jiang + Date: Thu Nov 7 18:50:10 2024 +0800 + + [reverse.iter.cons] Removed redundant wording + + commit 8caa49a8266d7ef6b4ef3132588d154de07bbabd + Author: Eisenwave + Date: Fri Mar 1 20:49:37 2024 +0100 + + [rand.req.seedseq] Remove 'compile-time' complexity for typedefs + + commit e2ddc7ab689bdaf91d2b2aa6424cef2510d3677a + Author: Eisenwave + Date: Fri Mar 1 20:50:27 2024 +0100 + + [rand.req.dist] Remove 'compile-time' complexity for typedefs + + commit c9155b214a51d069cf4a575f10af2b4c4caca5d7 + Author: Eisenwave + Date: Fri Mar 1 20:52:39 2024 +0100 + + [char.traits.require] Remove 'compile-time' complexity for typedefs + + commit 2cd11c5503e78251c0c0fb4147e2d8ccb0947727 + Author: Vlad Serebrennikov + Date: Tue Oct 8 15:30:13 2024 +0400 + + [temp.pre] Fix note about uniqueness of a template name in a scope + + commit 2edf50afeec8cf200504718646b2b12492dac8ec + Author: Alisdair Meredith + Date: Mon Oct 21 08:33:19 2024 -0400 + + [lex.header] Modernize text around header names + + The footnote better belongs in the main text as a regular note. + To make the notes flow consistently, switch the order of the + note and normative text in the first paragraph to lead with the + normative text. + + commit 4a5d988a24f6c9737ca076e790b05e22ba169a7a + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Nov 22 12:55:43 2024 +0100 + + [refwrap.invoke] Place period at end (#7402) + + commit aed97568c63ad5c3c200eff34799413f3ad842f4 + Author: Alisdair Meredith + Date: Sat Nov 23 07:53:16 2024 +0100 + + [lex.ccon, except.spec] Remove extraneous trailing linebreaks (#7403) + + commit 219b959258b6314a3c96bee86b8a18b0f4a7c37e + Author: mrussoLuxoft <117848841+mrussoLuxoft@users.noreply.github.com> + Date: Sat Nov 30 19:36:56 2024 +0100 + + [dcl.spec.auto.general] Clarify sentence structure by adding bullets (#7450) + + commit 861071a824419b955c4efb2d07980e78c9fc62c7 + Author: Daniel Krügler + Date: Wed Dec 4 15:05:03 2024 +0100 + + [iterator.requirements.general] Revert `indirectly_writable` to "writable" definition (#7471) + + This fixes a misapplication of the 2019 Belfast meeting LWG motion 9 (P1878R1), which erroneously replaced the "writable" definition by the `indirectly_writable` concept. + + commit c530fd8e0f80029e88b0977bebbf70252d38795e + Author: Hewill Kang + Date: Fri Dec 6 21:52:45 2024 +0800 + + [text.encoding.overview] Add cross-reference text_encoding​::​aliases_view (#7476) + + commit 10668dceb8186d7990ff4966a6808bb20ba3eed7 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Dec 12 18:47:14 2024 +0000 + + [vector.overview,vector.bool.pspc] Move`at() const` to after `at()` (#7484) + + This is consistent with the ordering for operator[]. + + commit 0b1256638ebf4f1c611c3ca6182bad69be4837ce + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Dec 16 19:53:51 2024 +0100 + + [unique.ptr.single.general] Fix typo + + commit 76465d7e42f56f763901e3f6a79ae6d77162a510 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Dec 16 12:17:46 2024 +0100 + + [expr.type] Fix typo + + commit c7fbd5974f4b5e8881d1dc3e8fdf0b59ecba3bab + Author: S. B. Tam + Date: Sun Dec 8 07:34:44 2024 +0800 + + [locale.ctype.virtuals] Fix a decade-old typo + + commit f9c835be8299556ae5943dbb340b4929a6100b15 + Author: Jens Maurer + Date: Fri Dec 6 16:51:49 2024 +0100 + + [except.spec] Remove misleading restriction in list of examples + + commit e99e78d67b631fbb328770fbcd4882e683360cb1 + Author: Jens Maurer + Date: Fri Dec 6 10:57:01 2024 +0100 + + [basic.pre,basic.lookup.general] Cleanup definition of term 'name lookup' + + commit 57ba5a5f4095ec3df6292cfdc371f554e8b684ef + Author: Alisdair Meredith + Date: Tue Dec 17 12:25:26 2024 -0500 + + [lex.phases] Reorder the first two sentences of phase 7 (#7432) + + Currently, the first sentence refers to "tokens" that do not exist until after the second sentence. + + commit 55a58f9206e41a831c664747dbacebd25c01b034 + Author: Jan Schultke + Date: Tue Dec 17 19:34:54 2024 +0100 + + [class.conv.ctor] Turn last paragraph into a note (#6505) + + commit 3443cd8af21845e5a4fda6246c4c1bbc74cd007b + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Dec 17 19:18:25 2024 +0100 + + [exec.envs] Fix typo + + commit 14199aed5adb4baaef28245b4de88e7ffe73a365 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Dec 17 20:02:55 2024 +0100 + + [atomics.ref.int, atomics.ref.float] Minor \tcode fixes (#7499) + + commit daae8f9a9b959c099e99f248324af95bbaf11779 + Author: A. Jiang + Date: Wed Dec 18 03:09:10 2024 +0800 + + [flat.{map,multimap,set,multiset}] Exposition-only formatting (#6404) + + commit 7cbd07c13063b9730d51385198e13bb036d40377 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Dec 16 11:08:10 2024 +0100 + + [depr.meta.types] Remove superfluous period + + commit 7fe908fa11ad69138975bfec2cf376c66a536d08 + Author: Alisdair Meredith + Date: Tue Dec 17 14:13:02 2024 -0500 + + [cpp] Distinguish "preprocessing token" from "token" (#7482) + + commit 9c9d19f6aef145cf2c074dcdd343e7a2446417a9 + Author: Jonathan Wakely + Date: Fri Dec 6 17:37:05 2024 +0000 + + [sequence.reqmts] Remove unnecessary qualification of which new element + + There is only one new element, and this avoids having to decide whether it should say args.... diff --git a/papers/wd-index.md b/papers/wd-index.md index bf7c4b1679..8b21e73321 100644 --- a/papers/wd-index.md +++ b/papers/wd-index.md @@ -50,5 +50,6 @@ * [N4971](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4971.pdf) 2023-12 C++ Working Draft * [N4981](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4981.pdf) 2024-03 C++ Working Draft * [N4986](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4986.pdf) 2024-06 C++ Working Draft - * [N4986](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4988.pdf) 2024-08 C++ Working Draft - * [N4986](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4993.pdf) 2024-10 C++ Working Draft + * [N4988](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4988.pdf) 2024-08 C++ Working Draft + * [N4993](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4993.pdf) 2024-10 C++ Working Draft + * [N5001](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n5001.pdf) 2024-12 C++ Working Draft diff --git a/source/algorithms.tex b/source/algorithms.tex index a8c3809b34..19a139e7ef 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -38,28 +38,9 @@ satisfying the assumptions on the algorithms. \pnum -The entities defined in the \tcode{std::ranges} namespace in this Clause -are not found by argument-dependent name lookup\iref{basic.lookup.argdep}. -When found by unqualified\iref{basic.lookup.unqual} name lookup -for the \grammarterm{postfix-expression} in a function call\iref{expr.call}, -they inhibit argument-dependent name lookup. - -\begin{example} -\begin{codeblock} -void foo() { - using namespace std::ranges; - std::vector vec{1,2,3}; - find(begin(vec), end(vec), 2); // \#1 -} -\end{codeblock} -The function call expression at \tcode{\#1} invokes \tcode{std::ranges::find}, -not \tcode{std::find}, despite that -(a) the iterator type returned from \tcode{begin(vec)} and \tcode{end(vec)} -may be associated with namespace \tcode{std} and -(b) \tcode{std::find} is more specialized\iref{temp.func.order} than -\tcode{std::ranges::find} since the former requires -its first two parameters to have the same type. -\end{example} +The entities defined in the \tcode{std::ranges} namespace in this Clause and +specified as function templates are +algorithm function objects\iref{alg.func.obj}. \pnum For purposes of determining the existence of data races, @@ -11156,15 +11137,31 @@ are destroyed in an unspecified order before allowing the exception to propagate. +\pnum +\begin{note} +When new objects are created by +the algorithms specified in \ref{specialized.algorithms}, +the lifetime ends for any existing objects +(including potentially-overlapping subobjects \ref{intro.object}) +in storage that is reused \ref{basic.life}. +\end{note} + \pnum Some algorithms specified in \ref{specialized.algorithms} -make use of the exposition-only function template -\tcode{\placeholdernc{voidify}}: +make use of the following exposition-only function templates: \begin{codeblock} template constexpr void* @\placeholdernc{voidify}@(T& obj) noexcept { return addressof(obj); } + +template + decltype(auto) @\exposid{deref-move}@(I& it) { + if constexpr (is_lvalue_reference_v) + return std::move(*it); + else + return *it; + } \end{codeblock} \rSec2[special.mem.concepts]{Special memory concepts} @@ -11258,7 +11255,8 @@ \indexlibraryglobal{uninitialized_default_construct}% \begin{itemdecl} template - void uninitialized_default_construct(NoThrowForwardIterator first, NoThrowForwardIterator last); + constexpr void uninitialized_default_construct(NoThrowForwardIterator first, + NoThrowForwardIterator last); \end{itemdecl} \begin{itemdescr} @@ -11277,10 +11275,10 @@ namespace ranges { template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> requires @\libconcept{default_initializable}@> - I uninitialized_default_construct(I first, S last); + constexpr I uninitialized_default_construct(I first, S last); template<@\exposconcept{nothrow-forward-range}@ R> requires @\libconcept{default_initializable}@> - borrowed_iterator_t uninitialized_default_construct(R&& r); + constexpr borrowed_iterator_t uninitialized_default_construct(R&& r); } \end{itemdecl} @@ -11298,7 +11296,8 @@ \indexlibraryglobal{uninitialized_default_construct_n}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); + constexpr NoThrowForwardIterator + uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); \end{itemdecl} \begin{itemdescr} @@ -11318,7 +11317,7 @@ namespace ranges { template<@\exposconcept{nothrow-forward-iterator}@ I> requires @\libconcept{default_initializable}@> - I uninitialized_default_construct_n(I first, iter_difference_t n); + constexpr I uninitialized_default_construct_n(I first, iter_difference_t n); } \end{itemdecl} @@ -11337,7 +11336,8 @@ \indexlibraryglobal{uninitialized_value_construct}% \begin{itemdecl} template - void uninitialized_value_construct(NoThrowForwardIterator first, NoThrowForwardIterator last); + constexpr void uninitialized_value_construct(NoThrowForwardIterator first, + NoThrowForwardIterator last); \end{itemdecl} \begin{itemdescr} @@ -11356,10 +11356,10 @@ namespace ranges { template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> requires @\libconcept{default_initializable}@> - I uninitialized_value_construct(I first, S last); + constexpr I uninitialized_value_construct(I first, S last); template<@\exposconcept{nothrow-forward-range}@ R> requires @\libconcept{default_initializable}@> - borrowed_iterator_t uninitialized_value_construct(R&& r); + constexpr borrowed_iterator_t uninitialized_value_construct(R&& r); } \end{itemdecl} @@ -11377,7 +11377,8 @@ \indexlibraryglobal{uninitialized_value_construct_n}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); + constexpr NoThrowForwardIterator + uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); \end{itemdecl} \begin{itemdescr} @@ -11397,7 +11398,7 @@ namespace ranges { template<@\exposconcept{nothrow-forward-iterator}@ I> requires @\libconcept{default_initializable}@> - I uninitialized_value_construct_n(I first, iter_difference_t n); + constexpr I uninitialized_value_construct_n(I first, iter_difference_t n); } \end{itemdecl} @@ -11416,8 +11417,8 @@ \indexlibraryglobal{uninitialized_copy}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last, - NoThrowForwardIterator result); + constexpr NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last, + NoThrowForwardIterator result); \end{itemdecl} \begin{itemdescr} @@ -11445,11 +11446,11 @@ template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S1, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> requires @\libconcept{constructible_from}@, iter_reference_t> - uninitialized_copy_result + constexpr uninitialized_copy_result uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast); template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> requires @\libconcept{constructible_from}@, range_reference_t> - uninitialized_copy_result, borrowed_iterator_t> + constexpr uninitialized_copy_result, borrowed_iterator_t> uninitialized_copy(IR&& in_range, OR&& out_range); } \end{itemdecl} @@ -11472,8 +11473,8 @@ \indexlibraryglobal{uninitialized_copy_n}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, - NoThrowForwardIterator result); + constexpr NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, + NoThrowForwardIterator result); \end{itemdecl} \begin{itemdescr} @@ -11500,7 +11501,7 @@ namespace ranges { template<@\libconcept{input_iterator}@ I, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> requires @\libconcept{constructible_from}@, iter_reference_t> - uninitialized_copy_n_result + constexpr uninitialized_copy_n_result uninitialized_copy_n(I ifirst, iter_difference_t n, O ofirst, S olast); } \end{itemdecl} @@ -11526,8 +11527,8 @@ \indexlibraryglobal{uninitialized_move}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last, - NoThrowForwardIterator result); + constexpr NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last, + NoThrowForwardIterator result); \end{itemdecl} \begin{itemdescr} @@ -11541,7 +11542,7 @@ \begin{codeblock} for (; first != last; (void)++result, ++first) ::new (@\placeholdernc{voidify}@(*result)) - typename iterator_traits::value_type(std::move(*first)); + typename iterator_traits::value_type(@\exposid{deref-move}@(first)); return result; \end{codeblock} \end{itemdescr} @@ -11552,11 +11553,11 @@ template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S1, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> - uninitialized_move_result + constexpr uninitialized_move_result uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast); template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> requires @\libconcept{constructible_from}@, range_rvalue_reference_t> - uninitialized_move_result, borrowed_iterator_t> + constexpr uninitialized_move_result, borrowed_iterator_t> uninitialized_move(IR&& in_range, OR&& out_range); } \end{itemdecl} @@ -11586,7 +11587,7 @@ \indexlibraryglobal{uninitialized_move_n}% \begin{itemdecl} template - pair + constexpr pair uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result); \end{itemdecl} @@ -11601,7 +11602,7 @@ \begin{codeblock} for (; n > 0; ++result, (void) ++first, --n) ::new (@\placeholdernc{voidify}@(*result)) - typename iterator_traits::value_type(std::move(*first)); + typename iterator_traits::value_type(@\exposid{deref-move}@(first)); return {first, result}; \end{codeblock} \end{itemdescr} @@ -11611,7 +11612,7 @@ namespace ranges { template<@\libconcept{input_iterator}@ I, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> - uninitialized_move_n_result + constexpr uninitialized_move_n_result uninitialized_move_n(I ifirst, iter_difference_t n, O ofirst, S olast); } \end{itemdecl} @@ -11643,7 +11644,8 @@ \indexlibraryglobal{uninitialized_fill}% \begin{itemdecl} template - void uninitialized_fill(NoThrowForwardIterator first, NoThrowForwardIterator last, const T& x); + constexpr void uninitialized_fill(NoThrowForwardIterator first, + NoThrowForwardIterator last, const T& x); \end{itemdecl} \begin{itemdescr} @@ -11662,10 +11664,10 @@ namespace ranges { template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S, class T> requires @\libconcept{constructible_from}@, const T&> - I uninitialized_fill(I first, S last, const T& x); + constexpr I uninitialized_fill(I first, S last, const T& x); template<@\exposconcept{nothrow-forward-range}@ R, class T> requires @\libconcept{constructible_from}@, const T&> - borrowed_iterator_t uninitialized_fill(R&& r, const T& x); + constexpr borrowed_iterator_t uninitialized_fill(R&& r, const T& x); } \end{itemdecl} @@ -11683,7 +11685,8 @@ \indexlibraryglobal{uninitialized_fill_n}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); + constexpr NoThrowForwardIterator + uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); \end{itemdecl} \begin{itemdescr} @@ -11703,7 +11706,7 @@ namespace ranges { template<@\exposconcept{nothrow-forward-iterator}@ I, class T> requires @\libconcept{constructible_from}@, const T&> - I uninitialized_fill_n(I first, iter_difference_t n, const T& x); + constexpr I uninitialized_fill_n(I first, iter_difference_t n, const T& x); } \end{itemdecl} @@ -11732,14 +11735,22 @@ \begin{itemdescr} \pnum \constraints -The expression \tcode{::new (declval()) T(declval()...)} +\tcode{is_unbounded_array_v} is \tcode{false}. +The expression \tcode{::new (declval()) T(\linebreak{}declval()...)} is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand}. +\pnum +\mandates +If \tcode{is_array_v} is \tcode{true}, \tcode{sizeof...(Args)} is zero. + \pnum \effects Equivalent to: \begin{codeblock} -return ::new (@\placeholdernc{voidify}@(*location)) T(std::forward(args)...); +if constexpr (is_array_v) + return ::new (@\placeholdernc{voidify}@(*location)) T[1](); +else + return ::new (@\placeholdernc{voidify}@(*location)) T(std::forward(args)...); \end{codeblock} \end{itemdescr} @@ -11910,7 +11921,8 @@ \begin{itemdecl} template requires @\libconcept{output_range}@> && @\libconcept{invocable}@ && - @\libconcept{uniform_random_bit_generator}@> + @\libconcept{uniform_random_bit_generator}@> && + is_arithmetic_v> constexpr borrowed_iterator_t ranges::generate_random(R&& r, G&& g, D&& d); \end{itemdecl} @@ -11959,7 +11971,8 @@ \begin{itemdecl} template> O, @\libconcept{sentinel_for}@ S> - requires @\libconcept{invocable}@ && @\libconcept{uniform_random_bit_generator}@> + requires @\libconcept{invocable}@ && @\libconcept{uniform_random_bit_generator}@> && + is_arithmetic_v> constexpr O ranges::generate_random(O first, S last, G&& g, D&& d); \end{itemdecl} diff --git a/source/basic.tex b/source/basic.tex index 9524265f81..748f040876 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -103,11 +103,13 @@ or the \tcode{*\keyword{this}} object\iref{expr.prim.this}. \pnum -Some names denote types or templates. In general, -whenever a name is encountered it is necessary to determine whether that name denotes -one of these entities before continuing to parse the program that contains it. The -process that determines this is called -\defnx{name lookup}{lookup!name}\iref{basic.lookup}. +\begin{note} +Some names denote types or templates. +In general, whenever a name is encountered +it is necessary to look it up\iref{basic.lookup} +to determine whether that name denotes one of these entities +before continuing to parse the program that contains it. +\end{note} \pnum Two names are \defnx{the same}{name!same} if @@ -441,24 +443,59 @@ A variable is named by an expression if the expression is an \grammarterm{id-expression} that denotes it. A variable \tcode{x} that is named by a -potentially-evaluated expression $E$ -is \defnx{odr-used}{odr-use} by $E$ unless +potentially-evaluated expression $N$ +that appears at a point $P$ +is \defnx{odr-used}{odr-use} by $N$ unless \begin{itemize} \item - \tcode{x} is a reference that is - usable in constant expressions\iref{expr.const}, or +\tcode{x} is a reference +that is usable in constant expressions at $P$\iref{expr.const} or \item - \tcode{x} is a variable of non-reference type that is - usable in constant expressions and has no mutable subobjects, and - $E$ is an element of the set of potential results of an expression - of non-volatile-qualified non-class type - to which the lvalue-to-rvalue conversion\iref{conv.lval} is applied, or +$N$ is an element of the set of potential results of an expression $E$, where +\begin{itemize} \item - \tcode{x} is a variable of non-reference type, and - $E$ is an element of the set of potential results - of a discarded-value expression\iref{expr.context} - to which the lvalue-to-rvalue conversion is not applied. +$E$ is a discarded-value expression\iref{expr.context} +to which the lvalue-to-rvalue conversion is not applied or +\item +\tcode{x} is a non-volatile object +that is usable in constant expressions at $P$ and +has no mutable subobjects and +\begin{itemize} +\item +$E$ is a class member access expression\iref{expr.ref} +naming a non-static data member of reference type and +whose object expression has non-volatile-qualified type or +\item +the lvalue-to-rvalue conversion\iref{conv.lval} is applied to $E$ and +$E$ has non-volatile-qualified non-class type +\end{itemize} +\end{itemize} \end{itemize} +\begin{example} +\begin{codeblock} +int f(int); +int g(int&); +struct A { + int x; +}; +struct B { + int& r; +}; +int h(bool cond) { + constexpr A a = {1}; + constexpr const volatile A& r = a; // odr-uses \tcode{a} + int _ = f(cond ? a.x : r.x); // does not odr-use \tcode{a} or \tcode{r} + int x, y; + constexpr B b1 = {x}, b2 = {y}; // odr-uses \tcode{x} and \tcode{y} + int _ = g(cond ? b1.r : b2.r); // does not odr-use \tcode{b1} or \tcode{b2} + int _ = ((cond ? x : y), 0); // does not odr-use \tcode{x} or \tcode{y} + return [] { + return b1.r; // error: \tcode{b1} is odr-used here because the object + // referred to by \tcode{b1.r} is not constexpr-referenceable here + }(); +} +\end{codeblock} +\end{example} \pnum A structured binding is odr-used if it appears as a potentially-evaluated expression. @@ -511,7 +548,8 @@ either: \begin{itemize} \item the intervening scope is a block scope, or -\item the intervening scope is the function parameter scope of a \grammarterm{lambda-expression}, or +\item the intervening scope is the function parameter scope of +a \grammarterm{lambda-expression} or \grammarterm{requires-expression}, or \item the intervening scope is the lambda scope of a \grammarterm{lambda-expression} that has a \grammarterm{simple-capture} @@ -1483,13 +1521,13 @@ \indextext{scope!name lookup and|see{lookup, name}}% \pnum +\defnx{Name lookup}{lookup!name} associates the use of a name +with a set of declarations\iref{basic.def} of that name. The name lookup rules apply uniformly to all names (including \grammarterm{typedef-name}{s}\iref{dcl.typedef}, \grammarterm{namespace-name}{s}\iref{basic.namespace}, and \grammarterm{class-name}{s}\iref{class.name}) wherever the grammar allows -such names in the context discussed by a particular rule. Name lookup -associates the use of a name with a set of declarations\iref{basic.def} of -that name. +such names in the context discussed by a particular rule. Unless otherwise specified, the program is ill-formed if no declarations are found. If the declarations found by name lookup @@ -2714,8 +2752,8 @@ \pnum An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage. -The name of an entity that belongs to a namespace scope -that has not been given internal linkage above +The name of an entity that belongs to a namespace scope, +that has not been given internal linkage above, and that is the name of \begin{itemize} \item a variable; or @@ -3103,11 +3141,10 @@ The number of bits in a byte is reported by the macro \tcode{CHAR_BIT} in the header \libheaderref{climits}. \end{footnote} -the number of which is \impldef{bits in a byte}. The least -significant bit is called the \defn{low-order bit}; the most -significant bit is called the \defn{high-order bit}. The memory -available to a \Cpp{} program consists of one or more sequences of -contiguous bytes. Every byte has a unique address. +the number of which is \impldef{bits in a byte}. +The memory available to a \Cpp{} program consists of one or more sequences of +contiguous bytes. +Every byte has a unique address. \pnum \begin{note} @@ -3116,7 +3153,9 @@ \end{note} \pnum -A \defn{memory location} is either an object of scalar type that is not a bit-field +A \defn{memory location} is +the storage occupied by the object representation of +either an object of scalar type that is not a bit-field or a maximal sequence of adjacent bit-fields all having nonzero width. \begin{note} Various @@ -3454,8 +3493,106 @@ \end{note} \indextext{object model|)} +\rSec2[basic.align]{Alignment} + +\pnum +Object types have \defnx{alignment requirements}{alignment requirement!implementation-defined}\iref{basic.fundamental,basic.compound} +which place restrictions on the addresses at which an object of that type +may be allocated. An \defn{alignment} is an \impldef{alignment} +integer value representing the number of bytes between successive addresses +at which a given object can be allocated. An object type imposes an alignment +requirement on every object of that type; stricter alignment can be requested +using the alignment specifier\iref{dcl.align}. +Attempting to create an object\iref{intro.object} in storage that +does not meet the alignment requirements of the object's type +is undefined behavior. + +\pnum +A \defnadj{fundamental}{alignment} is represented by an alignment +less than or equal to the greatest alignment supported by the implementation in +all contexts, which is equal to +\tcode{\keyword{alignof}(std::max_align_t)}\iref{support.types}. +The alignment required for a type may be different when it is used as the type +of a complete object and when it is used as the type of a subobject. +\begin{example} +\begin{codeblock} +struct B { long double d; }; +struct D : virtual B { char c; }; +\end{codeblock} + +When \tcode{D} is the type of a complete object, it will have a subobject of +type \tcode{B}, so it must be aligned appropriately for a \tcode{\keyword{long} \keyword{double}}. +If \tcode{D} appears as a subobject of another object that also has \tcode{B} +as a virtual base class, the \tcode{B} subobject might be part of a different +subobject, reducing the alignment requirements on the \tcode{D} subobject. +\end{example} +The result of the \keyword{alignof} operator reflects the alignment +requirement of the type in the complete-object case. + +\pnum +An \defnadj{extended}{alignment} is represented by an alignment +greater than \tcode{\keyword{alignof}(std::max_align_t)}. It is \impldef{support for extended alignments} +whether any extended alignments are supported and the contexts in which they are +supported\iref{dcl.align}. A type having an extended alignment +requirement is an \defnadj{over-aligned}{type}. +\begin{note} +Every over-aligned type is or contains a class type +to which extended alignment applies (possibly through a non-static data member). +\end{note} +A \defnadj{new-extended}{alignment} is represented by +an alignment greater than \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\iref{cpp.predefined}. + +\pnum +Alignments are represented as values of the type \tcode{std::size_t}. +Valid alignments include only those values returned by an \keyword{alignof} +expression for the fundamental types plus an additional \impldef{alignment additional +values} +set of values, which may be empty. +Every alignment value shall be a non-negative integral power of two. + +\pnum +Alignments have an order from \defnx{weaker}{alignment!weaker} to +\defnx{stronger}{alignment!stronger} or \defnx{stricter}{alignment!stricter} alignments. Stricter +alignments have larger alignment values. An address that satisfies an alignment +requirement also satisfies any weaker valid alignment requirement. + +\pnum +The alignment requirement of a complete type can be queried using an +\keyword{alignof} expression\iref{expr.alignof}. Furthermore, +the narrow character types\iref{basic.fundamental} shall have the weakest +alignment requirement. +\begin{note} +This enables the ordinary character types to be used as the +underlying type for an aligned memory area\iref{dcl.align}. +\end{note} + +\pnum +Comparing alignments is meaningful and provides the obvious results: + +\begin{itemize} +\item Two alignments are equal when their numeric values are equal. +\item Two alignments are different when their numeric values are not equal. +\item When an alignment is larger than another it represents a stricter alignment. +\end{itemize} + +\pnum +\begin{note} +The runtime pointer alignment function\iref{ptr.align} +can be used to obtain an aligned pointer within a buffer; +an \grammarterm{alignment-specifier}\iref{dcl.align} +can be used to align storage explicitly. +\end{note} + +\pnum +If a request for a specific extended alignment in a specific context is not +supported by an implementation, the program is ill-formed. + \rSec2[basic.life]{Lifetime} +\pnum +In this subclause, ``before'' and ``after'' refer to the ``happens before'' +relation\iref{intro.multithread}. + \pnum \indextext{object lifetime|(}% The \defn{lifetime} of an object or reference is a runtime property of the @@ -3631,6 +3768,12 @@ \keyword{typeid}. \end{itemize} +\begin{note} +Therefore, undefined behavior results +if an object that is being constructed in one thread is referenced from another +thread without adequate synchronization. +\end{note} + \pnum An object $o_1$ is \defn{transparently replaceable} by an object $o_2$ if \begin{itemize} @@ -3741,15 +3884,6 @@ } \end{codeblock} \end{example} - -\pnum -In this subclause, ``before'' and ``after'' refer to the ``happens before'' -relation\iref{intro.multithread}. -\begin{note} -Therefore, undefined behavior results -if an object that is being constructed in one thread is referenced from another -thread without adequate synchronization. -\end{note} \indextext{object lifetime|)} \rSec2[basic.indet]{Indeterminate and erroneous values} @@ -3912,6 +4046,12 @@ \pnum The storage duration categories apply to references as well. +\pnum +\indextext{storage duration!class member}% +The storage duration of subobjects and reference members +is that of their complete object\iref{intro.object}. +\indextext{storage duration|)}% + \rSec3[basic.stc.static]{Static storage duration} \pnum @@ -4244,108 +4384,6 @@ deallocation function shall deallocate the storage referenced by the pointer, ending the duration of the region of storage. -\rSec3[basic.stc.inherit]{Duration of subobjects} - -\pnum -\indextext{storage duration!class member}% -The storage duration of subobjects and reference members -is that of their complete object\iref{intro.object}. -\indextext{storage duration|)}% - -\rSec2[basic.align]{Alignment} - -\pnum -Object types have \defnx{alignment requirements}{alignment requirement!implementation-defined}\iref{basic.fundamental,basic.compound} -which place restrictions on the addresses at which an object of that type -may be allocated. An \defn{alignment} is an \impldef{alignment} -integer value representing the number of bytes between successive addresses -at which a given object can be allocated. An object type imposes an alignment -requirement on every object of that type; stricter alignment can be requested -using the alignment specifier\iref{dcl.align}. -Attempting to create an object\iref{intro.object} in storage that -does not meet the alignment requirements of the object's type -is undefined behavior. - -\pnum -A \defnadj{fundamental}{alignment} is represented by an alignment -less than or equal to the greatest alignment supported by the implementation in -all contexts, which is equal to -\tcode{\keyword{alignof}(std::max_align_t)}\iref{support.types}. -The alignment required for a type may be different when it is used as the type -of a complete object and when it is used as the type of a subobject. -\begin{example} -\begin{codeblock} -struct B { long double d; }; -struct D : virtual B { char c; }; -\end{codeblock} - -When \tcode{D} is the type of a complete object, it will have a subobject of -type \tcode{B}, so it must be aligned appropriately for a \tcode{\keyword{long} \keyword{double}}. -If \tcode{D} appears as a subobject of another object that also has \tcode{B} -as a virtual base class, the \tcode{B} subobject might be part of a different -subobject, reducing the alignment requirements on the \tcode{D} subobject. -\end{example} -The result of the \keyword{alignof} operator reflects the alignment -requirement of the type in the complete-object case. - -\pnum -An \defnadj{extended}{alignment} is represented by an alignment -greater than \tcode{\keyword{alignof}(std::max_align_t)}. It is \impldef{support for extended alignments} -whether any extended alignments are supported and the contexts in which they are -supported\iref{dcl.align}. A type having an extended alignment -requirement is an \defnadj{over-aligned}{type}. -\begin{note} -Every over-aligned type is or contains a class type -to which extended alignment applies (possibly through a non-static data member). -\end{note} -A \defnadj{new-extended}{alignment} is represented by -an alignment greater than \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\iref{cpp.predefined}. - -\pnum -Alignments are represented as values of the type \tcode{std::size_t}. -Valid alignments include only those values returned by an \keyword{alignof} -expression for the fundamental types plus an additional \impldef{alignment additional -values} -set of values, which may be empty. -Every alignment value shall be a non-negative integral power of two. - -\pnum -Alignments have an order from \defnx{weaker}{alignment!weaker} to -\defnx{stronger}{alignment!stronger} or \defnx{stricter}{alignment!stricter} alignments. Stricter -alignments have larger alignment values. An address that satisfies an alignment -requirement also satisfies any weaker valid alignment requirement. - -\pnum -The alignment requirement of a complete type can be queried using an -\keyword{alignof} expression\iref{expr.alignof}. Furthermore, -the narrow character types\iref{basic.fundamental} shall have the weakest -alignment requirement. -\begin{note} -This enables the ordinary character types to be used as the -underlying type for an aligned memory area\iref{dcl.align}. -\end{note} - -\pnum -Comparing alignments is meaningful and provides the obvious results: - -\begin{itemize} -\item Two alignments are equal when their numeric values are equal. -\item Two alignments are different when their numeric values are not equal. -\item When an alignment is larger than another it represents a stricter alignment. -\end{itemize} - -\pnum -\begin{note} -The runtime pointer alignment function\iref{ptr.align} -can be used to obtain an aligned pointer within a buffer; -an \grammarterm{alignment-specifier}\iref{dcl.align} -can be used to align storage explicitly. -\end{note} - -\pnum -If a request for a specific extended alignment in a specific context is not -supported by an implementation, the program is ill-formed. - \rSec2[class.temporary]{Temporary objects} \pnum @@ -4923,11 +4961,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.trivial.type}% -Scalar types, trivial class types\iref{class.prop}, -arrays of such types, and cv-qualified versions of these -types are collectively called -\defnadjx{trivial}{types}{type}. \label{term.standard.layout.type}% Scalar types, standard-layout class types\iref{class.prop}, arrays of such types, and @@ -5499,7 +5532,7 @@ a pointer past the end of the last element of an array \tcode{x} of $n$ elements is considered to be equivalent to -a pointer to a hypothetical array element $n$ of \tcode{x} and +a pointer to a hypothetical array element $n$ of \tcode{x}, and an object of type \tcode{T} that is not an array element is considered to belong to an array with one element of type \tcode{T}. The value representation of @@ -5517,7 +5550,7 @@ A pointer value $P$ is \indextext{value!valid in the context of an evaluation}% \defn{valid in the context of} an evaluation $E$ -if $P$ is a null pointer value, or +if $P$ is a pointer to function or a null pointer value, or if it is a pointer to or past the end of an object $O$ and $E$ happens before the end of the duration of the region of storage for $O$. If a pointer value $P$ is used in an evaluation $E$ and @@ -6039,13 +6072,30 @@ \end{note} The value computations of the operands of an operator are sequenced before the value computation of the result of the -operator. If a +operator. +The behavior is undefined if +\begin{itemize} +\item \indextext{side effects}% -side effect on a memory location\iref{intro.memory} is unsequenced -relative to either another side effect on the same memory location or +a side effect on a memory location\iref{intro.memory} or +\item +starting or ending the lifetime of an object in a memory location +\end{itemize} +is unsequenced relative to +\begin{itemize} +\item +another side effect on the same memory location, +\item +starting or ending the lifetime of an object occupying storage that +overlaps with the memory location, or +\item a value computation using the value of any object in the same memory location, -and they are not potentially concurrent\iref{intro.multithread}, -the behavior is undefined. +\end{itemize} +and the two evaluations are not potentially concurrent\iref{intro.multithread}. +\begin{note} +Starting the lifetime of an object in a memory location can end the lifetime of +objects in other memory locations\iref{basic.life}. +\end{note} \begin{note} The next subclause imposes similar, but more complex restrictions on potentially concurrent computations. @@ -6059,6 +6109,9 @@ i = i++ + 1; // the value of \tcode{i} is incremented i = i++ + i; // undefined behavior i = i + 1; // the value of \tcode{i} is incremented + + union U { int x, y; } u; + (u.x = 1, 0) + (u.y = 2, 0); // undefined behavior } \end{codeblock} \end{example} @@ -6069,8 +6122,13 @@ the postfix expression designating the called function are sequenced before every expression or statement in the body of the called function. -For each function invocation or -evaluation of an \grammarterm{await-expression} \placeholder{F}, +For each +\begin{itemize} +\item function invocation, +\item evaluation of an \grammarterm{await-expression}\iref{expr.await}, or +\item evaluation of a \grammarterm{throw-expression}\iref{expr.throw} +\end{itemize} +\placeholder{F}, each evaluation that does not occur within \placeholder{F} but is evaluated on the same thread and as part of the same signal handler (if any) is either sequenced before all evaluations that occur within \placeholder{F} @@ -6169,9 +6227,25 @@ \end{note} \pnum -Two expression evaluations \defn{conflict} if one of them modifies a memory -location\iref{intro.memory} and the other one reads or modifies the same -memory location. +Two expression evaluations \defn{conflict} if one of them +\begin{itemize} +\item +modifies\iref{defns.access} a memory location\iref{intro.memory} or +\item +starts or ends the lifetime of an object in a memory location +\end{itemize} +and the other one +\begin{itemize} +\item +reads or modifies the same memory location or +\item +starts or ends the lifetime of an object occupying storage that +overlaps with the memory location. +\end{itemize} +\begin{note} +A modification can still conflict +even if it does not alter the value of any bits. +\end{note} \pnum The library defines a number of atomic operations\iref{atomics} and @@ -6884,7 +6958,7 @@ \pnum \indextext{initialization!constant}% \defnx{Constant initialization}{constant initialization} is performed -if a variable or temporary object with static or thread storage duration +if a variable with static or thread storage duration is constant-initialized\iref{expr.const}. \indextext{initialization!zero-initialization}% If constant initialization is not performed, a variable with static diff --git a/source/classes.tex b/source/classes.tex index d5d733168e..c534b96c0a 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -172,15 +172,6 @@ \item that has a trivial, non-deleted destructor\iref{class.dtor}. \end{itemize} -\pnum -A \defnadj{trivial}{class} is a class that is trivially copyable and -has one or more eligible default constructors\iref{class.default.ctor}, -all of which are trivial. -\begin{note} -In particular, a trivially copyable or trivial class does not have -virtual functions or virtual base classes. -\end{note} - \pnum A class \tcode{S} is a \defnadj{standard-layout}{class} if it: \begin{itemize} @@ -272,25 +263,25 @@ \pnum \begin{example} \begin{codeblock} -struct N { // neither trivial nor standard-layout +struct N { // neither trivially copyable nor standard-layout int i; int j; virtual ~N(); }; -struct T { // trivial but not standard-layout +struct T { // trivially copyable but not standard-layout int i; private: int j; }; -struct SL { // standard-layout but not trivial +struct SL { // standard-layout but not trivially copyable int i; int j; ~SL(); }; -struct POD { // both trivial and standard-layout +struct POD { // both trivially copyable and standard-layout int i; int j; }; @@ -492,8 +483,7 @@ \begin{bnf} \nontermdef{virt-specifier-seq}\br - virt-specifier\br - virt-specifier-seq virt-specifier + virt-specifier \opt{virt-specifier-seq} \end{bnf} \begin{bnf} @@ -1231,28 +1221,28 @@ of reference type, \item any non-variant non-static data member of const-qualified type -(or possibly multi-dimensional array thereof) +(or possibly multidimensional array thereof) with no \grammarterm{brace-or-equal-initializer} is not const-default-constructible\iref{dcl.init}, \item \tcode{X} is a union and all of its variant members are of const-qualified -type (or possibly multi-dimensional array thereof), +type (or possibly multidimensional array thereof), \item \tcode{X} is a non-union class and all members of any anonymous union member are -of const-qualified type (or possibly multi-dimensional array thereof), +of const-qualified type (or possibly multidimensional array thereof), \item any potentially constructed subobject, except for a non-static data member with a \grammarterm{brace-or-equal-initializer} or a variant member of a union where another non-static data member has a \grammarterm{brace-or-equal-initializer}, -has class type \tcode{M} (or possibly multi-dimensional array thereof) +has class type \tcode{M} (or possibly multidimensional array thereof) and overload resolution\iref{over.match} as applied to find \tcode{M}'s corresponding constructor either does not result in a usable candidate\iref{over.match.general} or, in the case of a variant member, selects a non-trivial function, or \item any potentially constructed subobject has -class type \tcode{M} (or possibly multi-dimensional array thereof) and +class type \tcode{M} (or possibly multidimensional array thereof) and \tcode{M} has a destructor that is deleted or inaccessible from the defaulted default constructor. @@ -1519,14 +1509,14 @@ \tcode{X} is defined as deleted\iref{dcl.fct.def.delete} if \tcode{X} has: \begin{itemize} \item a potentially constructed subobject of type - \tcode{M} (or possibly multi-dimensional array thereof) for which + \tcode{M} (or possibly multidimensional array thereof) for which overload resolution\iref{over.match}, as applied to find \tcode{M}'s corresponding constructor, either does not result in a usable candidate\iref{over.match.general} or, in the case of a variant member, selects a non-trivial function, \item any potentially constructed subobject of - class type \tcode{M} (or possibly multi-dimensional array thereof) + class type \tcode{M} (or possibly multidimensional array thereof) where \tcode{M} has a destructor that is deleted or inaccessible from the defaulted constructor, or, @@ -1789,12 +1779,12 @@ class \tcode{X} is defined as deleted if \tcode{X} has: \begin{itemize} \item a non-static data member of \keyword{const} non-class - type (or possibly multi-dimensional array thereof), or + type (or possibly multidimensional array thereof), or \item a non-static data member of reference type, or \item a direct non-static data member of class type \tcode{M} - (or possibly multi-dimensional array thereof) or + (or possibly multidimensional array thereof) or a direct base class \tcode{M} that cannot be copied/moved because overload resolution \iref{over.match}, as applied to find \tcode{M}'s corresponding @@ -2033,7 +2023,7 @@ \tcode{X} is defined as deleted if \begin{itemize} \item any potentially constructed subobject has class type - \tcode{M} (or possibly multi-dimensional array thereof) and + \tcode{M} (or possibly multidimensional array thereof) and \tcode{M} has a destructor that is deleted or is inaccessible from the defaulted destructor or, in the case of a variant member, is non-trivial, @@ -2378,11 +2368,10 @@ \end{note} \pnum -A non-explicit copy/move constructor\iref{class.copy.ctor} is -a converting constructor. \begin{note} -An implicitly-declared copy/move constructor is not an explicit constructor; -it can be called for implicit type conversions. +A non-explicit copy/move constructor\iref{class.copy.ctor}, +including one implicitly declared, +is a converting constructor. \end{note} \rSec3[class.conv.fct]{Conversion functions}% @@ -3331,13 +3320,13 @@ \pnum \indextext{nested class!local class}% -If class \tcode{X} is a local class, a nested class \tcode{Y} may be -declared in class \tcode{X} and later defined in the definition of class -\tcode{X} or be later defined in the same scope as the definition of -class \tcode{X}. \indextext{restriction!local class}% A class nested within a local class is a local class. +A member of a local class \tcode{X} shall be +declared only in the definition of \tcode{X} or, +if the member is a nested class, +in the nearest enclosing block scope of \tcode{X}. \pnum \indextext{restriction!static member local class}% @@ -5942,7 +5931,7 @@ B bobj; // definition of \tcode{bobj} extern X xobj; -int* p3 = &xobj.i; // OK, \tcode{X} is a trivial class +int* p3 = &xobj.i; // OK, all constructors of \tcode{X} are trivial X xobj; \end{codeblock} For another example, @@ -6178,25 +6167,26 @@ \indextext{constructor!copy!elision}% \indextext{constructor!move!elision}% When certain criteria are met, an implementation is -allowed to omit the copy/move construction of a class object, -even if the constructor selected for the copy/move operation and/or the +allowed to omit the creation of a class object from +a source object of the same type (ignoring cv-qualification), +even if the selected constructor and/or the destructor for the object have \indextext{side effects}% side effects. In such cases, the implementation treats the source and target of the -omitted copy/move operation as simply two different ways of +omitted initialization as simply two different ways of referring to the same object. If the first parameter of the selected constructor is an rvalue reference to the object's type, the destruction of that object occurs when the target would have been destroyed; otherwise, the destruction occurs at the later of the times when the two objects would have been destroyed without the optimization. -\begin{footnote} +\begin{note} Because only one object is destroyed instead of two, -and one copy/move constructor -is not executed, there is still one object destroyed for each one constructed. -\end{footnote} -This elision of copy/move operations, called +and the creation of one object is omitted, +there is still one object destroyed for each one constructed. +\end{note} +This elision of object creation, called \indexdefn{copy elision|see{constructor, copy, elision}}% \indexdefn{elision!copy|see{constructor, copy, elision}}% \indexdefn{constructor!copy!elision}\indexdefn{constructor!move!elision}\term{copy elision}, @@ -6204,34 +6194,35 @@ following circumstances (which may be combined to eliminate multiple copies): \begin{itemize} -\item in a \tcode{return} statement in a function with a class return type, +\item in a \tcode{return} statement\iref{stmt.return} in +a function with a class return type, when the \grammarterm{expression} is the name of a non-volatile -object with automatic storage duration (other than a function parameter or a variable +object $o$ with automatic storage duration (other than a function parameter or a variable introduced by the \grammarterm{exception-declaration} of a -\grammarterm{handler}\iref{except.handle}) -with the same type (ignoring cv-qualification) as -the function return type, the copy/move operation can be -omitted by constructing the object directly -into the function call's return object +\grammarterm{handler}\iref{except.handle}), +the copy-initialization of the result object can be +omitted by constructing $o$ directly +into the function call's result object; \item in a \grammarterm{throw-expression}\iref{expr.throw}, when the operand -is the name of a non-volatile object with automatic storage duration -(other than a function or catch-clause parameter) +is the name of a non-volatile object $o$ with automatic storage duration +(other than a function parameter or +a variable introduced by +the \grammarterm{exception-declaration} of a \grammarterm{handler}) that belongs to a scope that does not contain the innermost enclosing \grammarterm{compound-statement} associated with a \grammarterm{try-block} (if there is one), -the copy/move operation can be omitted by -constructing the object directly into the exception object +the copy-initialization of the exception object can be omitted by +constructing $o$ directly into the exception object; \item in a coroutine\iref{dcl.fct.def.coroutine}, a copy of a coroutine parameter can be omitted and references to that copy replaced with references to the corresponding parameter if the meaning of the program will be unchanged except for -the execution of a constructor and destructor for the parameter copy object +the execution of a constructor and destructor for the parameter copy object; \item when the \grammarterm{exception-declaration} of a -\grammarterm{handler}\iref{except.handle} declares an object of the same -type (except for cv-qualification) as the exception -object\iref{except.throw}, the copy operation can be omitted by treating +\grammarterm{handler}\iref{except.handle} declares an object $o$, +the copy-initialization of $o$ can be omitted by treating the \grammarterm{exception-declaration} as an alias for the exception object if the meaning of the program will be unchanged except for the execution of constructors and destructors for the object declared by the diff --git a/source/compatibility.tex b/source/compatibility.tex index 93baac8554..51ba5f6b24 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -33,6 +33,25 @@ \end{codeblock} \end{example} +\diffref{expr.rel,expr.eq} +\change +Comparing two objects of array type is no longer valid. +\rationale +The old behavior was confusing since it compared not the contents of the two +arrays, but their addresses. +\effect +A valid \CppXXIII{} program directly comparing two array objects is rejected as +ill-formed in this document. +\begin{example} +\begin{codeblock} +int arr1[5]; +int arr2[5]; +bool same = arr1 == arr2; // ill-formed; previously well-formed +bool idem = arr1 == +arr2; // compare addresses +bool less = arr1 < +arr2; // compare addresses, unspecified result +\end{codeblock} +\end{example} + \diffref{expr.delete} \change Calling \tcode{delete} on a pointer to an incomplete class is ill-formed. @@ -122,6 +141,38 @@ \end{codeblock} \end{example} +\diffref{temp.deduct.call} +\change +Template argument deduction from overload sets succeeds in more cases. +\rationale +Allow consideration of constraints to disambiguate overload sets +used as parameters in function calls. +\effect +Valid \CppXXIII{} code may become ill-formed. +\begin{example} +\begin{codeblock} +template +void f(T &&, void (*)(T &&)); + +void g(int &); // \#1 +inline namespace A { + void g(short &&); // \#2 +} +inline namespace B { + void g(short &&); // \#3 +} + +void q() { + int x; + f(x, g); // ill-formed; previously well-formed, deducing \tcode{T = int\&} +} +\end{codeblock} +There is no change to the applicable deduction rules for +the individual \tcode{g} candidates: +Type deduction from \#1 does not succeed; +type deductions from \#2 and \#3 both succeed. +\end{example} + \rSec2[diff.cpp23.library]{\ref{library}: library introduction} \diffref{headers} @@ -135,7 +186,8 @@ \libheaderrefx{hazard_pointer}{hazard.pointer.syn}, \libheaderrefx{inplace_vector}{inplace.vector.syn}, \libheaderref{linalg}, -\libheaderref{rcu}, and +\libheaderref{rcu}, +\libheaderref{simd}, and \libheaderrefx{text_encoding}{text.encoding.syn}. Valid \CppXXIII{} code that \tcode{\#include}{s} headers with these names may be invalid in this revision of \Cpp{}. @@ -2893,6 +2945,30 @@ \howwide Seldom. +\diffref{expr.rel,expr.eq} +\change +C allows directly comparing two objects of array type; \Cpp{} does not. +\rationale +The behavior is confusing because it compares not the contents of the two +arrays, but their addresses. +\effect +Deletion of semantically well-defined feature that had unspecified behavior +in common use cases. +\difficulty +Violations will be diagnosed by the \Cpp{} translator. The original behavior +can be replicated by explicitly casting either array to a pointer, such as by +using a unary \tcode{+}. +\begin{example} +\begin{codeblock} +int arr1[5]; +int arr2[5]; +int same = arr1 == arr2; // valid C, ill-formed C++ +int idem = arr1 == +arr2; // valid in both C and C++ +\end{codeblock} +\end{example} +\howwide +Rare. + \diffref{expr.cond,expr.ass,expr.comma} \indextext{conversion!lvalue-to-rvalue}% \indextext{rvalue!lvalue conversion to}% diff --git a/source/config.tex b/source/config.tex index 8253638e61..c67f5c5823 100644 --- a/source/config.tex +++ b/source/config.tex @@ -1,13 +1,16 @@ %!TEX root = std.tex %%-------------------------------------------------- %% Version numbers -\newcommand{\docno}{N4993} -\newcommand{\prevdocno}{N4988} +\newcommand{\docno}{N5001} +\newcommand{\prevdocno}{N4993} \newcommand{\cppver}{202302L} %% Release date \newcommand{\reldate}{\today} +%% Core chapters +\newcommand{\lastcorechapter}{cpp} + %% Library chapters \newcommand{\firstlibchapter}{support} \newcommand{\lastlibchapter}{exec} diff --git a/source/containers.tex b/source/containers.tex index f43cc92f3b..c7cc854452 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -1463,7 +1463,7 @@ \pnum \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. -For \tcode{vector} and \tcode{deque}, +For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque}, \tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X} and \oldconcept{MoveAssignable}. @@ -1478,8 +1478,7 @@ \pnum \returns -An iterator that points to -the new element constructed from \tcode{args} into \tcode{a}. +An iterator that points to the new element. \end{itemdescr} \indexcont{insert}% @@ -3873,7 +3872,7 @@ \pnum \complexity -Logarithmic, +Logarithmic. \end{itemdescr} \indexordmem{upper_bound}% @@ -7200,10 +7199,13 @@ \rSec3[forward.list.modifiers]{Modifiers} \pnum -None of the overloads of \tcode{insert_after} shall affect the validity of iterators and -references, and \tcode{erase_after} shall invalidate only iterators and references to -the erased elements. If an exception is thrown during \tcode{insert_after} there shall -be no effect. Inserting \tcode{n} elements into a \tcode{forward_list} is linear in +The member functions in this subclause +do not affect the validity of iterators and references +when inserting elements, and when erasing elements +invalidate iterators and references to the erased elements only. +If an exception is thrown by any of these member functions +there is no effect on the container. +Inserting \tcode{n} elements into a \tcode{forward_list} is linear in \tcode{n}, and the number of calls to the copy or move constructor of \tcode{T} is exactly equal to \tcode{n}. Erasing \tcode{n} elements from a \tcode{forward_list} is linear in \tcode{n} and the number of calls to the destructor of type \tcode{T} is @@ -7780,7 +7782,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return erase_if(c, [\&](auto\& elem) \{ return elem == value; \});} +Equivalent to: \tcode{return erase_if(c, [\&](const auto\& elem) -> bool \{ return elem == value; \});} \end{itemdescr} \indexlibrarymember{erase_if}{forward_list}% @@ -8215,7 +8217,6 @@ \begin{itemdecl} iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last); - void pop_front(); void pop_back(); void clear() noexcept; @@ -8565,7 +8566,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return erase_if(c, [\&](auto\& elem) \{ return elem == value; \});} +Equivalent to: \tcode{return erase_if(c, [\&](const auto\& elem) -> bool \{ return elem == value; \});} \end{itemdescr} \indexlibrarymember{erase_if}{list}% @@ -8741,8 +8742,8 @@ // element access constexpr reference operator[](size_type n); constexpr const_reference operator[](size_type n) const; - constexpr const_reference at(size_type n) const; constexpr reference at(size_type n); + constexpr const_reference at(size_type n) const; constexpr reference front(); constexpr const_reference front() const; constexpr reference back(); @@ -9256,8 +9257,6 @@ // bit reference class @\libmember{reference}{vector}@ { - constexpr reference() noexcept; - public: constexpr reference(const reference&) = default; constexpr ~reference(); @@ -9323,8 +9322,8 @@ // element access constexpr reference operator[](size_type n); constexpr const_reference operator[](size_type n) const; - constexpr const_reference at(size_type n) const; constexpr reference at(size_type n); + constexpr const_reference at(size_type n) const; constexpr reference front(); constexpr const_reference front() const; constexpr reference back(); @@ -9537,8 +9536,9 @@ \pnum For any $\tcode{N} > 0$, -if \tcode{is_trivial_v} is \tcode{false}, then -no \tcode{inplace_vector} member functions +if \tcode{T} is not trivially copyable or +\tcode{is_trivially_default_constructible_v} is \tcode{false}, +then no \tcode{inplace_vector} member functions are usable in constant expressions. \pnum @@ -9638,7 +9638,7 @@ constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; - // \ref{inplace.vector.capacity} size/capacity + // \ref{inplace.vector.capacity}, size/capacity constexpr bool empty() const noexcept; constexpr size_type size() const noexcept; static constexpr size_type max_size() noexcept; @@ -15857,12 +15857,12 @@ class value_compare { private: - key_compare comp; // \expos - value_compare(key_compare c) : comp(c) { } // \expos + key_compare @\exposid{comp}@; // \expos + value_compare(key_compare c) : @\exposid{comp}@(c) { } // \expos public: bool operator()(const_reference x, const_reference y) const { - return comp(x.first, y.first); + return @\exposid{comp}@(x.first, y.first); } }; @@ -15875,7 +15875,7 @@ flat_map() : flat_map(key_compare()) { } explicit flat_map(const key_compare& comp) - : c(), compare(comp) { } + : @\exposid{c}@(), @\exposid{compare}@(comp) { } flat_map(key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare()); @@ -15885,12 +15885,12 @@ template flat_map(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) - : c(), compare(comp) { insert(first, last); } + : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(first, last); } template flat_map(sorted_unique_t s, InputIterator first, InputIterator last, const key_compare& comp = key_compare()) - : c(), compare(comp) { insert(s, first, last); } + : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(s, first, last); } template<@\exposconcept{container-compatible-range}@ R> flat_map(from_range_t fr, R&& rg) @@ -16055,8 +16055,8 @@ key_compare key_comp() const; value_compare value_comp() const; - const key_container_type& keys() const noexcept { return c.keys; } - const mapped_container_type& values() const noexcept { return c.values; } + const key_container_type& keys() const noexcept { return @\exposid{c}@.keys; } + const mapped_container_type& values() const noexcept { return @\exposid{c}@.values; } // map operations iterator find(const key_type& x); @@ -16094,11 +16094,11 @@ { x.swap(y); } private: - containers c; // \expos - key_compare compare; // \expos + containers @\exposid{c}@; // \expos + key_compare @\exposid{compare}@; // \expos - struct key_equiv { // \expos - key_equiv(key_compare c) : comp(c) { } + struct @\exposid{key-equiv}@ { // \expos + @\exposid{key-equiv}@(key_compare c) : comp(c) { } bool operator()(const_reference x, const_reference y) const { return !comp(x.first, y.first) && !comp(y.first, x.first); } @@ -16190,17 +16190,17 @@ \pnum \effects Initializes -\tcode{c.keys} with \tcode{std::move(key_cont)}, -\tcode{c.values} with \tcode{std::move(mapped_cont)}, and -\tcode{compare} with \tcode{comp}; +\tcode{\exposid{c}.keys} with \tcode{std::move(key_cont)}, +\tcode{\exposid{c}.values} with \tcode{std::move(mapped_cont)}, and +\exposid{compare} with \tcode{comp}; sorts the range \range{begin()}{end()} with respect to \tcode{value_comp()}; and finally erases the duplicate elements as if by: \begin{codeblock} -auto zv = views::zip(c.keys, c.values); -auto it = ranges::unique(zv, key_equiv(compare)).begin(); +auto zv = views::zip(@\exposid{c}@.keys, @\exposid{c}@.values); +auto it = ranges::unique(zv, @\exposid{key-equiv}@(@\exposid{compare}@)).begin(); auto dist = distance(zv.begin(), it); -c.keys.erase(c.keys.begin() + dist, c.keys.end()); -c.values.erase(c.values.begin() + dist, c.values.end()); +@\exposid{c}@.keys.erase(@\exposid{c}@.keys.begin() + dist, @\exposid{c}@.keys.end()); +@\exposid{c}@.values.erase(@\exposid{c}@.values.begin() + dist, @\exposid{c}@.values.end()); \end{codeblock} \pnum @@ -16220,9 +16220,9 @@ \pnum \effects Initializes -\tcode{c.keys} with \tcode{std::move(key_cont)}, -\tcode{c.values} with \tcode{std::move(mapped_cont)}, and -\tcode{compare} with \tcode{comp}. +\tcode{\exposid{c}.keys} with \tcode{std::move(key_cont)}, +\tcode{\exposid{c}.values} with \tcode{std::move(mapped_cont)}, and +\exposid{compare} with \tcode{comp}. \pnum \complexity @@ -16251,7 +16251,7 @@ \effects Equivalent to \tcode{flat_map(key_cont, mapped_cont)} and \tcode{flat_map(key_cont, mapped_cont, comp)}, respectively, -except that \tcode{c.keys} and \tcode{c.values} are constructed with +except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed with uses-allocator construction\iref{allocator.uses.construction}. \pnum @@ -16276,7 +16276,7 @@ \effects Equivalent to \tcode{flat_map(s, key_cont, mapped_cont)} and \tcode{flat_map(s, key_cont, \linebreak{}mapped_cont, comp)}, respectively, -except that \tcode{c.keys} and \tcode{c.values} are constructed +except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed with uses-allocator construction\iref{allocator.uses.construction}. \pnum @@ -16322,7 +16322,7 @@ \pnum \effects Equivalent to the corresponding non-allocator constructors -except that \tcode{c.keys} and \tcode{c.values} are constructed +except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed with uses-allocator construction\iref{allocator.uses.construction}. \end{itemdescr} @@ -16336,7 +16336,7 @@ \begin{itemdescr} \pnum \returns -\tcode{c.keys.size()}. +\tcode{\exposid{c}.keys.size()}. \end{itemdescr} \indexlibrarymember{max_size}{flat_map}% @@ -16347,7 +16347,7 @@ \begin{itemdescr} \pnum \returns -\tcode{min(c.keys.max_size(), c.values.max_size())}. +\tcode{min(\exposid{c}.keys.max_size(), \exposid{c}.values.max_size())}. \end{itemdescr} \rSec3[flat.map.access]{Access} @@ -16464,10 +16464,10 @@ \tcode{*this} is unchanged. Otherwise, equivalent to: \begin{codeblock} -auto key_it = ranges::upper_bound(c.keys, t.first, compare); -auto value_it = c.values.begin() + distance(c.keys.begin(), key_it); -c.keys.insert(key_it, std::move(t.first)); -c.values.insert(value_it, std::move(t.second)); +auto key_it = ranges::upper_bound(@\exposid{c}@.keys, t.first, @\exposid{compare}@); +auto value_it = @\exposid{c}@.values.begin() + distance(@\exposid{c}@.keys.begin(), key_it); +@\exposid{c}@.keys.insert(key_it, std::move(t.first)); +@\exposid{c}@.values.insert(value_it, std::move(t.second)); \end{codeblock} \pnum @@ -16505,12 +16505,12 @@ \begin{itemdescr} \pnum \effects -Adds elements to \tcode{c} as if by: +Adds elements to \exposid{c} as if by: \begin{codeblock} for (; first != last; ++first) { value_type value = *first; - c.keys.insert(c.keys.end(), std::move(value.first)); - c.values.insert(c.values.end(), std::move(value.second)); + @\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), std::move(value.first)); + @\exposid{c}@.values.insert(@\exposid{c}@.values.end(), std::move(value.second)); } \end{codeblock} Then, sorts the range of newly inserted elements @@ -16519,11 +16519,11 @@ the sorted range of pre-existing elements into a single sorted range; and finally erases the duplicate elements as if by: \begin{codeblock} -auto zv = views::zip(c.keys, c.values); -auto it = ranges::unique(zv, key_equiv(compare)).begin(); +auto zv = views::zip(@\exposid{c}@.keys, @\exposid{c}@.values); +auto it = ranges::unique(zv, @\exposid{key-equiv}@(@\exposid{compare}@)).begin(); auto dist = distance(zv.begin(), it); -c.keys.erase(c.keys.begin() + dist, c.keys.end()); -c.values.erase(c.values.begin() + dist, c.values.end()); +@\exposid{c}@.keys.erase(@\exposid{c}@.keys.begin() + dist, @\exposid{c}@.keys.end()); +@\exposid{c}@.values.erase(@\exposid{c}@.values.begin() + dist, @\exposid{c}@.values.end()); \end{codeblock} \pnum @@ -16546,23 +16546,23 @@ \begin{itemdescr} \pnum \effects -Adds elements to \tcode{c} as if by: +Adds elements to \exposid{c} as if by: \begin{codeblock} for (; first != last; ++first) { value_type value = *first; - c.keys.insert(c.keys.end(), std::move(value.first)); - c.values.insert(c.values.end(), std::move(value.second)); + @\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), std::move(value.first)); + @\exposid{c}@.values.insert(@\exposid{c}@.values.end(), std::move(value.second)); } \end{codeblock} Then, merges the sorted range of newly added elements and the sorted range of pre-existing elements into a single sorted range; and finally erases the duplicate elements as if by: \begin{codeblock} -auto zv = views::zip(c.keys, c.values); -auto it = ranges::unique(zv, key_equiv(compare)).begin(); +auto zv = views::zip(@\exposid{c}@.keys, @\exposid{c}@.values); +auto it = ranges::unique(zv, @\exposid{key-equiv}@(@\exposid{compare}@)).begin(); auto dist = distance(zv.begin(), it); -c.keys.erase(c.keys.begin() + dist, c.keys.end()); -c.values.erase(c.values.begin() + dist, c.values.end()); +@\exposid{c}@.keys.erase(@\exposid{c}@.keys.begin() + dist, @\exposid{c}@.keys.end()); +@\exposid{c}@.values.erase(@\exposid{c}@.values.begin() + dist, @\exposid{c}@.values.end()); \end{codeblock} \pnum @@ -16583,11 +16583,11 @@ \begin{itemdescr} \pnum \effects -Adds elements to \tcode{c} as if by: +Adds elements to \exposid{c} as if by: \begin{codeblock} for (const auto& e : rg) { - c.keys.insert(c.keys.end(), e.first); - c.values.insert(c.values.end(), e.second); + @\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), e.first); + @\exposid{c}@.values.insert(@\exposid{c}@.values.end(), e.second); } \end{codeblock} Then, sorts the range of newly inserted elements @@ -16596,11 +16596,11 @@ the sorted range of pre-existing elements into a single sorted range; and finally erases the duplicate elements as if by: \begin{codeblock} -auto zv = views::zip(c.keys, c.values); -auto it = ranges::unique(zv, key_equiv(compare)).begin(); +auto zv = views::zip(@\exposid{c}@.keys, @\exposid{c}@.values); +auto it = ranges::unique(zv, @\exposid{key-equiv}@(@\exposid{compare}@)).begin(); auto dist = distance(zv.begin(), it); -c.keys.erase(c.keys.begin() + dist, c.keys.end()); -c.values.erase(c.values.begin() + dist, c.values.end()); +@\exposid{c}@.keys.erase(@\exposid{c}@.keys.begin() + dist, @\exposid{c}@.keys.end()); +@\exposid{c}@.values.erase(@\exposid{c}@.values.begin() + dist, @\exposid{c}@.values.end()); \end{codeblock} \pnum @@ -16637,10 +16637,10 @@ \tcode{*this} and \tcode{args...} are unchanged. Otherwise equivalent to: \begin{codeblock} -auto key_it = ranges::upper_bound(c.keys, k, compare); -auto value_it = c.values.begin() + distance(c.keys.begin(), key_it); -c.keys.insert(key_it, std::forward(k)); -c.values.emplace(value_it, std::forward(args)...); +auto key_it = ranges::upper_bound(@\exposid{c}@.keys, k, @\exposid{compare}@); +auto value_it = @\exposid{c}@.values.begin() + distance(@\exposid{c}@.keys.begin(), key_it); +@\exposid{c}@.keys.insert(key_it, std::forward(k)); +@\exposid{c}@.values.emplace(value_it, std::forward(args)...); \end{codeblock} \pnum @@ -16694,10 +16694,10 @@ \tcode{*this} and \tcode{args...} are unchanged. Otherwise equivalent to: \begin{codeblock} -auto key_it = ranges::upper_bound(c.keys, k, compare); -auto value_it = c.values.begin() + distance(c.keys.begin(), key_it); -c.keys.emplace(key_it, std::forward(k)); -c.values.emplace(value_it, std::forward(args)...); +auto key_it = ranges::upper_bound(@\exposid{c}@.keys, k, @\exposid{compare}@); +auto value_it = @\exposid{c}@.values.begin() + distance(@\exposid{c}@.keys.begin(), key_it); +@\exposid{c}@.keys.emplace(key_it, std::forward(k)); +@\exposid{c}@.values.emplace(value_it, std::forward(args)...); \end{codeblock} \pnum @@ -16824,9 +16824,9 @@ \effects Equivalent to: \begin{codeblock} -ranges::swap(compare, y.compare); -ranges::swap(c.keys, y.c.keys); -ranges::swap(c.values, y.c.values); +ranges::swap(@\exposid{compare}@, y.@\exposid{compare}@); +ranges::swap(@\exposid{c}@.keys, y.@\exposid{c}@.keys); +ranges::swap(@\exposid{c}@.values, y.@\exposid{c}@.values); \end{codeblock} \end{itemdescr} @@ -16842,7 +16842,7 @@ \pnum \returns -\tcode{std::move(c)}. +\tcode{std::move(\exposid{c})}. \end{itemdescr} \indexlibrarymember{replace}{flat_map}% @@ -16854,15 +16854,15 @@ \pnum \expects \tcode{key_cont.size() == mapped_cont.size()} is \tcode{true}, -the elements of \tcode{key_cont} are sorted with respect to \tcode{compare}, and +the elements of \tcode{key_cont} are sorted with respect to \exposid{compare}, and \tcode{key_cont} contains no equal elements. \pnum \effects Equivalent to: \begin{codeblock} -c.keys = std::move(key_cont); -c.values = std::move(mapped_cont); +@\exposid{c}@.keys = std::move(key_cont); +@\exposid{c}@.values = std::move(mapped_cont); \end{codeblock} \end{itemdescr} @@ -17040,12 +17040,12 @@ class value_compare { private: - key_compare comp; // \expos - value_compare(key_compare c) : comp(c) { } // \expos + key_compare @\exposid{comp}@; // \expos + value_compare(key_compare c) : @\exposid{comp}@(c) { } // \expos public: bool operator()(const_reference x, const_reference y) const { - return comp(x.first, y.first); + return @\exposid{comp}@(x.first, y.first); } }; @@ -17058,7 +17058,7 @@ flat_multimap() : flat_multimap(key_compare()) { } explicit flat_multimap(const key_compare& comp) - : c(), compare(comp) { } + : @\exposid{c}@(), @\exposid{compare}@(comp) { } flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare()); @@ -17070,13 +17070,13 @@ template flat_multimap(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) - : c(), compare(comp) + : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(first, last); } template flat_multimap(sorted_equivalent_t s, InputIterator first, InputIterator last, const key_compare& comp = key_compare()) - : c(), compare(comp) { insert(s, first, last); } + : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(s, first, last); } template<@\exposconcept{container-compatible-range}@ R> flat_multimap(from_range_t fr, R&& rg) @@ -17209,8 +17209,8 @@ key_compare key_comp() const; value_compare value_comp() const; - const key_container_type& keys() const noexcept { return c.keys; } - const mapped_container_type& values() const noexcept { return c.values; } + const key_container_type& keys() const noexcept { return @\exposid{c}@.keys; } + const mapped_container_type& values() const noexcept { return @\exposid{c}@.values; } // map operations iterator find(const key_type& x); @@ -17250,8 +17250,8 @@ { x.swap(y); } private: - containers c; // \expos - key_compare compare; // \expos + containers @\exposid{c}@; // \expos + key_compare @\exposid{compare}@; // \expos }; template(args)...}, then inserts \tcode{t} as if by: \begin{codeblock} -auto it = ranges::upper_bound(c, t, compare); -c.insert(it, std::move(t)); +auto it = ranges::upper_bound(@\exposid{c}@, t, @\exposid{compare}@); +@\exposid{c}@.insert(it, std::move(t)); \end{codeblock} \pnum @@ -18715,7 +18715,7 @@ \effects Adds elements to \exposid{c} as if by: \begin{codeblock} -c.insert(c.end(), first, last); +@\exposid{c}@.insert(@\exposid{c}@.end(), first, last); \end{codeblock} Then, sorts the range of newly inserted elements with respect to \exposid{compare}, and merges the resulting sorted range and @@ -18757,8 +18757,8 @@ \effects Equivalent to: \begin{codeblock} -ranges::swap(compare, y.compare); -ranges::swap(c, y.c); +ranges::swap(@\exposid{compare}@, y.@\exposid{compare}@); +ranges::swap(@\exposid{c}@, y.@\exposid{c}@); \end{codeblock} \end{itemdescr} @@ -18774,7 +18774,7 @@ \pnum \returns -\tcode{std::move(c)}. +\tcode{std::move(\exposid{c})}. \end{itemdescr} \indexlibrarymember{replace}{flat_multiset}% @@ -18789,7 +18789,7 @@ \pnum \effects -Equivalent to: \tcode{c = std::move(cont);} +Equivalent to: \tcode{\exposid{c} = std::move(cont);} \end{itemdescr} \rSec3[flat.multiset.erasure]{Erasure} @@ -19778,6 +19778,10 @@ template class default_accessor; + // \ref{mdspan.accessor.aligned}, class template \tcode{aligned_accessor} + template + class aligned_accessor; + // \ref{mdspan.mdspan}, class template \tcode{mdspan} template> @@ -20618,13 +20622,13 @@ \end{codeblock} \pnum -Each of \tcode{layout_left}, \tcode{layout_right}, and \tcode{layout_stride} -meets the layout mapping policy requirements and is a trivial type. - -\pnum -Each specialization of -\tcode{layout_left_padded} and \tcode{layout_right_padded} -meets the layout mapping policy requirements and is a trivial type. +Each of \tcode{layout_left}, \tcode{layout_right}, and \tcode{layout_stride}, +as well as each specialization of +\tcode{layout_left_padded} and \tcode{layout_right_padded}, +meets the layout mapping policy requirements and is a trivially copyable type. +Furthermore, +\tcode{is_trivially_default_constructible_v} is \tcode{true} +for any such type \tcode{T}. \rSec4[mdspan.layout.left]{Class template \tcode{layout_left::mapping}} @@ -20760,7 +20764,7 @@ \indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -template +template constexpr explicit(!is_convertible_v) mapping(const layout_right::mapping& other) noexcept; \end{itemdecl} @@ -20831,8 +20835,7 @@ \pnum \effects -Effects: Direct-non-list-initializes -\tcode{extents_} with \tcode{other.extents()}. +Direct-non-list-initializes \tcode{extents_} with \tcode{other.extents()}. \end{itemdescr} \indexlibraryctor{layout_left::mapping}% @@ -23151,6 +23154,195 @@ Equivalent to: \tcode{return p + i;} \end{itemdescr} +\rSec4[mdspan.accessor.aligned]{Class template \tcode{aligned_accessor}} + +\rSec5[mdspan.accessor.aligned.overview]{Overview} + +\begin{codeblock} +namespace std { + template + struct @\libglobal{aligned_accessor}@ { + using offset_policy = default_accessor; + using element_type = ElementType; + using reference = ElementType&; + using data_handle_type = ElementType*; + + static constexpr size_t byte_alignment = ByteAlignment; + + constexpr aligned_accessor() noexcept = default; + template + constexpr aligned_accessor( + aligned_accessor) noexcept; + template + constexpr explicit aligned_accessor(default_accessor) noexcept; + + template + constexpr operator default_accessor() const noexcept; + + constexpr reference access(data_handle_type p, size_t i) const noexcept; + + constexpr typename offset_policy::data_handle_type offset( + data_handle_type p, size_t i) const noexcept; + }; +} +\end{codeblock} + +\pnum +\mandates +\begin{itemize} +\item \tcode{byte_alignment} is a power of two, and +\item \tcode{byte_alignment >= alignof(ElementType)} is \tcode{true}. +\end{itemize} + +\pnum +\tcode{aligned_accessor} meets the accessor policy requirements. + +\pnum +\tcode{ElementType} is required to be a complete object type +that is neither an abstract class type nor an array type. + +\pnum +Each specialization of \tcode{aligned_accessor} is +a trivially copyable type that models \libconcept{semiregular}. + +\pnum +\range{0}{$n$} is an accessible range +for an object \tcode{p} of type \tcode{data_handle_type} and +an object of type \tcode{aligned_accessor} if and only if +\begin{itemize} +\item +\range{p}{p + $n$} is a valid range, and, +\item +if $n$ is greater than zero, +then \tcode{is_sufficiently_aligned(p)} is \tcode{true}. +\end{itemize} + +\pnum +\begin{example} +The following function \tcode{compute} +uses \tcode{is_sufficiently_aligned} to check +whether a given \tcode{mdspan} with \tcode{default_accessor} has +a data handle with sufficient alignment +to be used with \tcode{aligned_accessor}. +If so, the function dispatches to +a function \tcode{compute_using_fourfold_overalignment} +that requires fourfold over-alignment of arrays, +but can therefore use hardware-specific instructions, +such as four-wide SIMD (Single Instruction Multiple Data) instructions. +Otherwise, \tcode{compute} dispatches to a +possibly less optimized function \tcode{compute_without_requiring_overalignment} +that has no over-alignment requirement. +\begin{codeblock} +void compute_using_fourfold_overalignment( + std::mdspan, std::layout_right, + std::aligned_accessor> x); + +void compute_without_requiring_overalignment( + std::mdspan, std::layout_right> x); + +void compute(std::mdspan> x) { + constexpr auto byte_alignment = 4 * sizeof(float); + auto accessor = std::aligned_accessor{}; + auto x_handle = x.data_handle(); + + if (std::is_sufficiently_aligned(x_handle)) { + compute_using_fourfold_overalignment(std::mdspan{x_handle, x.mapping(), accessor}); + } else { + compute_without_requiring_overalignment(x); + } +} +\end{codeblock} +\end{example} + +\rSec5[mdspan.accessor.aligned.members]{Members} + +\indexlibraryctor{aligned_accessor}% +\begin{itemdecl} +template + constexpr aligned_accessor(aligned_accessor) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v} +is \tcode{true}. +\item +\tcode{OtherByteAlignment >= byte_alignment} is \tcode{true}. +\end{itemize} + +\pnum +\effects +None. +\end{itemdescr} + +\indexlibraryctor{aligned_accessor}% +\begin{itemdecl} +template + constexpr explicit aligned_accessor(default_accessor) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_convertible_v} +is \tcode{true}. + +\pnum +\effects +None. +\end{itemdescr} + +\indexlibrarymember{access}{aligned_accessor}% +\begin{itemdecl} +constexpr reference access(data_handle_type p, size_t i) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\range{0}{i + 1} is an accessible range for \tcode{p} and \tcode{*this}. + +\pnum +\effects +Equivalent to: \tcode{return assume_aligned(p)[i];} +\end{itemdescr} + +\indexlibrarymember{operator default_accessor}{aligned_accessor}% +\begin{itemdecl} +template + constexpr operator default_accessor() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_convertible_v} +is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return \{\};} +\end{itemdescr} + +\indexlibrarymember{offset}{aligned_accessor}% +\begin{itemdecl} +constexpr typename offset_policy::data_handle_type + offset(data_handle_type p, size_t i) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\range{0}{i + 1} is an accessible range for \tcode{p} and \tcode{*this}. + +\pnum +\effects +Equivalent to: \tcode{return assume_aligned(p) + i;} +\end{itemdescr} + \rSec3[mdspan.mdspan]{Class template \tcode{mdspan}} \rSec4[mdspan.mdspan.overview]{Overview} @@ -24126,6 +24318,17 @@ let \tcode{offset} be a value of type \tcode{size_t} equal to \tcode{(*this)(\exposid{first_}(slices...)...)}. +\pnum +Given a layout mapping type \tcode{M}, a type \tcode{S} is a +\defnadjx{unit-stride}{slice for \tcode{M}}{slice} if +\begin{itemize} +\item \tcode{S} is a specialization of \tcode{strided_slice} +where \tcode{S::stride_type} models \exposconcept{integral-constant-like} +and \tcode{S::stride_type::value} equals \tcode{1}, +\item \tcode{S} models \tcode{\exposconcept{index-pair-like}}, or +\item \tcode{is_convertible_v} is \tcode{true}. +\end{itemize} + \rSec5[mdspan.sub.map.left]{\tcode{layout_left} specialization of \tcode{submdspan_mapping}} \indexlibrarymemberexpos{layout_left::mapping}{submdspan-mapping-impl}% @@ -24157,8 +24360,7 @@ \tcode{is_convertible_v<$S_k$, full_ext\-ent_t>} is \tcode{true}; and \item for $k$ equal to \tcode{SubExtents::rank() - 1}, - $S_k$ models \tcode{\exposconcept{index-pair-like}} or - \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; + $S_k$ is a unit-stride slice for \tcode{decltype(*this)}; \end{itemize} \begin{note} If the above conditions are true, @@ -24173,21 +24375,17 @@ \end{codeblock} if for a value $u$ for which $u+1$ is the smallest value $p$ larger than zero -for which $S_p$ models -\tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true}, +for which $S_p$ is a unit-stride slice for \tcode{decltype(*this)}, the following conditions are met: \begin{itemize} \item -$S_0$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_0$, full_extent_t>} is \tcode{true}; and +$S_0$ is a unit-stride slice for \tcode{decltype(*this)}; and \item for each $k$ in the range \range{$u$ + 1}{$u$ + SubExtents::rank() - 1}, \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and \item for $k$ equal to \tcode{$u$ + SubExtents::rank() - 1}, -$S_k$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; +$S_k$ is a unit-stride slice for \tcode{decltype(*this)}; \end{itemize} and where \tcode{S_static} is: \begin{itemize} @@ -24238,8 +24436,7 @@ \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and \item for $k$ equal to \exposid{_rank} - \tcode{SubExtents::rank()}, - $S_k$ models \tcode{\exposconcept{index-pair-like}} or - \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; + $S_k$ is a unit-stride slice for \tcode{decltype(*this)}; \end{itemize} \begin{note} If the above conditions are true, @@ -24254,23 +24451,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$ models -\tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true}, +for which $S_p$ is a unit-stride slice for \tcode{decltype(*this)}, the following conditions are met: \begin{itemize} \item for $k$ equal to \tcode{\exposid{rank_} - 1}, -$S_k$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_k$, full_extent_t> }is \tcode{true}; and +$S_k$ is a unit-stride slice for \tcode{decltype(*this)}; and \item for each $k$ in the range \range{\exposid{rank_} - SubExtents::rank() - $u$ + 1}{\exposid{rank_} - $u$ - 1}, \tcode{is_con\-vertible_v<$S_k$, full_extent_t>} is \tcode{true}; and \item -for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$}, -$S_k$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; +for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$},\newline +$S_k$ is a unit-stride slice for \tcode{decltype(*this)}; \end{itemize} and where \tcode{S_static} is: \begin{itemize} @@ -24346,8 +24539,7 @@ \item \tcode{SubExtents::rank() == 1} is \tcode{true} and \item -$S_0$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_0$ , full_extent_t>} is \tcode{true}; +$S_0$ is a unit-stride slice for \tcode{decltype(*this)}; \end{itemize} \item otherwise, @@ -24357,20 +24549,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$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true}, +for which $S_p$ is a unit-stride slice for \tcode{decltype(*this)}, the following conditions are met: \begin{itemize} \item -$S_0$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_0$, full_extent_t>} is \tcode{true}; and +$S_0$ is a unit-stride slice for \tcode{decltype(*this)}; and \item for each $k$ in the range \range{$u$ + 1}{$u$ + SubExtents::rank() - 1}, \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and \item for $k$ equal to \tcode{$u$ + SubExtents::rank() - 1}, -$S_k$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v} is \tcode{true}; +$S_k$ is a unit-stride slice for \tcode{decltype(*this)}; \end{itemize} where \tcode{S_static} is: \begin{itemize} @@ -24422,8 +24611,7 @@ \tcode{SubExtents::rank() == 1} is \tcode{true} and \item for $k$ equal to \tcode{\exposid{rank_} - 1}, -$S_k$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_k$ , full_extent_t>} is \tcode{true}; +$S_k$ is a unit-stride slice for \tcode{decltype(*this)}; \end{itemize} \item otherwise, @@ -24434,22 +24622,19 @@ 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$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true}, +for which $S_p$ is a unit-stride slice for \tcode{decltype(*this)}, the following conditions are met: \begin{itemize} \item for $k$ equal to \tcode{\exposid{rank_} - 1}, -$S_k$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and +$S_k$ is a unit-stride slice for \tcode{decltype(*this)}; and \item for each $k$ in the range \range{\exposid{rank_} - SubExtents::rank() - $u$ + 1}{\exposid{rank_} - $u$ - 1)}, \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and \item -for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$}, -$S_k$ models \tcode{\exposconcept{index-pair-like}} or -\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; +for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$},\newline +$S_k$ is a unit-stride slice for \tcode{decltype(*this)}; \end{itemize} and where \tcode{S_static} is: \begin{itemize} diff --git a/source/declarations.tex b/source/declarations.tex index 446aebd3aa..7cbe7fb501 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -13,8 +13,7 @@ the form \begin{bnf} \nontermdef{declaration-seq}\br - declaration\br - declaration-seq declaration + declaration \opt{declaration-seq} \end{bnf} \begin{bnf} @@ -69,19 +68,19 @@ \end{bnf} \begin{bnf} -\nontermdef{attributed-identifier}\br - identifier \opt{attribute-specifier-seq} +\nontermdef{sb-identifier}\br + \opt{\terminal{...}} identifier \opt{attribute-specifier-seq} \end{bnf} \begin{bnf} -\nontermdef{attributed-identifier-list}\br - attributed-identifier\br - attributed-identifier-list \terminal{,} attributed-identifier +\nontermdef{sb-identifier-list}\br + sb-identifier\br + sb-identifier-list \terminal{,} sb-identifier \end{bnf} \begin{bnf} \nontermdef{structured-binding-declaration}\br - \opt{attribute-specifier-seq} decl-specifier-seq \opt{ref-qualifier} \terminal{[} attributed-identifier-list \terminal{]} + \opt{attribute-specifier-seq} decl-specifier-seq \opt{ref-qualifier} \terminal{[} sb-identifier-list \terminal{]} \end{bnf} \begin{bnf} @@ -213,10 +212,16 @@ a \defn{structured binding declaration}\iref{dcl.struct.bind}. Each \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq} shall be +\tcode{constexpr}, +\tcode{constinit}, \tcode{static}, \tcode{thread_local}, \tcode{auto}\iref{dcl.spec.auto}, or a \grammarterm{cv-qualifier}. +The declaration shall contain at most one \grammarterm{sb-identifier} +whose \grammarterm{identifier} is preceded by an ellipsis. +If the declaration contains any such \grammarterm{sb-identifier}, +it shall declare a templated entity\iref{temp.pre}. \begin{example} \begin{codeblock} template concept C = true; @@ -850,7 +855,8 @@ \pnum The \keyword{constexpr} specifier shall be applied only to -the definition of a variable or variable template or +the definition of a variable or variable template, +a structured binding declaration, or the declaration of a function or function template. The \keyword{consteval} specifier shall be applied only to the declaration of a function or function template. @@ -995,9 +1001,7 @@ Such an object shall have literal type and shall be initialized. -In any \keyword{constexpr} variable declaration, -the full-expression of the initialization -shall be a constant expression\iref{expr.const}. +A \keyword{constexpr} variable shall be constant-initializable\iref{expr.const}. A \keyword{constexpr} variable that is an object, as well as any temporary to which a \keyword{constexpr} reference is bound, shall have constant destruction. @@ -1008,6 +1012,16 @@ }; constexpr pixel ur = { 1294, 1024 }; // OK constexpr pixel origin; // error: initializer missing + +namespace N { + void f() { + int x; + constexpr int& ar = x; // OK + static constexpr int& sr = x; // error: \tcode{x} is not constexpr-representable + // at the point indicated below + } + // immediate scope here is that of \tcode{N} +} \end{codeblock} \end{example} @@ -1016,7 +1030,12 @@ \pnum The \keyword{constinit} specifier shall be applied only -to a declaration of a variable with static or thread storage duration. +to a declaration of a variable with static or thread storage duration +or to a structured binding declaration\iref{dcl.struct.bind}. +\begin{note} +A structured binding declaration introduces a uniquely named variable, +to which the \tcode{constinit} specifier applies. +\end{note} If the specifier is applied to any declaration of a variable, it shall be applied to the initializing declaration. No diagnostic is required if no \keyword{constinit} declaration @@ -1771,9 +1790,11 @@ \pnum The type of a \grammarterm{parameter-declaration} of a -function declaration\iref{dcl.fct}, -\grammarterm{lambda-expression}\iref{expr.prim.lambda}, or -\grammarterm{template-parameter}\iref{temp.param} +\begin{itemize} + \item function declaration\iref{dcl.fct}, + \item \grammarterm{lambda-expression}\iref{expr.prim.lambda}, or + \item \grammarterm{template-parameter}\iref{temp.param} +\end{itemize} can be declared using a \grammarterm{placeholder-type-specifier} of the form \opt{\grammarterm{type-constraint}} \keyword{auto}. @@ -3602,8 +3623,10 @@ \indextext{declaration!function}% \begin{bnf} \nontermdef{parameter-declaration-clause}\br - \opt{parameter-declaration-list} \opt{\terminal{...}}\br - parameter-declaration-list \terminal{,} \terminal{...} + \terminal{...}\br + \opt{parameter-declaration-list}\br + parameter-declaration-list \terminal{,} \terminal{...}\br + parameter-declaration-list \terminal{...} \end{bnf} \begin{bnf} @@ -3639,7 +3662,7 @@ If the \grammarterm{parameter-declaration-clause} is empty, the function takes no arguments. -A parameter list consisting of a single unnamed parameter of +A parameter list consisting of a single unnamed non-object parameter of non-dependent type \keyword{void} is equivalent to an empty parameter list. \indextext{parameter!\idxcode{void}}% @@ -3659,9 +3682,13 @@ argument and are not function parameter packs. Where syntactically correct and where ``\tcode{...}'' is not part of an \grammarterm{abstract-declarator}, -``\tcode{, ...}'' +``\tcode{...}'' is synonymous with -``\tcode{...}''. +``\tcode{, ...}''. +A \grammarterm{parameter-declaration-clause} +of the form +\grammarterm{parameter-declaration-list} \tcode{...} +is deprecated\iref{depr.ellipsis.comma}. \begin{example} The declaration \begin{codeblock} @@ -5808,6 +5835,10 @@ return x; } constexpr int z = f(); // error: not a constant expression + +typedef int *A[3]; // array of 3 pointer to \tcode{int} +typedef const int *const CA[3]; // array of 3 const pointer to \tcode{const int} +ACPC &&r = AP{}; // binds directly \end{codeblock} \end{example} @@ -7019,17 +7050,23 @@ \pnum A structured binding declaration introduces the \grammarterm{identifier}{s} -$\tcode{v}_0$, $\tcode{v}_1$, $\tcode{v}_2, \dotsc$ +$\tcode{v}_0$, $\tcode{v}_1$, $\tcode{v}_2, \dotsc, \tcode{v}_{N-1}$ of the -\grammarterm{attributed-identifier-list} as names -of \defn{structured binding}{s}. +\grammarterm{sb-identifier-list} as names. +An \grammarterm{sb-identifier} that contains an ellipsis +introduces a structured binding pack\iref{temp.variadic}. +A \defn{structured binding} is either +an \grammarterm{sb-identifier} that does not contain an ellipsis or +an element of a structured binding pack. The optional \grammarterm{attribute-specifier-seq} of -an \grammarterm{attributed-identifier} -appertains to the structured binding so introduced. +an \grammarterm{sb-identifier} +appertains to the associated structured bindings. Let \cv{} denote the \grammarterm{cv-qualifier}{s} in the \grammarterm{decl-specifier-seq} and -\placeholder{S} consist of the \grammarterm{storage-class-specifier}{s} of -the \grammarterm{decl-specifier-seq} (if any). +\placeholder{S} consist of +each \grammarterm{decl-specifier} of the \grammarterm{decl-specifier-seq} +that is \tcode{constexpr}, \tcode{constinit}, or +a \grammarterm{storage-class-specifier}. A \cv{} that includes \tcode{volatile} is deprecated; see~\ref{depr.volatile.type}. First, a variable with a unique name \exposid{e} is introduced. If the @@ -7057,6 +7094,42 @@ \tcode{E} is never a reference type\iref{expr.prop}. \end{note} +\pnum +The \defn{structured binding size} of \tcode{E}, as defined below, +is the number of structured bindings +that need to be introduced by the structured binding declaration. +If there is no structured binding pack, +then the number of elements in the \grammarterm{sb-identifier-list} +shall be equal to the structured binding size of \tcode{E}. +Otherwise, the number of non-pack elements shall be no more than +the structured binding size of \tcode{E}; +the number of elements of the structured binding pack is +the structured binding size of \tcode{E} less +the number of non-pack elements in the\grammarterm{sb-identifier-list}. + +\pnum +Let $\textrm{SB}_i$ denote +the $i^\textrm{th}$ structured binding in the structured binding declaration +after expanding the structured binding pack, if any. +\begin{note} +If there is no structured binding pack, +then $\textrm{SB}_i$ denotes $\tcode{v}_i$. +\end{note} +\begin{example} +\begin{codeblock} +struct C { int x, y, z; }; + +template +void now_i_know_my() { + auto [a, b, c] = C(); // OK, $\textrm{SB}_0$ is \tcode{a}, $\textrm{SB}_1$ is \tcode{b}, and $\textrm{SB}_2$ is \tcode{c} + auto [d, ...e] = C(); // OK, $\textrm{SB}_0$ is \tcode{d}, the pack \tcode{e} $(\tcode{v}_1)$ contains two structured bindings: $\textrm{SB}_1$ and $\textrm{SB}_2$ + auto [...f, g] = C(); // OK, the pack \tcode{f} $(\tcode{v}_0)$ contains two structured bindings: $\textrm{SB}_0$ and $\textrm{SB}_1$, and $\textrm{SB}_2$ is \tcode{g} + auto [h, i, j, ...k] = C(); // OK, the pack \tcode{k} is empty + auto [l, m, n, o, ...p] = C(); // error: structured binding size is too small +} +\end{codeblock} +\end{example} + \pnum If a structured binding declaration appears as a \grammarterm{condition}, the decision variable\iref{stmt.pre} of the condition is \exposid{e}. @@ -7067,9 +7140,10 @@ the program is ill-formed. \pnum -If \tcode{E} is an array type with element type \tcode{T}, the number -of elements in the \grammarterm{attributed-identifier-list} shall be equal to the -number of elements of \tcode{E}. Each $\tcode{v}_i$ is the name of an +If \tcode{E} is an array type with element type \tcode{T}, +the structured binding size of \tcode{E} is equal to the +number of elements of \tcode{E}. +Each $\textrm{SB}_i$ is the name of an lvalue that refers to the element $i$ of the array and whose type is \tcode{T}; the referenced type is \tcode{T}. \begin{note} @@ -7080,6 +7154,19 @@ auto f() -> int(&)[2]; auto [ x, y ] = f(); // \tcode{x} and \tcode{y} refer to elements in a copy of the array return value auto& [ xr, yr ] = f(); // \tcode{xr} and \tcode{yr} refer to elements in the array referred to by \tcode{f}'s return value + +auto g() -> int(&)[4]; + +template +void h(int (&arr)[N]) { + auto [a, ...b, c] = arr; // \tcode{a} names the first element of the array, \tcode{b} is a pack referring to the second and + // third elements, and \tcode{c} names the fourth element + auto& [...e] = arr; // \tcode{e} is a pack referring to the four elements of the array +} + +void call_h() { + h(g()); +} \end{codeblock} \end{example} @@ -7090,8 +7177,7 @@ the expression \tcode{std::tuple_size::value} shall be a well-formed integral constant expression and -the number of elements in -the \grammarterm{attributed-identifier-list} shall be equal to the value of that +the structured binding size of \tcode{E} is equal to the value of that expression. Let \tcode{i} be an index prvalue of type \tcode{std::size_t} corresponding to $\tcode{v}_i$. @@ -7121,7 +7207,7 @@ \placeholder{S} \terminal{U$_i$ r$_i$ =} initializer \terminal{;} \end{ncbnf} -Each $\tcode{v}_i$ is the name of an lvalue of type $\tcode{T}_i$ +Each $\textrm{SB}_i$ is the name of an lvalue of type $\tcode{T}_i$ that refers to the object bound to $\tcode{r}_i$; the referenced type is $\tcode{T}_i$. The initialization of \exposid{e} and @@ -7139,12 +7225,12 @@ well-formed when named as \tcode{\exposidnc{e}.\placeholder{name}} in the context of the structured binding, \tcode{E} shall not have an anonymous union member, and -the number of elements in the \grammarterm{attributed-identifier-list} shall be +the structured binding size of \tcode{E} is equal to the number of non-static data members of \tcode{E}. Designating the non-static data members of \tcode{E} as $\tcode{m}_0$, $\tcode{m}_1$, $\tcode{m}_2, \dotsc$ (in declaration order), -each $\tcode{v}_i$ is the +each $\textrm{SB}_i$ is the name of an lvalue that refers to the member \tcode{m}$_i$ of \exposid{e} and whose type is that of \tcode{\exposidnc{e}.$\tcode{m}_i$}\iref{expr.ref}; @@ -8699,8 +8785,8 @@ \pnum \indextext{object!linkage specification}% \indextext{linkage!implementation-defined object}% -Linkage from \Cpp{} to objects defined in other languages and to objects -defined in \Cpp{} from other languages is \impldef{linkage of objects between \Cpp{} and other languages} and +Linkage from \Cpp{} to entities defined in other languages and to entities +defined in \Cpp{} from other languages is \impldef{linkage of entities between \Cpp{} and other languages} and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved.% @@ -8718,7 +8804,7 @@ \begin{bnf} \nontermdef{attribute-specifier-seq}\br - \opt{attribute-specifier-seq} attribute-specifier + attribute-specifier \opt{attribute-specifier-seq} \end{bnf} \begin{bnf} @@ -8774,8 +8860,7 @@ \begin{bnf} \nontermdef{balanced-token-seq}\br - balanced-token\br - balanced-token-seq balanced-token + balanced-token \opt{balanced-token-seq} \end{bnf} \begin{bnf} @@ -9009,6 +9094,7 @@ \rSec2[dcl.attr.assume]{Assumption attribute} +\pnum The \grammarterm{attribute-token} \tcode{assume} may be applied to a null statement; such a statement is an \defn{assumption}. An \grammarterm{attribute-argument-clause} shall be present and @@ -9021,7 +9107,10 @@ If the converted expression would evaluate to \tcode{true} at the point where the assumption appears, the assumption has no effect. -Otherwise, the behavior is undefined. +Otherwise, +evaluation of the assumption has runtime-undefined behavior. + +\pnum \begin{note} The expression is potentially evaluated\iref{basic.def.odr}. The use of assumptions is intended to allow implementations @@ -9035,6 +9124,8 @@ if an implementation does not attempt to deduce any such information from assumptions. \end{note} + +\pnum \begin{example} \begin{codeblock} int divide_by_32(int x) { @@ -9528,8 +9619,9 @@ translation unit, the program is ill-formed, no diagnostic required. \pnum -If a function \tcode{f} is called where \tcode{f} was previously declared with the \tcode{noreturn} -attribute and \tcode{f} eventually returns, the behavior is undefined. +If a function \tcode{f} is invoked where \tcode{f} was previously declared with the \tcode{noreturn} +attribute and that invocation eventually returns, +the behavior is runtime-undefined. \begin{note} The function can terminate by throwing an exception. diff --git a/source/diagnostics.tex b/source/diagnostics.tex index ef695fddef..e421b207f4 100644 --- a/source/diagnostics.tex +++ b/source/diagnostics.tex @@ -713,9 +713,6 @@ \indexlibraryglobal{error_code}% \indexlibraryglobal{error_condition}% \indexlibraryglobal{system_error}% -\indexlibraryglobal{is_error_code_enum}% -\indexlibraryglobal{is_error_condition_enum}% -\indexlibraryglobal{errc}% \begin{codeblock} #include // see \ref{compare.syn} @@ -729,12 +726,12 @@ class system_error; template - struct is_error_code_enum : public false_type {}; + struct @\libglobal{is_error_code_enum}@ : public false_type {}; template - struct is_error_condition_enum : public false_type {}; + struct @\libglobal{is_error_condition_enum}@ : public false_type {}; - enum class errc { // freestanding + enum class @\libglobal{errc}@ { // freestanding address_family_not_supported, // \tcode{EAFNOSUPPORT} address_in_use, // \tcode{EADDRINUSE} address_not_available, // \tcode{EADDRNOTAVAIL} @@ -837,7 +834,7 @@ // \ref{syserr}, system error support template - constexpr bool is_error_code_enum_v = is_error_code_enum::value; + constexpr bool @\libglobal{is_error_code_enum_v}@ = is_error_code_enum::value; template constexpr bool is_error_condition_enum_v = is_error_condition_enum::value; } diff --git a/source/exceptions.tex b/source/exceptions.tex index a462fe0bff..c14df21e84 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -751,7 +751,7 @@ \begin{bnf} \nontermdef{noexcept-specifier}\br \keyword{noexcept} \terminal{(} constant-expression \terminal{)}\br - \keyword{noexcept}\br + \keyword{noexcept} \end{bnf} \pnum @@ -846,7 +846,7 @@ (such as an overloaded operator, an allocation function in a \grammarterm{new-expression}, a constructor for a function argument, -or a destructor if $E$ is a full-expression\iref{intro.execution}) +or a destructor) that has a potentially-throwing exception specification, or \item @@ -1012,9 +1012,10 @@ \pnum \indextext{\idxcode{terminate}}% -% FIXME: What does it mean to abandon exception handling? -In some situations, exception handling is abandoned -for less subtle error handling techniques. +Some errors in a program cannot be recovered from, such as when an exception +is not handled or a \tcode{std::thread} object is destroyed while its thread +function is still executing. In such cases, +the function \tcode{std::terminate}\iref{exception.terminate} is invoked. \begin{note} These situations are: \indextext{\idxcode{terminate}!called}% @@ -1108,8 +1109,6 @@ \pnum \indextext{\idxcode{terminate}}% -In such cases, -the function \tcode{std::terminate} is invoked\iref{exception.terminate}. In the situation where no matching handler is found, it is \impldef{stack unwinding before invocation of \tcode{std::terminate}} whether or not the stack is unwound diff --git a/source/exec.tex b/source/exec.tex index 8608dd9624..e4bb77d9db 100644 --- a/source/exec.tex +++ b/source/exec.tex @@ -91,8 +91,8 @@ \item \tcode{err} if \tcode{decay_t} denotes the type \tcode{exception_ptr}. -\mandates -\tcode{err != exception_ptr()} is \tcode{true}. +\expects +\tcode{!err} is \tcode{false}. \item Otherwise, \tcode{make_exception_ptr(system_error(err))} @@ -155,7 +155,7 @@ \pnum Let \tcode{env} be an object of type \tcode{Env}. -The type \tcode{Env} models queryable +The type \tcode{Env} models \exposconcept{queryable} if for each callable object \tcode{q} and a pack of subexpressions \tcode{args}, if \tcode{requires \{ q(env, args...) \}} is \tcode{true} then \tcode{q(env, args...)} meets any semantic requirements imposed by \tcode{q}. @@ -229,7 +229,6 @@ representing the execution-time properties of the operation's caller. The caller of an asynchronous operation is its parent operation or the function that created it. -An asynchronous operation's operation state owns the operation's environment. \pnum An asynchronous operation has an associated receiver. @@ -434,13 +433,13 @@ concept @\exposconceptnc{queryable}@ = @\seebelownc@; // \expos // \ref{exec.queries}, queries - struct forwarding_query_t { @\unspec@ }; - struct get_allocator_t { @\unspec@ }; - struct get_stop_token_t { @\unspec@ }; + struct @\libglobal{forwarding_query_t}@ { @\unspec@ }; + struct @\libglobal{get_allocator_t}@ { @\unspec@ }; + struct @\libglobal{get_stop_token_t}@ { @\unspec@ }; - inline constexpr forwarding_query_t forwarding_query{}; - inline constexpr get_allocator_t get_allocator{}; - inline constexpr get_stop_token_t get_stop_token{}; + inline constexpr forwarding_query_t @\libglobal{forwarding_query}@{}; + inline constexpr get_allocator_t @\libglobal{get_allocator}@{}; + inline constexpr get_stop_token_t @\libglobal{get_stop_token}@{}; template using stop_token_of_t = remove_cvref_t()))>; @@ -451,39 +450,46 @@ namespace std::execution { // \ref{exec.queries}, queries - struct get_domain_t { @\unspec@ }; - struct get_scheduler_t { @\unspec@ }; - struct get_delegation_scheduler_t { @\unspec@ }; - struct get_forward_progress_guarantee_t { @\unspec@ }; + struct @\libglobal{get_domain_t}@ { @\unspec@ }; + struct @\libglobal{get_scheduler_t}@ { @\unspec@ }; + struct @\libglobal{get_delegation_scheduler_t}@ { @\unspec@ }; + struct @\libglobal{get_forward_progress_guarantee_t}@ { @\unspec@ }; template - struct get_completion_scheduler_t { @\unspec@ }; + struct @\libglobal{get_completion_scheduler_t}@ { @\unspec@ }; - inline constexpr get_domain_t get_domain{}; - inline constexpr get_scheduler_t get_scheduler{}; - inline constexpr get_delegation_scheduler_t get_delegation_scheduler{}; + inline constexpr get_domain_t @\libglobal{get_domain}@{}; + inline constexpr get_scheduler_t @\libglobal{get_scheduler}@{}; + inline constexpr get_delegation_scheduler_t @\libglobal{get_delegation_scheduler}@{}; enum class forward_progress_guarantee; - inline constexpr get_forward_progress_guarantee_t get_forward_progress_guarantee{}; + inline constexpr get_forward_progress_guarantee_t @\libglobal{get_forward_progress_guarantee}@{}; template - constexpr get_completion_scheduler_t get_completion_scheduler{}; + constexpr get_completion_scheduler_t @\libglobal{get_completion_scheduler}@{}; - struct empty_env {}; - struct get_env_t { @\unspec@ }; - inline constexpr get_env_t get_env{}; + struct @\libglobal{get_env_t}@ { @\unspec@ }; + inline constexpr get_env_t @\libglobal{get_env}@{}; template - using env_of_t = decltype(get_env(declval())); + using @\libglobal{env_of_t}@ = decltype(get_env(declval())); + + // \ref{exec.prop}, class template \tcode{prop} + template + struct prop; + + // \ref{exec.env}, class template \tcode{env} + template<@\exposconcept{queryable}@... Envs> + struct env; // \ref{exec.domain.default}, execution domains struct default_domain; // \ref{exec.sched}, schedulers - struct scheduler_t {}; + struct @\libglobal{scheduler_t}@ {}; template concept @\libconcept{scheduler}@ = @\seebelow@; // \ref{exec.recv}, receivers - struct receiver_t {}; + struct @\libglobal{receiver_t}@ {}; template concept @\libconcept{receiver}@ = @\seebelow@; @@ -491,30 +497,30 @@ template concept @\libconcept{receiver_of}@ = @\seebelow@; - struct set_value_t { @\unspec@ }; - struct set_error_t { @\unspec@ }; - struct set_stopped_t { @\unspec@ }; + struct @\libglobal{set_value_t}@ { @\unspec@ }; + struct @\libglobal{set_error_t}@ { @\unspec@ }; + struct @\libglobal{set_stopped_t}@ { @\unspec@ }; - inline constexpr set_value_t set_value{}; - inline constexpr set_error_t set_error{}; - inline constexpr set_stopped_t set_stopped{}; + inline constexpr set_value_t @\libglobal{set_value}@{}; + inline constexpr set_error_t @\libglobal{set_error}@{}; + inline constexpr set_stopped_t @\libglobal{set_stopped}@{}; // \ref{exec.opstate}, operation states - struct operation_state_t {}; + struct @\libglobal{operation_state_t}@ {}; template concept @\libconcept{operation_state}@ = @\seebelow@; - struct start_t; - inline constexpr start_t start{}; + struct @\libglobal{start_t}@; + inline constexpr start_t @\libglobal{start}@{}; // \ref{exec.snd}, senders - struct sender_t {}; + struct @\libglobal{sender_t}@ {}; template concept @\libconcept{sender}@ = @\seebelow@; - template + template> concept @\libconcept{sender_in}@ = @\seebelow@; template @@ -527,7 +533,7 @@ struct get_completion_signatures_t; inline constexpr get_completion_signatures_t get_completion_signatures {}; - template + template> requires @\libconcept{sender_in}@ using completion_signatures_of_t = @\exposid{call-result-t}@; @@ -537,18 +543,18 @@ template using @\exposidnc{variant-or-empty}@ = @\seebelownc@; // \expos - template, template class Tuple = @\exposid{decayed-tuple}@, template class Variant = @\exposid{variant-or-empty}@> requires @\libconcept{sender_in}@ using value_types_of_t = @\seebelow@; - template, template class Variant = @\exposid{variant-or-empty}@> requires @\libconcept{sender_in}@ using error_types_of_t = @\seebelow@; - template + template> requires @\libconcept{sender_in}@ constexpr bool sends_stopped = @\seebelow@; @@ -578,67 +584,67 @@ Domain dom, Tag, Sndr&& sndr, Args&&... args) noexcept(@\seebelow@); // \ref{exec.connect}, the connect sender algorithm - struct connect_t; - inline constexpr connect_t connect{}; + struct @\libglobal{connect_t}@; + inline constexpr connect_t @\libglobal{connect}@{}; template - using connect_result_t = + using @\libglobal{connect_result_t}@ = decltype(connect(declval(), declval())); // \ref{exec.factories}, sender factories - struct just_t { @\unspec@ }; - struct just_error_t { @\unspec@ }; - struct just_stopped_t { @\unspec@ }; - struct schedule_t { @\unspec@ }; + struct @\libglobal{just_t}@ { @\unspec@ }; + struct @\libglobal{just_error_t}@ { @\unspec@ }; + struct @\libglobal{just_stopped_t}@ { @\unspec@ }; + struct @\libglobal{schedule_t}@ { @\unspec@ }; - inline constexpr just_t just{}; - inline constexpr just_error_t just_error{}; - inline constexpr just_stopped_t just_stopped{}; - inline constexpr schedule_t schedule{}; - inline constexpr @\unspec@ read_env{}; + inline constexpr just_t @\libglobal{just}@{}; + inline constexpr just_error_t @\libglobal{just_error}@{}; + inline constexpr just_stopped_t @\libglobal{just_stopped}@{}; + inline constexpr schedule_t @\libglobal{schedule}@{}; + inline constexpr @\unspec@ @\libglobal{read_env}@{}; template<@\libconcept{scheduler}@ Sndr> - using schedule_result_t = decltype(schedule(declval())); + using @\libglobal{schedule_result_t}@ = decltype(schedule(declval())); // \ref{exec.adapt}, sender adaptors template<@\exposconcept{class-type}@ D> - struct sender_adaptor_closure { }; - - struct starts_on_t { @\unspec@ }; - struct continues_on_t { @\unspec@ }; - struct on_t { @\unspec@ }; - struct schedule_from_t { @\unspec@ }; - struct then_t { @\unspec@ }; - struct upon_error_t { @\unspec@ }; - struct upon_stopped_t { @\unspec@ }; - struct let_value_t { @\unspec@ }; - struct let_error_t { @\unspec@ }; - struct let_stopped_t { @\unspec@ }; - struct bulk_t { @\unspec@ }; - struct split_t { @\unspec@ }; - struct when_all_t { @\unspec@ }; - struct when_all_with_variant_t { @\unspec@ }; - struct into_variant_t { @\unspec@ }; - struct stopped_as_optional_t { @\unspec@ }; - struct stopped_as_error_t { @\unspec@ }; - - inline constexpr starts_on_t starts_on{}; - inline constexpr continues_on_t continues_on{}; - inline constexpr on_t on{}; - inline constexpr schedule_from_t schedule_from{}; - inline constexpr then_t then{}; - inline constexpr upon_error_t upon_error{}; - inline constexpr upon_stopped_t upon_stopped{}; - inline constexpr let_value_t let_value{}; - inline constexpr let_error_t let_error{}; - inline constexpr let_stopped_t let_stopped{}; - inline constexpr bulk_t bulk{}; - inline constexpr split_t split{}; - inline constexpr when_all_t when_all{}; - inline constexpr when_all_with_variant_t when_all_with_variant{}; - inline constexpr into_variant_t into_variant{}; - inline constexpr stopped_as_optional_t stopped_as_optional{}; - inline constexpr stopped_as_error_t stopped_as_error{}; + struct @\libglobal{sender_adaptor_closure}@ { }; + + struct @\libglobal{starts_on_t}@ { @\unspec@ }; + struct @\libglobal{continues_on_t}@ { @\unspec@ }; + struct @\libglobal{on_t}@ { @\unspec@ }; + struct @\libglobal{schedule_from_t}@ { @\unspec@ }; + struct @\libglobal{then_t}@ { @\unspec@ }; + struct @\libglobal{upon_error_t}@ { @\unspec@ }; + struct @\libglobal{upon_stopped_t}@ { @\unspec@ }; + struct @\libglobal{let_value_t}@ { @\unspec@ }; + struct @\libglobal{let_error_t}@ { @\unspec@ }; + struct @\libglobal{let_stopped_t}@ { @\unspec@ }; + struct @\libglobal{bulk_t}@ { @\unspec@ }; + struct @\libglobal{split_t}@ { @\unspec@ }; + struct @\libglobal{when_all_t}@ { @\unspec@ }; + struct @\libglobal{when_all_with_variant_t}@ { @\unspec@ }; + struct @\libglobal{into_variant_t}@ { @\unspec@ }; + struct @\libglobal{stopped_as_optional_t}@ { @\unspec@ }; + struct @\libglobal{stopped_as_error_t}@ { @\unspec@ }; + + inline constexpr starts_on_t @\libglobal{starts_on}@{}; + inline constexpr continues_on_t @\libglobal{continues_on}@{}; + inline constexpr on_t @\libglobal{on}@{}; + inline constexpr schedule_from_t @\libglobal{schedule_from}@{}; + inline constexpr then_t @\libglobal{then}@{}; + inline constexpr upon_error_t @\libglobal{upon_error}@{}; + inline constexpr upon_stopped_t @\libglobal{upon_stopped}@{}; + inline constexpr let_value_t @\libglobal{let_value}@{}; + inline constexpr let_error_t @\libglobal{let_error}@{}; + inline constexpr let_stopped_t @\libglobal{let_stopped}@{}; + inline constexpr bulk_t @\libglobal{bulk}@{}; + inline constexpr split_t @\libglobal{split}@{}; + inline constexpr when_all_t @\libglobal{when_all}@{}; + inline constexpr when_all_with_variant_t @\libglobal{when_all_with_variant}@{}; + inline constexpr into_variant_t @\libglobal{into_variant}@{}; + inline constexpr stopped_as_optional_t @\libglobal{stopped_as_optional}@{}; + inline constexpr stopped_as_error_t @\libglobal{stopped_as_error}@{}; // \ref{exec.util}, sender and receiver utilities // \ref{exec.util.cmplsig} @@ -646,7 +652,7 @@ concept @\exposconceptnc{completion-signature}@ = @\seebelownc@; // \expos template<@\exposconcept{completion-signature}@... Fns> - struct completion_signatures {}; + struct @\libglobal{completion_signatures}@ {}; template concept @\exposconceptnc{valid-completion-signatures}@ = @\seebelownc@; // \expos @@ -662,7 +668,7 @@ template< @\libconcept{sender}@ Sndr, - class Env = empty_env, + class Env = env<>, @\exposconcept{valid-completion-signatures}@ AdditionalSignatures = completion_signatures<>, template class SetValue = @\seebelow@, template class SetError = @\seebelow@, @@ -679,17 +685,17 @@ namespace std::this_thread { // \ref{exec.consumers}, consumers - struct sync_wait_t { @\unspec@ }; - struct sync_wait_with_variant_t { @\unspec@ }; + struct @\libglobal{sync_wait_t}@ { @\unspec@ }; + struct @\libglobal{sync_wait_with_variant_t}@ { @\unspec@ }; - inline constexpr sync_wait_t sync_wait{}; - inline constexpr sync_wait_with_variant_t sync_wait_with_variant{}; + inline constexpr sync_wait_t @\libglobal{sync_wait}@{}; + inline constexpr sync_wait_with_variant_t @\libglobal{sync_wait_with_variant}@{}; } namespace std::execution { // \ref{exec.as.awaitable} - struct as_awaitable_t { @\unspec@ }; - inline constexpr as_awaitable_t as_awaitable{}; + struct @\libglobal{as_awaitable_t}@ { @\unspec@ }; + inline constexpr as_awaitable_t @\libglobal{as_awaitable}@{}; // \ref{exec.with.awaitable.senders} template<@\exposconcept{class-type}@ Promise> @@ -834,7 +840,7 @@ The type of the expression above satisfies \exposconcept{queryable}\iref{exec.queryable}. \item -Otherwise, \tcode{empty_env\{\}}. +Otherwise, \tcode{env<>\{\}}. \end{itemize} \pnum @@ -908,7 +914,7 @@ \begin{codeblock} namespace std::execution { - enum class forward_progress_guarantee { + enum class @\libglobal{forward_progress_guarantee}@ { concurrent, parallel, weakly_parallel @@ -1012,7 +1018,7 @@ -> @\libconcept{same_as}@>; } && @\libconcept{equality_comparable}@> && - @\libconcept{copy_constructible}@>; + @\libconcept{copyable}@>; } \end{codeblock} @@ -1025,17 +1031,15 @@ shall be modeled. \pnum -None of a scheduler's -copy constructor, -destructor, -equality comparison, or -\tcode{swap} member functions +No operation required by +\tcode{\libconcept{copyable}>} and +\tcode{\libconcept{equality_comparable}>} shall exit via an exception. -None of these member functions, +None of these operations, nor a scheduler type's \tcode{schedule} function, shall introduce data races as a result of potentially concurrent\iref{intro.races} invocations -of those functions from different threads. +of those operations from different threads. \pnum For any two values \tcode{sch1} and \tcode{sch2} @@ -1198,7 +1202,7 @@ \pnum The program is ill-formed -if it performs a copy or move construction or assigment operation on +if it performs a copy or move construction or assignment operation on an operation state object created by connecting a library-provided sender. \rSec2[exec.opstate.start]{\tcode{execution::start}} @@ -1727,10 +1731,16 @@ \pnum The expression in the \tcode{noexcept} clause of -the constructor of \exposid{basic-state} is: +the constructor of \exposid{basic-state} is \begin{codeblock} is_nothrow_move_constructible_v && -@\exposconcept{nothrow-callable}@>::@\exposid{get-state}@), Sndr, Rcvr&> +@\exposconcept{nothrow-callable}@>::@\exposid{get-state}@), Sndr, Rcvr&> && +(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 @@ -1782,7 +1792,7 @@ if constexpr (sizeof...(child) == 1) return (@\exposid{FWD-ENV}@(get_env(child)), ...); else - return empty_env(); + return env<>(); } \end{codeblock} @@ -1879,11 +1889,24 @@ struct @\exposid{impls-for}@<@\exposid{write-env-t}@> : @\exposid{default-impls}@ { static constexpr auto @\exposid{get-env}@ = [](auto, const auto& state, const auto& rcvr) noexcept { - return @\exposid{JOIN-ENV}@(state, get_env(rcvr)); + return @\seebelow@; }; }; \end{codeblock} \end{itemdescr} +Invocation of +\tcode{\exposid{impls-for}<\exposid{write-env-t}>::\exposid{get-env}} +returns an object \tcode{e} such that +\begin{itemize} +\item +\tcode{decltype(e)} models \exposconcept{queryable} and +\item +given a query object \tcode{q}, +the expression \tcode{e.query(q)} is expression-equivalent +to \tcode{state.query(q)} if that expression is valid, +otherwise, \tcode{e.query(q)} is expression-equivalent +to \tcode{get_env(rcvr).query(q)}. +\end{itemize} \rSec2[exec.snd.concepts]{Sender concepts} @@ -1913,7 +1936,7 @@ template concept @\defexposconcept{enable-sender}@ = // \expos @\exposconcept{is-sender}@ || - @\exposconcept{is-awaitable}@>; // \ref{exec.awaitable} + @\exposconcept{is-awaitable}@>>; // \ref{exec.awaitable} template concept @\deflibconcept{sender}@ = @@ -1924,7 +1947,7 @@ @\libconcept{move_constructible}@> && @\libconcept{constructible_from}@, Sndr>; - template + template> concept @\deflibconcept{sender_in}@ = @\libconcept{sender}@ && @\exposconcept{queryable}@ && @@ -1982,7 +2005,7 @@ value_types_of_t); template - concept @\defexposconcept{sender-of}@ = @\exposconcept{sender-in-of}@; + concept @\defexposconcept{sender-of}@ = @\exposconcept{sender-in-of}@, Values...>; } \end{codeblock} @@ -2136,7 +2159,7 @@ } \end{codeblock} \begin{note} -of \exposid{env-promise} are used only for the purpose of type computation; +Specializations of \exposid{env-promise} are used only for the purpose of type computation; its members need not be defined. \end{note} @@ -2145,7 +2168,7 @@ \pnum \begin{codeblock} namespace std::execution { - struct default_domain { + 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) @@ -2161,6 +2184,7 @@ } \end{codeblock} +\indexlibrarymember{transform_sender}{default_domain}% \begin{itemdecl} template<@\libconcept{sender}@ Sndr, @\exposconcept{queryable}@... Env> requires (sizeof...(Env) <= 1) @@ -2181,10 +2205,12 @@ \returns \tcode{e}. +\pnum \remarks The exception specification is equivalent to \tcode{noexcept(e)}. \end{itemdescr} +\indexlibrarymember{transform_env}{default_domain}% \begin{itemdecl} template<@\libconcept{sender}@ Sndr, @\exposconcept{queryable}@ Env> constexpr @\exposconcept{queryable}@ decltype(auto) transform_env(Sndr&& sndr, Env&& env) noexcept; @@ -2208,6 +2234,7 @@ \tcode{e}. \end{itemdescr} +\indexlibrarymember{apply_sender}{default_domain}% \begin{itemdecl} template constexpr decltype(auto) apply_sender(Tag, Sndr&& sndr, Args&&... args) @@ -2236,6 +2263,7 @@ \rSec2[exec.snd.transform]{\tcode{execution::transform_sender}} +\indexlibraryglobal{transform_sender}% \begin{itemdecl} namespace std::execution { template @@ -2273,6 +2301,7 @@ \rSec2[exec.snd.transform.env]{\tcode{execution::transform_env}} +\indexlibraryglobal{transform_env}% \begin{itemdecl} namespace std::execution { template @@ -2302,6 +2331,7 @@ \rSec2[exec.snd.apply]{\tcode{execution::apply_sender}} +\indexlibraryglobal{apply_sender}% \begin{itemdecl} namespace std::execution { template @@ -2448,14 +2478,13 @@ Let \exposid{operation-state-task} be the following exposition-only class: \begin{codeblock} namespace std::execution { - struct @\exposid{operation-state-task}@ { + struct @\exposid{operation-state-task}@ { // \expos using operation_state_concept = operation_state_t; using promise_type = @\exposid{connect-awaitable-promise}@; explicit @\exposid{operation-state-task}@(coroutine_handle<> h) noexcept : coro(h) {} - @\exposid{operation-state-task}@(@\exposid{operation-state-task}@&& o) noexcept - : @\exposid{coro}@(exchange(o.@\exposid{coro}@, {})) {} - ~@\exposid{operation-state-task}@() { if (@\exposid{coro}@) @\exposid{coro}@.destroy(); } + @\exposid{operation-state-task}@(@\exposid{operation-state-task}@&&) = delete; + ~@\exposid{operation-state-task}@() { @\exposid{coro}@.destroy(); } void start() & noexcept { @\exposid{coro}@.resume(); @@ -2658,7 +2687,7 @@ \tcode{\exposid{FWD-ENV}(get_env(sndr))}\iref{exec.fwd.env}. \item A parent sender with more than one child sender has -an associated attributes object equal to \tcode{empty_env\{\}}. +an associated attributes object equal to \tcode{env<>\{\}}. \item When a parent sender is connected to a receiver \tcode{rcvr}, any receiver used to connect a child sender has @@ -2682,11 +2711,11 @@ \pnum A \defnadj{pipeable}{sender adaptor closure object} is a function object -that accepts one or more \tcode{sender} arguments and returns a \tcode{sender}. +that accepts one or more \libconcept{sender} arguments and returns a \libconcept{sender}. For a pipeable sender adaptor closure object \tcode{c} and an expression \tcode{sndr} -such that \tcode{decltype((sndr))} models \tcode{sender}, -the following expressions are equivalent and yield a \tcode{sender}: +such that \tcode{decltype((sndr))} models \libconcept{sender}, +the following expressions are equivalent and yield a \libconcept{sender}: \begin{codeblock} c(sndr) sndr | c @@ -2719,7 +2748,7 @@ if \tcode{T} models \tcode{\libconcept{derived_from}>}, \tcode{T} has no other base classes of type \tcode{sender_adaptor_closure} for any other type \tcode{U}, and -\tcode{T} does not satisfy \tcode{sender}. +\tcode{T} does not satisfy \libconcept{sender}. \pnum The template parameter \tcode{D} for \tcode{sender_adaptor_closure} can be @@ -2734,8 +2763,8 @@ \pnum A \defnadj{pipeable}{sender adaptor object} is a customization point object -that accepts a \tcode{sender} as its first argument and -returns a \tcode{sender}. +that accepts a \libconcept{sender} as its first argument and +returns a \libconcept{sender}. If a pipeable sender adaptor object accepts only one argument, then it is a pipeable sender adaptor closure object. @@ -3046,15 +3075,14 @@ using result_t = @\exposid{decayed-tuple}@; constexpr bool nothrow = is_nothrow_constructible_v; - @\exposid{TRY-EVAL}@(rcvr, [&]() noexcept(nothrow) { + try { state.@\exposid{async-result}@.template emplace(Tag(), std::forward(args)...); - }()); - - if (state.@\exposid{async-result}@.valueless_by_exception()) - return; - if (state.@\exposid{async-result}@.index() == 0) - return; - + } catch (...) { + if constexpr (!nothrow) { + set_error(std::move(rcvr), current_exception()); + return; + } + } start(state.@\exposid{op-state}@); }; \end{codeblock} @@ -3380,7 +3408,7 @@ \item \tcode{\exposid{MAKE-ENV}(get_domain, get_domain(get_env(sndr)))} \item -\tcode{(void(sndr), empty_env\{\})} +\tcode{(void(sndr), env<>\{\})} \end{itemize} \pnum @@ -3441,7 +3469,7 @@ } decltype(auto) get_env() const noexcept { - return @\exposid{JOIN-ENV}@(@\exposid{env}@, @\exposid{FWD-ENV}@(execution::get_env(@\exposid{rcvr}@))); + return @\seebelow@; } Rcvr& @\exposid{rcvr}@; // \expos @@ -3449,6 +3477,18 @@ }; } \end{codeblock} +Invocation of the function \tcode{\exposid{receiver2}::get_env} +returns an object \tcode{e} such that +\begin{itemize} +\item +\tcode{decltype(e)} models \exposconcept{queryable} and +\item +given a query object \tcode{q}, +the expression \tcode{e.query(q)} is expression-equivalent +to \tcode{\exposid{env}.query(q)} if that expression is valid, +otherwise \tcode{e.query(q)} is expression-equivalent +to \tcode{get_env(\exposid{rcvr}).query(q)}. +\end{itemize} \pnum \tcode{\exposid{impls-for}<\exposid{decayed-typeof}<\exposid{let-cpo}>>::\exposid{get-state}} @@ -3640,7 +3680,7 @@ \item on a value completion operation, invokes \tcode{f(i, args...)} -for every \tcode{i} of type \tcode{Shape} from \tcode{0} to \tcode{shape}, +for every \tcode{i} of type \tcode{Shape} in \range{\tcode{0}}{\tcode{shape}}, where \tcode{args} is a pack of lvalue subexpressions referring to the value completion result datums of the input sender, and \item @@ -4081,7 +4121,7 @@ \begin{codeblock} [](auto&&, auto&&... child) noexcept { if constexpr (@\libconcept{same_as}@) { - return empty_env(); + return env<>(); } else { return @\exposid{MAKE-ENV}@(get_domain, CD()); } @@ -4094,10 +4134,20 @@ equivalent to the following lambda expression: \begin{codeblock} [](auto&&, State& state, const Receiver& rcvr) noexcept { - return @\exposid{JOIN-ENV}@( - @\exposid{MAKE-ENV}@(get_stop_token, state.@\exposid{stop_src}@.get_token()), get_env(rcvr)); + return @\seebelow@; } \end{codeblock} +Returns an object \tcode{e} such that +\begin{itemize} +\item +\tcode{decltype(e)} models \exposconcept{queryable}, and +\item +\tcode{e.query(get_stop_token)} is expression-equivalent to +\tcode{state.\exposid{stop-src}.get_token()}, and +\item +given a query object \tcode{q} with type other than \cv{} \tcode{stop_token_t}, +\tcode{e.query(q)} is expression-equivalent to \tcode{get_env(rcvr).query(q)}. +\end{itemize} \pnum The member \tcode{\exposid{impls-for}::\exposid{get-state}} @@ -4809,23 +4859,21 @@ template<@\exposconcept{completion-signature}@... Fns> struct completion_signatures {}; - template, template class Tuple = @\exposid{decayed-tuple}@, template class Variant = @\exposid{variant-or-empty}@> requires @\libconcept{sender_in}@ using value_types_of_t = @\exposid{gather-signatures}@, Tuple, Variant>; - template, template class Variant = @\exposid{variant-or-empty}@> requires @\libconcept{sender_in}@ using error_types_of_t = @\exposid{gather-signatures}@, type_identity_t, Variant>; - template + template> requires @\libconcept{sender_in}@ constexpr bool sends_stopped = !@\libconcept{same_as}@<@\exposid{type-list}@<>, @@ -4934,6 +4982,149 @@ of all the \tcode{completion_signatures} specializations in the set \tcode{AdditionalSignatures}, \tcode{Vs...}, \tcode{Es...}, \tcode{Ss}. +\rSec1[exec.envs]{Queryable utilities} + +\rSec2[exec.prop]{Class template \tcode{prop}} + +\begin{codeblock} +namespace std::execution { + template + struct @\libglobal{prop}@ { + QueryTag @\exposid{query_}@; // \expos + ValueType @\exposid{value_}@; // \expos + + constexpr const ValueType& query(QueryTag) const noexcept { + return @\exposid{value_}@; + } + }; + + template + prop(QueryTag, ValueType) -> prop>; +} +\end{codeblock} + +\pnum +Class template \tcode{prop} is for building a queryable object +from a query object and a value. + +\pnum +\mandates +\tcode{\exposconcept{callable}>} +is modeled, +where \exposid{prop-like} is the following exposition-only class template: +\begin{codeblock} +template +struct @\exposid{prop-like}@ { // \expos + const ValueType& query(auto) const noexcept; +}; +\end{codeblock} + +\pnum +\begin{example} +\begin{codeblock} +template +sender auto parameterize_work(Sndr sndr) { + // Make an environment such that \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}}. + auto e = prop(get_allocator, my_alloc{}); + + // Parameterize the input sender so that it will use our custom execution environment. + return write_env(sndr, e); +} +\end{codeblock} +\end{example} + +\pnum +Specializations of \tcode{prop} are not assignable. + +\rSec2[exec.env]{Class template \tcode{env}} + +\begin{codeblock} +namespace std::execution { + template<@\exposconcept{queryable}@... Envs> + struct @\libglobal{env}@ { + Envs@$_0$@ @$\exposid{envs}_0$@; // \expos + Envs@$_1$@ @$\exposid{envs}_1$@; // \expos + @\vdots@ + Envs@$_{n-1}$@ @$\exposid{envs}_{n-1}$@; // \expos + + template + constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@); + }; + + template + env(Envs...) -> env...>; +} +\end{codeblock} + +\pnum +The class template \tcode{env} is used to construct a queryable object +from several queryable objects. +Query invocations on the resulting object are resolved +by attempting to query each subobject in lexical order. + +\pnum +Specializations of \tcode{env} are not assignable. + +\pnum +It is unspecified +whether \tcode{env} supports initialization +using a parenthesized \grammarterm{expression-list}\iref{dcl.init}, +unless the \grammarterm{expression-list} consist of +a single element of type (possibly const) \tcode{env}. + +\pnum +\begin{example} +\begin{codeblock} +template +sender auto parameterize_work(Sndr sndr) { + // Make an environment such that: + // \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}} + // \tcode{get_scheduler(env)} returns a reference to a copy of \tcode{my_sched\{\}} + auto e = env{prop(get_allocator, my_alloc{}), + prop(get_scheduler, my_sched{})}; + + // Parameterize the input sender so that it will use our custom execution environment. + return write_env(sndr, e); +} +\end{codeblock} +\end{example} + +\indexlibrarymember{query}{env}% +\begin{itemdecl} +template +constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \exposconcept{has-query} be the following exposition-only concept: +\begin{codeblock} +template + concept @\defexposconcept{has-query}@ = // \expos + requires (const Env& env) { + env.query(QueryTag()); + }; +\end{codeblock} + +\pnum +Let \exposid{fe} be the first element of +$\exposid{envs}_0$, $\exposid{envs}_1$, $\dotsc$, $\exposid{envs}_{n-1}$ +such that the expression \tcode{\exposid{fe}.query(q)} is well-formed. + +\pnum +\constraints +\tcode{(\exposconcept{has-query} || ...)} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return \exposid{fe}.query(q);} + +\pnum +\remarks +The expression in the \tcode{noexcept} clause is equivalent +to \tcode{noexcept(\exposid{fe}.query(q))}. +\end{itemdescr} + \rSec1[exec.ctx]{Execution contexts} \rSec2[exec.run.loop]{\tcode{execution::run_loop}} @@ -4950,7 +5141,8 @@ A \tcode{run_loop} instance has an associated \defn{count} that corresponds to the number of work items that are in its queue. Additionally, a \tcode{run_loop} instance has an associated state -that can be one of \defn{starting}, \defn{running}, or \defn{finishing}. +that can be one of +\defn{starting}, \defn{running}, \defn{finishing}, or \defn{finished}. \pnum Concurrent invocations of the member functions of \tcode{run_loop} @@ -4966,7 +5158,7 @@ \begin{codeblock} namespace std::execution { - class run_loop { + class @\libglobal{run_loop}@ { // \ref{exec.run.loop.types}, associated types class @\exposid{run-loop-scheduler}@; // \expos class @\exposid{run-loop-sender}@; // \expos @@ -5004,7 +5196,7 @@ \pnum \exposid{run-loop-scheduler} is an unspecified type -that models \tcode{scheduler}. +that models \libconcept{scheduler}. \pnum Instances of \exposid{run-loop-scheduler} remain valid @@ -5027,7 +5219,7 @@ \pnum \exposid{run-loop-sender} is an exposition-only type -that satisfies \tcode{sender}. +that satisfies \libconcept{sender}. For any type \tcode{Env}, \tcode{completion_signatures_of_t<\exposid{run-loop-sender}, Env>} is \begin{codeblock} @@ -5102,6 +5294,7 @@ \rSec3[exec.run.loop.ctor]{Constructor and destructor} +\indexlibraryctor{run_loop}% \begin{itemdecl} run_loop() noexcept; \end{itemdecl} @@ -5112,6 +5305,7 @@ \exposid{count} is \tcode{0} and \exposid{state} is \exposid{starting}. \end{itemdescr} +\indexlibrarydtor{run_loop}% \begin{itemdecl} ~run_loop(); \end{itemdecl} @@ -5137,7 +5331,8 @@ \begin{itemize} \item \exposid{count} is \tcode{0} and \exposid{state} is \exposid{finishing}, -in which case \exposid{pop-front} returns \tcode{nullptr}; or +in which case \exposid{pop-front} sets \exposid{state} to \exposid{finished} +and returns \tcode{nullptr}; or \item \exposid{count} is greater than \tcode{0}, in which case an item is removed from the front of the queue, @@ -5162,6 +5357,7 @@ the \exposid{pop-front} operation that obtains \tcode{item}. \end{itemdescr} +\indexlibrarymember{get_scheduler}{run_loop}% \begin{itemdecl} @\exposid{run-loop-scheduler}@ get_scheduler(); \end{itemdecl} @@ -5173,6 +5369,7 @@ that can be used to schedule work onto this \tcode{run_loop} instance. \end{itemdescr} +\indexlibrarymember{run}{run_loop}% \begin{itemdecl} void run(); \end{itemdecl} @@ -5180,11 +5377,14 @@ \begin{itemdescr} \pnum \expects -\exposid{state} is \exposid{starting}. +\exposid{state} is either \exposid{starting} or \exposid{finishing}. \pnum \effects -Sets the \exposid{state} to \exposid{running}. Then, equivalent to: +If \exposid{state} is \exposid{starting}, +sets the \exposid{state} to \exposid{running}, +otherwise leaves \exposid{state} unchanged. +Then, equivalent to: \begin{codeblock} while (auto* op = @\exposid{pop-front}@()) { op->@\exposid{execute}@(); @@ -5196,11 +5396,16 @@ When \exposid{state} changes, it does so without introducing data races. \end{itemdescr} +\indexlibrarymember{finish}{run_loop}% \begin{itemdecl} void finish(); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\exposid{state} is either \exposid{starting} or \exposid{running}. + \pnum \effects Changes \exposid{state} to \exposid{finishing}. @@ -5396,14 +5601,14 @@ \begin{codeblock} namespace std::execution { template<@\exposconcept{class-type}@ Promise> - struct with_awaitable_senders { + struct @\libglobal{with_awaitable_senders}@ { template requires (!@\libconcept{same_as}@) void set_continuation(coroutine_handle h) noexcept; - coroutine_handle<> continuation() const noexcept { return @\exposid{continuation}@; } + coroutine_handle<> @\libmember{continuation}{with_awaitable_senders}@() const noexcept { return @\exposid{continuation}@; } - coroutine_handle<> unhandled_stopped() noexcept { + coroutine_handle<> @\libmember{unhandled_stopped}{with_awaitable_senders}@() noexcept { return @\exposid{stopped-handler}@(@\exposid{continuation}@.address()); } @@ -5422,6 +5627,7 @@ } \end{codeblock} +\indexlibrarymember{set_continuation}{with_awaitable_senders}% \begin{itemdecl} template requires (!@\libconcept{same_as}@) @@ -5445,6 +5651,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{await_transform}{with_awaitable_senders}% \begin{itemdecl} template @\exposid{call-result-t}@ await_transform(Value&& value); diff --git a/source/expressions.tex b/source/expressions.tex index 54e40c91a9..9589921d5b 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -266,7 +266,8 @@ \end{note} \pnum -Whenever a prvalue appears as an operand of an operator that +Unless otherwise specified\iref{expr.reinterpret.cast, expr.const.cast}, +whenever a prvalue appears as an operand of an operator that expects a glvalue for that operand, the temporary materialization conversion\iref{conv.rval} is applied to convert the expression to an xvalue. @@ -335,9 +336,13 @@ \indextext{expression!reference}% If an expression initially has the type ``reference to \tcode{T}''\iref{dcl.ref,dcl.init.ref}, the type is adjusted to -\tcode{T} prior to any further analysis. The expression designates the -object or function denoted by the reference, and the expression -is an lvalue or an xvalue, depending on the expression. +\tcode{T} prior to any further analysis; +the value category of the expression is not altered. +Let $X$ be the object or function denoted by the reference. +If a pointer to $X$ would be valid in +the context of the evaluation of the expression\iref{basic.fundamental}, +the result designates $X$; +otherwise, the behavior is undefined. \begin{note} Before the lifetime of the reference has started or after it has ended, the behavior is undefined (see~\ref{basic.life}). @@ -433,7 +438,8 @@ \pnum \label{term.unevaluated.operand}% In some contexts, \defnx{unevaluated operands}{unevaluated operand} -appear\iref{expr.prim.req, +appear\iref{expr.prim.req.simple, +expr.prim.req.compound, expr.typeid, expr.sizeof, expr.unary.noexcept, @@ -673,11 +679,26 @@ pointer value\iref{basic.stc.dynamic.deallocation}, the behavior is \impldef{lvalue-to-rvalue conversion of an invalid pointer value}. -\item Otherwise, the object indicated by the glvalue is read\iref{defns.access}, -and the value contained in the object is the prvalue result. -If the result is an erroneous value\iref{basic.indet} and -the bits in the value representation are not valid for the object's type, -the behavior is undefined. +\item Otherwise, if the bits in the value representation of +the object to which the glvalue refers +are not valid for the object's type, the behavior is undefined. +\begin{example} +\begin{codeblock} +bool f() { + bool b = true; + char c = 42; + memcpy(&b, &c, 1); + return b; // undefined behavior if \tcode{42} is not a valid value representation for \keyword{bool} +} +\end{codeblock} +\end{example} + +\item Otherwise, the object indicated by the glvalue is read\iref{defns.access}. +Let \tcode{V} be the value contained in the object. +If \tcode{T} is an integer type, +the prvalue result is +the value of type \tcode{T} congruent\iref{basic.fundamental} to \tcode{V}, and +\tcode{V} otherwise. \end{itemize} \pnum @@ -1825,8 +1846,7 @@ \begin{bnf} \nontermdef{lambda-specifier-seq}\br - lambda-specifier\br - lambda-specifier lambda-specifier-seq + lambda-specifier \opt{lambda-specifier-seq} \end{bnf} \pnum @@ -2656,7 +2676,7 @@ void g() { const int N = 10; [=] { - int arr[N]; // OK, not an odr-use, refers to automatic variable + int arr[N]; // OK, not an odr-use, refers to variable with automatic storage duration f(&N); // OK, causes \tcode{N} to be captured; \tcode{\&N} points to // the corresponding member of the closure type }; @@ -2844,6 +2864,9 @@ } \end{codeblock} \end{example} + +\pnum +A fold expression is a pack expansion. \indextext{expression!fold|)}% \rSec2[expr.prim.req]{Requires expressions} @@ -2875,8 +2898,7 @@ \begin{bnf} \nontermdef{requirement-seq}\br - requirement\br - requirement requirement-seq + requirement \opt{requirement-seq} \end{bnf} \begin{bnf} @@ -2890,8 +2912,6 @@ \pnum A \grammarterm{requires-expression} is a prvalue of type \tcode{bool} whose value is described below. -Expressions appearing within a \grammarterm{requirement-body} -are unevaluated operands\iref{term.unevaluated.operand}. \pnum \begin{example} @@ -2983,10 +3003,10 @@ \pnum A \grammarterm{simple-requirement} asserts the validity of an \grammarterm{expression}. +The \grammarterm{expression} is an unevaluated operand. \begin{note} The enclosing \grammarterm{requires-expression} will evaluate to \keyword{false} if substitution of template arguments into the \grammarterm{expression} fails. -The \grammarterm{expression} is an unevaluated operand\iref{term.unevaluated.operand}. \end{note} \begin{example} \begin{codeblock} @@ -3054,7 +3074,9 @@ \pnum A \grammarterm{compound-requirement} asserts properties -of the \grammarterm{expression} $E$. Substitution +of the \grammarterm{expression} $E$. +The \grammarterm{expression} is an unevaluated operand. +Substitution of template arguments (if any) and verification of semantic properties proceed in the following order: @@ -3529,6 +3551,9 @@ if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise. +If it is a non-void prvalue, +the type of the function call expression shall be complete, +except as specified in \ref{dcl.type.decltype}. \rSec3[expr.type.conv]{Explicit type conversion (functional notation)} @@ -3555,6 +3580,44 @@ Otherwise, if the type contains a placeholder type, it is replaced by the type determined by placeholder type deduction\iref{dcl.type.auto.deduct}. +Let \tcode{T} denote the resulting type. +Then: + +\begin{itemize} +\item +If the initializer is a parenthesized single expression, +the type conversion expression is equivalent +to the corresponding cast +expression\iref{expr.cast}. + +\item +\indextext{type!incomplete}% +Otherwise, if \tcode{T} is \cv{}~\keyword{void}, +the initializer shall be \tcode{()} or \tcode{\{\}} +(after pack expansion, if any), and +the expression is a prvalue of type \keyword{void} +that performs no initialization. + +\item +Otherwise, if \tcode{T} is a reference type, +the expression has the same effect as +direct-initializing an invented variable \tcode{t} of type \tcode{T} from +the initializer and then +using \tcode{t} as the result of the expression; +the result is an lvalue if +\tcode{T} is an lvalue reference type or +an rvalue reference to function type and +an xvalue otherwise. + +\item +Otherwise, +the expression is a prvalue of type \tcode{T} +whose result object is direct-initialized\iref{dcl.init} +with the initializer. +\end{itemize} + +If the initializer is a parenthesized optional \grammarterm{expression-list}, +\tcode{T} shall not be an array type. \begin{example} \begin{codeblock} struct A {}; @@ -3569,24 +3632,6 @@ \end{codeblock} \end{example} -\pnum -If the initializer is a parenthesized single expression, -the type conversion expression is equivalent -to the corresponding cast -expression\iref{expr.cast}. -\indextext{type!incomplete}% -Otherwise, if the type is \cv{}~\keyword{void} -and the initializer is \tcode{()} or \tcode{\{\}} -(after pack expansion, if any), -the expression is a prvalue of type \keyword{void} -that performs no initialization. -Otherwise, -the expression is a prvalue of the specified type -whose result object is direct-initialized\iref{dcl.init} -with the initializer. -If the initializer is a parenthesized optional \grammarterm{expression-list}, -the specified type shall not be an array type. - \rSec3[expr.ref]{Class member access} \pnum @@ -3772,8 +3817,8 @@ \indextext{operator!increment}% \indextext{\idxcode{++}|see{operator, increment}}% \indextext{postfix \tcode{++}}% -The value of a postfix \tcode{++} expression is the value of its -operand. +The value of a postfix \tcode{++} expression is the value obtained by +applying the lvalue-to-rvalue conversion\iref{conv.lval} to its operand. \begin{note} The value obtained is a copy of the original value. \end{note} @@ -4388,9 +4433,6 @@ \tcode{T2}'' (where \tcode{T1} and \tcode{T2} are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified. -\begin{note} -See also~\ref{conv.ptr} for more details of pointer conversions. -\end{note} \pnum An object pointer @@ -4465,22 +4507,25 @@ \indextext{cast!reinterpret!reference}% \indextext{cast!reference}% \indextext{type pun}% -A glvalue of type \tcode{T1}, +If \tcode{v} is a glvalue of type \tcode{T1}, designating an object or function \placeholder{x}, -can be cast to the type ``reference to \tcode{T2}'' +it can be cast to the type ``reference to \tcode{T2}'' if an expression of type ``pointer to \tcode{T1}'' can be explicitly converted to the type ``pointer to \tcode{T2}'' using a \keyword{reinterpret_cast}. The result is that of \tcode{*reinterpret_cast(p)} where \tcode{p} is a pointer to \placeholder{x} of type ``pointer to \tcode{T1}''. -No temporary is created, no copy is made, and +\begin{note} +No temporary is materialized\iref{conv.rval} or created, +no copy is made, and no constructors\iref{class.ctor} or conversion functions\iref{class.conv} are called. \begin{footnote} This is sometimes referred to as a type pun when the result refers to the same object as the source glvalue. \end{footnote} +\end{note} \rSec3[expr.const.cast]{Const cast} @@ -4494,7 +4539,10 @@ otherwise, the result is a prvalue and the lvalue-to-rvalue\iref{conv.lval}, array-to-pointer\iref{conv.array}, and function-to-pointer\iref{conv.func} standard conversions are -performed on the expression \tcode{v}. Conversions that can be performed explicitly using +performed on the expression \tcode{v}. +The temporary materialization conversion\iref{conv.rval} is not +performed on \tcode{v}, other than as specified below. +Conversions that can be performed explicitly using \keyword{const_cast} are listed below. No other conversion shall be performed explicitly using \keyword{const_cast}. @@ -4505,23 +4553,16 @@ \end{note} \pnum -For two similar types \tcode{T1} and \tcode{T2}\iref{conv.qual}, -a prvalue of type \tcode{T1} may be explicitly +For two similar object pointer or pointer to data member types +\tcode{T1} and \tcode{T2}\iref{conv.qual}, +a prvalue of type \tcode{T1} can be explicitly converted to the type \tcode{T2} using a \keyword{const_cast} if, considering the qualification-decompositions of both types, each $P^1_i$ is the same as $P^2_i$ for all $i$. -The result of a \keyword{const_cast} refers to the original entity. -\begin{example} -\begin{codeblock} -typedef int *A[3]; // array of 3 pointer to \tcode{int} -typedef const int *const CA[3]; // array of 3 const pointer to \tcode{const int} - -CA &&r = A{}; // OK, reference binds to temporary array object - // after qualification conversion to type \tcode{CA} -A &&r1 = const_cast(CA{}); // error: temporary array decayed to pointer -A &&r2 = const_cast(CA{}); // OK -\end{codeblock} -\end{example} +If \tcode{v} is a null pointer or null member pointer, +the result is a null pointer or null member pointer, respectively. +Otherwise, the result points to or past the end of the same object, or +points to the same member, respectively, as \tcode{v}. \pnum For two object types \tcode{T1} and \tcode{T2}, if a pointer to \tcode{T1} can @@ -4534,20 +4575,22 @@ \item a glvalue of type \tcode{T1} can be explicitly converted to an xvalue of type \tcode{T2} using the cast \tcode{\keyword{const_cast}}; and -\item if \tcode{T1} is a class type, a prvalue of type \tcode{T1} can be +\item if \tcode{T1} is a class or array type, +a prvalue of type \tcode{T1} can be explicitly converted to an xvalue of type \tcode{T2} using the cast \tcode{\keyword{const_cast}}. +The temporary materialization conversion is performed on \tcode{v}. \end{itemize} -The result of a reference \keyword{const_cast} refers -to the original object if the operand is a glvalue and -to the result of applying the temporary materialization conversion\iref{conv.rval} otherwise. +The result refers to the same object as the (possibly converted) operand. +\begin{example} +\begin{codeblock} +typedef int *A[3]; // array of 3 pointer to \tcode{int} +typedef const int *const CA[3]; // array of 3 const pointer to \tcode{const int} -\pnum -A null pointer value\iref{basic.compound} is converted to the null pointer -value of the destination type. The null member pointer -value\iref{conv.mem} is converted to the null member pointer value of -the destination type. +auto &&r2 = const_cast(CA{}); // OK, temporary materialization conversion is performed +\end{codeblock} +\end{example} \pnum \begin{note} @@ -6626,13 +6669,11 @@ \end{bnf} % The -lvalue-to-rvalue\iref{conv.lval}, -array-to-pointer\iref{conv.array}, +lvalue-to-rvalue\iref{conv.lval} and function-to-pointer\iref{conv.func} standard conversions are performed on the operands. -The comparison is deprecated if -both operands were of array type -prior to these conversions\iref{depr.array.comp}. +If one of the operands is a pointer, the +array-to-pointer conversion\iref{conv.array} is performed on the other operand. \pnum The converted operands shall have arithmetic, enumeration, or pointer type. @@ -6644,7 +6685,7 @@ \pnum The usual arithmetic conversions\iref{expr.arith.conv} are performed on operands of arithmetic -or enumeration type. If both operands are pointers, +or enumeration type. If both converted operands are pointers, pointer conversions\iref{conv.ptr}, function pointer conversions\iref{conv.fctptr}, and qualification conversions\iref{conv.qual} @@ -6717,17 +6758,15 @@ The \tcode{==} (equal to) and the \tcode{!=} (not equal to) operators group left-to-right. The -lvalue-to-rvalue\iref{conv.lval}, -array-to-pointer\iref{conv.array}, +lvalue-to-rvalue\iref{conv.lval} and function-to-pointer\iref{conv.func} standard conversions are performed on the operands. -The comparison is deprecated if -both operands were of array type -prior to these conversions\iref{depr.array.comp}. +If one of the operands is a pointer or a null pointer constant\iref{conv.ptr}, +the array-to-pointer conversion\iref{conv.array} is performed +on the other operand. \pnum -The converted operands shall have arithmetic, enumeration, pointer, -or pointer-to-member type, or type \tcode{std::nullptr_t}. The operators +The converted operands shall have scalar type. The operators \tcode{==} and \tcode{!=} both yield \keyword{true} or \keyword{false}, i.e., a result of type \keyword{bool}. In each case below, the operands shall have the same type after the specified conversions have been applied. @@ -6735,7 +6774,7 @@ \pnum \indextext{comparison!pointer}% \indextext{comparison!pointer to function}% -If at least one of the operands is a pointer, +If at least one of the converted operands is a pointer, pointer conversions\iref{conv.ptr}, function pointer conversions\iref{conv.fctptr}, and qualification conversions\iref{conv.qual} @@ -7117,30 +7156,32 @@ subclause. \pnum -Lvalue-to-rvalue\iref{conv.lval}, array-to-pointer\iref{conv.array}, +Array-to-pointer\iref{conv.array} and function-to-pointer\iref{conv.func} standard conversions are performed on the second and third operands. After those conversions, one of the following shall hold: \begin{itemize} \item The second and third operands have the same type; the result is of -that type and the result object is initialized using the selected operand. +that type and the result is copy-initialized using the selected operand. \item The second and third operands have arithmetic or enumeration type; the usual arithmetic conversions\iref{expr.arith.conv} are performed to bring them to a common type, and the result is of that type. \item One or both of the second and third operands have pointer type; -pointer conversions\iref{conv.ptr}, -function pointer conversions\iref{conv.fctptr}, and +lvalue-to-rvalue\iref{conv.lval}, +pointer\iref{conv.ptr}, +function pointer\iref{conv.fctptr}, and qualification conversions\iref{conv.qual} are performed to bring them to their composite pointer type\iref{expr.type}. The result is of the composite pointer type. \item One or both of the second and third operands have pointer-to-member type; -pointer to member conversions\iref{conv.mem}, -function pointer conversions\iref{conv.fctptr}, and +lvalue-to-rvalue\iref{conv.lval}, +pointer to member\iref{conv.mem}, +function pointer\iref{conv.fctptr}, and qualification conversions\iref{conv.qual} are performed to bring them to their composite pointer type\iref{expr.type}. The result is of the composite pointer type. @@ -7307,9 +7348,13 @@ \end{bnf} \pnum -In simple assignment (\tcode{=}), the object referred to by the left operand -is modified\iref{defns.access} -by replacing its value with the result of the right operand. +In simple assignment (\tcode{=}), +let \tcode{V} be the result of the right operand; +the object referred to by the left operand is +modified\iref{defns.access} by replacing its value +with \tcode{V} or, +if the object is of integer type, +with the value congruent\iref{basic.fundamental} to \tcode{V}. \pnum \indextext{assignment!conversion by}% @@ -7449,27 +7494,140 @@ \end{bnf} \pnum -A variable or temporary object \tcode{o} is \defn{constant-initialized} if +The \defnx{constituent values}{constituent value} of an object $o$ are +\begin{itemize} +\item +if $o$ has scalar type, the value of $o$; +\item +otherwise, the constituent values of any direct subobjects of $o$ +other than inactive union members. +\end{itemize} +The \defnx{constituent references}{constituent reference} of an object $o$ are +\begin{itemize} +\item +any direct members of $o$ that have reference type, and +\item +the constituent references of any direct subobjects of $o$ +other than inactive union members. +\end{itemize} + +\pnum +The constituent values and constituent references of +a variable \tcode{x} are defined as follows: +\begin{itemize} +\item +If \tcode{x} declares an object, +the constituent values and references of that object are +constituent values and references of \tcode{x}. +\item +If \tcode{x} declares a reference, +that reference is a constituent reference of \tcode{x}. +\end{itemize} +For any constituent reference \tcode{r} of a variable \tcode{x}, +if \tcode{r} is bound to a temporary object or subobject thereof +whose lifetime is extended to that of \tcode{r}, +the constituent values and references of that temporary object +are also constituent values and references of \tcode{x}, recursively. + +\pnum +An object $o$ is \defn{constexpr-referenceable} from a point $P$ if +\begin{itemize} +\item +$o$ has static storage duration, or +\item +$o$ has automatic storage duration, and, letting \tcode{v} denote +\begin{itemize} +\item +the variable corresponding to $o$'s complete object or +\item +the variable to whose lifetime that of $o$ is extended, +\end{itemize} +the smallest scope enclosing \tcode{v} and the smallest scope enclosing $P$ +that are neither +\begin{itemize} +\item +block scopes nor +\item +function parameter scopes associated with +a \grammarterm{requirement-parameter-list} +\end{itemize} +are the same function parameter scope. +\end{itemize} +\begin{example} +\begin{codeblock} +struct A { + int m; + const int& r; +}; +void f() { + static int sx; + thread_local int tx; // \tcode{tx} is never constexpr-referenceable + int ax; + A aa = {1, 2}; + static A sa = {3, 4}; + // The objects \tcode{sx}, \tcode{ax}, and \tcode{aa.m}, \tcode{sa.m}, and the temporaries to which \tcode{aa.r} and \tcode{sa.r} are bound, are constexpr-referenceable. + auto lambda = [] { + int ay; + // The objects \tcode{sx}, \tcode{sa.m}, and \tcode{ay} (but not \tcode{ax} or \tcode{aa}), and the + // temporary to which \tcode{sa.r} is bound, are constexpr-referenceable. + }; +} +\end{codeblock} +\end{example} + +\pnum +An object or reference \tcode{x} is +\defn{constexpr-representable} at a point $P$ if, +for each constituent value of \tcode{x} that points to or past an object $o$, +and for each constituent reference of \tcode{x} that refers to an object $o$, +$o$ is constexpr-referenceable from $P$. + +\pnum +A variable \tcode{v} is \defn{constant-initializable} if \begin{itemize} \item - either it has an initializer or - its default-initialization results in some initialization being performed, and -\item - the full-expression of its initialization is a constant expression - when interpreted as a \grammarterm{constant-expression}, - except that if \tcode{o} is an object, - that full-expression - may also invoke constexpr constructors - for \tcode{o} and its subobjects - even if those objects are of non-literal class types. - \begin{note} - Such a class can have a non-trivial destructor. - Within this evaluation, - \tcode{std::is_constant_evaluated()}\iref{meta.const.eval} - returns \keyword{true}. +the full-expression of its initialization is a constant expression +when interpreted as a \grammarterm{constant-expression}, +\begin{note} +Within this evaluation, +\tcode{std::is_constant_evaluated()}\iref{meta.const.eval} +returns \keyword{true}. \end{note} +and +\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 default-initialization results in some initialization being performed. +\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 @@ -7484,16 +7642,43 @@ \item $V$ is not initialized to a TU-local value, or \item $P$ is in the same translation unit as $D$. \end{itemize} -An object or reference is \defn{usable in constant expressions} if it is +An object or reference is +\defn{potentially usable in constant expressions} at point $P$ if it is \begin{itemize} -\item a variable that is usable in constant expressions, or -\item a template parameter object\iref{temp.param}, or -\item a string literal object\iref{lex.string}, or -\item a temporary object of non-volatile const-qualified literal type - whose lifetime is extended\iref{class.temporary} - to that of a variable that is usable in constant expressions, or -\item a non-mutable subobject or reference member of any of the above. +\item +the object or reference declared by a variable +that is usable in constant expressions at $P$, +\item +a temporary object of non-volatile const-qualified literal type +whose lifetime is extended\iref{class.temporary} +to that of a variable that is usable in constant expressions at $P$, +\item +a template parameter object\iref{temp.param}, +\item +a string literal object\iref{lex.string}, +\item +a non-mutable subobject of any of the above, or +\item +a reference member of any of the above. \end{itemize} +An object or reference is \defn{usable in constant expressions} at point $P$ +if it is an object or reference +that is potentially usable in constant expressions at $P$ and +is constexpr-representable at $P$. +\begin{example} +\begin{codeblock} +struct A { + int* const & r; +}; +void f(int x) { + constexpr A a = {&x}; + static_assert(a.r == &x); // OK + [&] { + static_assert(a.r != nullptr); // error: \tcode{a.r} is not usable in constant expressions at this point + }(); +} +\end{codeblock} +\end{example} \pnum An expression $E$ is a \defnadj{core constant}{expression} @@ -7552,8 +7737,7 @@ \item an operation that would have undefined or erroneous behavior -as specified in \ref{intro} through \ref{cpp}, -excluding \ref{dcl.attr.assume} and \ref{dcl.attr.noreturn}; +as specified in \ref{intro} through \ref{\lastcorechapter}; \begin{footnote} This includes, for example, signed integer overflow\iref{expr.pre}, certain @@ -7565,6 +7749,9 @@ an lvalue-to-rvalue conversion\iref{conv.lval} unless it is applied to \begin{itemize} + \item + a glvalue of type \cv \tcode{std::nullptr_t}, + \item a non-volatile glvalue that refers to an object that is usable in constant expressions, or @@ -7609,7 +7796,8 @@ \begin{note} If the odr-use occurs in an invocation of a function call operator of a closure type, -it no longer refers to \keyword{this} or to an enclosing automatic variable +it no longer refers to \keyword{this} or to an enclosing +variable with automatic storage duration due to the transformation\iref{expr.prim.lambda.capture} of the \grammarterm{id-expression} into an access of the corresponding data member. @@ -7664,9 +7852,9 @@ \begin{itemize} \item the placement argument to the \grammarterm{new-expression} points to -an object that is pointer-interconvertible with an object of type \tcode{T} or, -if T is an array type, -with the first element of an object of type \tcode{T}, and +an object whose type is similar to \tcode{T}\iref{conv.qual} or, +if \tcode{T} is an array type, +to the first element of an object of a type similar to \tcode{T}, and \item the placement argument points to storage whose duration began within the evaluation of $E$; @@ -7689,6 +7877,13 @@ unless it deallocates a region of storage allocated within the evaluation of $E$; +\item +a construction of an exception object, +unless the exception object and +all of its implicit copies created by invocations of +\tcode{std::current_exception} or \tcode{std::rethrow_exception}\iref{propagation} +are destroyed within the evaluation of $E$; + \item an \grammarterm{await-expression}\iref{expr.await}; @@ -7700,15 +7895,18 @@ relational\iref{expr.rel}, or equality\iref{expr.eq} operator where the result is unspecified; -\item -a \grammarterm{throw-expression}\iref{expr.throw}; - \item a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or \keyword{typeid}\iref{expr.typeid} expression on a glvalue that refers to an object -whose dynamic type is constexpr-unknown or -that would throw an exception; +whose dynamic type is constexpr-unknown; + +\item +a \tcode{dynamic_cast}\iref{expr.dynamic.cast} expression, +\tcode{typeid}\iref{expr.typeid} expression, or +\tcode{new-expression}\iref{expr.new} +that would throw an exception +where no definition of the exception type is reachable; \item an \grammarterm{asm-declaration}\iref{dcl.asm}; @@ -7730,6 +7928,13 @@ \end{note} \end{itemize} +\pnum +It is +\impldef{whether an expression is a core constant expression} +whether $E$ is a core constant expression +if $E$ satisfies the constraints of a core constant expression, but +evaluation of $E$ has runtime-undefined behavior. + \pnum It is unspecified whether $E$ is a core constant expression if $E$ satisfies the constraints of a core constant expression, but @@ -7737,26 +7942,9 @@ \begin{itemize} \item an operation that has undefined behavior -as specified in \ref{library} through \ref{\lastlibchapter}, +as specified in \ref{library} through \ref{\lastlibchapter} or \item -an invocation of the \tcode{va_start} macro\iref{cstdarg.syn}, -\item -a call to a function -that was previously declared -with the \tcode{noreturn} attribute\iref{dcl.attr.noreturn} and -that call returns to its caller, or -\item -a statement with an assumption\iref{dcl.attr.assume} -whose converted \grammarterm{conditional-expression}, -if evaluated where the assumption appears, -would not disqualify $E$ from being a core constant expression and -would not evaluate to \tcode{true}. -\begin{note} -$E$ is not disqualified from being a core constant expression -if the hypothetical evaluation of -the converted \grammarterm{conditional-expression} -would disqualify $E$ from being a core constant expression. -\end{note} +an invocation of the \tcode{va_start} macro\iref{cstdarg.syn}. \end{itemize} \pnum @@ -7816,6 +8004,45 @@ The copy/move of the active member is trivial. \end{note} +\pnum +For the purposes of determining whether $E$ is a core constant expression, +the evaluation of an \grammarterm{id-expression} +that names a structured binding \tcode{v}\iref{dcl.struct.bind} has the +following semantics: +\begin{itemize} +\item +If \tcode{v} is an lvalue referring to the object bound to an invented reference \tcode{r}, +the behavior is as if \tcode{r} were nominated. +\item +Otherwise, if \tcode{v} names an array element or class member, +the behavior is that of +evaluating \tcode{$e$[$i$]} or \tcode{$e$.$m$}, respectively, +where $e$ is the name of the variable +initialized from the initializer of the structured binding declaration, and +$i$ is the index of the element referred to by \tcode{v} or +$m$ is the name of the member referred to by \tcode{v}, respectively. +\end{itemize} +\begin{example} +\begin{codeblock} +#include +struct S { + mutable int m; + constexpr S(int m): m(m) {} + virtual int g() const; +}; +void f(std::tuple t) { + auto [r] = t; + static_assert(r.g() >= 0); // error: dynamic type is constexpr-unknown + constexpr auto [m] = S(1); + static_assert(m == 1); // error: lvalue-to-rvalue conversion on mutable + // subobject \tcode{e.m}, where \tcode{e} is a constexpr object of type \tcode{S} + using A = int[2]; + constexpr auto [v0, v1] = A{2, 3}; + static_assert(v0 + v1 == 5); // OK, equivalent to \tcode{e[0] + e[1]} where \tcode{e} is a constexpr array +} +\end{codeblock} +\end{example} + \pnum During the evaluation of an expression $E$ as a core constant expression, all \grammarterm{id-expression}s and uses of \tcode{*\keyword{this}} @@ -7972,40 +8199,20 @@ \pnum A \defnadj{constant}{expression} is either a glvalue core constant expression that refers to -an entity that is a permitted result of a constant expression (as defined below), or +an object or a non-immediate function, or a prvalue core constant expression whose value satisfies the following constraints: \begin{itemize} - \item - if the value is an object of class type, - each non-static data member of reference type refers to - an entity that is a permitted result of a constant expression, - - \item - if the value is an object of scalar type, - it does not have an indeterminate or erroneous value\iref{basic.indet}, - - \item - if the value is of pointer type, it is - a pointer to an object with static storage duration, - a pointer past the end of such an object\iref{expr.add}, - a pointer to a non-immediate function, - or a null pointer value, - - \item - if the value is of pointer-to-member-function type, - it does not designate an immediate function, and - - \item - if the value is an object of class or array type, - each subobject satisfies these constraints for the value. +\item +each constituent reference refers to an object or a non-immediate function, +\item +no constituent value of scalar type is an indeterminate value\iref{basic.indet}, +\item +no constituent value of pointer type is a pointer to an immediate function or +an invalid pointer value\iref{basic.compound}, and +\item +no constituent value of pointer-to-member type designates an immediate function. \end{itemize} -An entity is a -\defnx{permitted result of a constant expression}{constant expression!permitted result of} -if it is an -object with static storage duration that either is not a temporary object or is -a temporary object whose value satisfies the above constraints, or if -it is a non-immediate function. \begin{note} A glvalue core constant expression that either refers to or points to an unspecified object diff --git a/source/future.tex b/source/future.tex index a16d108869..f29866fcc7 100644 --- a/source/future.tex +++ b/source/future.tex @@ -16,6 +16,26 @@ An implementation may declare library names and entities described in this Clause with the \tcode{deprecated} attribute\iref{dcl.attr.deprecated}. +\rSec1[depr.local]{Non-local use of TU-local entities} + +\pnum +A declaration of a non-TU-local entity that is an exposure\iref{basic.link} +is deprecated. +\begin{note} +Such a declaration in an importable module unit is ill-formed. +\end{note} +\begin{example} +\begin{codeblock} +namespace { + struct A { + void f() {} + }; +} +A h(); // deprecated: not internal linkage +inline void g() {A().f();} // deprecated: inline and not internal linkage +\end{codeblock} +\end{example} + \rSec1[depr.capture.this]{Implicit capture of \tcode{*this} by reference} \pnum @@ -35,25 +55,6 @@ \end{codeblock} \end{example} -\rSec1[depr.array.comp]{Array comparisons} - -\pnum -Equality and relational comparisons\iref{expr.eq,expr.rel} -between two operands of array type -are deprecated. -\begin{note} -Three-way comparisons\iref{expr.spaceship} between such operands are ill-formed. -\end{note} -\begin{example} -\begin{codeblock} -int arr1[5]; -int arr2[5]; -bool same = arr1 == arr2; // deprecated, same as \tcode{\&arr1[0] == \&arr2[0]}, - // does not compare array contents -auto cmp = arr1 <=> arr2; // error -\end{codeblock} -\end{example} - \rSec1[depr.volatile.type]{Deprecated \tcode{volatile} types} \pnum @@ -114,41 +115,17 @@ \end{codeblock} \end{example} +\rSec1[depr.ellipsis.comma]{Non-comma-separated ellipsis parameters} -\rSec1[depr.static.constexpr]{Redeclaration of \tcode{static constexpr} data members} - -\pnum -For compatibility with prior revisions of \Cpp{}, a \keyword{constexpr} -static data member may be redundantly redeclared outside the class with no -initializer\iref{basic.def,class.static.data}. -This usage is deprecated. +A \grammarterm{parameter-declaration-clause} +of the form +\grammarterm{parameter-declaration-list} \tcode{...} +is deprecated\iref{dcl.fct}. \begin{example} \begin{codeblock} -struct A { - static constexpr int n = 5; // definition (declaration in \CppXIV{}) -}; - -constexpr int A::n; // redundant declaration (definition in \CppXIV{}) -\end{codeblock} -\end{example} - -\rSec1[depr.local]{Non-local use of TU-local entities} - -\pnum -A declaration of a non-TU-local entity that is an exposure\iref{basic.link} -is deprecated. -\begin{note} -Such a declaration in an importable module unit is ill-formed. -\end{note} -\begin{example} -\begin{codeblock} -namespace { - struct A { - void f() {} - }; -} -A h(); // deprecated: not internal linkage -inline void g() {A().f();} // deprecated: inline and not internal linkage +void f(int...); // deprecated +void g(auto...); // OK, declares a function parameter pack +void h(auto......); // deprecated \end{codeblock} \end{example} @@ -166,6 +143,23 @@ It is possible that future versions of \Cpp{} will specify that these implicit definitions are deleted\iref{dcl.fct.def.delete}. +\rSec1[depr.static.constexpr]{Redeclaration of \tcode{static constexpr} data members} + +\pnum +For compatibility with prior revisions of \Cpp{}, a \keyword{constexpr} +static data member may be redundantly redeclared outside the class with no +initializer\iref{basic.def,class.static.data}. +This usage is deprecated. +\begin{example} +\begin{codeblock} +struct A { + static constexpr int n = 5; // definition (declaration in \CppXIV{}) +}; + +constexpr int A::n; // redundant declaration (definition in \CppXIV{}) +\end{codeblock} +\end{example} + \rSec1[depr.lit]{Literal operator function declarations using an identifier} \pnum @@ -187,13 +181,12 @@ \pnum The following type is defined in addition to those specified in \libheaderref{limits}: -\indexlibraryglobal{float_denorm_style}% \begin{codeblock} namespace std { - enum float_denorm_style { - denorm_indeterminate = -1, - denorm_absent = 0, - denorm_present = 1 + enum @\libglobal{float_denorm_style}@ { + @\libmember{denorm_indeterminate}{float_denorm_style}@ = -1, + @\libmember{denorm_absent}{float_denorm_style}@ = 0, + @\libmember{denorm_present}{float_denorm_style}@ = 1 }; } \end{codeblock} @@ -244,86 +237,6 @@ #define @\xname{bool_true_false_are_defined}@ 1 \end{codeblock} -\rSec1[depr.relops]{Relational operators}% -\indexlibraryglobal{rel_ops}% - -\pnum -The header \libheaderref{utility} has the following additions: - -\begin{codeblock} -namespace std::rel_ops { - template bool operator!=(const T&, const T&); - template bool operator> (const T&, const T&); - template bool operator<=(const T&, const T&); - template bool operator>=(const T&, const T&); -} -\end{codeblock} - -\pnum -To avoid redundant definitions of \tcode{operator!=} out of \tcode{operator==} -and operators \tcode{>}, \tcode{<=}, and \tcode{>=} out of \tcode{operator<}, -the library provides the following: - -\indexlibrary{\idxcode{operator"!=}}% -\begin{itemdecl} -template bool operator!=(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{T} meets the \oldconcept{EqualityComparable} requirements (\tref{cpp17.equalitycomparable}). - -\pnum -\returns -\tcode{!(x == y)}. -\end{itemdescr} - -\indexlibraryglobal{operator>}% -\begin{itemdecl} -template bool operator>(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). - -\pnum -\returns -\tcode{y < x}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator<=}}% -\begin{itemdecl} -template bool operator<=(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). - -\pnum -\returns -\tcode{!(y < x)}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator>=}}% -\begin{itemdecl} -template bool operator>=(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). - -\pnum -\returns -\tcode{!(x < y)}. -\end{itemdescr} - \rSec1[depr.cerrno]{Deprecated error numbers} \pnum @@ -348,10 +261,10 @@ in addition to those specified in \ref{system.error.syn}: \begin{codeblock} -no_message_available, // \tcode{ENODATA} -no_stream_resources, // \tcode{ENOSR} -not_a_stream, // \tcode{ENOSTR} -stream_timeout, // \tcode{ETIME} +@\libmember{no_message_available}{errc}@, // \tcode{ENODATA} +@\libmember{no_stream_resources}{errc}@, // \tcode{ENOSR} +@\libmember{not_a_stream}{errc}@, // \tcode{ENOSTR} +@\libmember{stream_timeout}{errc}@, // \tcode{ETIME} \end{codeblock} \pnum @@ -367,6 +280,8 @@ \begin{codeblock} namespace std { + template struct is_trivial; + template constexpr bool is_trivial_v = is_trivial::value; template struct is_pod; template constexpr bool is_pod_v = is_pod::value; template // \seebelow @@ -385,6 +300,17 @@ any of the templates defined in this subclause is undefined, unless explicitly permitted by the specification of the corresponding template. +\pnum +\label{term.trivial.type}% +A \defnadj{trivial}{class} is a class that is trivially copyable and +has one or more eligible default constructors, all of which are trivial. +\begin{note} +In particular, +a trivial class does not have virtual functions or virtual base classes. +\end{note} +A \defnadj{trivial}{type} is a scalar type, a trivial class, +an array of such a type, or a cv-qualified version of one of these types. + \pnum \indextext{POD}% A \term{POD class} is a class that is both a trivial class and a @@ -392,6 +318,30 @@ (or array thereof). A \term{POD type} is a scalar type, a POD class, an array of such a type, or a cv-qualified version of one of these types. +\indexlibraryglobal{is_trivial}% +\begin{itemdecl} +template struct is_trivial; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{remove_all_extents_t} shall be a complete type or \cv{} \keyword{void}. + +\pnum +\remarks +\tcode{is_trivial} is a \oldconcept{UnaryTypeTrait}\iref{meta.rqmts} +with a base characteristic of \tcode{true_type} +if \tcode{T} is a trivial type, +and \tcode{false_type} otherwise. + +\pnum +\begin{note} +It is unspecified +whether a closure type\iref{expr.prim.lambda.closure} is a trivial type. +\end{note} +\end{itemdescr} + \indexlibraryglobal{is_pod}% \begin{itemdecl} template struct is_pod; @@ -483,6 +433,86 @@ whose value is the strictest alignment of all types listed in \tcode{Types}. \end{itemdescr} +\rSec1[depr.relops]{Relational operators}% +\indexlibraryglobal{rel_ops}% + +\pnum +The header \libheaderref{utility} has the following additions: + +\begin{codeblock} +namespace std::rel_ops { + template bool operator!=(const T&, const T&); + template bool operator> (const T&, const T&); + template bool operator<=(const T&, const T&); + template bool operator>=(const T&, const T&); +} +\end{codeblock} + +\pnum +To avoid redundant definitions of \tcode{operator!=} out of \tcode{operator==} +and operators \tcode{>}, \tcode{<=}, and \tcode{>=} out of \tcode{operator<}, +the library provides the following: + +\indexlibrary{\idxcode{operator"!=}}% +\begin{itemdecl} +template bool operator!=(const T& x, const T& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{EqualityComparable} requirements (\tref{cpp17.equalitycomparable}). + +\pnum +\returns +\tcode{!(x == y)}. +\end{itemdescr} + +\indexlibraryglobal{operator>}% +\begin{itemdecl} +template bool operator>(const T& x, const T& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). + +\pnum +\returns +\tcode{y < x}. +\end{itemdescr} + +\indexlibrary{\idxcode{operator<=}}% +\begin{itemdecl} +template bool operator<=(const T& x, const T& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). + +\pnum +\returns +\tcode{!(y < x)}. +\end{itemdescr} + +\indexlibrary{\idxcode{operator>=}}% +\begin{itemdecl} +template bool operator>=(const T& x, const T& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). + +\pnum +\returns +\tcode{!(x < y)}. +\end{itemdescr} + \rSec1[depr.tuple]{Tuple} \pnum @@ -674,34 +704,6 @@ \tcode{current}. \end{itemdescr} -\rSec1[depr.format]{Deprecated formatting} - -\rSec2[depr.format.syn]{Header \tcode{} synopsis} - -\pnum -The header \libheaderref{format}{format.syn} has the following additions: - -\begin{codeblock} -namespace std { - template - decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); -} -\end{codeblock} - -\rSec2[depr.format.arg]{Formatting arguments} - -\indexlibraryglobal{visit_format_arg}% -\begin{itemdecl} -template - decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return visit(std::forward(vis), arg.value);} -\end{itemdescr} - \rSec1[depr.locale.category]{Deprecated locale category facets} \pnum @@ -741,6 +743,34 @@ \tcode{codecvt} convert between the UTF-32 and UTF-8 encoding forms. +\rSec1[depr.format]{Deprecated formatting} + +\rSec2[depr.format.syn]{Header \tcode{} synopsis} + +\pnum +The header \libheaderref{format} has the following additions: + +\begin{codeblock} +namespace std { + template + decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); +} +\end{codeblock} + +\rSec2[depr.format.arg]{Formatting arguments} + +\indexlibraryglobal{visit_format_arg}% +\begin{itemdecl} +template + decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return visit(std::forward(vis), arg.value);} +\end{itemdescr} + \rSec1[depr.fs.path.factory]{Deprecated filesystem path factory functions} \pnum diff --git a/source/intro.tex b/source/intro.tex index 4f2984457d..d5cb23dc23 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -206,6 +206,11 @@ constructs that it does not support. \end{defnote} +\definition{constant evaluation}{defns.const.eval} +\indexdefn{constant evaluation}% +evaluation that is performed as part of evaluating an expression +as a core constant expression\iref{expr.const} + \definition{constant subexpression}{defns.const.subexpr} \indexdefn{constant subexpression}% expression whose evaluation as subexpression of a @@ -256,7 +261,7 @@ Implementations are allowed, but not required, to diagnose it\iref{intro.compliance.general}. Evaluation of a constant expression\iref{expr.const} -never exhibits behavior specified as erroneous in \ref{intro} through \ref{cpp}. +never exhibits behavior specified as erroneous in \ref{intro} through \ref{\lastcorechapter}. \end{defnote} \definition{expression-equivalent}{defns.expression.equivalent} @@ -412,7 +417,7 @@ set of one or more \termref{defns.character}{character}{s} which share the same primary sort key: that is the sort key weighting that depends only upon character shape, and not accents, case, or -locale specific tailorings +locale-specific tailorings \definition{program-defined specialization}{defns.prog.def.spec} \defncontext{library} @@ -504,6 +509,23 @@ \indextext{undefined} \end{defnote} +\definition{runtime-undefined behavior}{defns.undefined.runtime} +\indexdefn{behavior!runtime-undefined}% +behavior that is undefined except when it occurs during constant evaluation + +\begin{defnote} +During constant evaluation, +\begin{itemize} +\item +it is +\impldef{whether runtime-undefined behavior results in the expression being deemed non-constant} +whether runtime-undefined behavior results in the expression being deemed non-constant +(as specified in~\ref{expr.const}) and +\item +runtime-undefined behavior has no other effect. +\end{itemize} +\end{defnote} + \indexdefn{signature}% \definition{signature}{defns.signature} \defncontext{function} @@ -644,7 +666,7 @@ issuance of a diagnostic message). Many incorrect program constructs do not engender undefined behavior; they are required to be diagnosed. Evaluation of a constant expression\iref{expr.const} never exhibits behavior explicitly -specified as undefined in \ref{intro} through \ref{cpp}. +specified as undefined in \ref{intro} through \ref{\lastcorechapter}. \end{defnote} \indexdefn{behavior!unspecified}% @@ -808,7 +830,7 @@ supports all the facilities described in this document, while a freestanding implementation supports the entire \Cpp{} language -described in \ref{lex} through \ref{cpp} and +described in \ref{lex} through \ref{\lastcorechapter} and the subset of the library facilities described in \ref{compliance}. \pnum @@ -958,7 +980,7 @@ \pnum \indextext{standard!structure of|(}% \indextext{standard!structure of}% -\ref{lex} through \ref{cpp} describe the \Cpp{} programming +\ref{lex} through \ref{\lastcorechapter} describe the \Cpp{} programming language. That description includes detailed syntactic specifications in a form described in~\ref{syntax}. For convenience, \ref{gram} repeats all such syntactic specifications. diff --git a/source/iostreams.tex b/source/iostreams.tex index 80a58115aa..528c4fb005 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -734,8 +734,8 @@ ios_base& defaultfloat(ios_base& str); // \ref{error.reporting}, error reporting - enum class io_errc { - stream = 1 + enum class @\libglobal{io_errc}@ { + @\libmember{stream}{io_errc}@ = 1 }; template<> struct is_error_code_enum : public true_type { }; @@ -831,7 +831,7 @@ virtual ~ios_base(); // \ref{ios.base.callback}, callbacks - enum event { erase_event, imbue_event, copyfmt_event }; + enum @\libmember{event}{ios_base}@ { erase_event, imbue_event, copyfmt_event }; using event_callback = void (*)(event, ios_base&, int idx); void register_callback(event_callback fn, int idx); @@ -6816,7 +6816,7 @@ \effects Equivalent to: \begin{codeblock} -print(os, "{}\n", format(fmt, std::forward(args)...)); +print(os, "{}\n", format(os.getloc(), fmt, std::forward(args)...)); \end{codeblock} \end{itemdescr} @@ -6854,25 +6854,31 @@ without regard to the value of \tcode{os.exceptions()} and without turning on \tcode{ios_base::badbit} in the error state of \tcode{os}. \end{itemize} + +\par % This paragraph is part of the \effects clause. After constructing a \tcode{sentry} object, -the function initializes an automatic variable via +the function initializes a variable with automatic storage duration via \begin{codeblock} string out = vformat(os.getloc(), fmt, args); \end{codeblock} +\begin{itemize} +\item If the function is \tcode{vprint_unicode} and -\tcode{os} is a stream that refers to a terminal capable of displaying Unicode +\tcode{os} is a stream that refers to a terminal that +is capable of displaying Unicode only via a native Unicode API, which is determined in an implementation-defined manner, +flushes \tcode{os} and then writes \tcode{out} to the terminal using the native Unicode API; if \tcode{out} contains invalid code units, \indextext{undefined}% -the behavior is undefined and -implementations are encouraged to diagnose it. -If the native Unicode API is used, -the function flushes \tcode{os} before writing \tcode{out}. -Otherwise (if \tcode{os} is not such a stream or -the function is \tcode{vprint_nonunicode}), +the behavior is undefined. +\item +Otherwise inserts the character sequence \range{out.begin()}{out.end()} into \tcode{os}. +\end{itemize} + +\par % This paragraph is part of the \effects clause. If writing to the terminal or inserting into \tcode{os} fails, calls \tcode{os.setstate(ios_base::badbit)} (which may throw \tcode{ios_base::failure}). @@ -7837,28 +7843,27 @@ Let \tcode{out} denote the character representation of formatting arguments provided by \tcode{args} formatted according to specifications given in \tcode{fmt}. -If \tcode{stream} refers to a terminal capable of displaying Unicode, +\begin{itemize} +\item +If \tcode{stream} refers to a terminal that +is capable of displaying Unicode only via a native Unicode API, +flushes \tcode{stream} and then writes \tcode{out} to the terminal using the native Unicode API; if \tcode{out} contains invalid code units, \indextext{undefined}% -the behavior is undefined and -implementations are encouraged to diagnose it. +the behavior is undefined. +\item Otherwise writes \tcode{out} to \tcode{stream} unchanged. -If the native Unicode API is used, -the function flushes \tcode{stream} before writing \tcode{out}. +\end{itemize} Unconditionally unlocks \tcode{stream} on function exit. \xrefc{7.21.2}. \begin{note} -On POSIX and Windows, \tcode{stream} referring to a terminal means that, -respectively, -\tcode{isatty(fileno(\linebreak{}stream))} and +On Windows the native Unicode API is \tcode{WriteConsoleW} and +\tcode{stream} referring to a terminal means that \tcode{GetConsoleMode(_get_osfhandle(_fileno(stream)), ...)} -return nonzero. -\end{note} -\begin{note} -On Windows, the native Unicode API is \tcode{WriteConsoleW}. +returns nonzero. \end{note} \pnum @@ -15696,10 +15701,10 @@ \lhdr{Constant} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{file_type}} & The type of the file has not been determined or an error occurred while trying to determine the type. \\ \rowsep -\tcode{not_found} & +\tcode{\libmember{not_found}{file_type}} & Pseudo-type indicating the file was not found. \begin{tailnote} The file @@ -15707,13 +15712,13 @@ type of a file. \end{tailnote} \\ \rowsep -\tcode{regular} & Regular file \\ \rowsep -\tcode{directory} & Directory file \\ \rowsep -\tcode{symlink} & Symbolic link file \\ \rowsep -\tcode{block} & Block special file \\ \rowsep -\tcode{character} & Character special file \\ \rowsep -\tcode{fifo} & FIFO or pipe file \\ \rowsep -\tcode{socket} & Socket file \\ \rowsep +\tcode{\libmember{regular}{file_type}} & Regular file \\ \rowsep +\tcode{\libmember{directory}{file_type}} & Directory file \\ \rowsep +\tcode{\libmember{symlink}{file_type}} & Symbolic link file \\ \rowsep +\tcode{\libmember{block}{file_type}} & Block special file \\ \rowsep +\tcode{\libmember{character}{file_type}} & Character special file \\ \rowsep +\tcode{\libmember{fifo}{file_type}} & FIFO or pipe file \\ \rowsep +\tcode{\libmember{socket}{file_type}} & Socket file \\ \rowsep \tcode{\textit{\impldef{additional \tcode{file_type} enumerators for file systems supporting additional types of file}}} & Implementations that support file systems having file types @@ -15723,7 +15728,7 @@ for file systems supporting additional types of file} \tcode{file_type} constants to separately identify each of those additional file types \\ \rowsep -\tcode{unknown} & +\tcode{\libmember{unknown}{file_type}} & The file exists but the type cannot be determined \\ \end{floattable} @@ -15745,42 +15750,42 @@ \topline \ohdrx{2}{Option group controlling \tcode{copy_file} function effects for existing target files} \\ \rowsep \lhdr{Constant} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{copy_options}} & (Default) Error; file already exists. \\ \rowsep -\tcode{skip_existing} & +\tcode{\libmember{skip_existing}{copy_options}} & Do not overwrite existing file, do not report an error. \\ \rowsep -\tcode{overwrite_existing} & +\tcode{\libmember{overwrite_existing}{copy_options}} & Overwrite the existing file. \\ \rowsep -\tcode{update_existing} & +\tcode{\libmember{update_existing}{copy_options}} & Overwrite the existing file if it is older than the replacement file. \\ \capsep \ohdrx{2}{Option group controlling \tcode{copy} function effects for subdirectories} \\ \rowsep \lhdr{Constant} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{copy_options}} & (Default) Do not copy subdirectories. \\ \rowsep -\tcode{recursive} & +\tcode{\libmember{recursive}{copy_options}} & Recursively copy subdirectories and their contents. \\ \capsep \ohdrx{2}{Option group controlling \tcode{copy} function effects for symbolic links} \\ \rowsep \lhdr{Constant} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{copy_options}} & (Default) Follow symbolic links. \\ \rowsep -\tcode{copy_symlinks} & +\tcode{\libmember{copy_symlinks}{copy_options}} & Copy symbolic links as symbolic links rather than copying the files that they point to. \\ \rowsep -\tcode{skip_symlinks} & +\tcode{\libmember{skip_symlinks}{copy_options}} & Ignore symbolic links. \\ \capsep \ohdrx{2}{Option group controlling \tcode{copy} function effects for choosing the form of copying} \\ \rowsep \lhdr{Constant} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{copy_options}} & (Default) Copy content. \\ \rowsep -\tcode{directories_only} & +\tcode{\libmember{directories_only}{copy_options}} & Copy directory structure only, do not copy non-directory files. \\ \rowsep -\tcode{create_symlinks} & +\tcode{\libmember{create_symlinks}{copy_options}} & Make symbolic links instead of copies of files. The source path shall be an absolute path unless the destination path is in the current directory. \\ \rowsep -\tcode{create_hard_links} & +\tcode{\libmember{create_hard_links}{copy_options}} & Make hard links instead of copies of files. \\ \end{floattable} @@ -15799,46 +15804,46 @@ \lhdr{Name} & \chdr{Value} & \chdr{POSIX} & \rhdr{Definition or notes} \\ & \chdr{(octal)} & \chdr{macro} & \\ \capsep -\tcode{none} & \tcode{0} & & +\tcode{\libmember{none}{perms}} & \tcode{0} & & There are no permissions set for the file. \\ \rowsep -\tcode{owner_read} & \tcode{0400} & \tcode{S_IRUSR} & +\tcode{\libmember{owner_read}{perms}} & \tcode{0400} & \tcode{S_IRUSR} & Read permission, owner \\ \rowsep -\tcode{owner_write} & \tcode{0200} & \tcode{S_IWUSR} & +\tcode{\libmember{owner_write}{perms}} & \tcode{0200} & \tcode{S_IWUSR} & Write permission, owner \\ \rowsep -\tcode{owner_exec} & \tcode{0100} & \tcode{S_IXUSR} & +\tcode{\libmember{owner_exec}{perms}} & \tcode{0100} & \tcode{S_IXUSR} & Execute/search permission, owner \\ \rowsep -\tcode{owner_all} & \tcode{0700} & \tcode{S_IRWXU} & +\tcode{\libmember{owner_all}{perms}} & \tcode{0700} & \tcode{S_IRWXU} & Read, write, execute/search by owner;\br \tcode{owner_read | owner_write | owner_exec} \\ \rowsep -\tcode{group_read} & \tcode{040} & \tcode{S_IRGRP} & +\tcode{\libmember{group_read}{perms}} & \tcode{040} & \tcode{S_IRGRP} & Read permission, group \\ \rowsep -\tcode{group_write} & \tcode{020} & \tcode{S_IWGRP} & +\tcode{\libmember{group_write}{perms}} & \tcode{020} & \tcode{S_IWGRP} & Write permission, group \\ \rowsep -\tcode{group_exec} & \tcode{010} & \tcode{S_IXGRP} & +\tcode{\libmember{group_exec}{perms}} & \tcode{010} & \tcode{S_IXGRP} & Execute/search permission, group \\ \rowsep -\tcode{group_all} & \tcode{070} & \tcode{S_IRWXG} & +\tcode{\libmember{group_all}{perms}} & \tcode{070} & \tcode{S_IRWXG} & Read, write, execute/search by group;\br \tcode{group_read | group_write | group_exec} \\ \rowsep -\tcode{others_read} & \tcode{04} & \tcode{S_IROTH} & +\tcode{\libmember{others_read}{perms}} & \tcode{04} & \tcode{S_IROTH} & Read permission, others \\ \rowsep -\tcode{others_write} & \tcode{02} & \tcode{S_IWOTH} & +\tcode{\libmember{others_write}{perms}} & \tcode{02} & \tcode{S_IWOTH} & Write permission, others \\ \rowsep -\tcode{others_exec} & \tcode{01} & \tcode{S_IXOTH} & +\tcode{\libmember{others_exec}{perms}} & \tcode{01} & \tcode{S_IXOTH} & Execute/search permission, others \\ \rowsep -\tcode{others_all} & \tcode{07} & \tcode{S_IRWXO} & +\tcode{\libmember{others_all}{perms}} & \tcode{07} & \tcode{S_IRWXO} & Read, write, execute/search by others;\br \tcode{others_read | others_write | others_exec} \\ \rowsep -\tcode{all} & \tcode{0777} & & +\tcode{\libmember{all}{perms}} & \tcode{0777} & & \tcode{owner_all | group_all | others_all} \\ \rowsep -\tcode{set_uid} & \tcode{04000} & \tcode{S_ISUID} & +\tcode{\libmember{set_uid}{perms}} & \tcode{04000} & \tcode{S_ISUID} & Set-user-ID on execution \\ \rowsep -\tcode{set_gid} & \tcode{02000} & \tcode{S_ISGID} & +\tcode{\libmember{set_gid}{perms}} & \tcode{02000} & \tcode{S_ISGID} & Set-group-ID on execution \\ \rowsep -\tcode{sticky_bit} & \tcode{01000} & \tcode{S_ISVTX} & +\tcode{\libmember{sticky_bit}{perms}} & \tcode{01000} & \tcode{S_ISVTX} & Operating system dependent. \\ \rowsep -\tcode{mask} & \tcode{07777} & & +\tcode{\libmember{mask}{perms}} & \tcode{07777} & & \tcode{all | set_uid | set_gid | sticky_bit} \\ \rowsep -\tcode{unknown} & \tcode{0xFFFF} & & +\tcode{\libmember{unknown}{perms}} & \tcode{0xFFFF} & & The permissions are not known, such as when a \tcode{file_status} object is created without specifying the permissions \\ \end{floattable} @@ -15860,15 +15865,15 @@ \topline \lhdr{Name} & \rhdr{Meaning} \\ \capsep -\tcode{replace} & +\tcode{\libmember{replace}{perm_options}} & \tcode{permissions} shall replace the file's permission bits with \tcode{perm} \\ \rowsep -\tcode{add} & +\tcode{\libmember{add}{perm_options}} & \tcode{permissions} shall replace the file's permission bits with the bitwise \logop{or} of \tcode{perm} and the file's current permission bits. \\ \rowsep -\tcode{remove} & +\tcode{\libmember{remove}{perm_options}} & \tcode{permissions} shall replace the file's permission bits with the bitwise \logop{and} of the complement of \tcode{perm} and the file's current permission bits. \\ \rowsep -\tcode{nofollow} & +\tcode{\libmember{nofollow}{perm_options}} & \tcode{permissions} shall change the permissions of a symbolic link itself rather than the permissions of the file the link resolves to. \\ \end{floattable} @@ -15891,11 +15896,11 @@ \lhdr{Name} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{directory_options}} & (Default) Skip directory symlinks, permission denied is an error. \\ \rowsep -\tcode{follow_directory_symlink} & +\tcode{\libmember{follow_directory_symlink}{directory_options}} & Follow rather than skip directory symlinks. \\ \rowsep -\tcode{skip_permission_denied} & +\tcode{\libmember{skip_permission_denied}{directory_options}} & Skip directories that would otherwise result in permission denied. \\ \end{floattable} @@ -18425,9 +18430,10 @@ \pnum \returns -\tcode{false} if \tcode{p} did not exist, - otherwise \tcode{true}. The signature with argument \tcode{ec} - returns \tcode{false} if an error occurs. +\tcode{true} if a file \tcode{p} has been removed and \tcode{false} otherwise. +\begin{note} +Absence of a file \tcode{p} is not an error. +\end{note} \pnum \throws diff --git a/source/iterators.tex b/source/iterators.tex index e1c8f73ad0..7fcbff2083 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -539,7 +539,7 @@ \defn{value type} of the iterator. An output iterator \tcode{i} has a non-empty set of types that are -\libconcept{indirectly_writable} to the iterator; +\defn{writable} to the iterator; for each such type \tcode{T}, the expression \tcode{*i = o} is valid where \tcode{o} is a value of type \tcode{T}. For every iterator type @@ -1969,6 +1969,7 @@ \item \tcode{to_address(a) == addressof(*a)}, \item \tcode{to_address(b) == to_address(a) + D(b - a)}, \item \tcode{to_address(c) == to_address(a) + D(c - a)}, +\item \tcode{to_address(I\{\})} is well-defined, \item \tcode{ranges::iter_move(a)} has the same type, value category, and effects as \tcode{std::move(*a)}, and \item if \tcode{ranges::iter_swap(a, b)} is well-formed, @@ -2932,32 +2933,8 @@ \end{example} \pnum -The function templates defined in \ref{range.iter.ops} are not found by -argument-dependent name lookup\iref{basic.lookup.argdep}. When found by -unqualified\iref{basic.lookup.unqual} name lookup for the -\grammarterm{postfix-expression} in a function call\iref{expr.call}, they -inhibit argument-dependent name lookup. - -\begin{example} -\begin{codeblock} -void foo() { - using namespace std::ranges; - std::vector vec{1,2,3}; - distance(begin(vec), end(vec)); // \#1 -} -\end{codeblock} -The function call expression at \tcode{\#1} invokes \tcode{std::ranges::distance}, -not \tcode{std::distance}, despite that -(a) the iterator type returned from \tcode{begin(vec)} and \tcode{end(vec)} -may be associated with namespace \tcode{std} and -(b) \tcode{std::distance} is more specialized\iref{temp.func.order} than -\tcode{std::ranges::distance} since the former requires its first two parameters -to have the same type. -\end{example} - -\pnum -The number and order of deducible template parameters for the function templates defined -in \ref{range.iter.ops} is unspecified, except where explicitly stated otherwise. +The entities defined in \ref{range.iter.ops} are +algorithm function objects\iref{alg.func.obj}. \rSec3[range.iter.op.advance]{\tcode{ranges::advance}} @@ -3318,9 +3295,6 @@ \effects Value-initializes \tcode{current}. -Iterator operations applied to the resulting iterator have defined behavior -if and only if the corresponding operations are defined on a value-initialized iterator of type -\tcode{Iterator}. \end{itemdescr} \indexlibraryctor{reverse_iterator}% diff --git a/source/lex.tex b/source/lex.tex index 45d30ff62a..f9f23382f6 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -90,7 +90,7 @@ does not constitute an endorsement by ISO or IEC of this product. \end{footnote} scalar values. -A sequence of translation character set elements is then formed +A sequence of translation character set elements\iref{lex.charset} is then formed by mapping each Unicode scalar value to the corresponding translation character set element. In the resulting sequence, @@ -103,7 +103,7 @@ For any other kind of input file supported by the implementation, characters are mapped, in an \impldef{mapping physical source file characters to translation character set} manner, -to a sequence of translation character set elements\iref{lex.charset}, +to a sequence of translation character set elements, representing end-of-line indicators as new-line characters. \item @@ -140,7 +140,7 @@ would arise from a source file ending with an unclosed \tcode{/*} comment. \end{footnote} -Each comment is replaced by one space character. New-line characters are +Each comment\iref{lex.comment} is replaced by one space character. New-line characters are retained. Whether each nonempty sequence of whitespace characters other than new-line is retained or replaced by one space character is unspecified. @@ -153,8 +153,8 @@ \grammarterm{r-char-sequence}, \grammarterm{h-char-sequence}, or \grammarterm{q-char-sequence}, -\grammarterm{universal-character-name}s are recognized and -replaced by the designated element of the translation character set. +\grammarterm{universal-character-name}s are recognized\iref{lex.universal.char} and +replaced by the designated element of the translation character set\iref{lex.charset}. The process of dividing a source file's characters into preprocessing tokens is context-dependent. \begin{example} @@ -162,9 +162,10 @@ directive\iref{cpp.include}. \end{example} -\item Preprocessing directives are executed, macro invocations are -expanded, and \tcode{_Pragma} unary operator expressions are executed. -A \tcode{\#include} preprocessing directive causes the named header or +\item The source file is analyzed as a \grammarterm{preprocessing-file}\iref{cpp.pre}. +Preprocessing directives\iref{cpp} are executed, macro invocations are +expanded\iref{cpp.replace}, and \tcode{_Pragma} unary operator expressions are executed\iref{cpp.pragma.op}. +A \tcode{\#include} preprocessing directive\iref{cpp.include} causes the named header or source file to be processed from phase 1 through phase 4, recursively. All preprocessing directives are then deleted. @@ -178,12 +179,13 @@ \item Adjacent \grammarterm{string-literal} tokens are concatenated\iref{lex.string}. -\item Whitespace characters separating tokens are no longer -significant. Each preprocessing token is converted into a -token\iref{lex.token}. The resulting tokens -constitute a \defn{translation unit} and +\item +Each preprocessing token is converted into a token\iref{lex.token}. +Whitespace characters separating tokens are no longer significant. +The resulting tokens constitute a \defn{translation unit} and are syntactically and -semantically analyzed and translated. +semantically analyzed as a \grammarterm{translation-unit}\iref{basic.link} and +translated. \begin{note} The process of analyzing and translating the tokens can occasionally result in one token being replaced by a sequence of other @@ -396,8 +398,7 @@ \begin{bnf} \nontermdef{n-char-sequence}\br - n-char\br - n-char-sequence n-char + n-char \opt{n-char-sequence} \end{bnf} \begin{bnf} @@ -412,8 +413,7 @@ \begin{bnf} \nontermdef{simple-hexadecimal-digit-sequence}\br - hexadecimal-digit\br - simple-hexadecimal-digit-sequence hexadecimal-digit + hexadecimal-digit \opt{simple-hexadecimal-digit-sequence} \end{bnf} \begin{bnf} @@ -467,6 +467,29 @@ None of these names or aliases have leading or trailing spaces. \end{note} +\rSec1[lex.comment]{Comments} + +\pnum +\indextext{comment|(}% +\indextext{comment!\tcode{/*} \tcode{*/}}% +\indextext{comment!\tcode{//}}% +The characters \tcode{/*} start a comment, which terminates with the +characters \tcode{*/}. These comments do not nest. +\indextext{comment!\tcode{//}}% +The characters \tcode{//} start a comment, which terminates immediately before the +next new-line character. If there is a form-feed or a vertical-tab +character in such a comment, only whitespace characters shall appear +between it and the new-line that terminates the comment; no diagnostic +is required. +\begin{note} +The comment characters \tcode{//}, \tcode{/*}, +and \tcode{*/} have no special meaning within a \tcode{//} comment and +are treated just like other characters. Similarly, the comment +characters \tcode{//} and \tcode{/*} have no special meaning within a +\tcode{/*} comment. +\end{note} +\indextext{comment|)} + \rSec1[lex.pptoken]{Preprocessing tokens} \indextext{token!preprocessing|(}% @@ -486,11 +509,6 @@ \textnormal{each non-whitespace character that cannot be one of the above} \end{bnf} -\pnum -Each preprocessing token that is converted to a token\iref{lex.token} -shall have the lexical form of a keyword, an identifier, a literal, -or an operator or punctuator. - \pnum A preprocessing token is the minimal lexical element of the language in translation phases 3 through 6. @@ -525,6 +543,22 @@ between the quotation characters in a character literal or string literal. +\pnum +Each preprocessing token that is converted to a token\iref{lex.token} +shall have the lexical form of a keyword, an identifier, a literal, +or an operator or punctuator. + +\pnum +The \grammarterm{import-keyword} is produced +by processing an \keyword{import} directive\iref{cpp.import}, +the \grammarterm{module-keyword} is produced +by preprocessing a \keyword{module} directive\iref{cpp.module}, and +the \grammarterm{export-keyword} is produced +by preprocessing either of the previous two directives. +\begin{note} +None has any observable spelling. +\end{note} + \pnum If the input stream has been parsed into preprocessing tokens up to a given character: @@ -554,7 +588,7 @@ except that a \grammarterm{header-name}\iref{lex.header} is only formed \begin{itemize} \item -after the \tcode{include} or \tcode{import} preprocessing token in an +after the \tcode{include} or \tcode{import} preprocessing token in a \tcode{\#include}\iref{cpp.include} or \tcode{import}\iref{cpp.import} directive, or @@ -564,6 +598,7 @@ \end{itemize} \end{itemize} +\pnum \begin{example} \begin{codeblock} #define R "x" @@ -571,17 +606,6 @@ \end{codeblock} \end{example} -\pnum -The \grammarterm{import-keyword} is produced -by preprocessing an \keyword{import} directive\iref{cpp.import}, -the \grammarterm{module-keyword} is produced -by preprocessing a \keyword{module} directive\iref{cpp.module}, and -the \grammarterm{export-keyword} is produced -by preprocessing either of the previous two directives. -\begin{note} -None has any observable spelling. -\end{note} - \pnum \begin{example} The program fragment \tcode{0xe+foo} is parsed as a @@ -604,106 +628,6 @@ \end{example} \indextext{token!preprocessing|)} -\rSec1[lex.digraph]{Alternative tokens} - -\pnum -\indextext{token!alternative|(}% -Alternative token representations are provided for some operators and -punctuators. -\begin{footnote} -\indextext{digraph}% -These include ``digraphs'' and additional reserved words. The term -``digraph'' (token consisting of two characters) is not perfectly -descriptive, since one of the alternative \grammarterm{preprocessing-token}s is -\tcode{\%:\%:} and of course several primary tokens contain two -characters. Nonetheless, those alternative tokens that aren't lexical -keywords are colloquially known as ``digraphs''. -\end{footnote} - -\pnum -In all respects of the language, each alternative token behaves the -same, respectively, as its primary token, except for its spelling. -\begin{footnote} -Thus the ``stringized'' values\iref{cpp.stringize} of -\tcode{[} and \tcode{<:} will be different, maintaining the source -spelling, but the tokens can otherwise be freely interchanged. -\end{footnote} -The set of alternative tokens is defined in -\tref{lex.digraph}. - -\begin{tokentable}{Alternative tokens}{lex.digraph}{Alternative}{Primary} -\tcode{<\%} & \tcode{\{} & -\keyword{and} & \tcode{\&\&} & -\keyword{and_eq} & \tcode{\&=} \\ \rowsep -\tcode{\%>} & \tcode{\}} & -\keyword{bitor} & \tcode{|} & -\keyword{or_eq} & \tcode{|=} \\ \rowsep -\tcode{<:} & \tcode{[} & -\keyword{or} & \tcode{||} & -\keyword{xor_eq} & \tcode{\caret=} \\ \rowsep -\tcode{:>} & \tcode{]} & -\keyword{xor} & \tcode{\caret} & -\keyword{not} & \tcode{!} \\ \rowsep -\tcode{\%:} & \tcode{\#} & -\keyword{compl} & \tcode{\~} & -\keyword{not_eq} & \tcode{!=} \\ \rowsep -\tcode{\%:\%:} & \tcode{\#\#} & -\keyword{bitand} & \tcode{\&} & - & \\ -\end{tokentable}% -\indextext{token!alternative|)} - -\rSec1[lex.token]{Tokens} - -\indextext{token|(}% -\begin{bnf} -\nontermdef{token}\br - identifier\br - keyword\br - literal\br - operator-or-punctuator -\end{bnf} - -\pnum -\indextext{\idxgram{token}}% -There are five kinds of tokens: identifiers, keywords, literals,% -\begin{footnote} -Literals include strings and character and numeric literals. -\end{footnote} -operators, and other separators. -\indextext{whitespace}% -Blanks, horizontal and vertical tabs, newlines, formfeeds, and comments -(collectively, ``whitespace''), as described below, are ignored except -as they serve to separate tokens. -\begin{note} -Whitespace can separate otherwise adjacent identifiers, keywords, numeric -literals, and alternative tokens containing alphabetic characters. -\end{note} -\indextext{token|)} - -\rSec1[lex.comment]{Comments} - -\pnum -\indextext{comment|(}% -\indextext{comment!\tcode{/*} \tcode{*/}}% -\indextext{comment!\tcode{//}}% -The characters \tcode{/*} start a comment, which terminates with the -characters \tcode{*/}. These comments do not nest. -\indextext{comment!\tcode{//}}% -The characters \tcode{//} start a comment, which terminates immediately before the -next new-line character. If there is a form-feed or a vertical-tab -character in such a comment, only whitespace characters shall appear -between it and the new-line that terminates the comment; no diagnostic -is required. -\begin{note} -The comment characters \tcode{//}, \tcode{/*}, -and \tcode{*/} have no special meaning within a \tcode{//} comment and -are treated just like other characters. Similarly, the comment -characters \tcode{//} and \tcode{/*} have no special meaning within a -\tcode{/*} comment. -\end{note} -\indextext{comment|)} - \rSec1[lex.header]{Header names} \indextext{header!name|(}% @@ -716,8 +640,7 @@ \begin{bnf} \nontermdef{h-char-sequence}\br - h-char\br - h-char-sequence h-char + h-char \opt{h-char-sequence} \end{bnf} \begin{bnf} @@ -727,8 +650,7 @@ \begin{bnf} \nontermdef{q-char-sequence}\br - q-char\br - q-char-sequence q-char + q-char \opt{q-char-sequence} \end{bnf} \begin{bnf} @@ -737,16 +659,16 @@ \end{bnf} \pnum +The sequences in both forms of \grammarterm{header-name}{s} are mapped in an +\impldef{mapping header name to header or external source file} manner to headers or to +external source file names as specified in~\ref{cpp.include}. \begin{note} -Header name preprocessing tokens only appear within +Header name preprocessing tokens appear only within a \tcode{\#include} preprocessing directive, a \tcode{__has_include} preprocessing expression, or after certain occurrences of an \tcode{import} token (see~\ref{lex.pptoken}). \end{note} -The sequences in both forms of \grammarterm{header-name}{s} are mapped in an -\impldef{mapping header name to header or external source file} manner to headers or to -external source file names as specified in~\ref{cpp.include}. \pnum The appearance of either of the characters \tcode{'} or \tcode{\textbackslash} or of @@ -756,12 +678,12 @@ \tcode{/*}, or \tcode{//} in a \grammarterm{q-char-sequence} or an \grammarterm{h-char-sequence}} semantics, as is the appearance of the character \tcode{"} in an \grammarterm{h-char-sequence}. -\begin{footnote} +\begin{note} Thus, a sequence of characters that resembles an escape sequence can result in an error, be interpreted as the character corresponding to the escape sequence, or have a completely different meaning, depending on the implementation. -\end{footnote} +\end{note} \indextext{header!name|)} \rSec1[lex.ppnumber]{Preprocessing numbers} @@ -793,6 +715,124 @@ a \grammarterm{floating-point-literal} token.% \indextext{number!preprocessing|)} +\rSec1[lex.operators]{Operators and punctuators} + +\pnum +\indextext{operator|(}% +\indextext{punctuator|(}% +The lexical representation of \Cpp{} programs includes a number of +preprocessing tokens that are used in the syntax of the preprocessor or +are converted into tokens for operators and punctuators: + +\begin{bnf} +\nontermdef{preprocessing-op-or-punc}\br + preprocessing-operator\br + operator-or-punctuator +\end{bnf} + +\begin{bnf} +%% Ed. note: character protrusion would misalign various operators. +\microtypesetup{protrusion=false}\obeyspaces +\nontermdef{preprocessing-operator} \textnormal{one of}\br + \terminal{\# \#\# \%: \%:\%:} +\end{bnf} + +\begin{bnf} +\microtypesetup{protrusion=false}\obeyspaces +\nontermdef{operator-or-punctuator} \textnormal{one of}\br + \terminal{\{ \} [ ] ( )}\br + \terminal{<: :> <\% \%> ; : ...}\br + \terminal{? :: . .* -> ->* \~}\br + \terminal{! + - * / \% \caret{} \& |}\br + \terminal{= += -= *= /= \%= \caret{}= \&= |=}\br + \terminal{== != < > <= >= <=> \&\& ||}\br + \terminal{<< >> <<= >>= ++ -- ,}\br + \terminal{\keyword{and} \keyword{or} \keyword{xor} \keyword{not} \keyword{bitand} \keyword{bitor} \keyword{compl}}\br + \terminal{\keyword{and_eq} \keyword{or_eq} \keyword{xor_eq} \keyword{not_eq}} +\end{bnf} + +Each \grammarterm{operator-or-punctuator} is converted to a single token +in translation phase 7\iref{lex.phases}.% +\indextext{punctuator|)}% +\indextext{operator|)} + +\rSec1[lex.digraph]{Alternative tokens} + +\pnum +\indextext{token!alternative|(}% +Alternative token representations are provided for some operators and +punctuators. +\begin{footnote} +\indextext{digraph}% +These include ``digraphs'' and additional reserved words. The term +``digraph'' (token consisting of two characters) is not perfectly +descriptive, since one of the alternative \grammarterm{preprocessing-token}s is +\tcode{\%:\%:} and of course several primary tokens contain two +characters. Nonetheless, those alternative tokens that aren't lexical +keywords are colloquially known as ``digraphs''. +\end{footnote} + +\pnum +In all respects of the language, each alternative token behaves the +same, respectively, as its primary token, except for its spelling. +\begin{footnote} +Thus the ``stringized'' values\iref{cpp.stringize} of +\tcode{[} and \tcode{<:} will be different, maintaining the source +spelling, but the tokens can otherwise be freely interchanged. +\end{footnote} +The set of alternative tokens is defined in +\tref{lex.digraph}. + +\begin{tokentable}{Alternative tokens}{lex.digraph}{Alternative}{Primary} +\tcode{<\%} & \tcode{\{} & +\keyword{and} & \tcode{\&\&} & +\keyword{and_eq} & \tcode{\&=} \\ \rowsep +\tcode{\%>} & \tcode{\}} & +\keyword{bitor} & \tcode{|} & +\keyword{or_eq} & \tcode{|=} \\ \rowsep +\tcode{<:} & \tcode{[} & +\keyword{or} & \tcode{||} & +\keyword{xor_eq} & \tcode{\caret=} \\ \rowsep +\tcode{:>} & \tcode{]} & +\keyword{xor} & \tcode{\caret} & +\keyword{not} & \tcode{!} \\ \rowsep +\tcode{\%:} & \tcode{\#} & +\keyword{compl} & \tcode{\~} & +\keyword{not_eq} & \tcode{!=} \\ \rowsep +\tcode{\%:\%:} & \tcode{\#\#} & +\keyword{bitand} & \tcode{\&} & + & \\ +\end{tokentable}% +\indextext{token!alternative|)} + +\rSec1[lex.token]{Tokens} + +\indextext{token|(}% +\begin{bnf} +\nontermdef{token}\br + identifier\br + keyword\br + literal\br + operator-or-punctuator +\end{bnf} + +\pnum +\indextext{\idxgram{token}}% +There are five kinds of tokens: identifiers, keywords, literals,% +\begin{footnote} +Literals include strings and character and numeric literals. +\end{footnote} +operators, and other separators. +\indextext{whitespace}% +Blanks, horizontal and vertical tabs, newlines, formfeeds, and comments +(collectively, ``whitespace''), as described below, are ignored except +as they serve to separate tokens. +\begin{note} +Whitespace can separate otherwise adjacent identifiers, keywords, numeric +literals, and alternative tokens containing alphabetic characters. +\end{note} +\indextext{token|)} + \rSec1[lex.name]{Identifiers} \indextext{identifier|(}% @@ -832,8 +872,7 @@ \indextext{name!length of}% \indextext{name}% \begin{note} -The character properties XID_Start and XID_Continue are Derived Core Properties -as described by \UAX{44} of the Unicode Standard. +The character properties XID_Start and XID_Continue are described by \UAX{44} of the Unicode Standard. \begin{footnote} On systems in which linkers cannot accept extended characters, an encoding of the \grammarterm{universal-character-name} can be used in @@ -1038,47 +1077,6 @@ \indextext{keyword|)}% -\rSec1[lex.operators]{Operators and punctuators} - -\pnum -\indextext{operator|(}% -\indextext{punctuator|(}% -The lexical representation of \Cpp{} programs includes a number of -preprocessing tokens that are used in the syntax of the preprocessor or -are converted into tokens for operators and punctuators: - -\begin{bnf} -\nontermdef{preprocessing-op-or-punc}\br - preprocessing-operator\br - operator-or-punctuator -\end{bnf} - -\begin{bnf} -%% Ed. note: character protrusion would misalign various operators. -\microtypesetup{protrusion=false}\obeyspaces -\nontermdef{preprocessing-operator} \textnormal{one of}\br - \terminal{\# \#\# \%: \%:\%:} -\end{bnf} - -\begin{bnf} -\microtypesetup{protrusion=false}\obeyspaces -\nontermdef{operator-or-punctuator} \textnormal{one of}\br - \terminal{\{ \} [ ] ( )}\br - \terminal{<: :> <\% \%> ; : ...}\br - \terminal{? :: . .* -> ->* \~}\br - \terminal{! + - * / \% \caret{} \& |}\br - \terminal{= += -= *= /= \%= \caret{}= \&= |=}\br - \terminal{== != < > <= >= <=> \&\& ||}\br - \terminal{<< >> <<= >>= ++ -- ,}\br - \terminal{\keyword{and} \keyword{or} \keyword{xor} \keyword{not} \keyword{bitand} \keyword{bitor} \keyword{compl}}\br - \terminal{\keyword{and_eq} \keyword{or_eq} \keyword{xor_eq} \keyword{not_eq}} -\end{bnf} - -Each \grammarterm{operator-or-punctuator} is converted to a single token -in translation phase 7\iref{lex.phases}.% -\indextext{punctuator|)}% -\indextext{operator|)} - \rSec1[lex.literal]{Literals}% \indextext{literal|(} @@ -1375,8 +1373,7 @@ \begin{bnf} \nontermdef{c-char-sequence}\br - c-char\br - c-char-sequence c-char + c-char \opt{c-char-sequence} \end{bnf} \begin{bnf} @@ -1417,8 +1414,7 @@ \begin{bnf} \nontermdef{simple-octal-digit-sequence}\br - octal-digit\br - simple-octal-digit-sequence octal-digit + octal-digit \opt{simple-octal-digit-sequence} \end{bnf} \begin{bnf} @@ -1426,7 +1422,7 @@ \terminal{\textbackslash} octal-digit\br \terminal{\textbackslash} octal-digit octal-digit\br \terminal{\textbackslash} octal-digit octal-digit octal-digit\br - \terminal{\textbackslash o\{} simple-octal-digit-sequence \terminal{\}}\br + \terminal{\textbackslash o\{} simple-octal-digit-sequence \terminal{\}} \end{bnf} \begin{bnf} @@ -1746,8 +1742,7 @@ \begin{bnf} \nontermdef{s-char-sequence}\br - s-char\br - s-char-sequence s-char + s-char \opt{s-char-sequence} \end{bnf} \begin{bnf} @@ -1770,8 +1765,7 @@ \begin{bnf} \nontermdef{r-char-sequence}\br - r-char\br - r-char-sequence r-char + r-char \opt{r-char-sequence} \end{bnf} \begin{bnf} @@ -1782,8 +1776,7 @@ \begin{bnf} \nontermdef{d-char-sequence}\br - d-char\br - d-char-sequence d-char + d-char\opt{d-char-sequence} \end{bnf} \begin{bnf} diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 86ab73dda5..fab923bf47 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -32,16 +32,15 @@ \ref{mem} & Memory management library \\ \ref{meta} & Metaprogramming library \\ \ref{utilities} & General utilities library \\ -\ref{strings} & Strings library \\ \ref{containers} & Containers library \\ \ref{iterators} & Iterators library \\ \ref{ranges} & Ranges library \\ \ref{algorithms} & Algorithms library \\ +\ref{strings} & Strings library \\ +\ref{text} & Text processing library \\ \ref{numerics} & Numerics library \\ \ref{time} & Time library \\ -\ref{localization} & Localization library \\ \ref{input.output} & Input/output library \\ -\ref{re} & Regular expressions library \\ \ref{thread} & Concurrency support library \\ \ref{exec} & Execution control library \\ \end{floattable} @@ -83,8 +82,13 @@ such as tuples and function wrappers. \pnum -The strings library\iref{strings} provides support for manipulating text represented -as sequences of type \tcode{char}, +The containers\iref{containers}, iterators\iref{iterators}, ranges\iref{ranges}, +and algorithms\iref{algorithms} libraries provide a \Cpp{} program with access +to a subset of the most widely used algorithms and data structures. + +\pnum +The strings library\iref{strings} provides support +for manipulating sequences of type \tcode{char}, sequences of type \keyword{char8_t}, sequences of type \keyword{char16_t}, sequences of type \keyword{char32_t}, @@ -92,9 +96,9 @@ and sequences of any other character-like type. \pnum -The containers\iref{containers}, iterators\iref{iterators}, ranges\iref{ranges}, -and algorithms\iref{algorithms} libraries provide a \Cpp{} program with access -to a subset of the most widely used algorithms and data structures. +The text processing library\iref{text} provides support for text processing, +including formatting, internationalization support and +regular expression matching and searching. \pnum The numerics library\iref{numerics} provides @@ -111,10 +115,6 @@ The time library\iref{time} provides generally useful time utilities. -\pnum -The localization library\iref{localization} provides extended internationalization -support for text processing. - \pnum The input/output library\iref{input.output} provides the \tcode{iostream} @@ -122,9 +122,6 @@ They can be used with other elements of the library, particularly strings, locales, and iterators. -\pnum -The regular expressions library\iref{re} provides regular expression matching and searching. - \pnum The concurrency support library\iref{thread} provides components to create and manage threads, @@ -859,9 +856,40 @@ \item \tcode{std::move(as_const(p))(args...)} \end{itemize} +\rSec3[alg.func.obj]{Algorithm function objects} + \pnum -Each customization point object type constrains its return type to model a -particular concept. +An \defn{algorithm function object} is +a customization point object\iref{customization.point.object} +that is specified as one or more overloaded function templates. +The name of these function templates designates +the corresponding algorithm function object. + +\pnum +For an algorithm function object \tcode{o}, +let $S$ be the corresponding set of function templates. +Then for any sequence of arguments $\tcode{args} \dotsc$, +$\tcode{o(args} \dotsc \tcode{)}$ is expression-equivalent to +$\tcode{s(args} \dotsc \tcode{)}$, +where the result of name lookup for \tcode{s} is the overload set $S$. +\begin{note} +Algorithm function objects are not found by +argument-dependent name lookup\iref{basic.lookup.argdep}. +When found by unqualified name lookup\iref{basic.lookup.unqual} +for the \grammarterm{postfix-expression} in a function call\iref{expr.call}, +they inhibit argument-dependent name lookup. +\begin{example} +\begin{codeblock} +void foo() { + using namespace std::ranges; + std::vector vec{1,2,3}; + find(begin(vec), end(vec), 2); // \#1 +} +\end{codeblock} +The function call expression at \#1 invokes \tcode{std::ranges::find}, +not \tcode{std::find}. +\end{example} +\end{note} \rSec3[functions.within.classes]{Functions within classes} @@ -1196,6 +1224,7 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1458,12 +1487,19 @@ \pnum The named module \tcode{std.compat} exports the same declarations as the named module \tcode{std}, and -additionally exports declarations in the global namespace +additionally exports +\begin{itemize} +\item +declarations in the global namespace corresponding to the declarations in namespace \tcode{std} that are provided by the \Cpp{} headers for C library facilities~(\tref{headers.cpp.c}), except the explicitly excluded declarations -described in \ref{support.c.headers.other}. +described in \ref{support.c.headers.other} and +\item +declarations provided by +the headers \libheaderref{stdbit.h} and \libheaderref{stdckdint.h}. +\end{itemize} \pnum It is unspecified to which module a declaration in the standard library @@ -1533,6 +1569,7 @@ \ref{concepts} & Concepts library & \tcode{} \\ \rowsep \ref{errno} & Error numbers & \tcode{} \\ \rowsep \ref{syserr} & System error support & \tcode{} \\ \rowsep +\ref{debugging} & Debugging & \tcode{} \\ \rowsep \ref{memory} & Memory & \tcode{} \\ \rowsep \ref{type.traits} & Type traits & \tcode{} \\ \rowsep \ref{ratio} & Compile-time rational arithmetic & \tcode{} \\ \rowsep @@ -1542,12 +1579,7 @@ \ref{variant} & Variants & \tcode{} \\ \rowsep \ref{expected} & Expected objects & \tcode{} \\ \rowsep \ref{function.objects} & Function objects & \tcode{} \\ \rowsep -\ref{charconv} & Primitive numeric conversions & \tcode{} \\ \rowsep \ref{bit} & Bit manipulation & \tcode{} \\ \rowsep -\ref{debugging} & Debugging & \tcode{} \\ \rowsep -\ref{string.view} & String view classes & \tcode{} \\ \rowsep -\ref{string.classes} & String classes & \tcode{} \\ \rowsep -\ref{c.strings} & Null-terminated sequence utilities & \tcode{}, \tcode{} \\ \rowsep \ref{array} & Class template \tcode{array} & \tcode{} \\ \rowsep \ref{inplace.vector} & Class template \tcode{inplace_vector} & \tcode{} \\ \rowsep \ref{views.contiguous} & Contiguous access & \tcode{} \\ \rowsep @@ -1555,6 +1587,10 @@ \ref{iterators} & Iterators library & \tcode{} \\ \rowsep \ref{ranges} & Ranges library & \tcode{} \\ \rowsep \ref{algorithms} & Algorithms library & \tcode{}, \tcode{} \\ \rowsep +\ref{string.view} & String view classes & \tcode{} \\ \rowsep +\ref{string.classes} & String classes & \tcode{} \\ \rowsep +\ref{c.strings} & Null-terminated sequence utilities & \tcode{}, \tcode{} \\ \rowsep +\ref{charconv} & Primitive numeric conversions & \tcode{} \\ \rowsep \ref{c.math} & Mathematical functions for floating-point types & \tcode{} \\ \rowsep \ref{atomics} & Atomics & \tcode{} \\ \rowsep \end{libsumtab} @@ -2237,7 +2273,7 @@ \end{itemdescr} \begin{itemdecl} -typename X::template rebind::other +typename X::rebind::other \end{itemdecl} \begin{itemdescr} @@ -3930,7 +3966,7 @@ Objects of types defined in the \Cpp{} standard library may be moved from\iref{class.copy.ctor}. Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall -be placed in a valid but unspecified state. +be placed in a valid but unspecified state\iref{defns.valid}. \pnum An object of a type defined in the \Cpp{} standard library may be diff --git a/source/macros.tex b/source/macros.tex index 9afe466f40..10e808750c 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -147,7 +147,7 @@ % \indeximpldef synthesizes a collation key from the argument; that is, an % invocation \indeximpldef{arg} emits an index entry `key@arg`, where `key` -% is derived from `arg` by replacing the folowing list of commands with their +% is derived from `arg` by replacing the following list of commands with their % bare content. This allows, say, collating plain text and code. \newcommand{\indeximpldef}[1]{% \let\otextup\textup% diff --git a/source/memory.tex b/source/memory.tex index 3a005667b7..ed7d8b8c05 100644 --- a/source/memory.tex +++ b/source/memory.tex @@ -83,6 +83,8 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space); // freestanding template constexpr T* assume_aligned(T* ptr); // freestanding + template + bool is_sufficiently_aligned(T* ptr); // \ref{obj.lifetime}, explicit lifetime management template @@ -185,14 +187,14 @@ concept @\exposconcept{nothrow-forward-range}@ = @\seebelow@; // \expos template - void uninitialized_default_construct(NoThrowForwardIterator first, // freestanding - NoThrowForwardIterator last); + constexpr void uninitialized_default_construct(NoThrowForwardIterator first, // freestanding + NoThrowForwardIterator last); template void uninitialized_default_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} NoThrowForwardIterator first, NoThrowForwardIterator last); template - NoThrowForwardIterator + constexpr NoThrowForwardIterator uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); // freestanding template NoThrowForwardIterator @@ -202,25 +204,26 @@ namespace ranges { template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> requires @\libconcept{default_initializable}@> - I uninitialized_default_construct(I first, S last); // freestanding + constexpr I uninitialized_default_construct(I first, S last); // freestanding template<@\exposconcept{nothrow-forward-range}@ R> requires @\libconcept{default_initializable}@> - borrowed_iterator_t uninitialized_default_construct(R&& r); // freestanding + constexpr borrowed_iterator_t uninitialized_default_construct(R&& r); // freestanding template<@\exposconcept{nothrow-forward-iterator}@ I> requires @\libconcept{default_initializable}@> - I uninitialized_default_construct_n(I first, iter_difference_t n); // freestanding + constexpr I uninitialized_default_construct_n(I first, // freestanding + iter_difference_t n); } template - void uninitialized_value_construct(NoThrowForwardIterator first, // freestanding - NoThrowForwardIterator last); + constexpr void uninitialized_value_construct(NoThrowForwardIterator first, // freestanding + NoThrowForwardIterator last); template void uninitialized_value_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} NoThrowForwardIterator first, NoThrowForwardIterator last); template - NoThrowForwardIterator + constexpr NoThrowForwardIterator uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); // freestanding template NoThrowForwardIterator @@ -230,27 +233,29 @@ namespace ranges { template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> requires @\libconcept{default_initializable}@> - I uninitialized_value_construct(I first, S last); // freestanding + constexpr I uninitialized_value_construct(I first, S last); // freestanding template<@\exposconcept{nothrow-forward-range}@ R> requires @\libconcept{default_initializable}@> - borrowed_iterator_t uninitialized_value_construct(R&& r); // freestanding + constexpr borrowed_iterator_t uninitialized_value_construct(R&& r); // freestanding template<@\exposconcept{nothrow-forward-iterator}@ I> requires @\libconcept{default_initializable}@> - I uninitialized_value_construct_n(I first, iter_difference_t n); // freestanding + constexpr I uninitialized_value_construct_n(I first, // freestanding + iter_difference_t n); } template - NoThrowForwardIterator uninitialized_copy(InputIterator first, // freestanding - InputIterator last, - NoThrowForwardIterator result); + constexpr NoThrowForwardIterator uninitialized_copy(InputIterator first, // freestanding + InputIterator last, + NoThrowForwardIterator result); template NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, NoThrowForwardIterator result); template - NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, // freestanding - NoThrowForwardIterator result); + constexpr NoThrowForwardIterator uninitialized_copy_n(InputIterator first, // freestanding + Size n, + NoThrowForwardIterator result); template NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} @@ -263,24 +268,24 @@ template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S1, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> requires @\libconcept{constructible_from}@, iter_reference_t> - uninitialized_copy_result + constexpr uninitialized_copy_result uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast); // freestanding template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> requires @\libconcept{constructible_from}@, range_reference_t> - uninitialized_copy_result, borrowed_iterator_t> + constexpr uninitialized_copy_result, borrowed_iterator_t> uninitialized_copy(IR&& in_range, OR&& out_range); // freestanding template using uninitialized_copy_n_result = in_out_result; // freestanding template<@\libconcept{input_iterator}@ I, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> requires @\libconcept{constructible_from}@, iter_reference_t> - uninitialized_copy_n_result + constexpr uninitialized_copy_n_result uninitialized_copy_n(I ifirst, iter_difference_t n, // freestanding O ofirst, S olast); } template - NoThrowForwardIterator uninitialized_move(InputIterator first, // freestanding + constexpr NoThrowForwardIterator uninitialized_move(InputIterator first, // freestanding InputIterator last, NoThrowForwardIterator result); template @@ -288,7 +293,7 @@ ForwardIterator first, ForwardIterator last, NoThrowForwardIterator result); template - pair + constexpr pair uninitialized_move_n(InputIterator first, Size n, // freestanding NoThrowForwardIterator result); template S1, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> - uninitialized_move_result + constexpr uninitialized_move_result uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast); // freestanding template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> requires @\libconcept{constructible_from}@, range_rvalue_reference_t> - uninitialized_move_result, borrowed_iterator_t> + constexpr uninitialized_move_result, borrowed_iterator_t> uninitialized_move(IR&& in_range, OR&& out_range); // freestanding template @@ -315,20 +320,20 @@ template<@\libconcept{input_iterator}@ I, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> - uninitialized_move_n_result + constexpr uninitialized_move_n_result uninitialized_move_n(I ifirst, iter_difference_t n, // freestanding O ofirst, S olast); } template - void uninitialized_fill(NoThrowForwardIterator first, // freestanding + constexpr void uninitialized_fill(NoThrowForwardIterator first, // freestanding NoThrowForwardIterator last, const T& x); template void uninitialized_fill(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} NoThrowForwardIterator first, NoThrowForwardIterator last, const T& x); template - NoThrowForwardIterator + constexpr NoThrowForwardIterator uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); // freestanding template NoThrowForwardIterator @@ -338,14 +343,15 @@ namespace ranges { template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S, class T> requires @\libconcept{constructible_from}@, const T&> - I uninitialized_fill(I first, S last, const T& x); // freestanding + constexpr I uninitialized_fill(I first, S last, const T& x); // freestanding template<@\exposconcept{nothrow-forward-range}@ R, class T> requires @\libconcept{constructible_from}@, const T&> - borrowed_iterator_t uninitialized_fill(R&& r, const T& x); // freestanding + constexpr borrowed_iterator_t uninitialized_fill(R&& r, const T& x); // freestanding template<@\exposconcept{nothrow-forward-iterator}@ I, class T> requires @\libconcept{constructible_from}@, const T&> - I uninitialized_fill_n(I first, iter_difference_t n, const T& x); // freestanding + constexpr I uninitialized_fill_n(I first, // freestanding + iter_difference_t n, const T& x); } // \ref{specialized.construct}, \tcode{construct_at} @@ -839,9 +845,9 @@ \pnum \expects -\tcode{ptr} points to an object \tcode{X} of +\tcode{ptr} points to an object $X$ of a type similar\iref{conv.qual} to \tcode{T}, -where \tcode{X} has alignment \tcode{N}\iref{basic.align}. +where $X$ has alignment \tcode{N}\iref{basic.align}. \pnum \returns @@ -853,17 +859,39 @@ \pnum \begin{note} -The alignment assumption on an object \tcode{X} +The alignment assumption on an object $X$ expressed by a call to \tcode{assume_aligned} might result in generation of more efficient code. It is up to the program to ensure that the assumption actually holds. The call does not cause the implementation to verify or enforce this. An implementation might only make the assumption -for those operations on \tcode{X} that access \tcode{X} +for those operations on $X$ that access $X$ through the pointer returned by \tcode{assume_aligned}. \end{note} \end{itemdescr} +\indexlibraryglobal{is_sufficiently_aligned}% +\begin{itemdecl} +template + bool is_sufficiently_aligned(T* ptr); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{p} points to +an object \tcode{X} of a type similar\iref{conv.qual} to \tcode{T}. + +\pnum +\returns +\tcode{true} if \tcode{X} has alignment at least \tcode{Alignment}, +otherwise \tcode{false}. + +\pnum +\throws +Nothing. +\end{itemdescr} + \rSec2[obj.lifetime]{Explicit lifetime management} \indexlibraryglobal{start_lifetime_as}% @@ -2084,6 +2112,14 @@ } \end{codeblock} +\pnum +A program that instantiates the definition of \tcode{unique_ptr} +is ill-formed if \tcode{T*} is an invalid type. +\begin{note} +This prevents the instantiation of specializations such as +\tcode{unique_ptr} and \tcode{unique_ptr}. +\end{note} + \pnum The default type for the template parameter \tcode{D} is \tcode{default_delete}. A client-supplied template argument @@ -2434,9 +2470,13 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{reference_converts_from_temporary_v, decltype(\linebreak{}*declval())>} is \tcode{false}. + \pnum \expects -\tcode{get() != nullptr}. +\tcode{get() != nullptr} is \tcode{true}. \pnum \returns @@ -3970,15 +4010,15 @@ \tcode{allocate_shared} shall initialize this (sub)object via the expression \begin{itemize} - \item \tcode{allocator_traits::construct(a2, pv, v)} or - \item \tcode{allocator_traits::construct(a2, pv, l...)} + \item \tcode{allocator_traits::construct(a2, pu, v)} or + \item \tcode{allocator_traits::construct(a2, pu, l...)} \end{itemize} respectively, - where \tcode{pv} points to storage - suitable to hold an object of type \tcode{U} and - \tcode{a2} of type \tcode{A2} is a rebound copy of - the allocator \tcode{a} passed to \tcode{allocate_shared} - such that its \tcode{value_type} is \tcode{remove_cv_t}. + where \tcode{pu} is a pointer of type \tcode{remove_cv_t*} + pointing to storage + suitable to hold an object of type \tcode{remove_cv_t} and + \tcode{a2} of type \tcode{A2} is a potentially rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared}. \item When a (sub)object of non-array type \tcode{U} is specified to have a default initial value, @@ -3989,13 +4029,13 @@ \item When a (sub)object of non-array type \tcode{U} is specified to have a default initial value, - \tcode{allocate_shared} shall initialize this (sub)object - via the expression \tcode{allocator_traits::construct(a2, pv)}, - where \tcode{pv} points to storage - suitable to hold an object of type \tcode{U} and - \tcode{a2} of type \tcode{A2} is a rebound copy of - the allocator \tcode{a} passed to \tcode{allocate_shared} - such that its \tcode{value_type} is \tcode{remove_cv_t}. + \tcode{allocate_shared} initializes this (sub)object + via the expression \tcode{allocator_traits::construct(a2, pu)}, + where \tcode{pu} is a pointer of type \tcode{remove_cv_t*} + pointing to storage + suitable to hold an object of type \tcode{remove_cv_t} and + \tcode{a2} of type \tcode{A2} is a potentially rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared}. \item When a (sub)object of non-array type \tcode{U} is initialized by \tcode{make_shared_for_overwrite} or\linebreak % avoid Overfull @@ -4012,18 +4052,20 @@ of their original construction. \item When a (sub)object of non-array type \tcode{U} - that was initialized by \tcode{make_shared} is to be destroyed, - it is destroyed via the expression \tcode{pv->\~{}U()} where - \tcode{pv} points to that object of type \tcode{U}. + that was initialized by \tcode{make_shared}, + \tcode{make_shared_for_overwrite}, or \tcode{allocate_shared_for_overwrite} + is to be destroyed, + it is destroyed via the expression \tcode{pu->\~{}U()} where + \tcode{pu} points to that object of type \tcode{U}. \item When a (sub)object of non-array type \tcode{U} that was initialized by \tcode{allocate_shared} is to be destroyed, it is destroyed via the expression - \tcode{allocator_traits::destroy(a2, pv)} where - \tcode{pv} points to that object of type \tcode{remove_cv_t} and - \tcode{a2} of type \tcode{A2} is a rebound copy of - the allocator \tcode{a} passed to \tcode{allocate_shared} - such that its \tcode{value_type} is \tcode{remove_cv_t}. + \tcode{allocator_traits::destroy(a2, pu)} where + \tcode{pu} is a pointer of type \tcode{remove_cv_t*} + pointing to that object of type \tcode{remove_cv_t} and + \tcode{a2} of type \tcode{A2} is a potentially rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared}. \end{itemize} \begin{note} These functions will typically allocate more memory than \tcode{sizeof(T)} to diff --git a/source/meta.tex b/source/meta.tex index 8903d5be01..d6bf2847cb 100644 --- a/source/meta.tex +++ b/source/meta.tex @@ -160,9 +160,9 @@ template struct integral_constant; template - using bool_constant = integral_constant; - using true_type = bool_constant; - using false_type = bool_constant; + using @\libglobal{bool_constant}@ = integral_constant; + using @\libglobal{true_type}@ = bool_constant; + using @\libglobal{false_type}@ = bool_constant; // \ref{meta.unary.cat}, primary type categories template struct is_void; @@ -192,7 +192,6 @@ // \ref{meta.unary.prop}, type properties template struct is_const; template struct is_volatile; - template struct is_trivial; template struct is_trivially_copyable; template struct is_standard_layout; template struct is_empty; @@ -430,8 +429,6 @@ constexpr bool @\libglobal{is_const_v}@ = is_const::value; template constexpr bool @\libglobal{is_volatile_v}@ = is_volatile::value; - template - constexpr bool @\libglobal{is_trivial_v}@ = is_trivial::value; template constexpr bool @\libglobal{is_trivially_copyable_v}@ = is_trivially_copyable::value; template @@ -595,7 +592,7 @@ \indexlibrarymember{value_type}{integral_constant}% \begin{codeblock} namespace std { - template struct integral_constant { + template struct @\libglobal{integral_constant}@ { static constexpr T value = v; using value_type = T; @@ -607,7 +604,6 @@ } \end{codeblock} -\indexlibraryglobal{integral_constant}% \indexlibraryglobal{bool_constant}% \indexlibraryglobal{true_type}% \indexlibraryglobal{false_type}% @@ -833,13 +829,6 @@ \tcode{T} is volatile-qualified\iref{basic.type.qualifier} & \\ \rowsep -\indexlibraryglobal{is_trivial}% -\tcode{template}\br - \tcode{struct is_trivial;} & - \tcode{T} is a trivial type\iref{term.trivial.type} & - \tcode{remove_all_extents_t} shall be a complete - type or \cv{}~\keyword{void}. \\ \rowsep - \indexlibraryglobal{is_trivially_copyable}% \tcode{template}\br \tcode{struct is_trivially_copyable;} & @@ -1228,8 +1217,8 @@ For an array type \tcode{T}, the same result as \tcode{has_unique_object_representations_v>}, otherwise \seebelow. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, or - an array of unknown bound. \\ \rowsep + \tcode{remove_all_extents_t} shall be a complete type or + \cv{}~\keyword{void}. \\ \rowsep \indexlibraryglobal{reference_constructs_from_temporary}% \tcode{template}\br @@ -1907,21 +1896,18 @@ \lhdr{Template} & \rhdr{Comments} \\ \capsep \endhead -\indexlibraryglobal{type_identity}% \tcode{template\br - struct type_identity;} + struct \libglobal{type_identity};} & The member typedef \tcode{type} denotes \tcode{T}. \\ \rowsep -\indexlibraryglobal{remove_cvref}% -\tcode{template\br struct remove_cvref;} +\tcode{template\br struct \libglobal{remove_cvref};} & The member typedef \tcode{type} denotes \tcode{remove_cv_t>}. \\ \rowsep -\indexlibraryglobal{decay}% -\tcode{template\br struct decay;} +\tcode{template\br struct \libglobal{decay};} & Let \tcode{U} be \tcode{remove_reference_t}. If \tcode{is_array_v} is \tcode{true}, the member typedef \tcode{type} denotes @@ -1937,8 +1923,7 @@ \end{tailnote} \\ \rowsep -\indexlibraryglobal{enable_if}% -\tcode{template} \tcode{struct enable_if;} +\tcode{template} \tcode{struct \libglobal{enable_if};} & If \tcode{B} is \tcode{true}, the member typedef \tcode{type} denotes \tcode{T}; otherwise, there shall be no member @@ -1946,7 +1931,7 @@ \tcode{template}\br - \tcode{struct conditional;} + \tcode{struct \libglobal{conditional};} & If \tcode{B} is \tcode{true}, the member typedef \tcode{type} denotes \tcode{T}. If \tcode{B} is \tcode{false}, the member typedef \tcode{type} denotes \tcode{F}. \\ \rowsep @@ -1959,36 +1944,32 @@ Each type in the template parameter pack \tcode{T} shall be complete, \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep -\indexlibraryglobal{basic_common_reference}% \tcode{template class,} \hspace*{2ex}\tcode{template class>} \keyword{struct} - \hspace*{2ex}\tcode{basic_common_reference;} + \hspace*{2ex}\tcode{\libglobal{basic_common_reference};} & Unless this trait is specialized, there shall be no member \tcode{type}. \\ \rowsep -\indexlibraryglobal{common_reference}% -\tcode{template} \tcode{struct common_reference;} +\tcode{template} \tcode{struct \libglobal{common_reference};} & The member \grammarterm{typedef-name} \tcode{type} is defined or omitted as specified below. Each type in the parameter pack \tcode{T} shall be complete or \cv{} \keyword{void}. \\ \rowsep -\indexlibraryglobal{underlying_type}% \tcode{template}\br - \tcode{struct underlying_type;} + \tcode{struct \libglobal{underlying_type};} & If \tcode{T} is an enumeration type, the member typedef \tcode{type} denotes the underlying type of \tcode{T}\iref{dcl.enum}; otherwise, there is no member \tcode{type}.\br \mandates \tcode{T} is not an incomplete enumeration type. \\ \rowsep -\indexlibraryglobal{invoke_result}% \tcode{template}\br - \tcode{struct invoke_result;} + \tcode{struct \libglobal{invoke_result};} & If the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)}\iref{func.require} is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand}, @@ -2009,8 +1990,7 @@ are complete types, \cv{}~\keyword{void}, or arrays of unknown bound.\\ \rowsep -\indexlibraryglobal{unwrap_reference}% -\tcode{template} \tcode{struct unwrap_reference;} +\tcode{template} \tcode{struct \libglobal{unwrap_reference};} & If \tcode{T} is a specialization \tcode{reference_wrapper} for some type \tcode{X}, @@ -2018,8 +1998,7 @@ denotes \tcode{X\&}, otherwise \tcode{type} denotes \tcode{T}. \\ \rowsep -\indexlibraryglobal{unwrap_ref_decay}% -\tcode{template} \tcode{unwrap_ref_decay;} +\tcode{template} \tcode{\libglobal{unwrap_ref_decay};} & The member typedef \tcode{type} of \tcode{unwrap_ref_decay} denotes the type \tcode{unwrap_reference_t>}.\\ diff --git a/source/modules.tex b/source/modules.tex index 2ed009a3b6..ced0320686 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -312,7 +312,7 @@ A redeclaration of an entity $X$ is implicitly exported if $X$ was introduced by an exported declaration; -otherwise it shall not be exported. +otherwise it shall not be exported if it is attached to a named module. \begin{example} \begin{codeblock} export module M; diff --git a/source/numerics.tex b/source/numerics.tex index e8afb21e09..5313c5f92e 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -17,15 +17,16 @@ as summarized in \tref{numerics.summary}. \begin{libsumtab}{Numerics library summary}{numerics.summary} -\ref{numeric.requirements} & Requirements & \\ \rowsep -\ref{cfenv} & Floating-point environment & \tcode{} \\ \rowsep -\ref{complex.numbers} & Complex numbers & \tcode{} \\ \rowsep -\ref{rand} & Random number generation & \tcode{} \\ \rowsep -\ref{numarray} & Numeric arrays & \tcode{} \\ \rowsep -\ref{c.math} & Mathematical functions for floating-point types & - \tcode{}, \tcode{} \\ \rowsep -\ref{numbers} & Numbers & \tcode{} \\ \rowsep -\ref{linalg} & Linear algebra & \tcode{} \\ +\ref{numeric.requirements} & Requirements & \\ \rowsep +\ref{cfenv} & Floating-point environment & \tcode{} \\ \rowsep +\ref{complex.numbers} & Complex numbers & \tcode{} \\ \rowsep +\ref{rand} & Random number generation & \tcode{} \\ \rowsep +\ref{numarray} & Numeric arrays & \tcode{} \\ \rowsep +\ref{c.math} & Mathematical functions for + floating-point types & \tcode{}, \tcode{} \\ \rowsep +\ref{numbers} & Numbers & \tcode{} \\ \rowsep +\ref{linalg} & Linear algebra & \tcode{} \\ \rowsep +\ref{simd} & Data-parallel types & \tcode{} \\ \end{libsumtab} \rSec1[numeric.requirements]{Numeric type requirements} @@ -1451,11 +1452,13 @@ template requires @\libconcept{output_range}@> && @\libconcept{invocable}@ && - @\libconcept{uniform_random_bit_generator}@> + @\libconcept{uniform_random_bit_generator}@> && + is_arithmetic_v> constexpr borrowed_iterator_t generate_random(R&& r, G&& g, D&& d); template> O, @\libconcept{sentinel_for}@ S> - requires @\libconcept{invocable}@ && @\libconcept{uniform_random_bit_generator}@> + requires @\libconcept{invocable}@ && @\libconcept{uniform_random_bit_generator}@> && + is_arithmetic_v> constexpr O generate_random(O first, S last, G&& g, D&& d); } @@ -1711,7 +1714,7 @@ & \tcode{T} & \tcode{T} is an unsigned integer type\iref{basic.fundamental} of at least 32 bits. - & compile-time + & \\ \rowsep \tcode{S()}% & @@ -2320,12 +2323,12 @@ \tcode{D::result_type} & \tcode{T} & \tcode{T} is an arithmetic type\iref{basic.fundamental}. - & compile-time + & \\ \rowsep \tcode{D::param_type} & \tcode{P} & - & compile-time + & \\ \rowsep \tcode{D()}% & @@ -3033,8 +3036,8 @@ first construct \tcode{e}, a \tcode{linear_congruential_engine} object, as if by the following definition: \begin{codeblock} -linear_congruential_engine e(value == 0u ? default_seed : value); +linear_congruential_engine e( + value == 0u ? default_seed : static_cast(value % 2147483563u)); \end{codeblock} Then, to set each $X_k$, obtain new values $z_0, \dotsc, z_{n-1}$ @@ -3077,8 +3080,8 @@ \pnum A \tcode{philox_engine} random number engine produces -unsigned integer random numbers in the closed interval \crange{0}{$m$}, -where $m = 2^w - 1$ and +unsigned integer random numbers in the interval \range{0}{$m$}, +where $m = 2^w$ and the template parameter $w$ defines the range of the produced numbers. The state of a \tcode{philox_engine} object consists of a sequence $X$ of $n$ unsigned integer values of width $w$, @@ -3131,15 +3134,13 @@ $f_n(j)$ is defined in \tref{rand.eng.philox.f}. \begin{floattable}{Values for the word permutation $\bm{f}_{\bm{n}}\bm{(j)}$}{rand.eng.philox.f} -{l|l|l|l|l|l|l|l|l|l|l|l|l|l|l|l|l|l} +{l|l|l|l|l|l} \topline - \multicolumn{2}{|c|}{$\bm{f}_{\bm{n}}\bm{(j)}$} & \multicolumn{16}{c|}{$\bm{j}$} \\ \cline{3-18} + \multicolumn{2}{|c|}{$\bm{f}_{\bm{n}}\bm{(j)}$} & \multicolumn{4}{c|}{$\bm{j}$} \\ \cline{3-6} \multicolumn{2}{|c|}{} - & 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 & 15 \\ \hline - $\bm{n} $ & 2 & 0 & 1 & \multicolumn{14}{c|}{} \\ \cline{2-18} - & 4 & 0 & 3 & 2 & 1 & \multicolumn{12}{c|}{} \\ \cline{2-18} - & 8 & 2 & 1 & 4 & 7 & 6 & 5 & 0 & 3 & \multicolumn{8}{c|}{} \\ \cline{2-18} - & 16 & 0 & 9 & 2 & 13 & 6 & 11 & 4 & 15 & 10 & 7 & 12 & 3 & 14 & 5 & 8 & 1 \\ \cline{2-18} + & 0 & 1 & 2 & 3 \\ \hline + $\bm{n} $ & 2 & 0 & 1 & \multicolumn{2}{c|}{} \\ \cline{2-6} + & 4 & 2 & 1 & 0 & 3 \\ \cline{2-6} \end{floattable} \begin{note} For $n = 2$ the sequence is not permuted. @@ -3148,8 +3149,8 @@ \item The following computations are applied to the elements of the $V$ sequence: \begin{codeblock} -@$X_{2k + 0} = \mullo(V_{2k + 1}, M_{k}, w)$@ -@$X_{2k + 1} = \mulhi(V_{2k + 1}, M_{k}, w) \xor \mathit{key}^q_k \xor V_{2k}$@ +@$X_{2k + 0} = \mulhi(V_{2k}, M_{k}, w) \xor \mathit{key}^q_k \xor V_{2k + 1}$@ +@$X_{2k + 1} = \mullo(V_{2k}, M_{k}, w)$@ \end{codeblock} where: \begin{itemize} @@ -3240,7 +3241,7 @@ \mandates \begin{itemize} \item \tcode{sizeof...(consts) == n} is \tcode{true}, and -\item \tcode{n == 2 || n == 4 || n == 8 || n == 16} is \tcode{true}, and +\item \tcode{n == 2 || n == 4} is \tcode{true}, and \item \tcode{0 < r} is \tcode{true}, and \item \tcode{0 < w \&\& w <= numeric_limits::digits} is \tcode{true}. \end{itemize} @@ -3908,7 +3909,7 @@ \begin{itemdecl} using philox4x32 = philox_engine; + 0xCD9E8D57, 0x9E3779B9, 0xD2511F53, 0xBB67AE85>; \end{itemdecl} \begin{itemdescr} @@ -3923,7 +3924,7 @@ \begin{itemdecl} using philox4x64 = philox_engine; + 0xCA5A826395121157, 0x9E3779B97F4A7C15, 0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B>; \end{itemdecl} \begin{itemdescr} @@ -11722,7 +11723,7 @@ \pnum Throughout \ref{linalg}, the following types are -\defnadjx{linear algebra}{value type}{linear algebra value types}: +\defnadjx{linear algebra}{value types}{value type}: \begin{itemize} \item the \tcode{value_type} type alias of @@ -12418,7 +12419,7 @@ bool @\exposid{compatible-static-extents}@(size_t r1, size_t r2) { // \expos return MDS1::static_extent(r1) == dynamic_extent || MDS2::static_extent(r2) == dynamic_extent || - MDS1::static_extent(r1) == MDS2::static_extent(r2)); + MDS1::static_extent(r1) == MDS2::static_extent(r2); } template<@\exposconcept{in-vector}@ In1, @\exposconcept{in-vector}@ In2, @\exposconcept{in-vector}@ Out> @@ -12495,7 +12496,7 @@ constexpr bool @\exposid{multipliable}@( // \expos const @\exposconcept{in-matrix}@ auto& in_mat1, const @\exposconcept{in-matrix}@ auto& in_mat2, const @\exposconcept{in-matrix}@ auto& out_mat) { return out_mat.extent(0) == in_mat1.extent(0) && out_mat.extent(1) == in_mat2.extent(1) && - in1_mat.extent(1) == in_mat2.extent(0); + in_mat1.extent(1) == in_mat2.extent(0); } \end{codeblock} @@ -12808,21 +12809,40 @@ \begin{itemdescr} \pnum Let \tcode{A} be +\begin{itemize} +\item \tcode{remove_cvref_t} -if \tcode{Accessor} is a specialization of \tcode{conjugated_accessor}, and -otherwise \tcode{conjugated_accessor}. +if \tcode{Accessor} is a specialization of \tcode{conjugated_accessor}; otherwise, +\item +\tcode{Accessor} if \tcode{remove_cvref_t} is an arithmetic type; otherwise, +\item +\tcode{Accessor} if the expression \tcode{conj(E)} is not valid for any subexpression \tcode{E} +whose type \tcode{T} is expression-equivalent to \tcode{remove_cvref_t} +with overload resolution performed in a context that includes the declaration +\tcode{template conj(const T\&) = delete;}; and otherwise, +\item +\tcode{conjugated_accessor}. +\end{itemize} \pnum \returns \begin{itemize} \item -If \tcode{Accessor} is a specialization of \tcode{conjugated_accessor}, +The value \begin{codeblock} mdspan(a.data_handle(), a.mapping(), a.accessor().nested_accessor()) \end{codeblock} +if \tcode{Accessor} is a specialization of \tcode{conjugated_accessor}; otherwise, \item -otherwise, +\tcode{a} if \tcode{remove_cvref_t} is an arithmetic type; otherwise, +\item +\tcode{a} if the expression \tcode{conj(E)} is not valid for any subexpression \tcode{E} +whose type \tcode{T} is expression-equivalent to \tcode{remove_cvref_t} +with overload resolution performed in a context that includes the declaration +\tcode{template conj(const T\&) = delete;}; and otherwise, +\item +the value \begin{codeblock} mdspan(a.data_handle(), a.mapping(), conjugated_accessor(a.accessor())) @@ -13066,6 +13086,14 @@ \item otherwise, \tcode{layout_left} if \tcode{Layout} is \tcode{layout_right}; \item +otherwise, \tcode{layout_right_padded} if \tcode{Layout} is\newline +\tcode{layout_left_padded} +for some \tcode{size_t} value \tcode{PaddingValue}; +\item +otherwise, \tcode{layout_left_padded} if \tcode{Layout} is\newline +\tcode{layout_right_padded} +for some \tcode{size_t} value \tcode{PaddingValue}; +\item otherwise, \tcode{layout_stride} if \tcode{Layout} is \tcode{layout_stride}; \item otherwise, @@ -13108,11 +13136,26 @@ a.accessor()) \end{codeblock} \item +otherwise, +\begin{codeblock} +R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents()), + a.mapping().stride(1)), a.accessor()) +\end{codeblock} +if \tcode{Layout} is \tcode{layout_left_padded} +for some \tcode{size_t} value \tcode{PaddingValue}; +\item +otherwise, +\begin{codeblock} +R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents()), + a.mapping().stride(0)), a.accessor()) +\end{codeblock} +if \tcode{Layout} is \tcode{layout_right_padded} +for some \tcode{size_t} value \tcode{PaddingValue}; +\item otherwise, if \tcode{Layout} is \tcode{layout_stride}, \begin{codeblock} R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents()), - array{a.mapping().stride(1), a.mapping().stride(0)}), - a.accessor()) + array{a.mapping().stride(1), a.mapping().stride(0)}), a.accessor()) \end{codeblock} \item otherwise, if \tcode{Layout} is a specialization of \tcode{layout_transpose}, @@ -16034,3 +16077,2918 @@ A, t, d, B, divides{}); \end{codeblock} \end{itemdescr} + +\rSec1[simd]{Data-parallel types} + +\rSec2[simd.general]{General} + +\pnum +Subclause \ref{simd} defines data-parallel types and operations on these types. +\begin{note} +The intent is to support acceleration through data-parallel execution resources +where available, such as SIMD registers and instructions or execution units +driven by a common instruction decoder. +\end{note} + +\pnum +The set of \defnadjx{vectorizable}{types}{type} comprises all standard integer +types, character types, and the types \tcode{float} and +\tcode{double}\iref{basic.fundamental}. +In addition, \tcode{std::float16_t}, \tcode{std::float32_t}, and +\tcode{std::float64_t} are vectorizable types if +defined\iref{basic.extended.fp}. + +\pnum +The term \defnadj{data-parallel}{type} refers to all enabled specializations of +the \tcode{basic_simd} and \tcode{basic_simd_mask} class templates. +A \defnadj{data-parallel}{object} is an object of data-parallel type. + +\pnum +Each specialization of \tcode{basic_simd} or \tcode{basic_simd_mask} is either +enabled or disabled, as described in \ref{simd.overview} and +\ref{simd.mask.overview}. + +\pnum +A data-parallel type consists of one or more elements of an underlying +vectorizable type, called the \defnadj{element}{type}. +The number of elements is a constant for each data-parallel type and called the +\defn{width} of that type. +The elements in a data-parallel type are indexed from 0 to $\textrm{width} - 1$. + +\pnum +An \defnadj{element-wise}{operation} applies a specified operation to the +elements of one or more data-parallel objects. +Each such application is unsequenced with respect to the others. +A \defnadj{unary element-wise}{operation} is an element-wise operation that +applies a unary operation to each element of a data-parallel object. +A \defnadj{binary element-wise}{operation} is an element-wise operation that +applies a binary operation to corresponding elements of two data-parallel +objects. + +\pnum +Given a \tcode{basic_simd_mask} object \tcode{mask}, the +\defnadj{selected}{indices} signify the integers $i$ in the range +\range{0}{mask.size()} for which \tcode{mask[$i$]} is \tcode{true}. +Given a data-parallel object \tcode{data}, the \defnadj{selected}{elements} +signify the elements \tcode{data[$i$]} for all selected indices $i$. + +\pnum +The conversion from an arithmetic type \tcode{U} to a vectorizable type +\tcode{T} is \defn{value-preserving} if all possible values of \tcode{U} can be +represented with type \tcode{T}. + +\rSec2[simd.expos]{Exposition-only types, variables, and concepts} + +\begin{codeblock} +using @\exposidnc{simd-size-type} = \seebelownc@; // \expos +template using @\exposidnc{integer-from} = \seebelownc@; // \expos + +template + constexpr @\exposidnc{simd-size-type} \exposidnc{simd-size-v} = \seebelownc@; // \expos +template constexpr size_t @\exposidnc{mask-element-size} = \seebelownc@; // \expos + +template + concept @\defexposconceptnc{constexpr-wrapper-like}@ = // \expos + convertible_to && + equality_comparable_with && + bool_constant::value && + bool_constant(T()) == T::value>::value; + +template using @\exposidnc{deduced-simd-t} = \seebelownc@; // \expos + +template using @\exposidnc{make-compatible-simd-t} = \seebelownc@; // \expos + +template + concept @\defexposconceptnc{simd-floating-point}@ = // \expos + same_as> && + is_default_constructible_v && floating_point; + +template + concept @\defexposconceptnc{math-floating-point}@ = // \expos + (@\exposconceptnc{simd-floating-point}<\exposidnc{deduced-simd-t}@> || ...); + +template + requires @\exposconceptnc{math-floating-point}@ + using @\exposidnc{math-common-simd-t} = \seebelownc@; // \expos + +template + concept @\exposconceptnc{reduction-binary-operation} = \seebelownc@; // \expos + +// \ref{simd.expos.abi}, \tcode{simd} ABI tags +template using @\exposidnc{native-abi} = \seebelownc@; // \expos +template using @\exposidnc{deduce-abi-t} = \seebelownc@; // \expos + +// \ref{simd.flags}, Load and store flags +struct @\exposidnc{convert-flag}@; // \expos +struct @\exposidnc{aligned-flag}@; // \expos +template struct @\exposidnc{overaligned-flag}@; // \expos +\end{codeblock} + +\rSec3[simd.expos.defn]{Exposition-only helpers} + +\begin{itemdecl} +using @\exposid{simd-size-type}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\exposid{simd-size-type} is an alias for a signed integer type. +\end{itemdescr} + +\begin{itemdecl} +template using @\exposid{integer-from}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{\exposid{integer-from}} is an alias for a signed integer type +\tcode{T} such that \tcode{sizeof(T)} equals \tcode{Bytes}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr @\exposid{simd-size-type} \exposid{simd-size-v}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{\exposid{simd-size-v}} denotes the width of \tcode{basic_simd} if the specialization \tcode{basic_simd} is enabled, or \tcode{0} +otherwise. +\end{itemdescr} + +\begin{itemdecl} +template constexpr size_t @\exposid{mask-element-size}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{\exposid{mask-element-size}>} has the value +\tcode{Bytes}. +\end{itemdescr} + +\begin{itemdecl} +template using @\exposid{deduced-simd-t}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{x} denote an lvalue of type \tcode{const T}. + +\pnum +\tcode{\exposid{deduced-simd-t}} is an alias for +\begin{itemize} + \item + \tcode{decltype(x + x)}, if the type of \tcode{x + x} is an enabled + specialization of \tcode{basic_simd}; otherwise + \item + \tcode{void}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template using @\exposid{make-compatible-simd-t}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{x} denote an lvalue of type \tcode{const T}. +\pnum +\tcode{\exposid{make-compatible-simd-t}} is an alias for +\begin{itemize} + \item + \tcode{\exposid{deduced-simd-t}}, if that type is not \tcode{void}, + otherwise + \item + \tcode{simd}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + requires @\exposconcept{math-floating-point}@ + using @\exposid{math-common-simd-t}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{T0} denote \tcode{Ts...[0]}. +Let \tcode{T1} denote \tcode{Ts...[1]}. +Let \tcode{TRest} denote a pack such that \tcode{T0, T1, TRest...} is equivalent +to \tcode{Ts...}. + +\pnum +Let \tcode{\exposid{math-common-simd-t}} be an alias for +\begin{itemize} + \item + \tcode{\exposid{deduced-simd-t}}, if \tcode{sizeof...(Ts)} equals $1$; + otherwise + \item + \tcode{common_type_t<\exposid{deduced-simd-t}, + \exposid{deduced-simd-t}>}, if \tcode{sizeof...(Ts)} equals $2$ and + \tcode{\exposconcept{math-floating-point} \&\& + \exposconcept{math-floating-point}} is \tcode{true}; otherwise + \item + \tcode{common_type_t<\exposid{deduced-simd-t}, T1>}, if + \tcode{sizeof...(Ts)} equals $2$ and + \tcode{\exposconceptx{math-floating-\brk{}point}{math-floating-point}<\brk{}T0>} + is \tcode{true}; otherwise + \item + \tcode{common_type_t>}, if + \tcode{sizeof...(Ts)} equals $2$; otherwise + \item + \tcode{common_type_t<\exposid{math-common-simd-t}, TRest...>}, if + \tcode{\exposid{math-common-simd-t}} is valid and denotes a type; + otherwise + \item + \tcode{common_type_t<\exposid{math-common-simd-t}, T0, T1>}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + concept @\defexposconcept{reduction-binary-operation}@ = + requires (const BinaryOperation binary_op, const simd v) { + { binary_op(v, v) } -> same_as>; + }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Types \tcode{BinaryOperation} and \tcode{T} model +\tcode{\exposconcept{reduction-binary-operation}} only if: +\begin{itemize} +\item \tcode{BinaryOperation} is a binary element-wise operation and the +operation is commutative. + +\item An object of type \tcode{BinaryOperation} can be invoked with two +arguments of type \tcode{basic_simd}, with unspecified ABI tag +\tcode{Abi}, returning a \tcode{basic_simd}. +\end{itemize} +\end{itemdescr} + +\rSec3[simd.expos.abi]{\tcode{simd} ABI tags} + +\begin{itemdecl} +template using @\exposid{native-abi}@ = @\seebelow@; +template using @\exposid{deduce-abi-t}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +An \defn{ABI tag} is a type that indicates a choice of size and binary +representation for objects of data-parallel type. +\begin{note} +The intent is for the size and binary representation to depend on the target +architecture and compiler flags. +The ABI tag, together with a given element type, implies the width. +\end{note} + +\pnum +\begin{note} +The ABI tag is orthogonal to selecting the machine instruction set. +The selected machine instruction set limits the usable ABI tag types, though +(see \ref{simd.overview}). +The ABI tags enable users to safely pass objects of data-parallel type between +translation unit boundaries (e.g., function calls or I/O). +\end{note} + +\pnum +An implementation defines ABI tag types as necessary for the following aliases. + +\pnum +\tcode{\exposid{deduce-abi-t}} is defined if +\begin{itemize} +\item \tcode{T} is a vectorizable type, +\item \tcode{N} is greater than zero, and +\item \tcode{N} is not larger than an implementation-defined maximum. +\end{itemize} +The \impldef{maximum width for \tcode{simd} and \tcode{simd_mask}} maximum for +\tcode{N} is not smaller than 64 and can differ depending on \tcode{T}. + +\pnum +Where present, \tcode{\exposid{deduce-abi-t}} names an ABI tag type such +that +\begin{itemize} + \item + \tcode{\exposid{simd-size-v}>} equals + \tcode{N}, \item \tcode{basic_simd>} is + enabled\iref{simd.overview}, and + \item + \tcode{basic_simd_mask, N>>} is enabled. +\end{itemize} + +\pnum +\tcode{\exposid{native-abi}} is an \impldef{default ABI tag for +\tcode{basic_simd} and \tcode{basic_simd_mask}} alias for an ABI tag. +\tcode{basic_simd>} is an enabled specialization. +\begin{note} +The intent is to use the ABI tag producing the most efficient data-parallel +execution for the element type \tcode{T} on the currently targeted system. +For target architectures with ISA extensions, compiler flags can change the type +of the \tcode{\exposid{native-abi}} alias. +\end{note} +\begin{example} +Consider a target architecture supporting the ABI tags \tcode{__simd128} and +\tcode{__simd256}, where hardware support for \tcode{__simd256} exists only for +floating-point types. +The implementation therefore defines \tcode{\exposid{native-abi}} as an alias +for +\begin{itemize} +\item \tcode{__simd256} if \tcode{T} is a floating-point type, and +\item \tcode{__simd128} otherwise. +\end{itemize} +\end{example} +\end{itemdescr} + +\rSec2[simd.syn]{Header \tcode{} synopsis} +\indexheader{simd}% +\begin{codeblock} +namespace std { + // \ref{simd.traits}, \tcode{simd} type traits + template struct simd_alignment; + template + constexpr size_t simd_alignment_v = simd_alignment::value; + + template struct rebind_simd { using type = @\seebelow@; }; + template using rebind_simd_t = typename rebind_simd::type; + template<@\exposid{simd-size-type}@ N, class V> struct resize_simd { using type = @\seebelow@; }; + template<@\exposid{simd-size-type}@ N, class V> using resize_simd_t = typename resize_simd::type; + + // \ref{simd.flags}, Load and store flags + template struct simd_flags; + inline constexpr simd_flags<> simd_flag_default{}; + inline constexpr simd_flags<@\exposid{convert-flag}@> simd_flag_convert{}; + inline constexpr simd_flags<@\exposid{aligned-flag}@> simd_flag_aligned{}; + template requires (has_single_bit(N)) + constexpr simd_flags<@\exposid{overaligned-flag}@> simd_flag_overaligned{}; + + // \ref{simd.class}, Class template \tcode{basic_simd} + template> class basic_simd; + template>> + using simd = basic_simd>; + + // \ref{simd.mask.class}, Class template \tcode{basic_simd_mask} + template>> class basic_simd_mask; + template>> + using simd_mask = basic_simd_mask>; + + // \ref{simd.loadstore}, \tcode{basic_simd} load and store functions + template + requires ranges::sized_range + constexpr V simd_unchecked_load(R&& r, simd_flags f = {}); + template + requires ranges::sized_range + constexpr V simd_unchecked_load(R&& r, const typename V::mask_type& k, + simd_flags f = {}); + template + constexpr V simd_unchecked_load(I first, iter_difference_t n, + simd_flags f = {}); + template + constexpr V simd_unchecked_load(I first, iter_difference_t n, + const typename V::mask_type& k, simd_flags f = {}); + template S, class... Flags> + constexpr V simd_unchecked_load(I first, S last, simd_flags f = {}); + template S, class... Flags> + constexpr V simd_unchecked_load(I first, S last, const typename V::mask_type& k, + simd_flags f = {}); + + template + requires ranges::sized_range + constexpr V simd_partial_load(R&& r, simd_flags f = {}); + template + requires ranges::sized_range + constexpr V simd_partial_load(R&& r, const typename V::mask_type& k, + simd_flags f = {}); + template + constexpr V simd_partial_load(I first, iter_difference_t n, simd_flags f = {}); + template + constexpr V simd_partial_load(I first, iter_difference_t n, + const typename V::mask_type& k, simd_flags f = {}); + template S, class... Flags> + constexpr V simd_partial_load(I first, S last, simd_flags f = {}); + template S, class... Flags> + constexpr V simd_partial_load(I first, S last, const typename V::mask_type& k, + simd_flags f = {}); + + template + requires ranges::sized_range && indirectly_writable, T> + constexpr void simd_unchecked_store(const basic_simd& v, R&& r, + simd_flags f = {}); + template + requires ranges::sized_range && indirectly_writable, T> + constexpr void simd_unchecked_store(const basic_simd& v, R&& r, + const typename basic_simd::mask_type& mask, simd_flags f = {}); + template + requires indirectly_writable + constexpr void simd_unchecked_store(const basic_simd& v, I first, + iter_difference_t n, simd_flags f = {}); + template + requires indirectly_writable + constexpr void simd_unchecked_store(const basic_simd& v, I first, + iter_difference_t n, const typename basic_simd::mask_type& mask, + simd_flags f = {}); + template S, class... Flags> + requires indirectly_writable + constexpr void simd_unchecked_store(const basic_simd& v, I first, S last, + simd_flags f = {}); + template S, class... Flags> + requires indirectly_writable + constexpr void simd_unchecked_store(const basic_simd& v, I first, S last, + const typename basic_simd::mask_type& mask, simd_flags f = {}); + + template + requires ranges::sized_range && indirectly_writable, T> + constexpr void simd_partial_store(const basic_simd& v, R&& r, + simd_flags f = {}); + template + requires ranges::sized_range && indirectly_writable, T> + constexpr void simd_partial_store(const basic_simd& v, R&& r, + const typename basic_simd::mask_type& mask, simd_flags f = {}); + template + requires indirectly_writable + constexpr void simd_partial_store( + const basic_simd& v, I first, iter_difference_t n, + simd_flags f = {}); + template + requires indirectly_writable + constexpr void simd_partial_store( + const basic_simd& v, I first, iter_difference_t n, + const typename basic_simd::mask_type& mask, simd_flags f = {}); + template S, class... Flags> + requires indirectly_writable + constexpr void simd_partial_store(const basic_simd& v, I first, S last, + simd_flags f = {}); + template S, class... Flags> + requires indirectly_writable + constexpr void simd_partial_store(const basic_simd& v, I first, S last, + const typename basic_simd::mask_type& mask, simd_flags f = {}); + + // \ref{simd.creation}, \tcode{basic_simd} and \tcode{basic_simd_mask} creation + template + constexpr auto + simd_split(const basic_simd& x) noexcept; + template + constexpr auto + simd_split(const basic_simd_mask<@\exposid{mask-element-size}@, Abi>& x) noexcept; + + template + constexpr basic_simd::size() + ...)>> + simd_cat(const basic_simd&...) noexcept; + template + constexpr basic_simd_mask, + (basic_simd_mask::size() + ...)>> + simd_cat(const basic_simd_mask&...) noexcept; + + // \ref{simd.mask.reductions}, \tcode{basic_simd_mask} reductions + template + constexpr bool all_of(const basic_simd_mask&) noexcept; + template + constexpr bool any_of(const basic_simd_mask&) noexcept; + template + constexpr bool none_of(const basic_simd_mask&) noexcept; + template + constexpr @\exposid{simd-size-type}@ reduce_count(const basic_simd_mask&) noexcept; + template + constexpr @\exposid{simd-size-type}@ reduce_min_index(const basic_simd_mask&); + template + constexpr @\exposid{simd-size-type}@ reduce_max_index(const basic_simd_mask&); + + constexpr bool all_of(same_as auto) noexcept; + constexpr bool any_of(same_as auto) noexcept; + constexpr bool none_of(same_as auto) noexcept; + constexpr @\exposid{simd-size-type}@ reduce_count(same_as auto) noexcept; + constexpr @\exposid{simd-size-type}@ reduce_min_index(same_as auto); + constexpr @\exposid{simd-size-type}@ reduce_max_index(same_as auto); + + // \ref{simd.reductions}, \tcode{basic_simd} reductions + template> + constexpr T reduce(const basic_simd&, BinaryOperation = {}); + template> + constexpr T reduce( + const basic_simd& x, const typename basic_simd::mask_type& mask, + BinaryOperation binary_op = {}, type_identity_t identity_element = @\seebelow@); + + template + constexpr T reduce_min(const basic_simd&) noexcept; + template + constexpr T reduce_min(const basic_simd&, + const typename basic_simd::mask_type&) noexcept; + template + constexpr T reduce_max(const basic_simd&) noexcept; + template + constexpr T reduce_max(const basic_simd&, + const typename basic_simd::mask_type&) noexcept; + + // \ref{simd.alg}, Algorithms + template + constexpr basic_simd + min(const basic_simd& a, const basic_simd& b) noexcept; + template + constexpr basic_simd + max(const basic_simd& a, const basic_simd& b) noexcept; + template + constexpr pair, basic_simd> + minmax(const basic_simd& a, const basic_simd& b) noexcept; + template + constexpr basic_simd + clamp(const basic_simd& v, const basic_simd& lo, + const basic_simd& hi); + + template + constexpr auto simd_select(bool c, const T& a, const U& b) + -> remove_cvref_t; + template + constexpr auto simd_select(const basic_simd_mask& c, const T& a, const U& b) + noexcept -> decltype(@\exposid{simd-select-impl}@(c, a, b)); + + // \ref{simd.math}, Mathematical functions + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ acos(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ asin(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ atan(const V& x); + template + constexpr @\exposid{math-common-simd-t}@ atan2(const V0& y, const V1& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cos(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sin(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tan(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ acosh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ asinh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ atanh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cosh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sinh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tanh(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ exp(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ exp2(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ expm1(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ + frexp(const V& value, rebind_simd_t>* exp); + template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_simd_t> ilogb(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ ldexp(const V& x, const + rebind_simd_t>& exp); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log10(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log1p(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log2(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ logb(const V& x); + template + constexpr basic_simd modf(const type_identity_t>& value, + basic_simd* iptr); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ scalbn(const V& x, const + rebind_simd_t>& n); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ scalbln( + const V& x, const rebind_simd_t>& n); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cbrt(const V& x); + template + constexpr basic_simd abs(const basic_simd& j); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ abs(const V& j); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ fabs(const V& x); + template + constexpr @\exposid{math-common-simd-t}@ hypot(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ hypot(const V0& x, const V1& y, const V2& z); + template + constexpr @\exposid{math-common-simd-t}@ pow(const V0& x, const V1& y); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sqrt(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ erf(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ erfc(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ lgamma(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tgamma(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ ceil(const V& x); + template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ floor(const V& x); + template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ nearbyint(const V& x); + template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ rint(const V& x); + template<@\exposconcept{math-floating-point}@ V> + rebind_simd_t> lrint(const V& x); + template<@\exposconcept{math-floating-point}@ V> + rebind_simd_t llrint(const @\exposid{deduced-simd-t}@& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ round(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_simd_t> lround(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_simd_t> llround(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ trunc(const V& x); + template + constexpr @\exposid{math-common-simd-t}@ fmod(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ remainder(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ + remquo(const V0& x, const V1& y, rebind_simd_t>* quo); + template + constexpr @\exposid{math-common-simd-t}@ copysign(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ nextafter(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ fdim(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ fmax(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ fmin(const V0& x, const V1& y); + template + constexpr @\exposid{math-common-simd-t}@ fma(const V0& x, const V1& y, const V2& z); + template + constexpr @\exposid{math-common-simd-t}@ + lerp(const V0& a, const V1& b, const V2& t) noexcept; + template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_simd_t> fpclassify(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isfinite(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isinf(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isnan(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isnormal(const V& x); + template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type signbit(const V& x); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + isgreater(const V0& x, const V1& y); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + isgreaterequal(const V0& x, const V1& y); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + isless(const V0& x, const V1& y); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + islessequal(const V0& x, const V1& y); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + islessgreater(const V0& x, const V1& y); + template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + isunordered(const V0& x, const V1& y); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ assoc_laguerre(const rebind_simd_t>& n, const + rebind_simd_t>& m, + const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ assoc_legendre(const rebind_simd_t>& l, const + rebind_simd_t>& m, + const V& x); + template + @\exposid{math-common-simd-t}@ beta(const V0& x, const V1& y); + template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ comp_ellint_1(const V& k); + template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ comp_ellint_2(const V& k); + template + @\exposid{math-common-simd-t}@ comp_ellint_3(const V0& k, const V1& nu); + template + @\exposid{math-common-simd-t}@ cyl_bessel_i(const V0& nu, const V1& x); + template + @\exposid{math-common-simd-t}@ cyl_bessel_j(const V0& nu, const V1& x); + template + @\exposid{math-common-simd-t}@ cyl_bessel_k(const V0& nu, const V1& x); + template + @\exposid{math-common-simd-t}@ cyl_neumann(const V0& nu, const V1& x); + template + @\exposid{math-common-simd-t}@ ellint_1(const V0& k, const V1& phi); + template + @\exposid{math-common-simd-t}@ ellint_2(const V0& k, const V1& phi); + template + @\exposid{math-common-simd-t}@ ellint_3(const V0& k, const V1& nu, const V2& phi); + template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ expint(const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ hermite(const rebind_simd_t>& n, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ laguerre(const rebind_simd_t>& n, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ legendre(const rebind_simd_t>& l, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ riemann_zeta(const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ sph_bessel( + const rebind_simd_t>& n, const V& x); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ sph_legendre(const rebind_simd_t>& l, + const rebind_simd_t>& m, const V& theta); + template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ + sph_neumann(const rebind_simd_t>& n, const V& x); +} +\end{codeblock} + +\rSec2[simd.traits]{\tcode{simd} type traits} + +\begin{itemdecl} +template struct simd_alignment { @\seebelow@ }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{simd_alignment} has a member \tcode{value} if and only if +\begin{itemize} + \item + \tcode{T} is a specialization of \tcode{basic_simd_mask} and \tcode{U} is + \tcode{bool}, or + \item + \tcode{T} is a specialization of \tcode{basic_simd} and \tcode{U} is a + vectorizable type. +\end{itemize} + +\pnum +If \tcode{value} is present, the type \tcode{simd_alignment} is a +\tcode{BinaryTypeTrait} with a base characteristic of +\tcode{integral_constant} for some unspecified +\tcode{N}\iref{simd.ctor,simd.loadstore}). +\begin{note} +\tcode{value} identifies the alignment restrictions on pointers used for +(converting) loads and stores for the given type \tcode{T} on arrays of type +\tcode{U}. +\end{note} + +\pnum +The behavior of a program that adds specializations for \tcode{simd_alignment} +is undefined. +\end{itemdescr} + +\begin{itemdecl} +template struct rebind_simd { using type = @\seebelow@; }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The member \tcode{type} is present if and only if +\begin{itemize} +\item \tcode{V} is a data-parallel type, +\item \tcode{T} is a vectorizable type, and +\item \tcode{\exposid{deduce-abi-t}} has a member type + \tcode{type}. +\end{itemize} + +\pnum +If \tcode V is a specialization of \tcode{basic_simd}, let \tcode{Abi1} denote +an ABI tag such that \tcode{basic_simd::\brk{}size()} equals +\tcode{V::size()}. +If \tcode V is a specialization of \tcode{basic_simd_mask}, let \tcode{Abi1} +denote an ABI tag such that \tcode{basic_simd_mask::\brk{}size()} equals \tcode{V::size()}. + +\pnum +Where present, the member typedef \tcode{type} names \tcode{basic_simd} +if \tcode V is a specialization of \tcode{basic_simd} or +\tcode{basic_simd_mask} if \tcode V is a specialization of +\tcode{basic_simd_mask}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposid{simd-size-type}@ N, class V> struct resize_simd { using type = @\seebelow@; }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{T} denote +\begin{itemize} + \item + \tcode{typename V::value_type} if \tcode{V} is a specialization of + \tcode{basic_simd}, + \item + otherwise \tcode{\exposid{integer-from}<\exposid{mask-element-size}>} if + \tcode{V} is a specialization of \tcode{basic_simd_mask}. +\end{itemize} + +\pnum +The member \tcode{type} is present if and only if +\begin{itemize} +\item \tcode{V} is a data-parallel type, and +\item \tcode{\exposid{deduce-abi-t}} has a member type \tcode{type}. +\end{itemize} + +\pnum +If \tcode V is a specialization of \tcode{basic_simd}, let \tcode{Abi1} denote an +ABI tag such that \tcode{basic_simd::\brk{}size()} equals +\tcode{V::size()}. +If \tcode V is a specialization of \tcode{basic_simd_mask}, let \tcode{Abi1} +denote an ABI tag such that \tcode{basic_simd_mask::\brk{}size()} equals \tcode{V::size()}. + +\pnum +Where present, the member typedef \tcode{type} names \tcode{basic_simd} +if \tcode V is a specialization of \tcode{basic_simd} or +\tcode{basic_simd_mask} if \tcode V is a specialization of +\tcode{basic_simd_mask}. +\end{itemdescr} + +\rSec2[simd.flags]{Load and store flags} + +\rSec3[simd.flags.overview]{Class template \tcode{simd_flags} overview} + +\begin{codeblock} +namespace std { + template struct simd_flags { + // \ref{simd.flags.oper}, \tcode{simd_flags} operators + template + friend consteval auto operator|(simd_flags, simd_flags); + }; +} +\end{codeblock} + +\pnum +\begin{note} +The class template \tcode{simd_flags} acts like an integer bit-flag for types. +\end{note} + +\pnum +\constraints +Every type in the parameter pack \tcode{Flags} is one of \tcode{\exposid{convert-flag}}, +\tcode{\exposid{aligned-flag}}, or \tcode{\exposid{over\-aligned-\brk{}flag}}. + +\rSec3[simd.flags.oper]{\tcode{simd_flags} operators} + +\begin{itemdecl} +template + friend consteval auto operator|(simd_flags a, simd_flags b); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns + A default-initialized object of type \tcode{simd_flags} for some + \tcode{Flags2} where every type in \tcode{Flags2} is present either in template parameter pack + \tcode{Flags} or in template parameter pack \tcode{Other}, and every type in template parameter + packs \tcode{Flags} and \tcode{Other} is present in \tcode{Flags2}. + If the packs \tcode{Flags} and \tcode{Other} contain two + different specializations \tcode{\exposid{overaligned-flag}} and + \tcode{\exposid{overaligned-flag}}, \tcode{Flags2} is not required to contain the + specialization \tcode{\exposid{overaligned-flag}}. +\end{itemdescr} + +\rSec2[simd.class]{Class template \tcode{basic_simd}} + +\rSec3[simd.overview]{Class template \tcode{basic_simd} overview} + +\begin{codeblock} +namespace std { + template class basic_simd { + public: + using value_type = T; + using mask_type = basic_simd_mask; + using abi_type = Abi; + + static constexpr integral_constant<@\exposid{simd-size-type}@, @\exposid{simd-size-v}@> size {}; + + constexpr basic_simd() noexcept = default; + + // \ref{simd.ctor}, \tcode{basic_simd} constructors + template constexpr basic_simd(U&& value) noexcept; + template + constexpr explicit(@\seebelow@) basic_simd(const basic_simd&) noexcept; + template constexpr explicit basic_simd(G&& gen) noexcept; + template + constexpr basic_simd(R&& range, simd_flags = {}); + template + constexpr basic_simd(R&& range, const mask_type& mask, simd_flags = {}); + + // \ref{simd.subscr}, \tcode{basic_simd} subscript operators + constexpr value_type operator[](@\exposid{simd-size-type}@) const; + + // \ref{simd.unary}, \tcode{basic_simd} unary operators + constexpr basic_simd& operator++() noexcept; + constexpr basic_simd operator++(int) noexcept; + constexpr basic_simd& operator--() noexcept; + constexpr basic_simd operator--(int) noexcept; + constexpr mask_type operator!() const noexcept; + constexpr basic_simd operator~() const noexcept; + constexpr basic_simd operator+() const noexcept; + constexpr basic_simd operator-() const noexcept; + + // \ref{simd.binary}, \tcode{basic_simd} binary operators + friend constexpr basic_simd operator+(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator-(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator*(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator/(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator%(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator&(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator|(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator^(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator<<(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator>>(const basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd operator<<(const basic_simd&, @\exposid{simd-size-type}@) noexcept; + friend constexpr basic_simd operator>>(const basic_simd&, @\exposid{simd-size-type}@) noexcept; + + // \ref{simd.cassign}, \tcode{basic_simd} compound assignment + friend constexpr basic_simd& operator+=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator-=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator*=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator/=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator%=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator&=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator|=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator^=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator<<=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator>>=(basic_simd&, const basic_simd&) noexcept; + friend constexpr basic_simd& operator<<=(basic_simd&, @\exposid{simd-size-type}@) noexcept; + friend constexpr basic_simd& operator>>=(basic_simd&, @\exposid{simd-size-type}@) noexcept; + + // \ref{simd.comparison}, \tcode{basic_simd} compare operators + friend constexpr mask_type operator==(const basic_simd&, const basic_simd&) noexcept; + friend constexpr mask_type operator!=(const basic_simd&, const basic_simd&) noexcept; + friend constexpr mask_type operator>=(const basic_simd&, const basic_simd&) noexcept; + friend constexpr mask_type operator<=(const basic_simd&, const basic_simd&) noexcept; + friend constexpr mask_type operator>(const basic_simd&, const basic_simd&) noexcept; + friend constexpr mask_type operator<(const basic_simd&, const basic_simd&) noexcept; + + // \ref{simd.cond}, \tcode{basic_simd} exposition only conditional operators + friend constexpr basic_simd @\exposid{simd-select-impl}@( // \expos + const mask_type&, const basic_simd&, const basic_simd&) noexcept; + }; + + template + basic_simd(R&& r, Ts...) -> @\seebelow@; +} +\end{codeblock} + +\pnum +Every specialization of \tcode{basic_simd} is a complete type. +The specialization of \tcode{basic_simd} is +\begin{itemize} + \item + enabled, if \tcode{T} is a vectorizable type, and there exists value + \tcode{N} in the range \crange{1}{64}, such that \tcode{Abi} is + \tcode{\exposid{deduce-abi-t}}, + \item + otherwise, disabled, if \tcode{T} is not a vectorizable type, + \item + otherwise, it is \impldef{set of enabled \tcode{basic_simd} + specializations} if such a specialization is enabled. +\end{itemize} + +If \tcode{basic_simd} is disabled, the specialization has a +deleted default constructor, deleted destructor, deleted copy constructor, and +deleted copy assignment. +In addition only the \tcode{value_type}, \tcode{abi_type}, and +\tcode{mask_type} members are present. + +If \tcode{basic_simd} is enabled, \tcode{basic_simd} is +trivially copyable. + +\pnum +\recommended +Implementations should support explicit conversions between specializations of +\tcode{basic_simd} and appropriate \impldef{conversions of \tcode{basic_simd} +from/to implementation-specific vector types} types. +\begin{note} +Appropriate types are non-standard vector types which are available in the +implementation. +\end{note} + +\rSec3[simd.ctor]{\tcode{basic_simd} constructors} + +\begin{itemdecl} +template constexpr basic_simd(U&&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{From} denote the type \tcode{remove_cvref_t}. + +\pnum +\constraints +\tcode{From} satisfies \tcode{convertible_to}, and either +\begin{itemize} + \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} is not an arithmetic type and does not satisfy + \tcode{\exposconcept{constexpr-wrapper-like}}, or + \item + \tcode{From} satisfies \tcode{\exposconcept{constexpr-wrapper-like}}, + \tcode{remove_const_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}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr explicit(@\seebelow@) basic_simd(const basic_simd& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{\exposid{simd-size-v} == size()} is \tcode{true}. + +\pnum +\effects +Initializes the $i^\text{th}$ element with \tcode{static_cast(x[$i$])} for +all $i$ in the range of \range{0}{size()}. + +\pnum +\remarks +The expression inside \tcode{explicit} evaluates to \tcode{true} if either +\begin{itemize} + \item + the conversion from \tcode{U} to \tcode{value_type} is not value-preserving, + or + \item + both \tcode{U} and \tcode{value_type} are integral types and the integer + conversion rank\iref{conv.rank} of \tcode{U} is greater than the integer + conversion rank of \tcode{value_type}, or + \item + both \tcode{U} and \tcode{value_type} are floating-point types and the + floating-point conversion rank\iref{conv.rank} of \tcode{U} is greater than + the floating-point conversion rank of \tcode{value_type}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template constexpr explicit basic_simd(G&& gen) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{From}$_i$ denote the type +\tcode{decltype(gen(integral_constant<\exposid{simd-size-type}, $i$>()))}. + +\pnum +\constraints +\tcode{From}$_i$ satisfies \tcode{convertible_to} for all $i$ in +the range of \range{0}{size()}. +In addition, for all $i$ in the range of \range{0}{size()}, if \tcode{From}$_i$ +is an arithmetic type, conversion from \tcode{From}$_i$ to \tcode{value_type} +is value-preserving. + +\pnum +\effects +Initializes the $i^\text{th}$ element with +\tcode{static_cast(gen(integral_constant<\exposid{simd-\brk{}size-\brk{}type}, +i>()))} for all $i$ in the range of \range{0}{size()}. + +\pnum +\remarks +The calls to \tcode{gen} are unsequenced with respect to each other. +Vectorization-unsafe\iref{algorithms.parallel.defns} standard library functions +may not be invoked by \tcode{gen}. +\tcode{gen} is invoked exactly once for each $i$. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr basic_simd(R&& r, simd_flags = {}); +template + constexpr basic_simd(R&& r, const mask_type& mask, simd_flags = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{mask} be \tcode{mask_type(true)} for the overload with no +\tcode{mask} parameter. + +\pnum +\constraints +\begin{itemize} +\item \tcode{R} models \tcode{ranges::contiguous_range} and + \tcode{ranges::sized_range}, +\item \tcode{ranges::size(r)} is a constant expression, and +\item \tcode{ranges::size(r)} is equal to \tcode{size()}. +\end{itemize} + +\pnum +\mandates +\begin{itemize} + \item + \tcode{ranges::range_value_t} is a vectorizable type, and + \item + if the template parameter pack \tcode{Flags} does not contain + \tcode{\exposid{convert-flag}}, then the conversion from + \tcode{ranges::range_value_t} to \tcode{value_type} is value-preserving. +\end{itemize} + +\pnum +\expects +\begin{itemize} + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{aligned-flag}}, \tcode{ranges::data(range)} points to + storage aligned by \tcode{simd_alignment_v>}. + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{overaligned-flag}}, \tcode{ranges::data(range)} points to + storage aligned by \tcode{N}. +\end{itemize} + +\pnum +\effects +Initializes the $i^\text{th}$ element with \tcode{mask[$i$] ? +static_cast(\brk{}ranges::\brk{}data(range)[$i$]) : T()} for all $i$ in the +range of \range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +template + basic_simd(R&& r, Ts...) -> @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{R} models \tcode{ranges::contiguous_range} and + \tcode{ranges::sized_range}, and +\item \tcode{ranges::size(r)} is a constant expression. +\end{itemize} + +\pnum +\remarks +The deduced type is equivalent to \tcode{simd, +ranges::size(r)>}. +\end{itemdescr} + +\rSec3[simd.subscr]{\tcode{basic_simd} subscript operator} + +\begin{itemdecl} +constexpr value_type operator[](@\exposid{simd-size-type}@ i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{i >= 0 \&\& i < size()} is \tcode{true}. + +\pnum +\returns +The value of the $i^\text{th}$ element. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\rSec3[simd.unary]{\tcode{basic_simd} unary operators} + +\pnum +Effects in [simd.unary] are applied as unary element-wise operations. + +\begin{itemdecl} +constexpr basic_simd& operator++() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (value_type a) \{ ++a; \}} is \tcode{true}. + +\pnum +\effects +Increments every element by one. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd operator++(int) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (value_type a) \{ a++; \}} is \tcode{true}. + +\pnum +\effects +Increments every element by one. + +\pnum +\returns +A copy of \tcode{*this} before incrementing. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd& operator--() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (value_type a) \{ --a; \}} is \tcode{true}. + +\pnum +\effects +Decrements every element by one. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd operator--(int) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (value_type a) \{ a--; \}} is \tcode{true}. + +\pnum +\effects +Decrements every element by one. + +\pnum +\returns +A copy of \tcode{*this} before decrementing. +\end{itemdescr} + +\begin{itemdecl} +constexpr mask_type operator!() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (const value_type a) \{ !a; \}} is \tcode{true}. + +\pnum +\returns +A \tcode{basic_simd_mask} object with the $i^\text{th}$ element set to +\tcode{!operator[]($i$)} for all $i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd operator~() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (const value_type a) \{ \~{}a; \}} is \tcode{true}. + +\pnum +\returns +A \tcode{basic_simd} object with the $i^\text{th}$ element set to +\tcode{\~{}operator[]($i$)} for all $i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd operator+() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (const value_type a) \{ +a; \}} is \tcode{true}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr basic_simd operator-() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{requires (const value_type a) \{ -a; \}} is \tcode{true}. + +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to +\tcode{-operator[]($i$)} for all $i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\rSec2[simd.nonmembers]{\tcode{basic_simd} non-member operations} + +\rSec3[simd.binary]{\tcode{basic_simd} binary operators} + +\begin{itemdecl} +friend constexpr basic_simd operator+(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator-(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator*(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator/(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator%(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator&(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator|(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator^(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator<<(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd operator>>(const basic_simd& lhs, const basic_simd& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\constraints +\tcode{requires (value_type a, value_type b) \{ a \placeholder{op} b; \}} is +\tcode{true}. + +\pnum +\returns +A \tcode{basic_simd} object initialized with the results of applying +\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise +operation. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr basic_simd operator<<(const basic_simd& v, @\exposid{simd-size-type}@ n) noexcept; +friend constexpr basic_simd operator>>(const basic_simd& v, @\exposid{simd-size-type}@ n) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\constraints +\tcode{requires (value_type a, \exposid{simd-size-type} b) \{ a +\placeholder{op} b; \}} is \tcode{true}. + +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to +the result of applying \placeholder{op} to \tcode{v[$i$]} and \tcode{n} for all +$i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\rSec3[simd.cassign]{\tcode{basic_simd} compound assignment} + +\begin{itemdecl} +friend constexpr basic_simd& operator+=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator-=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator*=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator/=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator%=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator&=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator|=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator^=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator<<=(basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr basic_simd& operator>>=(basic_simd& lhs, const basic_simd& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\constraints +\tcode{requires (value_type a, value_type b) \{ a \placeholder{op} b; \}} is +\tcode{true}. + +\pnum +\effects +These operators apply the indicated operator to \tcode{lhs} and \tcode{rhs} as +an element-wise operation. + +\pnum +\returns +\tcode{lhs}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr basic_simd& operator<<=(basic_simd& lhs, @\exposid{simd-size-type}@ n) noexcept; +friend constexpr basic_simd& operator>>=(basic_simd& lhs, @\exposid{simd-size-type}@ n) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\constraints +\tcode{requires (value_type a, \exposid{simd-size-type} b) \{ a +\placeholder{op} b; \}} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return operator \placeholder{op} (lhs, basic_simd(n));} +\end{itemdescr} + +\rSec3[simd.comparison]{\tcode{basic_simd} compare operators} + +\begin{itemdecl} +friend constexpr mask_type operator==(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr mask_type operator!=(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr mask_type operator>=(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr mask_type operator<=(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr mask_type operator>(const basic_simd& lhs, const basic_simd& rhs) noexcept; +friend constexpr mask_type operator<(const basic_simd& lhs, const basic_simd& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\constraints +\tcode{requires (value_type a, value_type b) \{ a \placeholder{op} b; \}} is +\tcode{true}. + +\pnum +\returns +A \tcode{basic_simd_mask} object initialized with the results of applying +\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise +operation. +\end{itemdescr} + +\rSec3[simd.cond]{\tcode{basic_simd} exposition only conditional operators} + +\begin{itemdecl} +friend constexpr basic_simd +@\exposid{simd-select-impl}@(const mask_type& mask, const basic_simd& a, const basic_simd& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ element equals +\tcode{mask[$i$] ? a[$i$] : b[$i$]} for all $i$ in the range of +\range{0}{size()}. +\end{itemdescr} + +\rSec3[simd.reductions]{\tcode{basic_simd} reductions} + +\begin{itemdecl} +template> + constexpr T reduce(const basic_simd& x, BinaryOperation binary_op = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{BinaryOperation} models +\tcode{\exposconcept{reduction-binary-operation}}. + +\pnum +\expects +\tcode{binary_op} does not modify \tcode{x}. + +\pnum +\returns +\tcode{\placeholdernc{GENERALIZED_SUM}(binary_op, simd(x[0]), $\ldots$, +simd(x[x.size() - 1])\brk{})[0]}\iref{numerics.defns}. + +\pnum +\throws +Any exception thrown from \tcode{binary_op}. +\end{itemdescr} + +\begin{itemdecl} +template> + constexpr T reduce( + const basic_simd& x, const typename basic_simd::mask_type& mask, + BinaryOperation binary_op = {}, type_identity_t identity_element = @\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item + \tcode{BinaryOperation} models + \tcode{\exposconcept{reduction-binary-operation}}. +\item + An argument for \tcode{identity_element} is provided for the invocation, + unless \tcode{BinaryOperation} is one of \tcode{plus<>}, + \tcode{multiplies<>}, \tcode{bit_and<>}, \tcode{bit_or<>}, or + \tcode{bit_xor<>}. +\end{itemize} + +\pnum +\expects +\begin{itemize} + \item + \tcode{binary_op} does not modify \tcode{x}. + \item + For all finite values \tcode{y} representable by \tcode{T}, the results of + \tcode{y == binary_op(simd(iden\-ti\-ty\-_\-element), simd(y))[0]} and \tcode{y == binary_op(simd(y), simd(iden\-ti\-ty\-_\-element))[0]} are \tcode{true}. +\end{itemize} + +\pnum +\returns +If \tcode{none_of(mask)} is \tcode{true}, returns \tcode{identity_element}. +Otherwise, returns \tcode{\placeholdernc{GENERALIZED_SUM}(binary_op, simd(x[$k_0$]), $\ldots$, simd(x[$k_n$]))[0]} where $k_0, \ldots, k_n$ are +the selected indices of \tcode{mask}. + +\pnum +\throws +Any exception thrown from \tcode{binary_op}. + +\pnum +\remarks +The default argument for \tcode{identity_element} is equal to +\begin{itemize} +\item \tcode{T()} if \tcode{BinaryOperation} is \tcode{plus<>}, +\item \tcode{T(1)} if \tcode{BinaryOperation} is \tcode{multiplies<>}, +\item \tcode{T(\~{}T())} if \tcode{BinaryOperation} is \tcode{bit_and<>}, +\item \tcode{T()} if \tcode{BinaryOperation} is \tcode{bit_or<>}, or +\item \tcode{T()} if \tcode{BinaryOperation} is \tcode{bit_xor<>}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template constexpr T reduce_min(const basic_simd& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +The value of an element \tcode{x[$j$]} for which \tcode{x[$i$] < x[$j$]} is +\tcode{false} for all $i$ in the range of \range{0}{basic_simd::size()}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr T reduce_min( + const basic_simd&, const typename basic_simd::mask_type&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +If \tcode{none_of(mask)} is \tcode{true}, returns +\tcode{numeric_limits::max()}. +Otherwise, returns the value of a selected element \tcode{x[$j$]} for which +\tcode{x[$i$] < x[$j$]} is \tcode{false} for all selected indices $i$ of +\tcode{mask}. +\end{itemdescr} + +\begin{itemdecl} +template constexpr T reduce_max(const basic_simd& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +The value of an element \tcode{x[$j$]} for which \tcode{x[$j$] < x[$i$]} is +\tcode{false} for all $i$ in the range of \range{0}{basic_simd::size()}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr T reduce_max( + const basic_simd&, const typename basic_simd::mask_type&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +If \tcode{none_of(mask)} is \tcode{true}, returns +\tcode{numeric_limits::lowest()}. +Otherwise, returns the value of a selected element \tcode{x[$j$]} for which +\tcode{x[$j$] < x[$i$]} is \tcode{false} for all selected indices $i$ of +\tcode{mask}. +\end{itemdescr} + +\rSec3[simd.loadstore]{\tcode{basic_simd} load and store functions} + +\begin{itemdecl} +template + requires ranges::sized_range + constexpr V simd_unchecked_load(R&& r, simd_flags f = {}); +template + requires ranges::sized_range + constexpr V simd_unchecked_load(R&& r, const typename V::mask_type& mask, + simd_flags f = {}); +template + constexpr V simd_unchecked_load(I first, iter_difference_t n, simd_flags f = {}); +template + constexpr V simd_unchecked_load(I first, iter_difference_t n, + const typename V::mask_type& mask, simd_flags f = {}); +template S, class... Flags> + constexpr V simd_unchecked_load(I first, S last, simd_flags f = {}); +template S, class... Flags> + constexpr V simd_unchecked_load(I first, S last, const typename V::mask_type& mask, + simd_flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let +\begin{itemize} + \item + \tcode{mask} be \tcode{V::mask_type(true)} for the overloads with no + \tcode{mask} parameter; + \item + \tcode{R} be \tcode{span>} for the overloads with no + template parameter \tcode{R}; + \item + \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n} + parameter and \tcode{R(first, last)} for the overloads with a \tcode{last} + parameter. +\end{itemize} + +\pnum +\mandates +If \tcode{ranges::size(r)} is a constant expression then +\tcode{ranges::size(r)} $\ge$ \tcode{V::size()}. + +\pnum +\expects +\begin{itemize} +\item \range{first}{first + n} is a valid range for the overloads with an + \tcode{n} parameter. +\item \range{first}{last} is a valid range for the overloads with a + \tcode{last} parameter. +\item \tcode{ranges::size(r)} $\ge$ \tcode{V::size()} +\end{itemize} + +\pnum +\effects +Equivalent to: \tcode{return simd_partial_load(r, mask, f);} + +\pnum +\remarks +The default argument for template parameter \tcode{V} is +\tcode{basic_simd>}. +\end{itemdescr} + +\begin{itemdecl} +template + requires ranges::sized_range + constexpr V simd_partial_load(R&& r, simd_flags f = {}); +template + requires ranges::sized_range + constexpr V simd_partial_load(R&& r, const typename V::mask_type& mask, + simd_flags f = {}); +template + constexpr V simd_partial_load(I first, iter_difference_t n, simd_flags f = {}); +template + constexpr V simd_partial_load(I first, iter_difference_t n, const typename V::mask_type& mask, + simd_flags f = {}); +template S, class... Flags> + constexpr V simd_partial_load(I first, S last, simd_flags f = {}); +template S, class... Flags> + constexpr V simd_partial_load(I first, S last, const typename V::mask_type& mask, + simd_flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let +\begin{itemize} + \item + \tcode{mask} be \tcode{V::mask_type(true)} for the overloads with no + \tcode{mask} parameter; + \item + \tcode{R} be \tcode{span>} for the overloads with no + template parameter \tcode{R}; + \item + \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n} + parameter and \tcode{R(first, last)} for the overloads with a \tcode{last} + parameter. +\end{itemize} + +\pnum +\mandates +\begin{itemize} + \item + \tcode{ranges::range_value_t} is a vectorizable type, + \item + \tcode{same_as, V>} is \tcode{true}, + \item + \tcode{V} is an enabled specialization of \tcode{basic_simd}, and + \item + if the template parameter pack \tcode{Flags} does not contain + \tcode{\exposid{convert-flag}}, then the conversion from + \tcode{ranges::range_value_t} to \tcode{V::value_type} is + value-preserving. +\end{itemize} + +\pnum +\expects +\begin{itemize} + \item + \range{first}{first + n} is a valid range for the overloads with an + \tcode{n} parameter. + \item + \range{first}{last} is a valid range for the overloads with a \tcode{last} + parameter. + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{aligned-flag}}, \tcode{ranges::data(r)} points to storage + aligned by \tcode{simd_alignment_v>}. + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{overaligned-flag}}, \tcode{ranges::data(r)} points to + storage aligned by \tcode{N}. +\end{itemize} + +\pnum +\effects +Initializes the $i^\text{th}$ element with\\ +\tcode{mask[$i$] \&\& $i$ < ranges::size(r) ? +static_cast(\brk{}ranges::data(r)[$i$]) : T()} for all $i$ in the range of +\range{0}{V::size()}. + +\pnum +\remarks +The default argument for template parameter \tcode{V} is +\tcode{basic_simd>}. +\end{itemdescr} + +\begin{itemdecl} +template + requires ranges::sized_range && indirectly_writable, T> + constexpr void simd_unchecked_store(const basic_simd& v, R&& r, + simd_flags f = {}); +template + requires ranges::sized_range && indirectly_writable, T> + constexpr void simd_unchecked_store(const basic_simd& v, R&& r, + const typename basic_simd::mask_type& mask, simd_flags f = {}); +template + requires indirectly_writable + constexpr void simd_unchecked_store(const basic_simd& v, I first, iter_difference_t n, + simd_flags f = {}); +template + requires indirectly_writable + constexpr void simd_unchecked_store(const basic_simd& v, I first, iter_difference_t n, + const typename basic_simd::mask_type& mask, simd_flags f = {}); +template S, class... Flags> + requires indirectly_writable + constexpr void simd_unchecked_store(const basic_simd& v, I first, S last, + simd_flags f = {}); +template S, class... Flags> + requires indirectly_writable + constexpr void simd_unchecked_store(const basic_simd& v, I first, S last, + const typename basic_simd::mask_type& mask, simd_flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let +\begin{itemize} + \item + \tcode{mask} be \tcode{basic_simd::mask_type(true)} for the + overloads with no \tcode{mask} parameter; + \item + \tcode{R} be \tcode{span>} for the overloads with no + template parameter \tcode{R}; + \item + \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n} + parameter and \tcode{R(first, last)} for the overloads with a \tcode{last} + parameter. +\end{itemize} + +\pnum +\mandates +If \tcode{ranges::size(r)} is a constant expression then +\tcode{ranges::size(r)} $\ge$ \tcode{\exposid{simd-size-v}}. + +\pnum +\expects +\begin{itemize} + \item + \range{first}{first + n} is a valid range for the overloads with an + \tcode{n} parameter. + \item + \range{first}{last} is a valid range for the overloads with a \tcode{last} + parameter. + \item + \tcode{ranges::size(r)} $\ge$ \tcode{\exposid{simd-size-v}} +\end{itemize} + +\pnum +\effects +Equivalent to: \tcode{simd_partial_store(v, r, mask, f)}. +\end{itemdescr} + +\begin{itemdecl} +template + requires ranges::sized_range && indirectly_writable, T> + constexpr void simd_partial_store(const basic_simd& v, R&& r, + simd_flags f = {}); +template + requires ranges::sized_range && indirectly_writable, T> + constexpr void simd_partial_store(const basic_simd& v, R&& r, + const typename basic_simd::mask_type& mask, simd_flags f = {}); +template + requires indirectly_writable + constexpr void simd_partial_store(const basic_simd& v, I first, iter_difference_t n, + simd_flags f = {}); +template + requires indirectly_writable + constexpr void simd_partial_store(const basic_simd& v, I first, iter_difference_t n, + const typename basic_simd::mask_type& mask, simd_flags f = {}); +template S, class... Flags> + requires indirectly_writable + constexpr void simd_partial_store(const basic_simd& v, I first, S last, + simd_flags f = {}); +template S, class... Flags> + requires indirectly_writable + constexpr void simd_partial_store(const basic_simd& v, I first, S last, + const typename basic_simd::mask_type& mask, simd_flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let +\begin{itemize} + \item + \tcode{mask} be \tcode{basic_simd::mask_type(true)} for the + overloads with no \tcode{mask} parameter; + \item + \tcode{R} be \tcode{span>} for the overloads with no + template parameter \tcode{R}; + \item + \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n} + parameter and \tcode{R(first, last)} for the overloads with a \tcode{last} + parameter. +\end{itemize} + +\pnum +\mandates +\begin{itemize} + \item + \tcode{ranges::range_value_t} is a vectorizable type, and + \item + if the template parameter pack \tcode{Flags} does not contain + \tcode{\exposid{convert-flag}}, then the conversion from \tcode{T} to + \tcode{ranges::range_value_t} is value-preserving. +\end{itemize} + +\pnum +\expects +\begin{itemize} + \item + \range{first}{first + n} is a valid range for the overloads with an + \tcode{n} parameter. + \item + \range{first}{last} is a valid range for the overloads with a \tcode{last} + parameter. + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{aligned-flag}}, \tcode{ranges::data(r)} points to storage + aligned by \tcode{simd_alignment_v, + ranges::range_value_t>}. + \item + If the template parameter pack \tcode{Flags} contains + \tcode{\exposid{overaligned-flag}}, \tcode{ranges::data(r)} points to + storage aligned by \tcode{N}. +\end{itemize} + +\pnum +\effects +For all $i$ in the range of \range{0}{basic_simd::size()}, if +\tcode{mask[$i$] \&\& $i$ < ranges::\brk{}size(r)} is \tcode{true}, evaluates +\tcode{ranges::data(r)[$i$] = v[$i$]}. +\end{itemdescr} + +\rSec3[simd.creation]{\tcode{basic_simd} and \tcode{basic_simd_mask} creation} + +\begin{itemdecl} +template + constexpr auto simd_split(const basic_simd& x) noexcept; +template + constexpr auto simd_split(const basic_simd_mask<@\exposid{mask-element-size}@, Abi>& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} + \item + For the first overload \tcode{T} is an enabled specialization of + \tcode{basic_simd}. + If \tcode{basic_simd<\brk{}typename T::\brk{}value_type, Abi>::size() \% + T::size()} is not \tcode{0} then + \tcode{resize_simd_t::size() + \% T::size(), T>} is valid and denotes a type. + + \item + For the second overload \tcode{T} is an enabled specialization of + \tcode{basic_simd\-_\-mask}. + If \tcode{basic_simd_mask<\exposid{mask-element-size}, Abi>::size() \% + T::size()} is not \tcode{0} then + \tcode{resize_simd_t<\brk{}ba\-sic\-_\-simd_mask<\brk{}\exposid{mask-element-size}, + Abi>::size() \% T::size(), T>} is valid and denotes a type. +\end{itemize} + +\pnum +Let $N$ be \tcode{x.size() / T::size()}. + +\pnum +\returns +\begin{itemize} + \item + If \tcode{x.size() \% T::size() == 0} is \tcode{true}, an \tcode{array} with the $i^\text{th}$ \tcode{basic_simd} or \tcode{basic_simd_mask} + element of the $j^\text{th}$ \tcode{array} element initialized to the value + of the element in \tcode{x} with index \tcode{$i$ + $j$ * T::size()}. + + \item + Otherwise, a \tcode{tuple} of $N$ objects of type \tcode{T} and one object + of type \tcode{resize_simd_t}. + The $i^\text{th}$ \tcode{basic_simd} or \tcode{basic_simd_mask} element of + the $j^\text{th}$ \tcode{tuple} element of type \tcode{T} is initialized to + the value of the element in \tcode{x} with index \tcode{$i$ + $j$ * + T::size()}. + The $i^\text{th}$ \tcode{basic_simd} or \tcode{basic_simd_mask} element of + the $N^\text{th}$ \tcode{tuple} element is initialized to the value of the + element in \tcode{x} with index \tcode{$i$ + $N$ * T::size()}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr simd::size() + ...)> + simd_cat(const basic_simd&... xs) noexcept; +template + constexpr basic_simd_mask, + (basic_simd_mask::size() + ...)>> + simd_cat(const basic_simd_mask&... xs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} + \item + For the first overload \tcode{simd::size() + ...)>} + is enabled. + \item + For the second overload + \tcode{basic_simd_mask, + (ba\-sic_simd_mask::size() + ...)>>} is enabled. +\end{itemize} + +\pnum +\returns +A data-parallel object initialized with the concatenated values in the +\tcode{xs} pack of data-parallel objects: The $i^\text{th}$ +\tcode{basic_simd}/\tcode{basic_simd_mask} element of the $j^\text{th}$ +parameter in the \tcode{xs} pack is copied to the return value's element with +index $i$ + the sum of the width of the first $j$ parameters in the \tcode{xs} +pack. +\end{itemdescr} + +\rSec3[simd.alg]{Algorithms} + +\begin{itemdecl} +template + constexpr basic_simd min(const basic_simd& a, + const basic_simd& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +The result of the element-wise application of \tcode{min(a[$i$], b[$i$])} for +all $i$ in the range of \range{0}{size()}[basic_simd::]. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr basic_simd max(const basic_simd& a, + const basic_simd& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\returns +The result of the element-wise application of \tcode{max(a[$i$], b[$i$])} for +all $i$ in the range of \range{0}{size()}[basic_simd::]. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr pair, basic_simd> + minmax(const basic_simd& a, const basic_simd& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return pair\{min(a, b), max(a, b)\};} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr basic_simd clamp( + const basic_simd& v, const basic_simd& lo, const basic_simd& hi); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \tcode{totally_ordered}. + +\pnum +\expects +No element in \tcode{lo} shall be greater than the corresponding element in +\tcode{hi}. + +\pnum +\returns +The result of element-wise application of \tcode{clamp(v[$i$], lo[$i$], +hi[$i$])} for all $i$ in the range of \range{0}{basic_simd::size()}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr auto simd_select(bool c, const T& a, const U& b) + -> remove_cvref_t; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return c ? a : b;} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr auto simd_select(const basic_simd_mask& c, const T& a, const U& b) + noexcept -> decltype(@\exposid{simd-select-impl}@(c, a, b)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{simd-select-impl}@(c, a, b); +\end{codeblock} +where \tcode{\exposid{simd-select-impl}} is found by argument-dependent +lookup\iref{basic.lookup.argdep} contrary to \ref{contents}. +\end{itemdescr} + +\rSec3[simd.math]{Mathematical functions} + +\begin{itemdecl} +template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_simd_t> ilogb(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ ldexp(const V& x, const rebind_simd_t>& exp); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ scalbn(const V& x, const rebind_simd_t>& n); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ + scalbln(const V& x, const rebind_simd_t>& n); +template + constexpr basic_simd abs(const basic_simd& j); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ abs(const V& j); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ fabs(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ ceil(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ floor(const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ nearbyint(const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ rint(const V& x); +template<@\exposconcept{math-floating-point}@ V> + rebind_simd_t> lrint(const V& x); +template<@\exposconcept{math-floating-point}@ V> + rebind_simd_t> llrint(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ round(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_simd_t> lround(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_simd_t> llround(const V& x); +template + constexpr @\exposid{math-common-simd-t}@ fmod(const V0& x, const V1& y); +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ trunc(const V& x); +template + constexpr @\exposid{math-common-simd-t}@ remainder(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ copysign(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ nextafter(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ fdim(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ fmax(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ fmin(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ fma(const V0& x, const V1& y, const V2& z); +template<@\exposconcept{math-floating-point}@ V> + constexpr rebind_simd_t> fpclassify(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isfinite(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isinf(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isnan(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type isnormal(const V& x); +template<@\exposconcept{math-floating-point}@ V> + constexpr typename @\exposid{deduced-simd-t}@::mask_type signbit(const V& x); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type isgreater(const V0& x, const V1& y); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type + isgreaterequal(const V0& x, const V1& y); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type isless(const V0& x, const V1& y); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type islessequal(const V0& x, const V1& y); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type islessgreater(const V0& x, const V1& y); +template + constexpr typename @\exposid{math-common-simd-t}@::mask_type isunordered(const V0& x, const V1& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Ret} denote the return type of the specialization of a function +template with the name \placeholder{math-func}. +Let \placeholder{math-func-simd} denote: +\begin{codeblock} +template +Ret @\placeholder{math-func-simd}@(Args... args) { + return Ret([&](@\exposid{simd-size-type}@ i) { + @\placeholder{math-func}@(@\exposid{make-compatible-simd-t}@(args)[i]...); + }); +} +\end{codeblock} + +\pnum +\returns +A value \tcode{ret} of type \tcode{Ret}, that is element-wise equal to the +result of calling \placeholder{math-func-simd} with the arguments of the above +functions. +If in an invocation of a scalar overload of \placeholder{math-func} for index +\tcode{i} in \placeholder{math-func-simd} a domain, pole, or range error would +occur, the value of \tcode{ret[i]} is unspecified. + +\pnum +\remarks +It is unspecified whether \tcode{errno}\iref{errno} is accessed. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ acos(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ asin(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ atan(const V& x); +template + constexpr @\exposid{math-common-simd-t}@ atan2(const V0& y, const V1& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cos(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sin(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tan(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ acosh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ asinh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ atanh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cosh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sinh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tanh(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ exp(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ exp2(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ expm1(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log10(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log1p(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ log2(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ logb(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ cbrt(const V& x); +template + constexpr @\exposid{math-common-simd-t}@ hypot(const V0& x, const V1& y); +template + constexpr @\exposid{math-common-simd-t}@ hypot(const V0& x, const V1& y, const V2& z); +template + constexpr @\exposid{math-common-simd-t}@ pow(const V0& x, const V1& y); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ sqrt(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ erf(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ erfc(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ lgamma(const V& x); +template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-simd-t}@ tgamma(const V& x); +template + constexpr @\exposid{math-common-simd-t}@ lerp(const V0& a, const V1& b, const V2& t) noexcept; +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ assoc_laguerre(const rebind_simd_t>& n, const + rebind_simd_t>& m, + const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ assoc_legendre(const rebind_simd_t>& l, const + rebind_simd_t>& m, + const V& x); +template + @\exposid{math-common-simd-t}@ beta(const V0& x, const V1& y); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ comp_ellint_1(const V& k); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ comp_ellint_2(const V& k); +template + @\exposid{math-common-simd-t}@ comp_ellint_3(const V0& k, const V1& nu); +template + @\exposid{math-common-simd-t}@ cyl_bessel_i(const V0& nu, const V1& x); +template + @\exposid{math-common-simd-t}@ cyl_bessel_j(const V0& nu, const V1& x); +template + @\exposid{math-common-simd-t}@ cyl_bessel_k(const V0& nu, const V1& x); +template + @\exposid{math-common-simd-t}@ cyl_neumann(const V0& nu, const V1& x); +template + @\exposid{math-common-simd-t}@ ellint_1(const V0& k, const V1& phi); +template + @\exposid{math-common-simd-t}@ ellint_2(const V0& k, const V1& phi); +template + @\exposid{math-common-simd-t}@ ellint_3(const V0& k, const V1& nu, const V2& phi); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ expint(const V& x); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ hermite(const rebind_simd_t>& n, const V& x); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ laguerre(const rebind_simd_t>& n, const V& x); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ legendre(const rebind_simd_t>& l, const V& x); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ riemann_zeta(const V& x); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ sph_bessel(const rebind_simd_t>& n, const V& x); +template<@\exposconcept{math-floating-point}@ V> + @\exposid{deduced-simd-t}@ sph_legendre(const rebind_simd_t>& l, + const rebind_simd_t>& m, + const V& theta); +template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-simd-t}@ sph_neumann(const rebind_simd_t>& n, const V& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Ret} denote the return type of the specialization of a function +template with the name \placeholder{math-func}. +Let \placeholder{math-func-simd} denote: +\begin{codeblock} +template +Ret @\placeholder{math-func-simd}@(Args... args) { + return Ret([&](@\exposid{simd-size-type}@ i) { + @\placeholder{math-func}@(@\exposid{make-compatible-simd-t}@(args)[i]...); + }); +} +\end{codeblock} + +\pnum +\returns +A value \tcode{ret} of type \tcode{Ret}, that is element-wise approximately +equal to the result of calling \placeholder{math-func-simd} with the arguments +of the above functions. +If in an invocation of a scalar overload of \placeholder{math-func} for index +\tcode{i} in \placeholder{math-func-simd} a domain, pole, or range error would +occur, the value of \tcode{ret[i]} is unspecified. + +\pnum +\remarks +It is unspecified whether \tcode{errno}\iref{errno} is accessed. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{math-floating-point}@ V> + constexpr @\exposid{deduced-simd-t}@ frexp(const V& value, rebind_simd_t>* exp); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Ret} be \tcode{\exposid{deduced-simd-t}}. +Let \placeholder{frexp-simd} denote: +\begin{codeblock} +template +pair> @\placeholder{frexp-simd}@(const V& x) { + int r1[Ret::size()]; + Ret r0([&](@\exposid{simd-size-type}@ i) { + frexp(@\exposid{make-compatible-simd-t}@(x)[i], &r1[i]); + }); + return {r0, rebind_simd_t(r1)}; +} +\end{codeblock} +Let \tcode{ret} be a value of type \tcode{pair>} +that is the same value as the result of calling +\placeholder{frexp-simd}\tcode{(x)}. + +\pnum +\effects +Sets \tcode{*exp} to \tcode{ret.second}. + +\pnum +\returns +\tcode{ret.first}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr @\exposid{math-common-simd-t}@ remquo(const V0& x, const V1& y, + rebind_simd_t>* quo); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Ret} be \tcode{\exposid{math-common-simd-t}}. +Let \placeholder{remquo-simd} denote: +\begin{codeblock} +template +pair> @\placeholder{remquo-simd}@(const V0& x, const V1& y) { + int r1[Ret::size()]; + Ret r0([&](@\exposid{simd-size-type}@ i) { + remquo(@\exposid{make-compatible-simd-t}@(x)[i], + @\exposid{make-compatible-simd-t}@(y)[i], &r1[i]); + }); + return {r0, rebind_simd_t(r1)}; +} +\end{codeblock} +Let \tcode{ret} be a value of type \tcode{pair>} +that is the same value as the result of calling +\placeholder{remquo-simd}\tcode{(x, y)}. +If in an invocation of a scalar overload of \tcode{remquo} for index \tcode{i} +in \placeholder{remquo-simd} a domain, pole, or range error would occur, the +value of \tcode{ret[i]} is unspecified. + +\pnum +\effects +Sets \tcode{*quo} to \tcode{ret.second}. + +\pnum +\returns +\tcode{ret.first}. + +\pnum +\remarks +It is unspecified whether \tcode{errno}\iref{errno} is accessed. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr basic_simd modf(const type_identity_t>& value, + basic_simd* iptr); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{V} be \tcode{basic_simd}. +Let \placeholder{modf-simd} denote: +\begin{codeblock} +pair @\placeholder{modf-simd}@(const V& x) { + T r1[Ret::size()]; + V r0([&](@\exposid{simd-size-type}@ i) { + modf(V(x)[i], &r1[i]); + }); + return {r0, V(r1)}; +} +\end{codeblock} +Let \tcode{ret} be a value of type \tcode{pair} that is the same value as +the result of calling \placeholder{modf-simd}\tcode{(value)}. + +\pnum +\effects +Sets \tcode{*iptr} to \tcode{ret.second}. + +\pnum +\returns +\tcode{ret.first}. +\end{itemdescr} + +\rSec2[simd.mask.class]{Class template \tcode{basic_simd_mask}} + +\rSec3[simd.mask.overview]{Class template \tcode{basic_simd_mask} overview} + +\begin{codeblock} +namespace std { + template class basic_simd_mask { + public: + using value_type = bool; + using abi_type = Abi; + + static constexpr integral_constant<@\exposid{simd-size-type}@, @\exposid{simd-size-v}@<@\exposid{integer-from}@, Abi>> + size {}; + + constexpr basic_simd_mask() noexcept = default; + + // \ref{simd.mask.ctor}, \tcode{basic_simd_mask} constructors + constexpr explicit basic_simd_mask(value_type) noexcept; + template + constexpr explicit basic_simd_mask(const basic_simd_mask&) noexcept; + template constexpr explicit basic_simd_mask(G&& gen) noexcept; + + // \ref{simd.mask.subscr}, \tcode{basic_simd_mask} subscript operators + constexpr value_type operator[](@\exposid{simd-size-type}@) const; + + // \ref{simd.mask.unary}, \tcode{basic_simd_mask} unary operators + constexpr basic_simd_mask operator!() const noexcept; + constexpr basic_simd<@\exposid{integer-from}@, Abi> operator+() const noexcept; + constexpr basic_simd<@\exposid{integer-from}@, Abi> operator-() const noexcept; + constexpr basic_simd<@\exposid{integer-from}@, Abi> operator~() const noexcept; + + // \ref{simd.mask.conv}, \tcode{basic_simd_mask} conversion operators + template + constexpr explicit(sizeof(U) != Bytes) operator basic_simd() const noexcept; + + // \ref{simd.mask.binary}, \tcode{basic_simd_mask} binary operators + friend constexpr basic_simd_mask + operator&&(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator||(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator&(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator|(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator^(const basic_simd_mask&, const basic_simd_mask&) noexcept; + + // \ref{simd.mask.cassign}, \tcode{basic_simd_mask} compound assignment + friend constexpr basic_simd_mask& + operator&=(basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask& + operator|=(basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask& + operator^=(basic_simd_mask&, const basic_simd_mask&) noexcept; + + // \ref{simd.mask.comparison}, \tcode{basic_simd_mask} comparisons + friend constexpr basic_simd_mask + operator==(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator!=(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator>=(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator<=(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator>(const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask + operator<(const basic_simd_mask&, const basic_simd_mask&) noexcept; + + // \ref{simd.mask.cond}, \tcode{basic_simd_mask} exposition only conditional operators + friend constexpr basic_simd_mask @\exposid{simd-select-impl}@( // \expos + const basic_simd_mask&, const basic_simd_mask&, const basic_simd_mask&) noexcept; + friend constexpr basic_simd_mask @\exposid{simd-select-impl}@( // \expos + const basic_simd_mask&, same_as auto, same_as auto) noexcept; + template + friend constexpr simd<@\seebelow@, size()> + @\exposid{simd-select-impl}@(const basic_simd_mask&, const T0&, const T1&) noexcept; // \expos + }; +} +\end{codeblock} + +\pnum +Every specialization of \tcode{basic_simd_mask} is a complete type. +The specialization of \tcode{basic_simd_mask} is: +\begin{itemize} + \item + disabled, if there is no vectorizable type \tcode{T} such that \tcode{Bytes} + is equal to \tcode{sizeof(T)}, + \item + otherwise, enabled, if there exists a vectorizable type \tcode{T} and a + value \tcode{N} in the range \crange{1}{64} such that \tcode{Bytes} is equal + to \tcode{sizeof(T)} and \tcode{Abi} is \tcode{\exposid{deduce-abi-t}}, + \item + otherwise, it is \impldef{set of enabled \tcode{basic_simd_mask} + specializations} if such a specialization is enabled. +\end{itemize} + +If \tcode{basic_simd_mask} is disabled, the specialization has a +deleted default constructor, deleted destructor, deleted copy constructor, and +deleted copy assignment. +In addition only the \tcode{value_type} and \tcode{abi_type} members are +present. + +If \tcode{basic_simd_mask} is enabled, +\tcode{basic_simd_mask} is trivially copyable. + +\pnum +\recommended Implementations should support explicit conversions between +specializations of \tcode{basic_simd_mask} and appropriate \impldef{conversions +of \tcode{basic_simd_mask} from/to implementation-specific vector types} types. +\begin{note} +Appropriate types are non-standard vector types which are available in the +implementation. +\end{note} + +\rSec3[simd.mask.ctor]{\tcode{basic_simd_mask} constructors} + +\begin{itemdecl} +constexpr explicit basic_simd_mask(value_type x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes each element with \tcode{x}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr explicit basic_simd_mask(const basic_simd_mask& x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{basic_simd_mask::size() == size()} is +\tcode{true}. + +\pnum +\effects +Initializes the $i^\text{th}$ element with \tcode{x[$i$]} for all $i$ in the +range of \range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +template constexpr explicit basic_simd_mask(G&& gen) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The expression \tcode{gen(integral_constant<\exposid{simd-size-type}, i>())} is +well-formed and its type is \tcode{bool} for all $i$ in the range of +\range{0}{size()}. + +\pnum +\effects +Initializes the $i^\text{th}$ element with +\tcode{gen(integral_constant<\exposid{simd-size-type}, i>())} for all $i$ in +the range of \range{0}{size()}. + +\pnum +\remarks +The calls to \tcode{gen} are unsequenced with respect to each other. +Vectorization-unsafe\iref{algorithms.parallel.defns} standard library +functions may not be invoked by \tcode{gen}. +\tcode{gen} is invoked exactly once for each $i$. +\end{itemdescr} + +\rSec3[simd.mask.subscr]{\tcode{basic_simd_mask} subscript operator} + +\begin{itemdecl} +constexpr value_type operator[](@\exposid{simd-size-type}@ i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{i >= 0 \&\& i < size()} is \tcode{true}. + +\pnum +\returns +The value of the $i^\text{th}$ element. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\rSec3[simd.mask.unary]{\tcode{basic_simd_mask} unary operators} + +\begin{itemdecl} +constexpr basic_simd_mask operator!() const noexcept; +constexpr basic_simd<@\exposid{integer-from}@, Abi> operator+() const noexcept; +constexpr basic_simd<@\exposid{integer-from}@, Abi> operator-() const noexcept; +constexpr basic_simd<@\exposid{integer-from}@, Abi> operator~() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\returns +A data-parallel object where the $i^\text{th}$ element is initialized to the +results of applying \placeholder{op} to \tcode{operator[]($i$)} for all $i$ in +the range of \range{0}{size()}. +\end{itemdescr} + +\rSec3[simd.mask.conv]{\tcode{basic_simd_mask} conversion operators} + +\begin{itemdecl} +template + constexpr explicit(sizeof(U) != Bytes) operator basic_simd() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{\exposid{simd-size-v} == \exposid{simd-size-v}}. + +\pnum +\returns +A data-parallel object where the $i^\text{th}$ element is initialized to +\tcode{static_cast(operator[]($i$))}. +\end{itemdescr} + +\rSec2[simd.mask.nonmembers]{Non-member operations} + +\rSec3[simd.mask.binary]{\tcode{basic_simd_mask} binary operators} + +\begin{itemdecl} +friend constexpr basic_simd_mask + operator&&(const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask + operator||(const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask + operator& (const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask + operator| (const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask + operator^ (const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\returns +A \tcode{basic_simd_mask} object initialized with the results of applying +\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise +operation. +\end{itemdescr} + +\rSec3[simd.mask.cassign]{\tcode{basic_simd_mask} compound assignment} + +\begin{itemdecl} +friend constexpr basic_simd_mask& + operator&=(basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask& + operator|=(basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +friend constexpr basic_simd_mask& + operator^=(basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\effects +These operators apply \placeholder{op} to \tcode{lhs} and \tcode{rhs} as a +binary element-wise operation. + +\pnum +\returns +\tcode{lhs}. +\end{itemdescr} + +\rSec3[simd.mask.comparison]{\tcode{basic_simd_mask} comparisons} + +\begin{itemdecl} +friend constexpr basic_simd_mask + operator==(const basic_simd_mask&, const basic_simd_mask&) noexcept; +friend constexpr basic_simd_mask + operator!=(const basic_simd_mask&, const basic_simd_mask&) noexcept; +friend constexpr basic_simd_mask + operator>=(const basic_simd_mask&, const basic_simd_mask&) noexcept; +friend constexpr basic_simd_mask + operator<=(const basic_simd_mask&, const basic_simd_mask&) noexcept; +friend constexpr basic_simd_mask + operator>(const basic_simd_mask&, const basic_simd_mask&) noexcept; +friend constexpr basic_simd_mask + operator<(const basic_simd_mask&, const basic_simd_mask&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\returns +A \tcode{basic_simd_mask} object initialized with the results of applying +\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise +operation. +\end{itemdescr} + +\rSec3[simd.mask.cond]{\tcode{basic_simd_mask} exposition only conditional operators} + +\begin{itemdecl} +friend constexpr basic_simd_mask @\exposid{simd-select-impl}@( + const basic_simd_mask& mask, const basic_simd_mask& a, const basic_simd_mask& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{basic_simd_mask} object where the $i^\text{th}$ element equals +\tcode{mask[$i$] ? a[$i$] : b[$i$]} for all $i$ in the range of +\range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr basic_simd_mask +@\exposid{simd-select-impl}@(const basic_simd_mask& mask, same_as auto a, same_as auto b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{basic_simd_mask} object where the $i^\text{th}$ element equals +\tcode{mask[$i$] ? a : b} for all $i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\begin{itemdecl} +template + friend constexpr simd<@\seebelow@, size()> + @\exposid{simd-select-impl}@(const basic_simd_mask& mask, const T0& a, const T1& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} + \item + \tcode{same_as} is \tcode{true}, + \item + \tcode{T0} is a vectorizable type, and + \item + \tcode{sizeof(T0) == Bytes}. +\end{itemize} + +\pnum +\returns +A \tcode{simd} object where the $i^\text{th}$ element equals +\tcode{mask[$i$] ? a : b} for all $i$ in the range of \range{0}{size()}. +\end{itemdescr} + +\rSec3[simd.mask.reductions]{\tcode{basic_simd_mask} reductions} + +\begin{itemdecl} +template + constexpr bool all_of(const basic_simd_mask& k) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if all boolean elements in \tcode{k} are \tcode{true}, otherwise +\tcode{false}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr bool any_of(const basic_simd_mask& k) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if at least one boolean element in \tcode{k} is \tcode{true}, +otherwise \tcode{false}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr bool none_of(const basic_simd_mask& k) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!any_of(k)}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr @\exposid{simd-size-type}@ reduce_count(const basic_simd_mask& k) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The number of boolean elements in \tcode{k} that are \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr @\exposid{simd-size-type}@ reduce_min_index(const basic_simd_mask& k); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{any_of(k)} is \tcode{true}. + +\pnum +\returns +The lowest element index $i$ where \tcode{k[$i$]} is \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr @\exposid{simd-size-type}@ reduce_max_index(const basic_simd_mask& k); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{any_of(k)} is \tcode{true}. + +\pnum +\returns +The greatest element index $i$ where \tcode{k[$i$]} is \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +constexpr bool all_of(same_as auto x) noexcept; +constexpr bool any_of(same_as auto x) noexcept; +constexpr @\exposid{simd-size-type}@ reduce_count(same_as auto x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x}. +\end{itemdescr} + +\begin{itemdecl} +constexpr bool none_of(same_as auto x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!x}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{simd-size-type}@ reduce_min_index(same_as auto x); +constexpr @\exposid{simd-size-type}@ reduce_max_index(same_as auto x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x} is \tcode{true}. + +\pnum +\returns +\tcode{0}. +\end{itemdescr} + +\rSec1[numerics.c]{C compatibility} + +\rSec2[stdckdint.h.syn]{Header \tcode{} synopsis} + +\begin{codeblock} +#define @\libglobal{__STDC_VERSION_STDCKDINT_H__}@ 202311L + +template + bool ckd_add(type1* result, type2 a, type3 b); +template + bool ckd_sub(type1* result, type2 a, type3 b); +template + bool ckd_mul(type1* result, type2 a, type3 b); +\end{codeblock} + +\pnum +\xref{\IsoCUndated{}:2024, 7.20} %% TODO: change to \xrefc{7.20} + +\rSec2[numerics.c.ckdint]{Checked integer operations} + +\indexlibraryglobal{ckd_add}% +\indexlibraryglobal{ckd_sub}% +\indexlibraryglobal{ckd_mul}% +\begin{itemdecl} +template + bool ckd_add(type1* result, type2 a, type3 b); +template + bool ckd_sub(type1* result, type2 a, type3 b); +template + bool ckd_mul(type1* result, type2 a, type3 b); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +Each of the types \tcode{type1}, \tcode{type2}, and \tcode{type3} is a +cv-unqualified signed or unsigned integer type. + +\pnum +\remarks +Each function template has the same semantics as +the corresponding type-generic macro with the same name +specified in \IsoCUndated{}:2024, 7.20. +\end{itemdescr} diff --git a/source/overloading.tex b/source/overloading.tex index fb40049638..cf7d80931c 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -1118,11 +1118,11 @@ \begin{itemize} \item ``lvalue reference to \cvqual{cv2} \tcode{T2}'' -(when initializing an lvalue reference or an rvalue reference to function) and +(when converting to an lvalue) and \item ``\cvqual{cv2} \tcode{T2}'' -and ``rvalue reference to \cvqual{cv2} \tcode{T2}'' (when initializing an -rvalue reference or an lvalue reference to function) +and ``rvalue reference to \cvqual{cv2} \tcode{T2}'' +(when converting to an rvalue or an lvalue of function type) \end{itemize} for any \tcode{T2}. The permissible types for non-explicit conversion functions are @@ -1755,8 +1755,8 @@ \item the context is an initialization by conversion function for direct reference binding\iref{over.match.ref} of a reference to function type, the -return type of \tcode{F1} is the same kind of reference (lvalue or rvalue) -as the reference being initialized, and the return type of \tcode{F2} is not +return type of $\tcode{F}_1$ is the same kind of reference (lvalue or rvalue) +as the reference being initialized, and the return type of $\tcode{F}_2$ is not \begin{example} \begin{codeblock} template struct A { @@ -1772,43 +1772,31 @@ or, if not that, \item -\tcode{F1} +$\tcode{F}_1$ is not a function template specialization and -\tcode{F2} +$\tcode{F}_2$ is a function template specialization, or, if not that, \item -\tcode{F1} +$\tcode{F}_1$ and -\tcode{F2} +$\tcode{F}_2$ are function template specializations, and the function template for -\tcode{F1} +$\tcode{F}_1$ is more specialized than the template for -\tcode{F2} +$\tcode{F}_2$ according to the partial ordering rules described in~\ref{temp.func.order}, or, if not that, \item -\tcode{F1} and \tcode{F2} are non-template functions and -\begin{itemize} -\item -they have the same non-object-parameter-type-lists\iref{dcl.fct}, and -\item -if they are member functions, both are direct members of the same class, and -\item -if both are non-static member functions, -they have the same types for their object parameters, and -\item -\tcode{F1} is more constrained than \tcode{F2} -according to the partial ordering of constraints described in -\ref{temp.constr.order}, -\end{itemize} -or if not that, +$\tcode{F}_1$ and $\tcode{F}_2$ are non-template functions and +$\tcode{F}_1$ is more partial-ordering-constrained than +$\tcode{F}_2$\iref{temp.constr.order} \begin{example} \begin{codeblock} template @@ -1823,12 +1811,13 @@ } \end{codeblock} \end{example} +or, if not that, \item -\tcode{F1} is a constructor for a class \tcode{D}, -\tcode{F2} is a constructor for a base class \tcode{B} of \tcode{D}, and +$\tcode{F}_1$ is a constructor for a class \tcode{D}, +$\tcode{F}_2$ is a constructor for a base class \tcode{B} of \tcode{D}, and for all arguments -the corresponding parameters of \tcode{F1} and \tcode{F2} have the same type +the corresponding parameters of $\tcode{F}_1$ and $\tcode{F}_2$ have the same type \begin{example} \begin{codeblock} struct A { @@ -1848,8 +1837,8 @@ or, if not that, \item -\tcode{F2} is a rewritten candidate\iref{over.match.oper} and -\tcode{F1} is not +$\tcode{F}_2$ is a rewritten candidate\iref{over.match.oper} and +$\tcode{F}_1$ is not \begin{example} \begin{codeblock} struct S { @@ -1862,10 +1851,10 @@ or, if not that, \item -\tcode{F1} and \tcode{F2} are rewritten candidates, and -\tcode{F2} is a synthesized candidate +$\tcode{F}_1$ and $\tcode{F}_2$ are rewritten candidates, and +$\tcode{F}_2$ is a synthesized candidate with reversed order of parameters -and \tcode{F1} is not +and $\tcode{F}_1$ is not \begin{example} \begin{codeblock} struct S { @@ -1875,32 +1864,32 @@ bool b = 1 < S(); // calls \#2 \end{codeblock} \end{example} -or, if not that +or, if not that, \item -\tcode{F1} and \tcode{F2} are generated +$\tcode{F}_1$ and $\tcode{F}_2$ are generated from class template argument deduction\iref{over.match.class.deduct} for a class \tcode{D}, and -\tcode{F2} is generated +$\tcode{F}_2$ is generated from inheriting constructors from a base class of \tcode{D} -while \tcode{F1} is not, and +while $\tcode{F}_1$ is not, and for each explicit function argument, -the corresponding parameters of \tcode{F1} and \tcode{F2} +the corresponding parameters of $\tcode{F}_1$ and $\tcode{F}_2$ are either both ellipses or have the same type, or, if not that, \item -\tcode{F1} is generated from a +$\tcode{F}_1$ is generated from a \grammarterm{deduction-guide}\iref{over.match.class.deduct} -and \tcode{F2} is not, or, if not that, +and $\tcode{F}_2$ is not, or, if not that, \item -\tcode{F1} is the copy deduction candidate\iref{over.match.class.deduct} -and \tcode{F2} is not, or, if not that, +$\tcode{F}_1$ is the copy deduction candidate\iref{over.match.class.deduct} +and $\tcode{F}_2$ is not, or, if not that, \item -\tcode{F1} is generated from a non-template constructor -and \tcode{F2} is generated from a constructor template. +$\tcode{F}_1$ is generated from a non-template constructor +and $\tcode{F}_2$ is generated from a constructor template. \begin{example} \begin{codeblock} template struct A { @@ -2296,7 +2285,7 @@ \pnum If the user-defined conversion is specified by a specialization of a conversion function template, -the second standard conversion sequence shall have exact match rank. +the second standard conversion sequence shall have Exact Match rank. \pnum A conversion of an expression of class type @@ -2318,7 +2307,7 @@ \rSec4[over.ics.ref]{Reference binding} \pnum -When a parameter of type ``reference to \cv \tcode{T}'' +When a parameter of type ``reference to \cv~\tcode{T}'' binds directly\iref{dcl.init.ref} to an argument expression: \begin{itemize} \item @@ -2329,16 +2318,16 @@ \item Otherwise, -if \tcode{T} is a function type, or if the type of the argument is possibly cv-qualified \tcode{T}, or if \tcode{T} is an array type of unknown bound with element type \tcode{U} and the argument has an array type of known bound whose element type is possibly cv-qualified \tcode{U}, the implicit conversion sequence is the identity conversion. -\begin{note} -When \tcode{T} is a function type, -the type of the argument can differ only by the presence of \keyword{noexcept}. -\end{note} + +\item +Otherwise, +if \tcode{T} is a function type, +the implicit conversion sequence is a function pointer conversion. \item Otherwise, the implicit conversion sequence is a qualification conversion. @@ -2351,6 +2340,11 @@ int f(A&); int f(B&); int i = f(b); // calls \tcode{f(B\&)}, an exact match, rather than \tcode{f(A\&)}, a conversion + +void g() noexcept; +int h(void (&)() noexcept); // \#1 +int h(void (&)()); // \#2 +int j = h(g); // calls \#1, an exact match, rather than \#2, a function pointer conversion \end{codeblock} \end{example} If the parameter binds directly to the result of @@ -2835,15 +2829,11 @@ b.f(); // calls \tcode{X::f()} } -int h1(int (&)[]); -int h1(int (&)[1]); -int h2(void (&)()); -int h2(void (&)() noexcept); +int h(int (&)[]); +int h(int (&)[1]); void g2() { int a[1]; - h1(a); // calls \tcode{h1(int (\&)[1])} - extern void f2() noexcept; - h2(f2); // calls \tcode{h2(void (\&)() noexcept)} + h(a); // calls \tcode{h(int (\&)[1])} } \end{codeblock} \end{example} @@ -3116,6 +3106,9 @@ a non-type \grammarterm{template-parameter}\iref{temp.arg.nontype}. \end{itemize} +If the target type contains a placeholder type, +placeholder type deduction is performed\iref{dcl.type.auto.deduct}, and +the remainder of this subclause uses the target type so deduced. The \grammarterm{id-expression} can be preceded by the \tcode{\&} operator. \begin{note} Any redundant set of parentheses surrounding the function name is @@ -3168,10 +3161,8 @@ \tcode{F0} is eliminated if the set contains a second non-template function that -is more constrained than -\tcode{F0} -according to -the partial ordering rules of \ref{temp.constr.order}. +is more partial-ordering-constrained than +\tcode{F0}\iref{temp.constr.order}. Any given function template specialization \tcode{F1} @@ -3207,8 +3198,9 @@ with type \tcode{int(...)} has been declared, and not because of any ambiguity. -For another example, +\end{example} +\begin{example} \begin{codeblock} struct X { int f(int); @@ -3225,6 +3217,21 @@ \end{codeblock} \end{example} +\begin{example} +\begin{codeblock} +template struct X { + void f(short) requires B; + void f(long); + template void g(short) requires B; + template void g(long); +}; +void test() { + &X::f; // error: ambiguous; constraints are not considered + &X::g; // error: ambiguous; constraints are not considered +} +\end{codeblock} +\end{example} + \pnum \begin{note} If \tcode{f} and \tcode{g} are both overload sets, @@ -3351,15 +3358,10 @@ \pnum \indextext{restriction!overloading}% An operator function -shall either -\begin{itemize} -\item -be a member function or -\item -be a non-member function that -has at least one non-object parameter whose type is a class, a reference to a class, an +shall have at least one +function parameter or implicit object parameter whose type is +a class, a reference to a class, an enumeration, or a reference to an enumeration. -\end{itemize} It is not possible to change the precedence, grouping, or number of operands of operators. The meaning of diff --git a/source/preprocessor.tex b/source/preprocessor.tex index 0d50198e26..7c29effcf4 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -75,8 +75,7 @@ \begin{bnf} \nontermdef{elif-groups}\br - elif-group\br - elif-groups elif-group + elif-group \opt{elif-groups} \end{bnf} \begin{bnf}\obeyspaces @@ -124,8 +123,7 @@ \begin{bnf} \nontermdef{pp-tokens}\br - preprocessing-token\br - pp-tokens preprocessing-token + preprocessing-token \opt{pp-tokens} \end{bnf} \begin{bnf} @@ -137,7 +135,7 @@ A \defn{preprocessing directive} consists of a sequence of preprocessing tokens that satisfies the following constraints: At the start of translation phase 4, -the first token in the sequence, +the first preprocessing token in the sequence, referred to as a \defnadj{directive-introducing}{token}, begins with the first character in the source file (optionally after whitespace containing no new-line characters) or @@ -172,7 +170,7 @@ one of the two preceding forms. \end{itemize} -The last token in the sequence is the first token within the sequence that +The last preprocessing token in the sequence is the first preprocessing token within the sequence that is immediately followed by whitespace containing a new-line character. \begin{footnote} Thus, @@ -216,6 +214,16 @@ \pnum A sequence of preprocessing tokens is only a \grammarterm{text-line} if it does not begin with a directive-introducing token. +\begin{example} +\begin{codeblock} +using module = int; +module i; // not a \grammarterm{text-line} and not a \grammarterm{control-line} +int foo() { + return i; +} +\end{codeblock} +The example is not a valid \grammarterm{preprocessing-file}. +\end{example} A sequence of preprocessing tokens is only a \grammarterm{conditionally-supported-directive} if it does not begin with any of the directive names appearing after a \tcode{\#} in the syntax. @@ -290,8 +298,7 @@ \begin{bnf} \nontermdef{h-pp-tokens}\br - h-preprocessing-token\br - h-pp-tokens h-preprocessing-token + h-preprocessing-token \opt{h-pp-tokens} \end{bnf} \begin{bnf} @@ -439,7 +446,7 @@ \tcode{defined} unary operator), just as in normal text. -If the token +If the preprocessing token \tcode{defined} is generated as a result of this replacement process or use of the @@ -756,7 +763,7 @@ \pnum A \grammarterm{pp-module} shall not appear in a context where \tcode{module} -or (if it is the first token of the \grammarterm{pp-module}) \tcode{export} +or (if it is the first preprocessing token of the \grammarterm{pp-module}) \tcode{export} is an identifier defined as an object-like macro. \pnum @@ -817,7 +824,7 @@ \pnum A \grammarterm{pp-import} shall not appear in a context where \tcode{import} -or (if it is the first token of the \grammarterm{pp-import}) \tcode{export} +or (if it is the first preprocessing token of the \grammarterm{pp-import}) \tcode{export} is an identifier defined as an object-like macro. \pnum @@ -1202,7 +1209,7 @@ For each parameter in the replacement list that is neither preceded by a \tcode{\#} or \tcode{\#\#} preprocessing token nor followed by a \tcode{\#\#} preprocessing token, the preprocessing tokens -naming the parameter are replaced by a token sequence determined as follows: +naming the parameter are replaced by a preprocessing token sequence determined as follows: \begin{itemize} \item If the parameter is of the form \grammarterm{va-opt-replacement}, @@ -1215,7 +1222,7 @@ macros contained therein have been expanded. The argument's preprocessing tokens are completely macro replaced before being substituted as if they formed the rest of the preprocessing - tranlation unit with no other preprocessing tokens being available. + translation unit with no other preprocessing tokens being available. \end{itemize} \begin{example} \begin{codeblock} @@ -1408,7 +1415,7 @@ \end{note} If the result is not a valid preprocessing token, the behavior is undefined. -The resulting token is available for further macro replacement. +The resulting preprocessing token is available for further macro replacement. The order of evaluation of \tcode{\#\#} operators is unspecified. @@ -1451,7 +1458,7 @@ "hello, world" \end{codeblock} -Space around the \tcode{\#} and \tcode{\#\#} tokens in the macro definition +Space around the \tcode{\#} and \tcode{\#\#} preprocessing tokens in the macro definition is optional. \end{example} @@ -1477,8 +1484,8 @@ "x ## y" \end{codeblock} -In other words, expanding \tcode{hash_hash} produces a new token, -consisting of two adjacent sharp signs, but this new token is not the +In other words, expanding \tcode{hash_hash} produces a new preprocessing token, +consisting of two adjacent sharp signs, but this new preprocessing token is not the \tcode{\#\#} operator. \end{example} @@ -1600,10 +1607,12 @@ \pnum The \defn{line number} -of the current source line is one greater than +of the current source line is +the line number of the current physical source line, +i.e., it is one greater than the number of new-line characters read or introduced in translation phase 1\iref{lex.phases} -while processing the source file to the current token. +while processing the source file to the current preprocessing token. \pnum A preprocessing directive of the form @@ -1850,6 +1859,7 @@ \defnxname{cpp_conditional_explicit} & \tcode{201806L} \\ \rowsep \defnxname{cpp_constexpr} & \tcode{202406L} \\ \rowsep \defnxname{cpp_constexpr_dynamic_alloc} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_constexpr_exceptions} & \tcode{202411L} \\ \rowsep \defnxname{cpp_constexpr_in_decltype} & \tcode{201711L} \\ \rowsep \defnxname{cpp_consteval} & \tcode{202211L} \\ \rowsep \defnxname{cpp_constinit} & \tcode{201907L} \\ \rowsep @@ -1895,7 +1905,7 @@ \defnxname{cpp_sized_deallocation} & \tcode{201309L} \\ \rowsep \defnxname{cpp_static_assert} & \tcode{202306L} \\ \rowsep \defnxname{cpp_static_call_operator} & \tcode{202207L} \\ \rowsep -\defnxname{cpp_structured_bindings} & \tcode{202403L} \\ \rowsep +\defnxname{cpp_structured_bindings} & \tcode{202411L} \\ \rowsep \defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep \defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep \defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep diff --git a/source/ranges.tex b/source/ranges.tex index 805f0e8b6d..a6cebb51e4 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -396,7 +396,7 @@ // \ref{range.as.const}, as const view template<@\libconcept{input_range}@ R> constexpr auto& @\exposid{possibly-const-range}@(R& r) noexcept { // \expos - if constexpr (@\libconcept{constant_range}@ && !@\libconcept{constant_range}@) { + if constexpr (@\libconcept{input_range}@) { return const_cast(r); } else { return r; @@ -541,6 +541,13 @@ class cartesian_product_view; // freestanding namespace views { inline constexpr @\unspecnc@ cartesian_product = @\unspecnc@; } // freestanding + + // \ref{range.cache.latest}, cache latest view + template<@\libconcept{input_range}@ V> + requires @\libconcept{view}@ + class cache_latest_view; + + namespace views { inline constexpr @\unspec@ cache_latest = @\unspec@; } } namespace std { @@ -1407,7 +1414,7 @@ \pnum \begin{note} -\tcode{disable_sized_range} allows use of range types with the library +\tcode{disable_sized_range} allows use of \libconcept{range} types with the library that satisfy but do not in fact model \libconcept{sized_range}. \end{note} \end{itemdescr} @@ -1634,7 +1641,7 @@ template concept @\defexposconceptnc{has-arrow}@ = // \expos - @\libconcept{input_iterator}@ && (is_pointer_v || requires(I i) { i.operator->(); }); + @\libconcept{input_iterator}@ && (is_pointer_v || requires(const I i) { i.operator->(); }); template concept @\defexposconceptnc{different-from}@ = // \expos @@ -8866,7 +8873,7 @@ \indexlibrarymember{\exposid{satisfy}}{concat_view::\exposid{iterator}}% \begin{itemdecl} template - constexpr void @\exposid{satisfy}@(); // \expos + constexpr void @\exposid{satisfy}@(); \end{itemdecl} \begin{itemdescr} @@ -8886,7 +8893,7 @@ \indexlibrarymember{\exposid{prev}}{concat_view::\exposid{iterator}}% \begin{itemdecl} template - constexpr void @\exposid{prev}@(); // \expos + constexpr void @\exposid{prev}@(); \end{itemdecl} \begin{itemdescr} @@ -8910,7 +8917,7 @@ \indexlibrarymember{\exposid{advance-fwd}}{concat_view::\exposid{iterator}}% \begin{itemdecl} template - constexpr void @\exposid{advance-fwd}@(difference_type offset, difference_type steps); // \expos + constexpr void @\exposid{advance-fwd}@(difference_type offset, difference_type steps); \end{itemdecl} \begin{itemdescr} @@ -8936,7 +8943,7 @@ \indexlibrarymember{\exposid{advance-bwd}}{concat_view::\exposid{iterator}}% \begin{itemdecl} template - constexpr void @\exposid{advance-bwd}@(difference_type offset, difference_type steps); // \expos + constexpr void @\exposid{advance-bwd}@(difference_type offset, difference_type steps); \end{itemdecl} \begin{itemdescr} @@ -8962,7 +8969,7 @@ \indexlibraryctor{concat_view::\exposid{iterator}}% \begin{itemdecl} template - constexpr explicit @\exposid{iterator}@(@\exposid{maybe-const}@* parent, // \expos + constexpr explicit @\exposid{iterator}@(@\exposid{maybe-const}@* parent, Args&&... args) requires @\libconcept{constructible_from}@<@\exposid{base-iter}@, Args&&...>; \end{itemdecl} @@ -15684,7 +15691,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{++*this;} +Equivalent to \tcode{++*this;} \end{itemdescr} \indexlibrarymember{operator++}{stride_view::\exposid{iterator}}% @@ -16737,6 +16744,346 @@ \end{itemize} \end{itemdescr} +\rSec2[range.cache.latest]{Cache latest view} + +\rSec3[range.cache.latest.overview]{Overview} + +\pnum +\tcode{cache_latest_view} caches the last-accessed element of +its underlying sequence +so that the element does not have to be recomputed on repeated access. +\begin{note} +This is useful if computation of the element to produce is expensive. +\end{note} + +\pnum +The name \tcode{views::cache_latest} denotes +a range adaptor object\iref{range.adaptor.object}. +Let \tcode{E} be an expression. +The expression \tcode{views::cache_latest(E)} is expression-equivalent to +\tcode{cache_latest_view(E)}. + +\rSec3[range.cache.latest.view]{Class template \tcode{cache_latest_view}} + +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@ V> + requires @\libconcept{view}@ + class @\libglobal{cache_latest_view}@ : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + using @\exposid{cache-t}@ = conditional_t>, // \expos + add_pointer_t>, + range_reference_t>; + + @\exposid{non-propagating-cache}@ @\exposid{cache_}@; // \expos + + class @\exposid{iterator}@; // \expos + class @\exposid{sentinel}@; // \expos + + public: + cache_latest_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit cache_latest_view(V base); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr auto begin(); + constexpr auto end(); + + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; + }; + + template + cache_latest_view(R&&) -> cache_latest_view>; +} +\end{codeblock} + +\indexlibraryctor{cache_latest_view}% +\begin{itemdecl} +constexpr explicit cache_latest_view(V base); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. +\end{itemdescr} + +\indexlibrarymember{begin}{cache_latest_view}% +\begin{itemdecl} +constexpr auto begin(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{iterator}(*this);} +\end{itemdescr} + +\indexlibrarymember{end}{cache_latest_view}% +\begin{itemdecl} +constexpr auto end(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{sentinel}(*this);} +\end{itemdescr} + +\indexlibrarymember{size}{cache_latest_view}% +\begin{itemdecl} +constexpr auto size() requires sized_range; +constexpr auto size() const requires sized_range; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return ranges::size(\exposid{base_});} +\end{itemdescr} + +\rSec3[range.cache.latest.iterator]{Class \tcode{cache_latest_view::\exposid{iterator}}} + +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@ V> + requires @\libconcept{view}@ + class cache_latest_view::@\exposid{iterator}@ { + cache_latest_view* @\exposid{parent_}@; // \expos + iterator_t @\exposid{current_}@; // \expos + + constexpr explicit @\exposid{iterator}@(cache_latest_view& parent); // \expos + + public: + using difference_type = range_difference_t; + using value_type = range_value_t; + using iterator_concept = input_iterator_tag; + + @\exposid{iterator}@(@\exposid{iterator}@&&) = default; + @\exposid{iterator}@& operator=(@\exposid{iterator}@&&) = default; + + constexpr iterator_t base() &&; + constexpr const iterator_t& base() const & noexcept; + + constexpr range_reference_t& operator*() const; + + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); + + friend constexpr range_rvalue_reference_t iter_move(const @\exposid{iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); + + friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@))) + requires @\libconcept{indirectly_swappable}@>; + }; +} +\end{codeblock} + +\indexlibraryctor{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr explicit @\exposid{iterator}@(cache_latest_view& parent); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with +\tcode{ranges::begin(parent.\exposid{base_})} +and \exposid{parent_} with \tcode{addressof(par\-ent)}. +\end{itemdescr} + +\indexlibrarymember{base}{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr iterator_t base() &&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{std::move(\exposid{current_})}. +\end{itemdescr} + +\indexlibrarymember{base}{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr const iterator_t& base() const & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{current_}. +\end{itemdescr} + +\indexlibrarymember{operator++}{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr iterator& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{parent_}@->@\exposid{cache_}@.reset(); +++@\exposid{current_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{++*this}. +\end{itemdescr} + +\indexlibrarymember{operator*}{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr range_reference_t& operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if constexpr (is_reference_v>) { + if (!@\exposid{parent_}@->@\exposid{cache_}@) { + @\exposid{parent_}@->@\exposid{cache_}@ = addressof(@\exposid{as-lvalue}@(*@\exposid{current_}@)); + } + return **@\exposid{parent_}@->@\exposid{cache_}@; +} else { + if (!@\exposid{parent_}@->c@\exposid{ache_}@) { + @\exposid{parent_}@->@\exposid{cache_}@.@\exposid{emplace-deref}@(@\exposid{current_}@); + } + return *@\exposid{parent_}@->@\exposid{cache_}@; +} +\end{codeblock} +\begin{note} +Evaluations of \tcode{operator*} on the same iterator object +can conflict\iref{intro.races}. +\end{note} +\end{itemdescr} + +\indexlibrarymember{iter_move}{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr range_rvalue_reference_t iter_move(const @\exposid{iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});} +\end{itemdescr} + +\indexlibrarymember{iter_swap}{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@))) + requires @\libconcept{indirectly_swappable}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to +\tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_})}. +\end{itemdescr} + +\rSec3[range.cache.latest.sentinel]{Class \tcode{cache_latest_view::\exposid{sentinel}}} + +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@ V> + requires @\libconcept{view}@ + class cache_latest_view::@\exposid{sentinel}@ { + sentinel_t @\exposid{end_}@ = sentinel_t(); // \expos + + constexpr explicit @\exposid{sentinel}@(cache_latest_view& parent); // \expos + + public: + @\exposid{sentinel}@() = default; + + constexpr sentinel_t base() const; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + friend constexpr range_difference_t operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y) + requires sized_sentinel_for, iterator_t>; + friend constexpr range_difference_t operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y) + requires sized_sentinel_for, iterator_t>; + }; +} +\end{codeblock} + +\indexlibraryctor{cache_latest_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(cache_latest_view& parent); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}. +\end{itemdescr} + +\indexlibrarymember{base}{cache_latest_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr sentinel_t base() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{end_}. +\end{itemdescr} + +\indexlibrarymember{operator==}{cache_latest_view::\exposid{iterator}}% +\indexlibrarymember{operator==}{cache_latest_view::\exposid{sentinel}}% +\begin{itemdecl} +friend constexpr bool operator==(const iterator& x, const sentinel& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} == y.\exposid{end_}}. +\end{itemdescr} + +\indexlibrarymember{operator-}{cache_latest_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{cache_latest_view::\exposid{sentinel}}% +\begin{itemdecl} +friend constexpr range_difference_t operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y) + requires sized_sentinel_for, iterator_t>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} - y.\exposid{end_}}. +\end{itemdescr} + +\indexlibrarymember{operator-}{cache_latest_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{cache_latest_view::\exposid{sentinel}}% +\begin{itemdecl} +friend constexpr range_difference_t operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y) + requires sized_sentinel_for, iterator_t>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{end_} - y.\exposid{current_}}. +\end{itemdescr} + \rSec1[coro.generator]{Range generators} \rSec2[coroutine.generator.overview]{Overview} @@ -16995,6 +17342,9 @@ template requires @\libconcept{same_as}@::yielded, yielded> auto yield_value(ranges::elements_of&&, Unused> g) noexcept; + template + requires @\libconcept{same_as}@::yielded, yielded> + auto yield_value(ranges::elements_of&, Unused> g) noexcept; template requires @\libconcept{convertible_to}@, yielded> @@ -17009,13 +17359,11 @@ requires @\libconcept{same_as}@ || @\libconcept{default_initializable}@; template - requires @\libconcept{same_as}@ || @\libconcept{convertible_to}@ - void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...); + void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...); template - requires @\libconcept{same_as}@ || @\libconcept{convertible_to}@ - void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc, - const Args&...); + void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc, + const Args&...); void operator delete(void* pointer, size_t size) noexcept; @@ -17122,6 +17470,9 @@ template requires @\libconcept{same_as}@::yielded, yielded> auto yield_value(ranges::elements_of&&, Unused> g) noexcept; +template + requires @\libconcept{same_as}@::yielded, yielded> + auto yield_value(ranges::elements_of&, Unused> g) noexcept; \end{itemdecl} \begin{itemdescr} @@ -17154,7 +17505,7 @@ \pnum \remarks -A \grammarterm{yield-expression} that calls this function +A \grammarterm{yield-expression} that calls one of these functions has type \tcode{void}\iref{expr.yield}. \end{itemdescr} @@ -17171,7 +17522,7 @@ Equivalent to: \begin{codeblock} auto nested = [](allocator_arg_t, Alloc, ranges::iterator_t i, ranges::sentinel_t s) - -> generator, Alloc> { + -> generator { for (; i != s; ++i) { co_yield static_cast(*i); } @@ -17214,11 +17565,9 @@ requires @\libconcept{same_as}@ || @\libconcept{default_initializable}@; template - requires @\libconcept{same_as}@ || @\libconcept{convertible_to}@ void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...); template - requires @\libconcept{same_as}@ || @\libconcept{convertible_to}@ void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc, const Args&...); \end{itemdecl} @@ -17241,6 +17590,9 @@ \pnum \mandates \tcode{allocator_traits::pointer} is a pointer type. +For the overloads with a template parameter \tcode{Alloc}, +\tcode{\libconcept{same_as} || \libconcept{convertible_to}} +is modeled. \pnum \effects diff --git a/source/statements.tex b/source/statements.tex index 9940ee28de..7fcee85848 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -226,14 +226,12 @@ \begin{bnf} \nontermdef{statement-seq}\br - statement\br - statement-seq statement + statement \opt{statement-seq} \end{bnf} \begin{bnf} \nontermdef{label-seq}\br - label\br - label-seq label + label \opt{label-seq} \end{bnf} A label at the end of a \grammarterm{compound-statement} diff --git a/source/strings.tex b/source/strings.tex index c0dc123c6f..48e2bee8a3 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -5,7 +5,8 @@ \pnum This Clause describes components for manipulating sequences of -any non-array trivial standard-layout\iref{term.standard.layout.type} type. +any non-array trivially copyable standard-layout\iref{term.standard.layout.type} type \tcode{T} +where \tcode{is_trivially_default_constructible_v} is \tcode{true}. Such types are called \defnx{char-like types}{char-like type}, and objects of char-like types are called \defnx{char-like objects}{char-like object} or @@ -122,15 +123,15 @@ & & \chdr{pre-/post-condition} & \\ \capsep \endhead \tcode{X::char_type} & \tcode{C} & - & compile-time \\ \rowsep + & \\ \rowsep \tcode{X::int_type} & & -(described in~\ref{char.traits.typedefs}) & compile-time \\ \rowsep +(described in~\ref{char.traits.typedefs}) & \\ \rowsep \tcode{X::off_type} & & -(described in~\ref{iostreams.limits.pos} and \ref{iostream.forward}) & compile-time \\ \rowsep +(described in~\ref{iostreams.limits.pos} and \ref{iostream.forward}) & \\ \rowsep \tcode{X::pos_type} & & -(described in~\ref{iostreams.limits.pos} and \ref{iostream.forward}) & compile-time \\ \rowsep +(described in~\ref{iostreams.limits.pos} and \ref{iostream.forward}) & \\ \rowsep \tcode{X::state_type} & & -(described in~\ref{char.traits.typedefs}) & compile-time \\ \rowsep +(described in~\ref{char.traits.typedefs}) & \\ \rowsep \tcode{X::eq(c,d)} & \tcode{bool} & \returns whether \tcode{c} is to be treated as equal to \tcode{d}. & constant \\ \rowsep @@ -5514,9 +5515,11 @@ \indextext{signal-safe!\idxcode{memcpy}}% \indextext{signal-safe!\idxcode{memmove}}% The functions \tcode{memcpy} and \tcode{memmove} are signal-safe\iref{support.signal}. -Both functions implicitly create objects\iref{intro.object} +Each of these functions implicitly creates objects\iref{intro.object} in the destination region of storage immediately prior to copying the sequence of characters to the destination. +Each of these functions returns a pointer to a suitable created object, if any, +otherwise the value of the first parameter. \pnum \begin{note} diff --git a/source/support.tex b/source/support.tex index 28c15ac913..a7fdcbd7ae 100644 --- a/source/support.tex +++ b/source/support.tex @@ -333,9 +333,10 @@ \pnum The type \indexlibraryglobal{max_align_t}% -\tcode{max_align_t} is a trivial standard-layout type whose alignment requirement +\tcode{max_align_t} is a trivially copyable standard-layout type whose alignment requirement is at least as great as that of every scalar type, and whose alignment requirement is supported in every context\iref{basic.align}. +\tcode{std::is_trivially_default_constructible_v} is \tcode{true}. \xrefc{7.19} @@ -557,6 +558,7 @@ // also in \libheader{algorithm}, \libheader{ranges}, \libheader{string}, \libheader{deque}, \libheader{list}, \libheader{forward_list}, \libheader{vector} #define @\defnlibxname{cpp_lib_algorithm_iterator_requirements}@ 202207L // also in \libheader{algorithm}, \libheader{numeric}, \libheader{memory} +#define @\defnlibxname{cpp_lib_aligned_accessor}@ 202411L // also in \libheader{mdspan} #define @\defnlibxname{cpp_lib_allocate_at_least}@ 202302L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_allocator_traits_is_always_equal}@ 201411L // freestanding, also in \libheader{memory}, \libheader{scoped_allocator}, \libheader{string}, \libheader{deque}, \libheader{forward_list}, \libheader{list}, @@ -575,7 +577,7 @@ #define @\defnlibxname{cpp_lib_atomic_is_always_lock_free}@ 201603L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_lock_free_type_aliases}@ 201907L // also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_min_max}@ 202403L // freestanding, also in \libheader{atomic} -#define @\defnlibxname{cpp_lib_atomic_ref}@ 201806L // freestanding, also in \libheader{atomic} +#define @\defnlibxname{cpp_lib_atomic_ref}@ 202411L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_shared_ptr}@ 201711L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_atomic_value_initialization}@ 201911L // freestanding, also in \libheader{atomic}, \libheader{memory} #define @\defnlibxname{cpp_lib_atomic_wait}@ 201907L // freestanding, also in \libheader{atomic} @@ -596,17 +598,19 @@ #define @\defnlibxname{cpp_lib_chrono}@ 202306L // also in \libheader{chrono} #define @\defnlibxname{cpp_lib_chrono_udls}@ 201304L // also in \libheader{chrono} #define @\defnlibxname{cpp_lib_clamp}@ 201603L // also in \libheader{algorithm} -#define @\defnlibxname{cpp_lib_common_reference}@ 202302L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_common_reference_wrapper}@ 202302L // also in \libheader{functional} +#define @\defnlibxname{cpp_lib_common_reference}@ 202302L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_common_reference_wrapper}@ 202302L // freestanding, also in \libheader{functional} #define @\defnlibxname{cpp_lib_complex_udls}@ 201309L // also in \libheader{complex} #define @\defnlibxname{cpp_lib_concepts}@ 202207L // freestanding, also in \libheader{concepts}, \libheader{compare} #define @\defnlibxname{cpp_lib_constexpr_algorithms}@ 202306L // also in \libheader{algorithm}, \libheader{utility} +#define @\defnlibxname{cpp_lib_constexpr_atomic}@ 202411L // also in \libheader{atomic} #define @\defnlibxname{cpp_lib_constexpr_bitset}@ 202207L // also in \libheader{bitset} -#define @\defnlibxname{cpp_lib_constexpr_charconv}@ 202207L // also in \libheader{charconv} +#define @\defnlibxname{cpp_lib_constexpr_charconv}@ 202207L // freestanding, also in \libheader{charconv} #define @\defnlibxname{cpp_lib_constexpr_cmath}@ 202306L // also in \libheader{cmath}, \libheader{cstdlib} #define @\defnlibxname{cpp_lib_constexpr_complex}@ 202306L // also in \libheader{complex} #define @\defnlibxname{cpp_lib_constexpr_dynamic_alloc}@ 201907L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_constexpr_exceptions}@ 202411L // also in \libheader{exception} #define @\defnlibxname{cpp_lib_constexpr_functional}@ 201907L // freestanding, also in \libheader{functional} #define @\defnlibxname{cpp_lib_constexpr_iterator}@ 201811L // freestanding, also in \libheader{iterator} #define @\defnlibxname{cpp_lib_constexpr_memory}@ 202202L // freestanding, also in \libheader{memory} @@ -618,13 +622,13 @@ #define @\defnlibxname{cpp_lib_constexpr_typeinfo}@ 202106L // freestanding, also in \libheader{typeinfo} #define @\defnlibxname{cpp_lib_constexpr_utility}@ 201811L // freestanding, also in \libheader{utility} #define @\defnlibxname{cpp_lib_constexpr_vector}@ 201907L // also in \libheader{vector} -#define @\defnlibxname{cpp_lib_constrained_equality}@ 202403L // freestanding, - // also in \libheader{utility}, \libheader{tuple}, \libheader{optional}, \libheader{variant} +#define @\defnlibxname{cpp_lib_constrained_equality}@ 202411L // freestanding, + // also in \libheader{utility}, \libheader{tuple}, \libheader{optional}, \libheader{variant}, \libheader{expected} #define @\defnlibxname{cpp_lib_containers_ranges}@ 202202L // also in \libheader{vector}, \libheader{list}, \libheader{forward_list}, \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set}, // \libheader{deque}, \libheader{queue}, \libheader{stack}, \libheader{string} #define @\defnlibxname{cpp_lib_copyable_function}@ 202306L // also in \libheader{functional} -#define @\defnlibxname{cpp_lib_coroutine}@ 201902L // also in \libheader{coroutine} +#define @\defnlibxname{cpp_lib_coroutine}@ 201902L // freestanding, also in \libheader{coroutine} #define @\defnlibxname{cpp_lib_debugging}@ 202403L // freestanding, also in \libheader{debugging} #define @\defnlibxname{cpp_lib_destroying_delete}@ 201806L // freestanding, also in \libheader{new} #define @\defnlibxname{cpp_lib_enable_shared_from_this}@ 201603L // also in \libheader{memory} @@ -693,20 +697,21 @@ #define @\defnlibxname{cpp_lib_is_aggregate}@ 201703L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_constant_evaluated}@ 201811L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_final}@ 201402L // freestanding, also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_implicit_lifetime}@ 202302L // also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_is_implicit_lifetime}@ 202302L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_invocable}@ 201703L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_layout_compatible}@ 201907L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_nothrow_convertible}@ 201806L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_null_pointer}@ 201309L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_pointer_interconvertible}@ 201907L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_scoped_enum}@ 202011L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_is_sufficiently_aligned}@ 202411L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_is_swappable}@ 201603L // freestanding, also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_virtual_base_of}@ 202406L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_within_lifetime}@ 202306L // also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_is_virtual_base_of}@ 202406L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_is_within_lifetime}@ 202306L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_jthread}@ 201911L // also in \libheader{stop_token}, \libheader{thread} #define @\defnlibxname{cpp_lib_latch}@ 201907L // also in \libheader{latch} #define @\defnlibxname{cpp_lib_launder}@ 201606L // freestanding, also in \libheader{new} -#define @\defnlibxname{cpp_lib_linalg}@ 202311L // also in \libheader{linalg} +#define @\defnlibxname{cpp_lib_linalg}@ 202412L // also in \libheader{linalg} #define @\defnlibxname{cpp_lib_list_remove_return_type}@ 201806L // also in \libheader{forward_list}, \libheader{list} #define @\defnlibxname{cpp_lib_logical_traits}@ 201510L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_make_from_tuple}@ 201606L // freestanding, also in \libheader{tuple} @@ -715,7 +720,7 @@ #define @\defnlibxname{cpp_lib_map_try_emplace}@ 201411L // also in \libheader{map} #define @\defnlibxname{cpp_lib_math_constants}@ 201907L // also in \libheader{numbers} #define @\defnlibxname{cpp_lib_math_special_functions}@ 201603L // also in \libheader{cmath} -#define @\defnlibxname{cpp_lib_mdspan}@ 202406L // also in \libheader{mdspan} +#define @\defnlibxname{cpp_lib_mdspan}@ 202406L // freestanding, also in \libheader{mdspan} #define @\defnlibxname{cpp_lib_memory_resource}@ 201603L // also in \libheader{memory_resource} #define @\defnlibxname{cpp_lib_modules}@ 202207L // freestanding #define @\defnlibxname{cpp_lib_move_iterator_concept}@ 202207L // freestanding, also in \libheader{iterator} @@ -739,6 +744,7 @@ // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_as_const}@ 202311L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_as_rvalue}@ 202207L // freestanding, also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_cache_latest}@ 202411L // 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} @@ -757,8 +763,8 @@ #define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // freestanding, also in \libheader{ranges}, \libheader{tuple}, \libheader{utility} -#define @\defnlibxname{cpp_lib_ratio}@ 202306L // also in \libheader{ratio} -#define @\defnlibxname{cpp_lib_raw_memory_algorithms}@ 201606L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_ratio}@ 202306L // freestanding, also in \libheader{ratio} +#define @\defnlibxname{cpp_lib_raw_memory_algorithms}@ 202411L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_rcu}@ 202306L // also in \libheader{rcu} #define @\defnlibxname{cpp_lib_reference_from_temporary}@ 202202L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_reference_wrapper}@ 202403L // freestanding, also in \libheader{functional} @@ -776,11 +782,12 @@ #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}@ 202411L // also in \libheader{simd} #define @\defnlibxname{cpp_lib_smart_ptr_for_overwrite}@ 202002L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_smart_ptr_owner_equality}@ 202306L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_source_location}@ 201907L // freestanding, also in \libheader{source_location} #define @\defnlibxname{cpp_lib_span}@ 202311L // freestanding, also in \libheader{span} -#define @\defnlibxname{cpp_lib_span_initializer_list}@ 202311L // also in \libheader{span} +#define @\defnlibxname{cpp_lib_span_initializer_list}@ 202311L // freestanding, also in \libheader{span} #define @\defnlibxname{cpp_lib_spanstream}@ 202106L // also in \libheader{spanstream} #define @\defnlibxname{cpp_lib_ssize}@ 201902L // freestanding, also in \libheader{iterator} #define @\defnlibxname{cpp_lib_sstream_from_string_view}@ 202306L // also in \libheader{sstream} @@ -792,12 +799,12 @@ #define @\defnlibxname{cpp_lib_string_resize_and_overwrite}@ 202110L // also in \libheader{string} #define @\defnlibxname{cpp_lib_string_udls}@ 201304L // also in \libheader{string} #define @\defnlibxname{cpp_lib_string_view}@ 202403L // also in \libheader{string}, \libheader{string_view} -#define @\defnlibxname{cpp_lib_submdspan}@ 202403L // also in \libheader{mdspan} +#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_text_encoding}@ 202306L // also in \libheader{text_encoding} #define @\defnlibxname{cpp_lib_three_way_comparison}@ 201907L // freestanding, also in \libheader{compare} #define @\defnlibxname{cpp_lib_to_address}@ 201711L // freestanding, also in \libheader{memory} -#define @\defnlibxname{cpp_lib_to_array}@ 201907L // also in \libheader{array} +#define @\defnlibxname{cpp_lib_to_array}@ 201907L // freestanding, also in \libheader{array} #define @\defnlibxname{cpp_lib_to_chars}@ 202306L // also in \libheader{charconv} #define @\defnlibxname{cpp_lib_to_string}@ 202306L // also in \libheader{string} #define @\defnlibxname{cpp_lib_to_underlying}@ 202102L // freestanding, also in \libheader{utility} @@ -2941,7 +2948,7 @@ class bad_alloc : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -2954,7 +2961,7 @@ \indexlibrarymember{what}{bad_alloc}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -2972,7 +2979,7 @@ class bad_array_new_length : public bad_alloc { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -2985,7 +2992,7 @@ \indexlibrarymember{what}{bad_array_new_length}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3310,7 +3317,7 @@ class bad_cast : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -3326,7 +3333,7 @@ \indexlibrarymember{what}{bad_cast}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3344,7 +3351,7 @@ class bad_typeid : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -3360,7 +3367,7 @@ \indexlibrarymember{what}{bad_typeid}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3775,16 +3782,16 @@ terminate_handler set_terminate(terminate_handler f) noexcept; [[noreturn]] void terminate() noexcept; - int uncaught_exceptions() noexcept; + constexpr int uncaught_exceptions() noexcept; using exception_ptr = @\unspec@; - exception_ptr current_exception() noexcept; - [[noreturn]] void rethrow_exception(exception_ptr p); - template exception_ptr make_exception_ptr(E e) noexcept; + constexpr exception_ptr current_exception() noexcept; + [[noreturn]] constexpr void rethrow_exception(exception_ptr p); + template constexpr exception_ptr make_exception_ptr(E e) noexcept; - template [[noreturn]] void throw_with_nested(T&& t); - template void rethrow_if_nested(const E& e); + template [[noreturn]] constexpr void throw_with_nested(T&& t); + template constexpr void rethrow_if_nested(const E& e); } \end{codeblock} @@ -3796,11 +3803,11 @@ namespace std { class exception { public: - exception() noexcept; - exception(const exception&) noexcept; - exception& operator=(const exception&) noexcept; - virtual ~exception(); - virtual const char* what() const noexcept; + constexpr exception() noexcept; + constexpr exception(const exception&) noexcept; + constexpr exception& operator=(const exception&) noexcept; + constexpr virtual ~exception(); + constexpr virtual const char* what() const noexcept; }; } \end{codeblock} @@ -3833,8 +3840,8 @@ \indexlibraryctor{exception}% \indexlibrarymember{operator=}{exception}% \begin{itemdecl} -exception(const exception& rhs) noexcept; -exception& operator=(const exception& rhs) noexcept; +constexpr exception(const exception& rhs) noexcept; +constexpr exception& operator=(const exception& rhs) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3846,7 +3853,7 @@ \indexlibrarydtor{exception}% \begin{itemdecl} -virtual ~exception(); +constexpr virtual ~exception(); \end{itemdecl} \begin{itemdescr} @@ -3858,13 +3865,15 @@ \indexlibrarymember{what}{exception}% \begin{itemdecl} -virtual const char* what() const noexcept; +constexpr virtual const char* what() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -An \impldef{return value of \tcode{exception::what}} \ntbs{}. +An \impldef{return value of \tcode{exception::what}} \ntbs{}, +which during constant evaluation is encoded with +the ordinary literal encoding\iref{lex.ccon}. \pnum \remarks @@ -3885,7 +3894,7 @@ class bad_exception : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -3900,7 +3909,7 @@ \indexlibrarymember{what}{bad_exception}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -4007,7 +4016,7 @@ \indexlibraryglobal{uncaught_exceptions}% \begin{itemdecl} -int uncaught_exceptions() noexcept; +constexpr int uncaught_exceptions() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4068,11 +4077,14 @@ Changes in the number of \tcode{exception_ptr} objects that refer to a particular exception do not introduce a data race. \end{note} + +\pnum +All member functions are marked \tcode{constexpr}. \end{itemdescr} \indexlibraryglobal{current_exception}% \begin{itemdecl} -exception_ptr current_exception() noexcept; +constexpr exception_ptr current_exception() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4103,7 +4115,7 @@ \indexlibraryglobal{rethrow_exception}% \begin{itemdecl} -[[noreturn]] void rethrow_exception(exception_ptr p); +[[noreturn]] constexpr void rethrow_exception(exception_ptr p); \end{itemdecl} \begin{itemdescr} @@ -4131,7 +4143,7 @@ \indexlibraryglobal{make_exception_ptr}% \begin{itemdecl} -template exception_ptr make_exception_ptr(E e) noexcept; +template constexpr exception_ptr make_exception_ptr(E e) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4160,18 +4172,18 @@ namespace std { class nested_exception { public: - nested_exception() noexcept; - nested_exception(const nested_exception&) noexcept = default; - nested_exception& operator=(const nested_exception&) noexcept = default; - virtual ~nested_exception() = default; + constexpr nested_exception() noexcept; + constexpr nested_exception(const nested_exception&) noexcept = default; + constexpr nested_exception& operator=(const nested_exception&) noexcept = default; + constexpr virtual ~nested_exception() = default; // access functions - [[noreturn]] void rethrow_nested() const; - exception_ptr nested_ptr() const noexcept; + [[noreturn]] constexpr void rethrow_nested() const; + constexpr exception_ptr nested_ptr() const noexcept; }; - template [[noreturn]] void throw_with_nested(T&& t); - template void rethrow_if_nested(const E& e); + template [[noreturn]] constexpr void throw_with_nested(T&& t); + template constexpr void rethrow_if_nested(const E& e); } \end{codeblock} @@ -4188,7 +4200,7 @@ \indexlibraryctor{nested_exception}% \begin{itemdecl} -nested_exception() noexcept; +constexpr nested_exception() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4199,7 +4211,7 @@ \indexlibrarymember{rethrow_nested}{nested_exception}% \begin{itemdecl} -[[noreturn]] void rethrow_nested() const; +[[noreturn]] constexpr void rethrow_nested() const; \end{itemdecl} \begin{itemdescr} @@ -4211,7 +4223,7 @@ \indexlibrarymember{nested_ptr}{nested_exception}% \begin{itemdecl} -exception_ptr nested_ptr() const noexcept; +constexpr exception_ptr nested_ptr() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4222,7 +4234,7 @@ \indexlibrarymember{throw_with_nested}{nested_exception}% \begin{itemdecl} -template [[noreturn]] void throw_with_nested(T&& t); +template [[noreturn]] constexpr void throw_with_nested(T&& t); \end{itemdecl} \begin{itemdescr} @@ -4245,7 +4257,7 @@ \indexlibrarymember{rethrow_if_nested}{nested_exception}% \begin{itemdecl} -template void rethrow_if_nested(const E& e); +template constexpr void rethrow_if_nested(const E& e); \end{itemdecl} \begin{itemdescr} @@ -5295,7 +5307,8 @@ Otherwise, if the expressions \tcode{E == F}, \tcode{E < F}, and \tcode{F < E} are all well-formed and - each of \tcode{decltype(E == F)} and \tcode{decltype(E < F)} models + each of \tcode{decltype(E == F)}, \tcode{decltype(E < F)}, and + \tcode{decltype(F < E)} models \exposconcept{boolean-testable}, \begin{codeblock} E == F ? partial_ordering::equivalent : @@ -6217,16 +6230,18 @@ \libheader{stdalign.h} \\ \libheaderdef{stdarg.h} \\ \libheader{stdatomic.h} \\ +\libheader{stdbit.h} \\ \libheader{stdbool.h} \\ -\libheaderdef{stddef.h} \\ \columnbreak +\libheader{stdckdint.h} \\ +\libheaderdef{stddef.h} \\ \libheaderdef{stdint.h} \\ \libheaderdef{stdio.h} \\ \libheaderdef{stdlib.h} \\ \libheaderdef{string.h} \\ +\columnbreak \libheader{tgmath.h} \\ \libheaderdef{time.h} \\ -\columnbreak \libheaderdef{uchar.h} \\ \libheaderdef{wchar.h} \\ \libheaderdef{wctype.h} \\ @@ -6330,7 +6345,9 @@ \libheaderref{iso646.h}, \libheaderref{stdalign.h},\newline \libheaderref{stdatomic.h}, -\libheaderref{stdbool.h}, and +\libheaderref{stdbit.h}, +\libheaderref{stdbool.h}, +\libheaderref{stdckdint.h}, and\newline \libheaderref{tgmath.h}, each of which has a name of the form diff --git a/source/templates.tex b/source/templates.tex index ba8462df53..d616394cc3 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -143,12 +143,26 @@ \begin{note} A template cannot have the same name as any other name bound in the same scope\iref{basic.scope.scope}, except -that a function template can share a name with non-template -functions\iref{dcl.fct} and/or function templates\iref{temp.over}. +that a function template can share a name with \grammarterm{using-declarator}s, +a type, non-template functions\iref{dcl.fct} and/or function templates\iref{temp.over}. Specializations, including partial specializations\iref{temp.spec.partial}, do not reintroduce or bind names. Their target scope is the target scope of the primary template, so all specializations of a template belong to the same scope as it does. +\begin{example} +\begin{codeblock} +void f() {} +class f {}; // OK +namespace N { + void f(int) {} +} +using N::f; // OK +template void f(long) {} // \#1, OK +template void f(long) {} // error: redefinition of \#1 +template void f(long long) {} // OK +template<> void f(long long) {} // OK, doesn't bind a name +\end{codeblock} +\end{example} \end{note} \pnum @@ -399,8 +413,8 @@ \item all base classes and non-static data members are public and non-mutable and \item -the types of all bases classes and non-static data members are -structural types or (possibly multidimensional) array thereof. +the types of all base classes and non-static data members are +structural types or (possibly multidimensional) arrays thereof. \end{itemize} \end{itemize} @@ -1135,20 +1149,22 @@ \rSec2[temp.arg.nontype]{Template non-type arguments} \pnum -If the type \tcode{T} of a \grammarterm{template-parameter}\iref{temp.param} -contains a placeholder type\iref{dcl.spec.auto} -or a placeholder for a deduced class type\iref{dcl.type.class.deduct}, -the type of the parameter is the type deduced -for the variable \tcode{x} in the invented declaration +A template argument $E$ for +a non-type \grammarterm{template-parameter} with declared type \tcode{T} +shall be such that the invented declaration \begin{codeblock} T x = @$E$@ ; \end{codeblock} -where $E$ is the template argument provided for the parameter. +satisfies the semantic constraints for the definition of +a \tcode{constexpr} variable with static storage duration\iref{dcl.constexpr}. +If \tcode{T} contains a placeholder type\iref{dcl.spec.auto} +or a placeholder for a deduced class type\iref{dcl.type.class.deduct}, +the type of the parameter is deduced from the above declaration. \begin{note} $E$ is a \grammarterm{template-argument} or (for a default template argument) an \grammarterm{initializer-clause}. \end{note} -If a deduced parameter type is not permitted +If the parameter type thus deduced is not permitted for a \grammarterm{template-parameter} declaration\iref{temp.param}, the program is ill-formed. @@ -1210,6 +1226,19 @@ \item a subobject\iref{intro.object} of one of the above. \end{itemize} +\pnum +\begin{example} +\begin{codeblock} +template class A{}; +extern int x; +A a; // OK +void f(int p) { + constexpr int& r = p; // OK + A a; // error: a static constexpr \tcode{int\&} variable cannot be initialized to refer to \tcode{p} here +} +\end{codeblock} +\end{example} + \pnum \begin{example} \begin{codeblock} @@ -2119,6 +2148,22 @@ \end{codeblock} \end{example} +\pnum +A non-template function \tcode{F1} is \defn{more partial-ordering-constrained} +than a non-template function \tcode{F2} if +\begin{itemize} +\item +they have the same non-object-parameter-type-lists\iref{dcl.fct}, and +\item +if they are member functions, both are direct members of the same class, and +\item +if both are non-static member functions, +they have the same types for their object parameters, and +\item +the declaration of \tcode{F1} is more constrained than +the declaration of \tcode{F2}. +\end{itemize} + \rSec1[temp.type]{Type equivalence} \pnum @@ -2504,7 +2549,7 @@ \begin{bnf} \nontermdef{deduction-guide}\br - \opt{explicit-specifier} template-name \terminal{(} parameter-declaration-clause \terminal{)} \opt{requires-clause} \terminal{->} simple-template-id \terminal{;} + \opt{explicit-specifier} template-name \terminal{(} parameter-declaration-clause \terminal{)} \terminal{->} simple-template-id \opt{requires-clause} \terminal{;} \end{bnf} \pnum @@ -2795,11 +2840,27 @@ \end{codeblock} \end{example} +\pnum +A \defn{structured binding pack} is an \grammarterm{sb-identifier} +that introduces zero or more structured bindings\iref{dcl.struct.bind}. +\begin{example} +\begin{codeblock} +auto foo() -> int(&)[2]; + +template +void g() { + auto [...a] = foo(); // \tcode{a} is a structured binding pack containing two elements + auto [b, c, ...d] = foo(); // \tcode{d} is a structured binding pack containing zero elements +} +\end{codeblock} +\end{example} + \pnum A \defn{pack} is a template parameter pack, a function parameter pack, -or an \grammarterm{init-capture} pack. +an \grammarterm{init-capture} pack, or +a structured binding pack. The number of elements of a template parameter pack or a function parameter pack is the number of arguments provided for the parameter pack. @@ -2954,7 +3015,6 @@ designating the $i^\text{th}$ function parameter that resulted from instantiation of the function parameter pack declaration; -otherwise \item if the pack is an \grammarterm{init-capture} pack, @@ -2962,7 +3022,14 @@ designating the variable introduced by the $i^\text{th}$ \grammarterm{init-capture} that resulted from instantiation of -the \grammarterm{init-capture} pack declaration. +the \grammarterm{init-capture} pack declaration; +otherwise + +\item +if the pack is a structured binding pack, +the element is an \grammarterm{id-expression} +designating the $i^\textrm{th}$ structured binding in the pack +that resulted from the structured binding declaration. \end{itemize} When $N$ is zero, the instantiation of a pack expansion does not alter the syntactic interpretation of the enclosing construct, @@ -4973,13 +5040,16 @@ \item in the definition of a nested class of a class template, the name of the nested class referenced as a member of the -current instantiation, or +current instantiation, \item in the definition of a class template partial specialization or a member of a class template partial specialization, the name of the class template followed by a template argument list equivalent to that of the partial specialization\iref{temp.spec.partial} -enclosed in \tcode{<>} (or an equivalent template alias specialization). +enclosed in \tcode{<>} (or an equivalent template alias specialization), or +\item +in the definition of a templated function, +the name of a local class\iref{class.local}. \end{itemize} \pnum @@ -5290,6 +5360,28 @@ a structured binding declaration\iref{dcl.struct.bind} whose \grammarterm{brace-or-equal-initializer} is type-dependent, \item +associated by name lookup with a pack, +\begin{example} +\begin{codeblock} +struct C { }; + +void g(...); // \#1 + +template +void f() { + C arr[1]; + auto [...e] = arr; + g(e...); // calls \#2 +} + +void g(C); // \#2 + +int main() { + f(); +} +\end{codeblock} +\end{example} +\item associated by name lookup with an entity captured by copy\iref{expr.prim.lambda.capture} in a \grammarterm{lambda-expression} @@ -5432,8 +5524,7 @@ \keyword{sizeof} \terminal{(} type-id \terminal{)}\br \keyword{typeid} \terminal{(} expression \terminal{)}\br \keyword{typeid} \terminal{(} type-id \terminal{)}\br -\keyword{alignof} \terminal{(} type-id \terminal{)}\br -\keyword{noexcept} \terminal{(} expression \terminal{)} +\keyword{alignof} \terminal{(} type-id \terminal{)} \end{ncsimplebnf} \begin{note} @@ -5443,20 +5534,28 @@ \pnum Expressions of the following form are value-dependent if either the -\grammarterm{type-id} -or -\grammarterm{simple-type-specifier} +\grammarterm{type-id}, +\grammarterm{simple-type-specifier}, or +\grammarterm{typename-specifier} is dependent or the \grammarterm{expression} or \grammarterm{cast-expression} +is value-dependent or +any \grammarterm{expression} in the \grammarterm{expression-list} +is value-dependent or +any \grammarterm{assignment-expression} in the \grammarterm{braced-init-list} is value-dependent: \begin{ncsimplebnf} simple-type-specifier \terminal{(} \opt{expression-list} \terminal{)}\br +typename-specifier \terminal{(} opt{expression-list} \terminal{)}\br +simple-type-specifier braced-init-list\br +typename-specifier braced-init-list\br \keyword{static_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br \keyword{const_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br \keyword{reinterpret_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br +dynamic_cast \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br \terminal{(} type-id \terminal{)} cast-expression \end{ncsimplebnf} @@ -5467,6 +5566,13 @@ \keyword{sizeof} \terminal{...} \terminal{(} identifier \terminal{)}\br fold-expression \end{ncsimplebnf} +unless the \grammarterm{identifier} is a structured binding pack +whose initializer is not dependent. + +\pnum +A \grammarterm{noexcept-expression}\iref{expr.unary.noexcept} +is value-dependent if +its \grammarterm{expression} involves a template parameter. \pnum An expression of the form \tcode{\&}\grammarterm{qualified-id} where the @@ -7578,7 +7684,7 @@ \tcode{A}) as described below. If removing references and cv-qualifiers from \tcode{P} gives -\tcode{std::initializer_list} +$\tcode{std::initializer_list}$ or $\tcode{P}'\tcode{[N]}$ for some $\tcode{P}'$ and \tcode{N} and the argument is a non-empty initializer list\iref{dcl.init.list}, then deduction is @@ -7840,10 +7946,11 @@ the parameter is treated as a non-deduced context. \item If the argument is an overload set (not containing function templates), trial -argument deduction is attempted using each of the members of the set. If -deduction succeeds for only one of the overload set members, that member is -used as the argument value for the deduction. If deduction succeeds for more than -one member of the overload set the parameter is treated as a non-deduced context. +argument deduction is attempted using each of the members of the set +whose associated constraints\iref{temp.constr.constr} are satisfied. +If all successful deductions yield the same deduced \tcode{A}, +that deduced \tcode{A} is the result of deduction; +otherwise, the parameter is treated as a non-deduced context. \end{itemize} \pnum @@ -7879,6 +7986,21 @@ \end{codeblock} \end{example} +\pnum +\begin{example} +\begin{codeblock} +// All arguments for placeholder type deduction\iref{dcl.type.auto.deduct} yield the same deduced type. +template struct X { + static void f(short) requires B; // \#1 + static void f(short); // \#2 +}; +void test() { + auto x = &X::f; // OK, deduces \tcode{void(*)(short)}, selects \#1 + auto y = &X::f; // OK, deduces \tcode{void(*)(short)}, selects \#2 +} +\end{codeblock} +\end{example} + \rSec3[temp.deduct.funcaddr]{Deducing template arguments taking the address of a function template} \pnum @@ -8312,16 +8434,22 @@ deduction is being done. \item A function parameter for which the associated argument is an -overload set\iref{over.over}, and one or more of the following apply: +overload set such that one or more of the following apply: \begin{itemize} \item -more than one function matches the function parameter type (resulting in -an ambiguous deduction), or +functions whose associated constraints are satisfied and +that do not all have the same function type +match the function parameter type (resulting in an ambiguous deduction), or \item -no function matches the function parameter type, or +no function whose associated constraints are satisfied +matches the function parameter type, or \item the overload set supplied as an argument contains one or more function templates. \end{itemize} +\begin{tailnote} +A particular function from the overload set is selected\iref{over.over} +after template argument deduction has succeeded\iref{temp.over}. +\end{tailnote} \item A function parameter for which the associated argument is an initializer list\iref{dcl.init.list} but the parameter does not have a type for which deduction from an initializer list is specified\iref{temp.deduct.call}. diff --git a/source/text.tex b/source/text.tex index 99d63ad2c5..f1786cea2f 100644 --- a/source/text.tex +++ b/source/text.tex @@ -36,28 +36,18 @@ \indexheader{charconv}% \begin{codeblock} namespace std { -@% -\indexlibraryglobal{chars_format}% -\indexlibrarymember{scientific}{chars_format}% -\indexlibrarymember{fixed}{chars_format}% -\indexlibrarymember{hex}{chars_format}% -\indexlibrarymember{general}{chars_format}% -@ // floating-point format for primitive numerical conversion - enum class chars_format { - scientific = @\unspec@, - fixed = @\unspec@, - hex = @\unspec@, - general = fixed | scientific + // floating-point format for primitive numerical conversion + enum class @\libglobal{chars_format}@ { + @\libmember{scientific}{chars_format}@ = @\unspec@, + @\libmember{fixed}{chars_format}@ = @\unspec@, + @\libmember{hex}{chars_format}@ = @\unspec@, + @\libmember{general}{chars_format}@ = fixed | scientific }; -@% -\indexlibraryglobal{to_chars_result}% -\indexlibrarymember{ptr}{to_chars_result}% -\indexlibrarymember{ec}{to_chars_result} -@ + // \ref{charconv.to.chars}, primitive numerical output conversion - struct to_chars_result { // freestanding - char* ptr; - errc ec; + struct @\libglobal{to_chars_result}@ { // freestanding + char* @\libmember{ptr}{to_chars_result}@; + errc @\libmember{ec}{to_chars_result}@; friend bool operator==(const to_chars_result&, const to_chars_result&) = default; constexpr explicit operator bool() const noexcept { return ec == errc{}; } }; @@ -73,15 +63,11 @@ @\placeholder{floating-point-type}@ value, chars_format fmt); to_chars_result to_chars(char* first, char* last, // freestanding-deleted @\placeholder{floating-point-type}@ value, chars_format fmt, int precision); -@% -\indexlibraryglobal{from_chars_result}% -\indexlibrarymember{ptr}{from_chars_result}% -\indexlibrarymember{ec}{from_chars_result} -@ + // \ref{charconv.from.chars}, primitive numerical input conversion - struct from_chars_result { // freestanding - const char* ptr; - errc ec; + struct @\libglobal{from_chars_result}@ { // freestanding + const char* @\libmember{ptr}{from_chars_result}@; + errc @\libmember{ec}{from_chars_result}@; friend bool operator==(const from_chars_result&, const from_chars_result&) = default; constexpr explicit operator bool() const noexcept { return ec == errc{}; } }; @@ -369,7 +355,7 @@ \rSec2[localization.general]{General} \pnum -This Clause describes components that \Cpp{} programs may use to +Subclause \ref{localization} describes components that \Cpp{} programs may use to encapsulate (and therefore be more portable when confronting) cultural differences. The locale facility includes @@ -385,9 +371,9 @@ as summarized in \tref{localization.summary}. \begin{libsumtab}{Localization library summary}{localization.summary} -\ref{locales} & Locales & \tcode{} \\ -\ref{locale.categories} & Standard \tcode{locale} categories & \\ \rowsep -\ref{c.locales} & C library locales & \tcode{} \\ \rowsep +\ref{locales} & Locales & \tcode{} \\ +\ref{locale.categories} & Standard \tcode{locale} categories & \\ \rowsep +\ref{c.locales} & C library locales & \tcode{} \\ \rowsep \end{libsumtab} \rSec2[locale.syn]{Header \tcode{} synopsis} @@ -1629,7 +1615,7 @@ are those in the basic character set\iref{lex.charset}. For any named \tcode{ctype} category with -a \tcode{ctype} facet \tcode{ctc} and +a \tcode{ctype} facet \tcode{ctc} and valid \tcode{ctype_base::mask} value \tcode{M}, \tcode{(ctc.\brk{}is(M, c) || !is(M, do_widen(c)) )} is \tcode{true}. \begin{footnote} @@ -2174,10 +2160,10 @@ Stops if it encounters a character it cannot convert. It always leaves the \tcode{from_next} and \tcode{to_next} pointers pointing one beyond the last element successfully converted. -If returns \tcode{noconv}, -\tcode{internT} and \tcode{externT} are the same type and +If it returns \tcode{noconv}, +\tcode{internT} and \tcode{externT} are the same type, and the converted sequence is identical to -the input sequence \range{from}{from\textunderscore\nobreak next}. +the input sequence \range{from}{from\textunderscore\nobreak next}, \tcode{to_next} is set equal to \tcode{to}, the value of \tcode{state} is unchanged, and there are no changes to the values in \range{to}{to_end}. @@ -2979,7 +2965,8 @@ {lc} \topline \lhdr{State} & \rhdr{\tcode{stdio} equivalent} \\ \capsep -\tcode{floatfield == ios_base::fixed} & \tcode{\%f} \\ \rowsep +\tcode{floatfield == ios_base::fixed \&\& !uppercase} & \tcode{\%f} \\ \rowsep +\tcode{floatfield == ios_base::fixed} & \tcode{\%F} \\ \rowsep \tcode{floatfield == ios_base::scientific \&\& !uppercase} & \tcode{\%e} \\ \rowsep \tcode{floatfield == ios_base::scientific} & \tcode{\%E} \\ \rowsep \tcode{floatfield == (ios_base::fixed | ios_base::scientific) \&\& !uppercase} & \tcode{\%a} \\ \rowsep @@ -5057,6 +5044,7 @@ constexpr id mib() const noexcept; constexpr const char* name() const noexcept; + // \ref{text.encoding.aliases}, class \tcode{text_encoding::aliases_view} struct aliases_view; constexpr aliases_view aliases() const noexcept; @@ -5127,7 +5115,7 @@ \tcode{e.mib() == text_encoding::id::other} is \tcode{false} maintains the following invariants: \begin{itemize} -\item \tcode{e.name() == nullptr} is \tcode{false}, and +\item \tcode{*e.name() == '\textbackslash 0'} is \tcode{false}, and \item \tcode{e.mib() == text_encoding(e.name()).mib()} is \tcode{true}. \end{itemize} @@ -5227,13 +5215,10 @@ \begin{itemdescr} \pnum \returns -\exposid{name_} if \tcode{(\exposid{name_}[0] != '\textbackslash 0')} -is \tcode{true}, and -\keyword{nullptr} otherwise. +\exposid{name_}. \pnum \remarks -If \tcode{name() == nullptr} is \tcode{false}, \tcode{name()} is an \ntbs{} and accessing elements of \exposid{name_} outside of the range \countedrange{name()}{strlen(name()) + 1} @@ -5904,7 +5889,7 @@ @\libconcept{formattable}@, charT> struct formatter : @\exposid{range-default-formatter}@, R, charT> { }; - template + template requires (format_kind != range_format::disabled) constexpr bool enable_nonlocking_formatter_optimization = false; @@ -6366,7 +6351,7 @@ \begin{itemize} \item any code point with the \tcode{East_Asian_Width="W"} or -\tcode{East_Asian_Width="F"} Derived Extracted Property as described by +\tcode{East_Asian_Width="F"} property as described by \UAX{44} of the Unicode Standard \item \ucode{4dc0} -- \ucode{4dff} (Yijing Hexagram Symbols) @@ -7640,6 +7625,7 @@ \begin{itemdescr} \pnum \mandates +$\tcode{sizeof...(Ts)} \ge 1$. The types in \tcode{Ts...} are unique. Each type in \tcode{Ts...} is one of \keyword{bool}, @@ -9020,7 +9006,7 @@ \rSec2[re.general]{General} \pnum -This Clause describes components that \Cpp{} programs may use to +Subclause \ref{re} describes components that \Cpp{} programs may use to perform operations involving regular expression matching and searching. diff --git a/source/threads.tex b/source/threads.tex index cb0f99e12a..08e1cb7165 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -2401,7 +2401,7 @@ inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; // freestanding template - T kill_dependency(T y) noexcept; // freestanding + constexpr T kill_dependency(T y) noexcept; // freestanding } // \ref{atomics.lockfree}, lock-free property @@ -2437,57 +2437,58 @@ void atomic_store(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - void atomic_store(atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr void atomic_store(atomic*, // freestanding + typename atomic::value_type) noexcept; template void atomic_store_explicit(volatile atomic*, // freestanding - typename atomic::value_type, - memory_order) noexcept; + typename atomic::value_type, memory_order) noexcept; template - void atomic_store_explicit(atomic*, typename atomic::value_type, // freestanding - memory_order) noexcept; + constexpr void atomic_store_explicit(atomic*, // freestanding + typename atomic::value_type, memory_order) noexcept; template T atomic_load(const volatile atomic*) noexcept; // freestanding template - T atomic_load(const atomic*) noexcept; // freestanding + constexpr T atomic_load(const atomic*) noexcept; // freestanding template T atomic_load_explicit(const volatile atomic*, memory_order) noexcept; // freestanding template - T atomic_load_explicit(const atomic*, memory_order) noexcept; // freestanding + constexpr T atomic_load_explicit(const atomic*, memory_order) noexcept; // freestanding template T atomic_exchange(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - T atomic_exchange(atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr T atomic_exchange(atomic*, // freestanding + typename atomic::value_type) noexcept; template T atomic_exchange_explicit(volatile atomic*, // freestanding - typename atomic::value_type, - memory_order) noexcept; + typename atomic::value_type, memory_order) noexcept; template - T atomic_exchange_explicit(atomic*, typename atomic::value_type, // freestanding - memory_order) noexcept; + constexpr T atomic_exchange_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; template bool atomic_compare_exchange_weak(volatile atomic*, // freestanding typename atomic::value_type*, typename atomic::value_type) noexcept; template - bool atomic_compare_exchange_weak(atomic*, // freestanding - typename atomic::value_type*, - typename atomic::value_type) noexcept; + constexpr bool atomic_compare_exchange_weak(atomic*, // freestanding + typename atomic::value_type*, + typename atomic::value_type) noexcept; template bool atomic_compare_exchange_strong(volatile atomic*, // freestanding typename atomic::value_type*, typename atomic::value_type) noexcept; template - bool atomic_compare_exchange_strong(atomic*, // freestanding - typename atomic::value_type*, - typename atomic::value_type) noexcept; + constexpr bool atomic_compare_exchange_strong(atomic*, // freestanding + typename atomic::value_type*, + typename atomic::value_type) noexcept; template bool atomic_compare_exchange_weak_explicit(volatile atomic*, // freestanding typename atomic::value_type*, typename atomic::value_type, memory_order, memory_order) noexcept; template - bool atomic_compare_exchange_weak_explicit(atomic*, // freestanding + constexpr bool atomic_compare_exchange_weak_explicit(atomic*, // freestanding typename atomic::value_type*, typename atomic::value_type, memory_order, memory_order) noexcept; @@ -2497,7 +2498,7 @@ typename atomic::value_type, memory_order, memory_order) noexcept; template - bool atomic_compare_exchange_strong_explicit(atomic*, // freestanding + constexpr bool atomic_compare_exchange_strong_explicit(atomic*, // freestanding typename atomic::value_type*, typename atomic::value_type, memory_order, memory_order) noexcept; @@ -2506,110 +2507,122 @@ T atomic_fetch_add(volatile atomic*, // freestanding typename atomic::difference_type) noexcept; template - T atomic_fetch_add(atomic*, typename atomic::difference_type) noexcept; // freestanding + constexpr T atomic_fetch_add(atomic*, // freestanding + typename atomic::difference_type) noexcept; template T atomic_fetch_add_explicit(volatile atomic*, // freestanding typename atomic::difference_type, memory_order) noexcept; template - T atomic_fetch_add_explicit(atomic*, typename atomic::difference_type, // freestanding - memory_order) noexcept; + constexpr T atomic_fetch_add_explicit(atomic*, // freestanding + typename atomic::difference_type, + memory_order) noexcept; template T atomic_fetch_sub(volatile atomic*, // freestanding typename atomic::difference_type) noexcept; template - T atomic_fetch_sub(atomic*, typename atomic::difference_type) noexcept; // freestanding + constexpr T atomic_fetch_sub(atomic*, // freestanding + typename atomic::difference_type) noexcept; template T atomic_fetch_sub_explicit(volatile atomic*, // freestanding typename atomic::difference_type, memory_order) noexcept; template - T atomic_fetch_sub_explicit(atomic*, typename atomic::difference_type, // freestanding - memory_order) noexcept; + constexpr T atomic_fetch_sub_explicit(atomic*, // freestanding + typename atomic::difference_type, + memory_order) noexcept; template T atomic_fetch_and(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - T atomic_fetch_and(atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr T atomic_fetch_and(atomic*, // freestanding + typename atomic::value_type) noexcept; template T atomic_fetch_and_explicit(volatile atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template - T atomic_fetch_and_explicit(atomic*, typename atomic::value_type, // freestanding - memory_order) noexcept; + constexpr T atomic_fetch_and_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; template T atomic_fetch_or(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - T atomic_fetch_or(atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr T atomic_fetch_or(atomic*, // freestanding + typename atomic::value_type) noexcept; template T atomic_fetch_or_explicit(volatile atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template - T atomic_fetch_or_explicit(atomic*, typename atomic::value_type, // freestanding - memory_order) noexcept; + constexpr T atomic_fetch_or_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; template T atomic_fetch_xor(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - T atomic_fetch_xor(atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr T atomic_fetch_xor(atomic*, // freestanding + typename atomic::value_type) noexcept; template T atomic_fetch_xor_explicit(volatile atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template - T atomic_fetch_xor_explicit(atomic*, typename atomic::value_type, // freestanding - memory_order) noexcept; + constexpr T atomic_fetch_xor_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; template T atomic_fetch_max(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - T atomic_fetch_max(atomic*, // freestanding + constexpr T atomic_fetch_max(atomic*, // freestanding typename atomic::value_type) noexcept; template T atomic_fetch_max_explicit(volatile atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template - T atomic_fetch_max_explicit(atomic*, // freestanding + constexpr T atomic_fetch_max_explicit(atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template T atomic_fetch_min(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - T atomic_fetch_min(atomic*, // freestanding + constexpr T atomic_fetch_min(atomic*, // freestanding typename atomic::value_type) noexcept; template T atomic_fetch_min_explicit(volatile atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template - T atomic_fetch_min_explicit(atomic*, // freestanding + constexpr T atomic_fetch_min_explicit(atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template void atomic_wait(const volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - void atomic_wait(const atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr void atomic_wait(const atomic*, // freestanding + typename atomic::value_type) noexcept; template void atomic_wait_explicit(const volatile atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template - void atomic_wait_explicit(const atomic*, typename atomic::value_type, // freestanding - memory_order) noexcept; + constexpr void atomic_wait_explicit(const atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; template void atomic_notify_one(volatile atomic*) noexcept; // freestanding template - void atomic_notify_one(atomic*) noexcept; // freestanding + constexpr void atomic_notify_one(atomic*) noexcept; // freestanding template void atomic_notify_all(volatile atomic*) noexcept; // freestanding template - void atomic_notify_all(atomic*) noexcept; // freestanding + constexpr void atomic_notify_all(atomic*) noexcept; // freestanding // \ref{atomics.alias}, type aliases using atomic_bool = atomic; // freestanding @@ -2670,35 +2683,37 @@ struct atomic_flag; // freestanding bool atomic_flag_test(const volatile atomic_flag*) noexcept; // freestanding - bool atomic_flag_test(const atomic_flag*) noexcept; // freestanding + constexpr bool atomic_flag_test(const atomic_flag*) noexcept; // freestanding bool atomic_flag_test_explicit(const volatile atomic_flag*, // freestanding memory_order) noexcept; - bool atomic_flag_test_explicit(const atomic_flag*, memory_order) noexcept; // freestanding + constexpr bool atomic_flag_test_explicit(const atomic_flag*, // freestanding + memory_order) noexcept; bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept; // freestanding - bool atomic_flag_test_and_set(atomic_flag*) noexcept; // freestanding + constexpr bool atomic_flag_test_and_set(atomic_flag*) noexcept; // freestanding bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, // freestanding memory_order) noexcept; - bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept; // freestanding + constexpr bool atomic_flag_test_and_set_explicit(atomic_flag*, // freestanding + memory_order) noexcept; void atomic_flag_clear(volatile atomic_flag*) noexcept; // freestanding - void atomic_flag_clear(atomic_flag*) noexcept; // freestanding + constexpr void atomic_flag_clear(atomic_flag*) noexcept; // freestanding void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept; // freestanding - void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; // freestanding + constexpr void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; // freestanding void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept; // freestanding - void atomic_flag_wait(const atomic_flag*, bool) noexcept; // freestanding + constexpr void atomic_flag_wait(const atomic_flag*, bool) noexcept; // freestanding void atomic_flag_wait_explicit(const volatile atomic_flag*, // freestanding bool, memory_order) noexcept; - void atomic_flag_wait_explicit(const atomic_flag*, // freestanding + constexpr void atomic_flag_wait_explicit(const atomic_flag*, // freestanding bool, memory_order) noexcept; void atomic_flag_notify_one(volatile atomic_flag*) noexcept; // freestanding - void atomic_flag_notify_one(atomic_flag*) noexcept; // freestanding + constexpr void atomic_flag_notify_one(atomic_flag*) noexcept; // freestanding void atomic_flag_notify_all(volatile atomic_flag*) noexcept; // freestanding - void atomic_flag_notify_all(atomic_flag*) noexcept; // freestanding + constexpr void atomic_flag_notify_all(atomic_flag*) noexcept; // freestanding #define ATOMIC_FLAG_INIT @\seebelownc@ // freestanding // \ref{atomics.fences}, fences - extern "C" void atomic_thread_fence(memory_order) noexcept; // freestanding - extern "C" void atomic_signal_fence(memory_order) noexcept; // freestanding + extern "C" constexpr void atomic_thread_fence(memory_order) noexcept; // freestanding + extern "C" constexpr void atomic_signal_fence(memory_order) noexcept; // freestanding } \end{codeblock} @@ -2978,7 +2993,7 @@ \indexlibraryglobal{kill_dependency}% \begin{itemdecl} template - T kill_dependency(T y) noexcept; + constexpr T kill_dependency(T y) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3126,34 +3141,36 @@ T* ptr; // \expos public: - using value_type = T; + using value_type = remove_cv_t; static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; bool is_lock_free() const noexcept; - explicit atomic_ref(T&); - atomic_ref(const atomic_ref&) noexcept; + constexpr explicit atomic_ref(T&); + constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; - void store(T, memory_order = memory_order::seq_cst) const noexcept; - T operator=(T) const noexcept; - T load(memory_order = memory_order::seq_cst) const noexcept; - operator T() const noexcept; - - T exchange(T, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(T&, T, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(T&, T, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(T&, T, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(T&, T, - memory_order = memory_order::seq_cst) const noexcept; + constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type operator=(value_type) const noexcept; + constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; + constexpr operator value_type() const noexcept; - void wait(T, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; + constexpr value_type exchange(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr void notify_one() const noexcept; + constexpr void notify_all() const noexcept; + constexpr T* address() const noexcept; }; } \end{codeblock} @@ -3188,6 +3205,11 @@ to enable atomic operations to be applied to the referenced object. \end{note} +\pnum +The program is ill-formed +if \tcode{is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{true}. + \rSec3[atomics.ref.ops]{Operations} \indexlibrarymember{required_alignment}{atomic_ref}% @@ -3252,7 +3274,7 @@ \indexlibrary{\idxcode{atomic_ref<\placeholder{integral-type}>}!constructor}% \indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point-type}>}!constructor}% \begin{itemdecl} -atomic_ref(T& obj); +constexpr atomic_ref(T& obj); \end{itemdecl} \begin{itemdescr} @@ -3274,7 +3296,7 @@ \indexlibrary{\idxcode{atomic_ref<\placeholder{integral-type}>}!constructor}% \indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point-type}>}!constructor}% \begin{itemdecl} -atomic_ref(const atomic_ref& ref) noexcept; +constexpr atomic_ref(const atomic_ref& ref) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3288,10 +3310,15 @@ \indexlibrarymember{store}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{store}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -void store(T desired, memory_order order = memory_order::seq_cst) const noexcept; +constexpr void store(value_type desired, + memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \expects \tcode{order} is @@ -3311,10 +3338,14 @@ \indexlibrarymember{operator=}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{operator=}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -T operator=(T desired) const noexcept; +constexpr value_type operator=(value_type desired) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3329,7 +3360,7 @@ \indexlibrarymember{load}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{load}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -T load(memory_order order = memory_order::seq_cst) const noexcept; +constexpr value_type load(memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3355,7 +3386,7 @@ \indexlibrarymember{operator \placeholder{integral-type}}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{operator \placeholder{floating-point-type}}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -operator T() const noexcept; +constexpr operator value_type() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3369,10 +3400,15 @@ \indexlibrarymember{exchange}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{exchange}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -T exchange(T desired, memory_order order = memory_order::seq_cst) const noexcept; +constexpr value_type exchange(value_type desired, + memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Atomically replaces the value referenced by \tcode{*ptr} @@ -3395,20 +3431,24 @@ \indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -bool compare_exchange_weak(T& expected, T desired, +constexpr bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success, memory_order failure) const noexcept; -bool compare_exchange_strong(T& expected, T desired, +constexpr bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success, memory_order failure) const noexcept; -bool compare_exchange_weak(T& expected, T desired, +constexpr bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept; -bool compare_exchange_strong(T& expected, T desired, +constexpr bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \expects \tcode{failure} is @@ -3472,7 +3512,7 @@ \indexlibrarymember{wait}{atomic_ref}% \begin{itemdecl} -void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; +constexpr void wait(value_type old, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3506,10 +3546,14 @@ \indexlibrarymember{notify_one}{atomic_ref}% \begin{itemdecl} -void notify_one() const noexcept; +constexpr void notify_one() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Unblocks the execution of at least one atomic waiting operation on \tcode{*ptr} @@ -3524,10 +3568,14 @@ \indexlibrarymember{notify_all}{atomic_ref}% \begin{itemdecl} -void notify_all() const noexcept; +constexpr void notify_all() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Unblocks the execution of all atomic waiting operations on \tcode{*ptr} @@ -3535,8 +3583,19 @@ \pnum \remarks - This function is an atomic notifying operation\iref{atomics.wait} - on atomic object \tcode{*ptr}. +This function is an atomic notifying operation\iref{atomics.wait} +on atomic object \tcode{*ptr}. +\end{itemdescr} + +\indexlibrarymember{address}{atomic_ref}% +\begin{itemdecl} +constexpr T* address() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{ptr}. \end{itemdescr} \rSec3[atomics.ref.int]{Specializations for integral types} @@ -3544,23 +3603,7 @@ \pnum \indexlibrary{\idxcode{atomic_ref<\placeholder{integral-type}>}}% There are specializations of the \tcode{atomic_ref} class template -for the integral types -\tcode{char}, -\tcode{signed char}, -\tcode{unsigned char}, -\tcode{short}, -\tcode{unsigned short}, -\tcode{int}, -\tcode{unsigned int}, -\tcode{long}, -\tcode{unsigned long}, -\tcode{long long}, -\tcode{unsigned long long}, -\keyword{char8_t}, -\keyword{char16_t}, -\keyword{char32_t}, -\keyword{wchar_t}, -and any other types needed by the typedefs in the header \libheaderref{cstdint}. +for all integral types except \cv{} \tcode{bool}. For each such type \tcode{\placeholder{integral-type}}, the specialization \tcode{atomic_ref<\placeholder{integral-type}>} provides additional atomic operations appropriate to integral types. @@ -3569,6 +3612,11 @@ uses the primary template\iref{atomics.ref.generic}. \end{note} +\pnum +The program is ill-formed +if \tcode{is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{true}. + \begin{codeblock} namespace std { template<> struct atomic_ref<@\placeholder{integral-type}@> { @@ -3576,61 +3624,62 @@ @\placeholder{integral-type}@* ptr; // \expos public: - using value_type = @\placeholder{integral-type}@; + using value_type = remove_cv_t<@\placeholder{integral-type}@>; using difference_type = value_type; static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; bool is_lock_free() const noexcept; - explicit atomic_ref(@\placeholder{integral-type}@&); - atomic_ref(const atomic_ref&) noexcept; + constexpr explicit atomic_ref(@\placeholder{integral-type}@&); + constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; - void store(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ operator=(@\placeholder{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ load(memory_order = memory_order::seq_cst) const noexcept; - operator @\placeholdernc{integral-type}@() const noexcept; - - @\placeholdernc{integral-type}@ exchange(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; + constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type operator=(value_type) const noexcept; + constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; + constexpr operator value_type() const noexcept; - @\placeholdernc{integral-type}@ fetch_add(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_sub(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_and(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_or(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_max(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_min(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - - @\placeholdernc{integral-type}@ operator++(int) const noexcept; - @\placeholdernc{integral-type}@ operator--(int) const noexcept; - @\placeholdernc{integral-type}@ operator++() const noexcept; - @\placeholdernc{integral-type}@ operator--() const noexcept; - @\placeholdernc{integral-type}@ operator+=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator-=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator&=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator|=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator^=(@\placeholdernc{integral-type}@) const noexcept; - - void wait(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; + constexpr value_type exchange(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr value_type fetch_add(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_sub(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_and(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_or(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_xor(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_max(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_min(value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr value_type operator++(int) const noexcept; + constexpr value_type operator--(int) const noexcept; + constexpr value_type operator++() const noexcept; + constexpr value_type operator--() const noexcept; + constexpr value_type operator+=(value_type) const noexcept; + constexpr value_type operator-=(value_type) const noexcept; + constexpr value_type operator&=(value_type) const noexcept; + constexpr value_type operator|=(value_type) const noexcept; + constexpr value_type operator^=(value_type) const noexcept; + + constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr void notify_one() const noexcept; + constexpr void notify_all() const noexcept; + constexpr @\placeholder{integral-type}@* address() const noexcept; }; } \end{codeblock} @@ -3652,11 +3701,15 @@ \indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{fetch_xor}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -@\placeholdernc{integral-type}@ fetch_@\placeholdernc{key}@(@\placeholdernc{integral-type}@ operand, +constexpr value_type fetch_@\placeholdernc{key}@(value_type operand, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{integral-type}>} is \tcode{false}. + \pnum \effects Atomically replaces the value referenced by \tcode{*ptr} with @@ -3695,10 +3748,14 @@ \indexlibrarymember{operator"|=}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{operator\caret=}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -@\placeholdernc{integral-type}@ operator @\placeholder{op}@=(@\placeholdernc{integral-type}@ operand) const noexcept; +constexpr value_type operator @\placeholder{op}@=(value_type operand) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{integral-type}>} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3710,11 +3767,16 @@ \pnum \indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point-type}>}}% There are specializations of the \tcode{atomic_ref} class template -for all cv-unqualified floating-point types. +for all floating-point types. For each such type \tcode{\placeholder{floating-point-type}}, the specialization \tcode{atomic_ref<\placeholder{floating-\-point}>} provides additional atomic operations appropriate to floating-point types. +\pnum +The program is ill-formed +if \tcode{is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{true}. + \begin{codeblock} namespace std { template<> struct atomic_ref<@\placeholder{floating-point-type}@> { @@ -3722,44 +3784,47 @@ @\placeholder{floating-point-type}@* ptr; // \expos public: - using value_type = @\placeholder{floating-point-type}@; + using value_type = remove_cv_t<@\placeholder{floating-point-type}@>; using difference_type = value_type; static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; bool is_lock_free() const noexcept; - explicit atomic_ref(@\placeholder{floating-point-type}@&); - atomic_ref(const atomic_ref&) noexcept; + constexpr explicit atomic_ref(@\placeholder{floating-point-type}@&); + constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; - void store(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point-type}@ operator=(@\placeholder{floating-point-type}@) const noexcept; - @\placeholder{floating-point-type}@ load(memory_order = memory_order::seq_cst) const noexcept; - operator @\placeholdernc{floating-point-type}@() const noexcept; + constexpr void store(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type operator=(value_type) const noexcept; + constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; + constexpr operator @\placeholdernc{floating-point-type}@() const noexcept; - @\placeholder{floating-point-type}@ exchange(@\placeholdernc{floating-point-type}@, + constexpr value_type exchange(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_weak(value_type&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) const noexcept; - bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_strong(value_type&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) const noexcept; - bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_weak(value_type&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_strong(value_type&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point-type}@ fetch_add(@\placeholdernc{floating-point-type}@, + constexpr value_type fetch_add(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point-type}@ fetch_sub(@\placeholdernc{floating-point-type}@, + constexpr value_type fetch_sub(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point-type}@ operator+=(@\placeholder{floating-point-type}@) const noexcept; - @\placeholder{floating-point-type}@ operator-=(@\placeholder{floating-point-type}@) const noexcept; + constexpr value_type operator+=(value_type) const noexcept; + constexpr value_type operator-=(value_type) const noexcept; - void wait(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; + constexpr void wait(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void notify_one() const noexcept; + constexpr void notify_all() const noexcept; + constexpr @\placeholder{floating-point-type}@* address() const noexcept; }; } \end{codeblock} @@ -3776,11 +3841,15 @@ \indexlibrarymember{fetch_add}{atomic_ref<\placeholder{floating-point-type}>}% \indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -@\placeholder{floating-point-type}@ fetch_@\placeholdernc{key}@(@\placeholder{floating-point-type}@ operand, +constexpr value_type fetch_@\placeholdernc{key}@(value_type operand, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\exposid{floating-point-type}>} is \tcode{false}. + \pnum \effects Atomically replaces the value referenced by \tcode{*ptr} with @@ -3800,20 +3869,24 @@ the result is unspecified, but the operations otherwise have no undefined behavior. Atomic arithmetic operations on \tcode{\placeholder{floating-point-type}} should conform to -the \tcode{std::numeric_limits<\placeholder{floating-point-type}>} traits +the \tcode{std::numeric_limits} traits associated with the floating-point type\iref{limits.syn}. The floating-point environment\iref{cfenv} -for atomic arithmetic operations on \tcode{\placeholder{floating-point-type}} +for atomic arithmetic operations on \tcode{\placeholder{floating-\newline point-type}} may be different than the calling thread's floating-point environment. \end{itemdescr} \indexlibrarymember{operator+=}{atomic_ref<\placeholder{floating-point-type}>}% \indexlibrarymember{operator-=}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -@\placeholder{floating-point-type}@ operator @\placeholder{op}@=(@\placeholder{floating-point-type}@ operand) const noexcept; +constexpr value_type operator @\placeholder{op}@=(value_type operand) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\exposid{floating-point-type}>} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3823,54 +3896,72 @@ \rSec3[atomics.ref.pointer]{Partial specialization for pointers} \indexlibraryglobal{atomic_ref}% +\pnum +There are specializations of the \tcode{atomic_ref} class template +for all pointer-to-object types. +For each such type \placeholder{pointer-type}, +the specialization \tcode{atomic_ref<\placeholder{pointer-type}>} provides +additional atomic operations appropriate to pointer types. + +\pnum +The program is ill-formed +if \tcode{is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{true}. + \begin{codeblock} namespace std { - template struct atomic_ref { + template struct atomic_ref<@\placeholder{pointer-type}@> { private: - T** ptr; // \expos + @\placeholder{pointer-type}@* ptr; // \expos public: - using value_type = T*; + using value_type = remove_cv_t<@\placeholder{pointer-type}@>; using difference_type = ptrdiff_t; static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; bool is_lock_free() const noexcept; - explicit atomic_ref(T*&); - atomic_ref(const atomic_ref&) noexcept; + constexpr explicit atomic_ref(@\placeholder{pointer-type}@&); + constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; - void store(T*, memory_order = memory_order::seq_cst) const noexcept; - T* operator=(T*) const noexcept; - T* load(memory_order = memory_order::seq_cst) const noexcept; - operator T*() const noexcept; - - T* exchange(T*, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(T*&, T*, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(T*&, T*, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(T*&, T*, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(T*&, T*, - memory_order = memory_order::seq_cst) const noexcept; + constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type operator=(value_type) const noexcept; + constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; + constexpr operator value_type() const noexcept; - T* fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept; - T* fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept; - T* fetch_max(T*, memory_order = memory_order::seq_cst) const noexcept; - T* fetch_min(T*, memory_order = memory_order::seq_cst) const noexcept; - - T* operator++(int) const noexcept; - T* operator--(int) const noexcept; - T* operator++() const noexcept; - T* operator--() const noexcept; - T* operator+=(difference_type) const noexcept; - T* operator-=(difference_type) const noexcept; - - void wait(T*, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; + constexpr value_type exchange(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr value_type fetch_add(difference_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_sub(difference_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_max(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_min(value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr value_type operator++(int) const noexcept; + constexpr value_type operator--(int) const noexcept; + constexpr value_type operator++() const noexcept; + constexpr value_type operator--() const noexcept; + constexpr value_type operator+=(difference_type) const noexcept; + constexpr value_type operator-=(difference_type) const noexcept; + + constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr void notify_one() const noexcept; + constexpr void notify_all() const noexcept; + constexpr @\placeholder{pointer-type}@* address() const noexcept; }; } \end{codeblock} @@ -3889,13 +3980,18 @@ \indexlibrarymember{fetch_max}{atomic_ref}% \indexlibrarymember{fetch_min}{atomic_ref}% \begin{itemdecl} -T* fetch_@\placeholdernc{key}@(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept; +constexpr value_type fetch_@\placeholdernc{key}@(difference_type operand, + memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{pointer-type}>} is \tcode{false}. + \pnum \mandates -\tcode{T} is a complete object type. +\tcode{remove_pointer_t<\placeholder{pointer-type}>} is a complete object type. \pnum \effects @@ -3928,15 +4024,17 @@ \end{note} \end{itemdescr} - - \indexlibrarymember{operator+=}{atomic_ref}% \indexlibrarymember{operator-=}{atomic_ref}% \begin{itemdecl} -T* operator @\placeholder{op}@=(difference_type operand) const noexcept; +constexpr value_type operator @\placeholder{op}@=(difference_type operand) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{pointer-type}>} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3946,13 +4044,25 @@ \rSec3[atomics.ref.memop]{Member operators common to integers and pointers to objects} +\pnum +Let \placeholder{referred-type} +be \placeholder{pointer-type} +for the specializations in \ref{atomics.ref.pointer} and +be \placeholder{integral-type} +for the specializations in \ref{atomics.ref.int}. + + \indexlibrarymember{operator++}{atomic_ref}% \indexlibrarymember{operator++}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -value_type operator++(int) const noexcept; +constexpr value_type operator++(int) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_add(1);} @@ -3961,10 +4071,14 @@ \indexlibrarymember{operator--}{atomic_ref}% \indexlibrarymember{operator--}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -value_type operator--(int) const noexcept; +constexpr value_type operator--(int) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_sub(1);} @@ -3973,10 +4087,14 @@ \indexlibrarymember{operator++}{atomic_ref}% \indexlibrarymember{operator++}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -value_type operator++() const noexcept; +constexpr value_type operator++() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_add(1) + 1;} @@ -3985,10 +4103,14 @@ \indexlibrarymember{operator--}{atomic_ref}% \indexlibrarymember{operator--}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -value_type operator--() const noexcept; +constexpr value_type operator--() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_sub(1) - 1;} @@ -4017,31 +4139,31 @@ atomic& operator=(const atomic&) volatile = delete; T load(memory_order = memory_order::seq_cst) const volatile noexcept; - T load(memory_order = memory_order::seq_cst) const noexcept; + constexpr T load(memory_order = memory_order::seq_cst) const noexcept; operator T() const volatile noexcept; - operator T() const noexcept; + constexpr operator T() const noexcept; void store(T, memory_order = memory_order::seq_cst) volatile noexcept; - void store(T, memory_order = memory_order::seq_cst) noexcept; + constexpr void store(T, memory_order = memory_order::seq_cst) noexcept; T operator=(T) volatile noexcept; - T operator=(T) noexcept; + constexpr T operator=(T) noexcept; T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept; - T exchange(T, memory_order = memory_order::seq_cst) noexcept; + constexpr T exchange(T, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept; + constexpr bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept; bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept; + constexpr bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept; bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept; + constexpr bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept; + constexpr bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept; void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(T, memory_order = memory_order::seq_cst) const noexcept; + constexpr void wait(T, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; - void notify_one() noexcept; + constexpr void notify_one() noexcept; void notify_all() volatile noexcept; - void notify_all() noexcept; + constexpr void notify_all() noexcept; }; } \end{codeblock} @@ -4055,8 +4177,9 @@ \item \tcode{is_trivially_copyable_v}, \item \tcode{is_copy_constructible_v}, \item \tcode{is_move_constructible_v}, -\item \tcode{is_copy_assignable_v}, or -\item \tcode{is_move_assignable_v} +\item \tcode{is_copy_assignable_v}, +\item \tcode{is_move_assignable_v}, or +\item \tcode{same_as>}, \end{itemize} is \tcode{false}. \begin{note} @@ -4087,7 +4210,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints \tcode{is_default_constructible_v} is \tcode{true}. \pnum @@ -4169,7 +4292,7 @@ \indexlibrarymember{store}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; -void store(T desired, memory_order order = memory_order::seq_cst) noexcept; +constexpr void store(T desired, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4198,7 +4321,7 @@ \indexlibrarymember{operator=}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} T operator=(T desired) volatile noexcept; -T operator=(T desired) noexcept; +constexpr T operator=(T desired) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4224,7 +4347,7 @@ \indexlibrarymember{load}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} T load(memory_order order = memory_order::seq_cst) const volatile noexcept; -T load(memory_order order = memory_order::seq_cst) const noexcept; +constexpr T load(memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4256,7 +4379,7 @@ \indexlibrarymember{operator \placeholder{floating-point-type}}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} operator T() const volatile noexcept; -operator T() const noexcept; +constexpr operator T() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4279,7 +4402,7 @@ \indexlibrarymember{exchange}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; -T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept; +constexpr T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4315,19 +4438,19 @@ \begin{itemdecl} bool compare_exchange_weak(T& expected, T desired, memory_order success, memory_order failure) volatile noexcept; -bool compare_exchange_weak(T& expected, T desired, +constexpr bool compare_exchange_weak(T& expected, T desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_strong(T& expected, T desired, memory_order success, memory_order failure) volatile noexcept; -bool compare_exchange_strong(T& expected, T desired, +constexpr bool compare_exchange_strong(T& expected, T desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_weak(T& expected, T desired, memory_order order = memory_order::seq_cst) volatile noexcept; -bool compare_exchange_weak(T& expected, T desired, +constexpr bool compare_exchange_weak(T& expected, T desired, memory_order order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order::seq_cst) volatile noexcept; -bool compare_exchange_strong(T& expected, T desired, +constexpr bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} @@ -4488,7 +4611,7 @@ \indexlibrarymember{wait}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept; -void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; +constexpr void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4525,7 +4648,7 @@ \indexlibrarymember{notify_one}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} void notify_one() volatile noexcept; -void notify_one() noexcept; +constexpr void notify_one() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4546,7 +4669,7 @@ \indexlibrarymember{notify_all}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} void notify_all() volatile noexcept; -void notify_all() noexcept; +constexpr void notify_all() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4606,89 +4729,89 @@ atomic& operator=(const atomic&) volatile = delete; void store(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - void store(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; + constexpr void store(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ operator=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator=(@\placeholdernc{integral-type}@) noexcept; @\placeholdernc{integral-type}@ load(memory_order = memory_order::seq_cst) const volatile noexcept; - @\placeholdernc{integral-type}@ load(memory_order = memory_order::seq_cst) const noexcept; + constexpr @\placeholdernc{integral-type}@ load(memory_order = memory_order::seq_cst) const noexcept; operator @\placeholdernc{integral-type}@() const volatile noexcept; - operator @\placeholdernc{integral-type}@() const noexcept; + constexpr operator @\placeholdernc{integral-type}@() const noexcept; @\placeholdernc{integral-type}@ exchange(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ exchange(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ exchange(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, + constexpr bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order, memory_order) noexcept; bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, + constexpr bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order, memory_order) noexcept; bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, + constexpr bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, + constexpr bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_add(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_add(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_add(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_sub(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_sub(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_sub(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_and(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_and(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_and(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_or(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_or(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_or(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_max( @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_max( @\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_max( @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_min( @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_min( @\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_min( @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ operator++(int) volatile noexcept; - @\placeholdernc{integral-type}@ operator++(int) noexcept; + constexpr @\placeholdernc{integral-type}@ operator++(int) noexcept; @\placeholdernc{integral-type}@ operator--(int) volatile noexcept; - @\placeholdernc{integral-type}@ operator--(int) noexcept; + constexpr @\placeholdernc{integral-type}@ operator--(int) noexcept; @\placeholdernc{integral-type}@ operator++() volatile noexcept; - @\placeholdernc{integral-type}@ operator++() noexcept; + constexpr @\placeholdernc{integral-type}@ operator++() noexcept; @\placeholdernc{integral-type}@ operator--() volatile noexcept; - @\placeholdernc{integral-type}@ operator--() noexcept; + constexpr @\placeholdernc{integral-type}@ operator--() noexcept; @\placeholdernc{integral-type}@ operator+=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator+=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator+=(@\placeholdernc{integral-type}@) noexcept; @\placeholdernc{integral-type}@ operator-=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator-=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator-=(@\placeholdernc{integral-type}@) noexcept; @\placeholdernc{integral-type}@ operator&=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator&=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator&=(@\placeholdernc{integral-type}@) noexcept; @\placeholdernc{integral-type}@ operator|=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator|=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator|=(@\placeholdernc{integral-type}@) noexcept; @\placeholdernc{integral-type}@ operator^=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator^=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator^=(@\placeholdernc{integral-type}@) noexcept; void wait(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const noexcept; + constexpr void wait(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; - void notify_one() noexcept; + constexpr void notify_one() noexcept; void notify_all() volatile noexcept; - void notify_all() noexcept; + constexpr void notify_all() noexcept; }; } \end{codeblock} @@ -4762,7 +4885,7 @@ \indexlibrarymember{fetch_xor}{atomic<\placeholder{integral-type}>}% \begin{itemdecl} T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; -T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; +constexpr T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4811,7 +4934,7 @@ \indexlibrarymember{operator\caret=}{atomic<\placeholder{integral-type}>}% \begin{itemdecl} T operator @\placeholder{op}@=(T operand) volatile noexcept; -T operator @\placeholder{op}@=(T operand) noexcept; +constexpr T operator @\placeholder{op}@=(T operand) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4852,55 +4975,56 @@ atomic& operator=(const atomic&) volatile = delete; void store(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - void store(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; + constexpr void store(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{floating-point-type}@ operator=(@\placeholder{floating-point-type}@) volatile noexcept; - @\placeholdernc{floating-point-type}@ operator=(@\placeholder{floating-point-type}@) noexcept; + constexpr @\placeholdernc{floating-point-type}@ operator=(@\placeholder{floating-point-type}@) noexcept; @\placeholdernc{floating-point-type}@ load(memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point-type}@ load(memory_order = memory_order::seq_cst) noexcept; + constexpr @\placeholdernc{floating-point-type}@ load(memory_order = memory_order::seq_cst) noexcept; operator @\placeholdernc{floating-point-type}@() volatile noexcept; - operator @\placeholdernc{floating-point-type}@() noexcept; + constexpr operator @\placeholdernc{floating-point-type}@() noexcept; @\placeholdernc{floating-point-type}@ exchange(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point-type}@ exchange(@\placeholdernc{floating-point-type}@, + constexpr @\placeholdernc{floating-point-type}@ exchange(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) noexcept; bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) noexcept; bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{floating-point-type}@ fetch_add(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point-type}@ fetch_add(@\placeholdernc{floating-point-type}@, + constexpr @\placeholdernc{floating-point-type}@ fetch_add(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{floating-point-type}@ fetch_sub(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point-type}@ fetch_sub(@\placeholdernc{floating-point-type}@, + constexpr @\placeholdernc{floating-point-type}@ fetch_sub(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{floating-point-type}@ operator+=(@\placeholder{floating-point-type}@) volatile noexcept; - @\placeholdernc{floating-point-type}@ operator+=(@\placeholder{floating-point-type}@) noexcept; + constexpr @\placeholdernc{floating-point-type}@ operator+=(@\placeholder{floating-point-type}@) noexcept; @\placeholdernc{floating-point-type}@ operator-=(@\placeholder{floating-point-type}@) volatile noexcept; - @\placeholdernc{floating-point-type}@ operator-=(@\placeholder{floating-point-type}@) noexcept; + constexpr @\placeholdernc{floating-point-type}@ operator-=(@\placeholder{floating-point-type}@) noexcept; void wait(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; + constexpr void wait(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; - void notify_one() noexcept; + constexpr void notify_one() noexcept; void notify_all() volatile noexcept; - void notify_all() noexcept; + constexpr void notify_all() noexcept; }; } \end{codeblock} @@ -4927,7 +5051,7 @@ \indexlibrarymember{fetch_sub}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; -T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; +constexpr T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4966,7 +5090,7 @@ \indexlibrarymember{operator-=}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} T operator @\placeholder{op}@=(T operand) volatile noexcept; -T operator @\placeholder{op}@=(T operand) noexcept; +constexpr T operator @\placeholder{op}@=(T operand) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5011,57 +5135,57 @@ atomic& operator=(const atomic&) volatile = delete; void store(T*, memory_order = memory_order::seq_cst) volatile noexcept; - void store(T*, memory_order = memory_order::seq_cst) noexcept; + constexpr void store(T*, memory_order = memory_order::seq_cst) noexcept; T* operator=(T*) volatile noexcept; - T* operator=(T*) noexcept; + constexpr T* operator=(T*) noexcept; T* load(memory_order = memory_order::seq_cst) const volatile noexcept; - T* load(memory_order = memory_order::seq_cst) const noexcept; + constexpr T* load(memory_order = memory_order::seq_cst) const noexcept; operator T*() const volatile noexcept; - operator T*() const noexcept; + constexpr operator T*() const noexcept; T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept; - T* exchange(T*, memory_order = memory_order::seq_cst) noexcept; + constexpr T* exchange(T*, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept; + constexpr bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept; bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept; + constexpr bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept; bool compare_exchange_weak(T*&, T*, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(T*&, T*, + constexpr bool compare_exchange_weak(T*&, T*, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T*&, T*, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(T*&, T*, + constexpr bool compare_exchange_strong(T*&, T*, memory_order = memory_order::seq_cst) noexcept; T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; - T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; + constexpr T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; - T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; + constexpr T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; T* fetch_max(T*, memory_order = memory_order::seq_cst) volatile noexcept; - T* fetch_max(T*, memory_order = memory_order::seq_cst) noexcept; + constexpr T* fetch_max(T*, memory_order = memory_order::seq_cst) noexcept; T* fetch_min(T*, memory_order = memory_order::seq_cst) volatile noexcept; - T* fetch_min(T*, memory_order = memory_order::seq_cst) noexcept; + constexpr T* fetch_min(T*, memory_order = memory_order::seq_cst) noexcept; T* operator++(int) volatile noexcept; - T* operator++(int) noexcept; + constexpr T* operator++(int) noexcept; T* operator--(int) volatile noexcept; - T* operator--(int) noexcept; + constexpr T* operator--(int) noexcept; T* operator++() volatile noexcept; - T* operator++() noexcept; + constexpr T* operator++() noexcept; T* operator--() volatile noexcept; - T* operator--() noexcept; + constexpr T* operator--() noexcept; T* operator+=(ptrdiff_t) volatile noexcept; - T* operator+=(ptrdiff_t) noexcept; + constexpr T* operator+=(ptrdiff_t) noexcept; T* operator-=(ptrdiff_t) volatile noexcept; - T* operator-=(ptrdiff_t) noexcept; + constexpr T* operator-=(ptrdiff_t) noexcept; void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(T*, memory_order = memory_order::seq_cst) const noexcept; + constexpr void wait(T*, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; - void notify_one() noexcept; + constexpr void notify_one() noexcept; void notify_all() volatile noexcept; - void notify_all() noexcept; + constexpr void notify_all() noexcept; }; } \end{codeblock} @@ -5117,7 +5241,7 @@ \indexlibrarymember{fetch_sub}{atomic}% \begin{itemdecl} T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept; -T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept; +constexpr T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5167,7 +5291,7 @@ \indexlibrarymember{operator-=}{atomic}% \begin{itemdecl} T* operator @\placeholder{op}@=(ptrdiff_t operand) volatile noexcept; -T* operator @\placeholder{op}@=(ptrdiff_t operand) noexcept; +constexpr T* operator @\placeholder{op}@=(ptrdiff_t operand) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5187,7 +5311,7 @@ \indexlibrarymember{operator++}{atomic<\placeholder{integral-type}>}% \begin{itemdecl} value_type operator++(int) volatile noexcept; -value_type operator++(int) noexcept; +constexpr value_type operator++(int) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5205,7 +5329,7 @@ \indexlibrarymember{operator--}{atomic<\placeholder{integral-type}>}% \begin{itemdecl} value_type operator--(int) volatile noexcept; -value_type operator--(int) noexcept; +constexpr value_type operator--(int) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5223,7 +5347,7 @@ \indexlibrarymember{operator++}{atomic<\placeholder{integral-type}>}% \begin{itemdecl} value_type operator++() volatile noexcept; -value_type operator++() noexcept; +constexpr value_type operator++() noexcept; \end{itemdecl} \begin{itemdescr} @@ -5241,7 +5365,7 @@ \indexlibrarymember{operator--}{atomic<\placeholder{integral-type}>}% \begin{itemdecl} value_type operator--() volatile noexcept; -value_type operator--() noexcept; +constexpr value_type operator--() noexcept; \end{itemdecl} \begin{itemdescr} @@ -5994,18 +6118,18 @@ atomic_flag& operator=(const atomic_flag&) volatile = delete; bool test(memory_order = memory_order::seq_cst) const volatile noexcept; - bool test(memory_order = memory_order::seq_cst) const noexcept; + constexpr bool test(memory_order = memory_order::seq_cst) const noexcept; bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept; - bool test_and_set(memory_order = memory_order::seq_cst) noexcept; + constexpr bool test_and_set(memory_order = memory_order::seq_cst) noexcept; void clear(memory_order = memory_order::seq_cst) volatile noexcept; - void clear(memory_order = memory_order::seq_cst) noexcept; + constexpr void clear(memory_order = memory_order::seq_cst) noexcept; void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(bool, memory_order = memory_order::seq_cst) const noexcept; + constexpr void wait(bool, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; - void notify_one() noexcept; + constexpr void notify_one() noexcept; void notify_all() volatile noexcept; - void notify_all() noexcept; + constexpr void notify_all() noexcept; }; } \end{codeblock} @@ -6037,13 +6161,13 @@ \indexlibrarymember{test}{atomic_flag}% \begin{itemdecl} bool atomic_flag_test(const volatile atomic_flag* object) noexcept; -bool atomic_flag_test(const atomic_flag* object) noexcept; +constexpr bool atomic_flag_test(const atomic_flag* object) noexcept; bool atomic_flag_test_explicit(const volatile atomic_flag* object, memory_order order) noexcept; -bool atomic_flag_test_explicit(const atomic_flag* object, +constexpr bool atomic_flag_test_explicit(const atomic_flag* object, memory_order order) noexcept; bool atomic_flag::test(memory_order order = memory_order::seq_cst) const volatile noexcept; -bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept; +constexpr bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -6072,11 +6196,11 @@ \indexlibrarymember{test_and_set}{atomic_flag}% \begin{itemdecl} bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept; -bool atomic_flag_test_and_set(atomic_flag* object) noexcept; +constexpr bool atomic_flag_test_and_set(atomic_flag* object) noexcept; bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept; -bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept; +constexpr bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept; bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept; -bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept; +constexpr bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -6095,11 +6219,11 @@ \indexlibrarymember{clear}{atomic_flag}% \begin{itemdecl} void atomic_flag_clear(volatile atomic_flag* object) noexcept; -void atomic_flag_clear(atomic_flag* object) noexcept; +constexpr void atomic_flag_clear(atomic_flag* object) noexcept; void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept; -void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept; +constexpr void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept; void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept; -void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept; +constexpr void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -6121,14 +6245,14 @@ \indexlibrarymember{wait}{atomic_flag}% \begin{itemdecl} void atomic_flag_wait(const volatile atomic_flag* object, bool old) noexcept; -void atomic_flag_wait(const atomic_flag* object, bool old) noexcept; +constexpr void atomic_flag_wait(const atomic_flag* object, bool old) noexcept; void atomic_flag_wait_explicit(const volatile atomic_flag* object, bool old, memory_order order) noexcept; -void atomic_flag_wait_explicit(const atomic_flag* object, +constexpr void atomic_flag_wait_explicit(const atomic_flag* object, bool old, memory_order order) noexcept; void atomic_flag::wait(bool old, memory_order order = memory_order::seq_cst) const volatile noexcept; -void atomic_flag::wait(bool old, memory_order order = +constexpr void atomic_flag::wait(bool old, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} @@ -6167,9 +6291,9 @@ \begin{itemdecl} void atomic_flag_notify_one(volatile atomic_flag* object) noexcept; -void atomic_flag_notify_one(atomic_flag* object) noexcept; +constexpr void atomic_flag_notify_one(atomic_flag* object) noexcept; void atomic_flag::notify_one() volatile noexcept; -void atomic_flag::notify_one() noexcept; +constexpr void atomic_flag::notify_one() noexcept; \end{itemdecl} \begin{itemdescr} @@ -6186,9 +6310,9 @@ \begin{itemdecl} void atomic_flag_notify_all(volatile atomic_flag* object) noexcept; -void atomic_flag_notify_all(atomic_flag* object) noexcept; +constexpr void atomic_flag_notify_all(atomic_flag* object) noexcept; void atomic_flag::notify_all() volatile noexcept; -void atomic_flag::notify_all() noexcept; +constexpr void atomic_flag::notify_all() noexcept; \end{itemdecl} \begin{itemdescr} @@ -6255,7 +6379,7 @@ \indexlibraryglobal{atomic_thread_fence}% \begin{itemdecl} -extern "C" void atomic_thread_fence(memory_order order) noexcept; +extern "C" constexpr void atomic_thread_fence(memory_order order) noexcept; \end{itemdecl} \begin{itemdescr} @@ -6277,7 +6401,7 @@ \indexlibraryglobal{atomic_signal_fence}% \begin{itemdecl} -extern "C" void atomic_signal_fence(memory_order order) noexcept; +extern "C" constexpr void atomic_signal_fence(memory_order order) noexcept; \end{itemdecl} \begin{itemdescr} @@ -7588,7 +7712,7 @@ // \ref{thread.lock.unique.obs}, observers bool owns_lock() const noexcept; - explicit operator bool () const noexcept; + explicit operator bool() const noexcept; mutex_type* mutex() const noexcept; private: @@ -8079,7 +8203,7 @@ // \ref{thread.lock.shared.obs}, observers bool owns_lock() const noexcept; - explicit operator bool () const noexcept; + explicit operator bool() const noexcept; mutex_type* mutex() const noexcept; private: @@ -8726,7 +8850,6 @@ \rSec2[condition.variable.syn]{Header \tcode{} synopsis} \indexheader{condition_variable}% -\indexlibraryglobal{cv_status}% \begin{codeblock} namespace std { // \ref{thread.condition.condvar}, class \tcode{condition_variable} @@ -8737,7 +8860,7 @@ // \ref{thread.condition.nonmember}, non-member functions void notify_all_at_thread_exit(condition_variable& cond, unique_lock lk); - enum class cv_status { no_timeout, timeout }; + enum class @\libglobal{cv_status}@ { @\libmember{no_timeout}{cv_status}@, @\libmember{timeout}{cv_status}@ }; } \end{codeblock} @@ -10349,26 +10472,25 @@ \rSec2[future.syn]{Header \tcode{} synopsis} \indexheader{future}% -\indexlibraryglobal{future_errc}% \begin{codeblock} namespace std { - enum class future_errc { - broken_promise = @\impdefx{value of \tcode{future_errc::broken_promise}}@, - future_already_retrieved = @\impdefx{value of \tcode{future_errc::future_already_retrieved}}@, - promise_already_satisfied = @\impdefx{value of \tcode{future_errc::promise_already_satisfied}}@, - no_state = @\impdefx{value of \tcode{future_errc::no_state}}@ + enum class @\libglobal{future_errc}@ { + @\libmember{broken_promise}{future_errc}@ = @\impdefx{value of \tcode{future_errc::broken_promise}}@, + @\libmember{future_already_retrieved}{future_errc}@ = @\impdefx{value of \tcode{future_errc::future_already_retrieved}}@, + @\libmember{promise_already_satisfied}{future_errc}@ = @\impdefx{value of \tcode{future_errc::promise_already_satisfied}}@, + @\libmember{no_state}{future_errc}@ = @\impdefx{value of \tcode{future_errc::no_state}}@ }; - enum class launch : @\unspec{}@ { - async = @\unspec{}@, - deferred = @\unspec{}@, + enum class @\libglobal{launch}@ : @\unspec{}@ { + @\libmember{async}{launch}@ = @\unspec{}@, + @\libmember{deferred}{launch}@ = @\unspec{}@, @\impdefx{last enumerator of \tcode{launch}}@ }; - enum class future_status { - ready, - timeout, - deferred + enum class @\libglobal{future_status}@ { + @\libmember{ready}{future_status}@, + @\libmember{timeout}{future_status}@, + @\libmember{deferred}{future_status}@ }; // \ref{futures.errors}, error handling @@ -11863,16 +11985,13 @@ \pnum \mandates -\tcode{is_invocable_r_v} is \tcode{true}. - -\pnum -\expects -Invoking a copy of \tcode{f} behaves the same as invoking \tcode{f}. +\tcode{is_invocable_r_v\&, ArgTypes...>} is \tcode{true}. \pnum \effects -Constructs a new \tcode{packaged_task} object with a shared state and -initializes the object's stored task with \tcode{std::forward(f)}. +Constructs a new \tcode{packaged_task} object with +a stored task of type \tcode{decay_t} and a shared state. +Initializes the object's stored task with \tcode{std::forward(f)}. \pnum \throws diff --git a/source/time.tex b/source/time.tex index dfa1601013..f74e3a87fd 100644 --- a/source/time.tex +++ b/source/time.tex @@ -10994,6 +10994,9 @@ \pnum \remarks +If the \fmtgrammarterm{chrono-specs} is omitted, +the result is equivalent to using \tcode{\%F \%T \%Z} as +the \fmtgrammarterm{chrono-specs}. If \tcode{\%Z} is used, it is replaced with \tcode{*f.abbrev} if \tcode{f.abbrev} is not a null pointer value. @@ -11012,7 +11015,7 @@ \begin{codeblock} template struct formatter, charT> - : formatter, charT> { + : formatter>, charT> { template typename FormatContext::iterator format(const chrono::zoned_time& tp, FormatContext& ctx) const; @@ -11032,7 +11035,7 @@ Equivalent to: \begin{codeblock} sys_info info = tp.get_info(); -return formatter, charT>:: +return formatter>, charT>:: format({tp.get_local_time(), &info.abbrev, &info.offset}, ctx); \end{codeblock} \end{itemdescr} diff --git a/source/utilities.tex b/source/utilities.tex index 2f66d7d65f..ad5fe79cd4 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -3269,7 +3269,7 @@ constexpr explicit optional(in_place_t, Args&&...); template constexpr explicit optional(in_place_t, initializer_list, Args&&...); - template + template> constexpr explicit(@\seebelow@) optional(U&&); template constexpr explicit(@\seebelow@) optional(const optional&); @@ -3283,7 +3283,7 @@ constexpr optional& operator=(nullopt_t) noexcept; constexpr optional& operator=(const optional&); constexpr optional& operator=(optional&&) noexcept(@\seebelow@); - template constexpr optional& operator=(U&&); + template> constexpr optional& operator=(U&&); template constexpr optional& operator=(const optional&); template constexpr optional& operator=(optional&&); template constexpr T& emplace(Args&&...); @@ -3311,8 +3311,8 @@ constexpr T& value() &; // freestanding-deleted constexpr T&& value() &&; // freestanding-deleted constexpr const T&& value() const &&; // freestanding-deleted - template constexpr T value_or(U&&) const &; - template constexpr T value_or(U&&) &&; + template> constexpr T value_or(U&&) const &; + template> constexpr T value_or(U&&) &&; // \ref{optional.monadic}, monadic operations template constexpr auto and_then(F&& f) &; @@ -3342,8 +3342,7 @@ Any instance of \tcode{optional} at any given time either contains a value or does not contain a value. When an instance of \tcode{optional} \defnx{contains a value}{contains a value!\idxcode{optional}}, it means that an object of type \tcode{T}, referred to as the optional object's \defnx{contained value}{contained value!\idxcode{optional}}, -is allocated within the storage of the optional object. -Implementations are not permitted to use additional storage, such as dynamic memory, to allocate its contained value. +is nested within\iref{intro.object} the optional object. When an object of type \tcode{optional} is contextually converted to \tcode{bool}, the conversion returns \tcode{true} if the object contains a value; otherwise the conversion returns \tcode{false}. @@ -3504,7 +3503,7 @@ \indexlibraryctor{optional}% \begin{itemdecl} -template constexpr explicit(@\seebelow@) optional(U&& v); +template> constexpr explicit(@\seebelow@) optional(U&& v); \end{itemdecl} \begin{itemdescr} @@ -3756,7 +3755,7 @@ \indexlibrarymember{operator=}{optional}% \begin{itemdecl} -template constexpr optional& operator=(U&& v); +template> constexpr optional& operator=(U&& v); \end{itemdecl} \begin{itemdescr} @@ -4193,7 +4192,7 @@ \indexlibrarymember{value_or}{optional}% \begin{itemdecl} -template constexpr T value_or(U&& v) const &; +template> constexpr T value_or(U&& v) const &; \end{itemdecl} \begin{itemdescr} @@ -4211,7 +4210,7 @@ \indexlibrarymember{value_or}{optional}% \begin{itemdecl} -template constexpr T value_or(U&& v) &&; +template> constexpr T value_or(U&& v) &&; \end{itemdecl} \begin{itemdescr} @@ -4659,6 +4658,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{U} is not a specialization of \tcode{optional}. The expression \tcode{*x == v} is well-formed and its result is convertible to \tcode{bool}. \begin{note} @@ -4678,6 +4678,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{T} is not a specialization of \tcode{optional}. The expression \tcode{v == *x} is well-formed and its result is convertible to \tcode{bool}. @@ -4694,6 +4695,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{U} is not a specialization of \tcode{optional}. The expression \tcode{*x != v} is well-formed and its result is convertible to \tcode{bool}. @@ -4710,6 +4712,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{T} is not a specialization of \tcode{optional}. The expression \tcode{v != *x} is well-formed and its result is convertible to \tcode{bool}. @@ -4726,6 +4729,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{U} is not a specialization of \tcode{optional}. The expression \tcode{*x < v} is well-formed and its result is convertible to \tcode{bool}. @@ -4742,6 +4746,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{T} is not a specialization of \tcode{optional}. The expression \tcode{v < *x} is well-formed and its result is convertible to \tcode{bool}. @@ -4758,6 +4763,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{U} is not a specialization of \tcode{optional}. The expression \tcode{*x > v} is well-formed and its result is convertible to \tcode{bool}. @@ -4774,6 +4780,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{T} is not a specialization of \tcode{optional}. The expression \tcode{v > *x} is well-formed and its result is convertible to \tcode{bool}. @@ -4790,6 +4797,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{U} is not a specialization of \tcode{optional}. The expression \tcode{*x <= v} is well-formed and its result is convertible to \tcode{bool}. @@ -4806,6 +4814,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{T} is not a specialization of \tcode{optional}. The expression \tcode{v <= *x} is well-formed and its result is convertible to \tcode{bool}. @@ -4822,6 +4831,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{U} is not a specialization of \tcode{optional}. The expression \tcode{*x >= v} is well-formed and its result is convertible to \tcode{bool}. @@ -4838,6 +4848,7 @@ \begin{itemdescr} \pnum \constraints +\tcode{T} is not a specialization of \tcode{optional}. The expression \tcode{v >= *x} is well-formed and its result is convertible to \tcode{bool}. @@ -5132,10 +5143,9 @@ of one of its alternative types or holds no value. When an instance of \tcode{variant} holds a value of alternative type \tcode{T}, it means that a value of type \tcode{T}, referred to as the \tcode{variant} -object's \defnx{contained value}{contained value!\idxcode{variant}}, is allocated within the storage of the +object's \defnx{contained value}{contained value!\idxcode{variant}}, +is nested within\iref{intro.object} the \tcode{variant} object. -Implementations are not permitted to use additional storage, such as dynamic -memory, to allocate the contained value. \pnum All types in \tcode{Types} shall meet @@ -7428,7 +7438,7 @@ template constexpr explicit(@\seebelow@) expected(expected&&); - template + template> constexpr explicit(@\seebelow@) expected(U&& v); template @@ -7451,7 +7461,7 @@ // \ref{expected.object.assign}, assignment constexpr expected& operator=(const expected&); constexpr expected& operator=(expected&&) noexcept(@\seebelow@); - template constexpr expected& operator=(U&&); + template> constexpr expected& operator=(U&&); template constexpr expected& operator=(const unexpected&); template @@ -7483,8 +7493,8 @@ constexpr E& error() & noexcept; constexpr const E&& error() const && noexcept; constexpr E&& error() && noexcept; - template constexpr T value_or(U&&) const &; - template constexpr T value_or(U&&) &&; + template> constexpr T value_or(U&&) const &; + template> constexpr T value_or(U&&) &&; template constexpr E error_or(G&&) const &; template constexpr E error_or(G&&) &&; @@ -7527,10 +7537,8 @@ \pnum Any object of type \tcode{expected} either contains a value of type \tcode{T} or -a value of type \tcode{E} within its own storage. -Implementations are not permitted to use additional storage, -such as dynamic memory, -to allocate the object of type \tcode{T} or the object of type \tcode{E}. +a value of type \tcode{E} +nested within\iref{intro.object} it. Member \exposid{has_val} indicates whether the \tcode{expected} object contains an object of type \tcode{T}. @@ -7735,7 +7743,7 @@ \indexlibraryctor{expected}% \begin{itemdecl} -template +template> constexpr explicit(!is_convertible_v) expected(U&& v); \end{itemdecl} @@ -8054,7 +8062,7 @@ \indexlibrarymember{operator=}{expected}% \begin{itemdecl} -template +template> constexpr expected& operator=(U&& v); \end{itemdecl} @@ -8422,7 +8430,7 @@ \indexlibrarymember{value_or}{expected}% \begin{itemdecl} -template constexpr T value_or(U&& v) const &; +template> constexpr T value_or(U&& v) const &; \end{itemdecl} \begin{itemdescr} @@ -8438,7 +8446,7 @@ \indexlibrarymember{value_or}{expected}% \begin{itemdecl} -template constexpr T value_or(U&& v) &&; +template> constexpr T value_or(U&& v) &&; \end{itemdecl} \begin{itemdescr} @@ -8767,7 +8775,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expressions \tcode{*x == *y} and \tcode{x.error() == y.error()} are well-formed and their results are convertible to \tcode{bool}. @@ -8785,7 +8793,8 @@ \begin{itemdescr} \pnum -\mandates +\constraints +\tcode{T2} is not a specialization of \tcode{expected}. The expression \tcode{*x == v} is well-formed and its result is convertible to \tcode{bool}. \begin{note} @@ -8804,7 +8813,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{x.error() == e.error()} is well-formed and its result is convertible to \tcode{bool}. @@ -8913,9 +8922,8 @@ \pnum Any object of type \tcode{expected} either represents a value of type \tcode{T}, or -contains a value of type \tcode{E} within its own storage. -Implementations are not permitted to use additional storage, -such as dynamic memory, to allocate the object of type \tcode{E}. +contains a value of type \tcode{E} +nested within\iref{intro.object} it. Member \exposid{has_val} indicates whether the \tcode{expected} object represents a value of type \tcode{T}. @@ -9726,7 +9734,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{x.error() == y.error()} is well-formed and its result is convertible to \tcode{bool}. @@ -9744,7 +9752,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{x.error() == e.error()} is well-formed and its result is convertible to \tcode{bool}. @@ -9796,8 +9804,6 @@ public: // bit reference class reference { - constexpr reference() noexcept; - public: constexpr reference(const reference&) = default; constexpr ~reference(); @@ -11219,7 +11225,7 @@ \pnum \returns -\tcode{\placeholdernc{INVOKE}(get(), std::forward(args)...)}.\iref{func.require} +\tcode{\placeholdernc{INVOKE}(get(), std::forward(args)...)}\iref{func.require}. \end{itemdescr} \rSec3[refwrap.comparisons]{Comparisons} @@ -13170,7 +13176,7 @@ \pnum \ensures \tcode{!*this} if \tcode{!f}; otherwise, -the target object of \tcode{*this} is a copy of \tcode{f.target()}. +the target object of \tcode{*this} is a copy of the target object of \tcode{f}. \pnum \throws @@ -15152,7 +15158,7 @@ \item Otherwise, if $b$ is indeterminate, the behavior is undefined. \item -Otherwise, the behaviour is erroneous, and the result is as specified above. +Otherwise, the behavior is erroneous, and the result is as specified above. \end{itemize} The result does not otherwise contain any indeterminate or erroneous values. @@ -15474,3 +15480,131 @@ Otherwise, \tcode{endian::native} is not equal to either \tcode{endian::big} or \tcode{endian::little}. \end{itemdescr} + +\rSec1[stdbit.h.syn]{Header \tcode{} synopsis} + +\begin{codeblock} +#define @\libglobal{__STDC_VERSION_STDBIT_H__}@ 202311L + +#define @\libglobal{__STDC_ENDIAN_BIG__}@ @\seebelow@ +#define @\libglobal{__STDC_ENDIAN_LITTLE__}@ @\seebelow@ +#define @\libglobal{__STDC_ENDIAN_NATIVE__}@ @\seebelow@ + +unsigned int @\libglobal{stdc_leading_zeros_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_leading_zeros_us}@(unsigned short value); +unsigned int @\libglobal{stdc_leading_zeros_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_leading_zeros_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_leading_zeros_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_leading_zeros}@(T value); + +unsigned int @\libglobal{stdc_leading_ones_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_leading_ones_us}@(unsigned short value); +unsigned int @\libglobal{stdc_leading_ones_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_leading_ones_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_leading_ones_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_leading_ones}@(T value); + +unsigned int @\libglobal{stdc_trailing_zeros_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_trailing_zeros_us}@(unsigned short value); +unsigned int @\libglobal{stdc_trailing_zeros_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_trailing_zeros_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_trailing_zeros_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_trailing_zeros}@(T value); + +unsigned int @\libglobal{stdc_trailing_ones_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_trailing_ones_us}@(unsigned short value); +unsigned int @\libglobal{stdc_trailing_ones_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_trailing_ones_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_trailing_ones_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_trailing_ones}@(T value); + +unsigned int @\libglobal{stdc_first_leading_zero_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_first_leading_zero_us}@(unsigned short value); +unsigned int @\libglobal{stdc_first_leading_zero_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_first_leading_zero_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_first_leading_zero_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_first_leading_zero}@(T value); + +unsigned int @\libglobal{stdc_first_leading_one_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_first_leading_one_us}@(unsigned short value); +unsigned int @\libglobal{stdc_first_leading_one_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_first_leading_one_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_first_leading_one_ull}@(unsigned long long int value); +template @\seebelow@ stdc_first_leading_one(T value); + +unsigned int @\libglobal{stdc_first_trailing_zero_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_first_trailing_zero_us}@(unsigned short value); +unsigned int @\libglobal{stdc_first_trailing_zero_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_first_trailing_zero_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_first_trailing_zero_ull}@(unsigned long long int value); +template @\seebelow@ stdc_first_trailing_zero(T value); + +unsigned int @\libglobal{stdc_first_trailing_one_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_first_trailing_one_us}@(unsigned short value); +unsigned int @\libglobal{stdc_first_trailing_one_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_first_trailing_one_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_first_trailing_one_ull}@(unsigned long long int value); +template @\seebelow@ stdc_first_trailing_one(T value); + +unsigned int @\libglobal{stdc_count_zeros_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_count_zeros_us}@(unsigned short value); +unsigned int @\libglobal{stdc_count_zeros_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_count_zeros_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_count_zeros_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_count_zeros}@(T value); + +unsigned int @\libglobal{stdc_count_ones_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_count_ones_us}@(unsigned short value); +unsigned int @\libglobal{stdc_count_ones_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_count_ones_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_count_ones_ull}@(unsigned long long int value); +template @\seebelow@ stdc_count_ones(T value); + +bool @\libglobal{stdc_has_single_bit_uc}@(unsigned char value); +bool @\libglobal{stdc_has_single_bit_us}@(unsigned short value); +bool @\libglobal{stdc_has_single_bit_ui}@(unsigned int value); +bool @\libglobal{stdc_has_single_bit_ul}@(unsigned long int value); +bool @\libglobal{stdc_has_single_bit_ull}@(unsigned long long int value); +template bool @\libglobal{stdc_has_single_bit}@(T value); + +unsigned int @\libglobal{stdc_bit_width_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_bit_width_us}@(unsigned short value); +unsigned int @\libglobal{stdc_bit_width_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_bit_width_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_bit_width_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_bit_width}@(T value); + +unsigned char @\libglobal{stdc_bit_floor_uc}@(unsigned char value); +unsigned short @\libglobal{stdc_bit_floor_us}@(unsigned short value); +unsigned int @\libglobal{stdc_bit_floor_ui}@(unsigned int value); +unsigned long int @\libglobal{stdc_bit_floor_ul}@(unsigned long int value); +unsigned long long int @\libglobal{stdc_bit_floor_ull}@(unsigned long long int value); +template T @\libglobal{stdc_bit_floor}@(T value); + +unsigned char @\libglobal{stdc_bit_ceil_uc}@(unsigned char value); +unsigned short @\libglobal{stdc_bit_ceil_us}@(unsigned short value); +unsigned int @\libglobal{stdc_bit_ceil_ui}@(unsigned int value); +unsigned long int @\libglobal{stdc_bit_ceil_ul}@(unsigned long int value); +unsigned long long int @\libglobal{stdc_bit_ceil_ull}@(unsigned long long int value); +template T @\libglobal{stdc_bit_ceil}@(T value); +\end{codeblock} + +\pnum +For a function template whose return type is not specified above, +the return type is +an \impldef{return types for \tcode{} functions} unsigned integer type +large enough to represent all possible result values. +Each function template has the same semantics +as the corresponding type-generic function with the same name +specified in \IsoCUndated{}:2024, 7.18. %% change to \xrefc{7.18} + +\pnum +\mandates +\tcode{T} is an unsigned integer type. + +\pnum +Otherwise, +the contents and meaning of the header \libheader{stdbit.h} are the same as +the C standard library header \tcode{}. + +\xref{\IsoCUndated{}:2024, 7.18} %% TODO: change to \xrefc{7.18} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index 04302a06d0..6484384dc1 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -22,6 +22,9 @@ % P2864R2 Remove deprecated arithmetic conversions \removedxref{depr.arith.conv.enum} +% P2866R5 Remove deprecated array comparisons +\removedxref{depr.array.comp} + % P2871R3 Remove deprecated header \removedxref{depr.codecvt.syn} \removedxref{depr.locale.stdcvt} @@ -95,6 +98,9 @@ \movedxref{stoptoken.cons}{stopsource} \movedxref{stoptoken.nonmembers}{stopsource} +% https://github.com/cplusplus/draft/pull/7345 +\movedxref{basic.stc.inherit}{basic.stc.general} + %%% Deprecated features. %%% Example: % diff --git a/tools/check-source.sh b/tools/check-source.sh index 74ca99b93d..336a38f1bc 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -6,7 +6,7 @@ failed=0 # Ignore files where rules may be violated within macro definitions. texfiles=$(ls *.tex | grep -v macros.tex | grep -v layout.tex | grep -v tables.tex) -texlibdesc="support.tex concepts.tex diagnostics.tex memory.tex meta.tex utilities.tex strings.tex containers.tex iterators.tex ranges.tex algorithms.tex numerics.tex time.tex locales.tex iostreams.tex threads.tex" +texlibdesc="support.tex concepts.tex diagnostics.tex memory.tex meta.tex utilities.tex containers.tex iterators.tex ranges.tex algorithms.tex strings.tex text.tex numerics.tex time.tex iostreams.tex threads.tex exec.tex" texlib="lib-intro.tex $texlibdesc" # Filter that reformats the error message as a "workflow command",