diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 925ac7e8fe..f3d4a5f770 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -22,7 +22,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install GNU tools if: matrix.cfg.os == 'macos-13' @@ -68,7 +68,7 @@ jobs: - name: upload PDF if: matrix.cfg.os == 'ubuntu-22.04' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: draft-snapshot path: source/std.pdf diff --git a/papers/n4982.html b/papers/n4982.html new file mode 100644 index 0000000000..3f97397fec --- /dev/null +++ b/papers/n4982.html @@ -0,0 +1,613 @@ + + + + + +N4982 + + +

N4982 Editors’ Report:
Programming Languages — C++

+ +

Date: 2024-04-16

+ +

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

+ +

Email: cxxeditor@gmail.com

+ +

Acknowledgements

+ +

Thanks to all those who have submitted editorial +issues +and to those who have provided pull requests with fixes.

+ +

New papers

+ + + +

Motions incorporated into working draft

+ +

Notes on motions

+ +

All motions were applied cleanly.

+ +

Core working group polls

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

CWG Poll 8 was withdrawn.

+ +

Library working group polls

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

LWG Poll 15 was withdrawn.

+ +

Editorial changes

+ +

Major editorial changes

+ +

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

+ +

Minor editorial changes

+ +

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

+ +
commit 08649a5a81ba91d8597c263b99dc80ed71767940
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Dec 22 11:33:39 2023 +0100
+
+    [stmt.expr] Use \grammarterm for expression (#6469)
+
+commit acb68797051c9a6a5f51e4adb5091b376f1ba13a
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jan 1 16:23:56 2024 +0100
+
+    [basic.life] Fix indentation in example (#6727)
+
+commit f6692f25130834672ba5a212f739100669abbbe8
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Jan 2 20:21:54 2024 +0100
+
+    [basic.scope.pdecl,basic.types.general] Remove extra whitespace (#6756)
+
+commit 7ddcd43c96589fc13342ac4cee549da75360fde7
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Fri Jan 5 15:41:01 2024 -0500
+
+    [basic.scope.param] Add missing \grammarterm for requires-expression (#6759)
+
+commit 29c0e4882a1ae62e7cd5f8d3fabcb22ae6153219
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Dec 18 17:22:30 2023 +0100
+
+    [std] Remove problematic 'requires' phrases from notes.
+
+    Only specific phrases involving the word "required" are problematic,
+    namely when they appear to establish a normative requirement. They
+    have been reworded, often by replacing "is required" with "needs",
+    sometimes with slightly larger edits.
+
+commit 43fc5a16147e720568b68ecae77f12fa3fb15102
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jan 5 15:32:55 2024 +0000
+
+    [std] Reword "necessary", "permitted", "allowed", "may" in notes.
+
+    This is so that notes do not (inappropriately) state requirements or
+    permissions.
+
+commit 74433025763f83bbccfb001dab8aa084647ffb2f
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Jan 11 19:11:17 2024 +0100
+
+    [basic.def] Fix punctuation (#6766)
+
+commit b67e0b70e88abf65d9b49875133c68d55744b1de
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Jan 12 12:53:10 2024 +0000
+
+    [text.encoding.overview] Use same parameter names as detailed description (#6768)
+
+commit bc5a56b6e9cadd030d48066601fc8098382c7469
+Author: Casey Carter <Casey@Carter.net>
+Date:   Mon Jan 15 11:19:13 2024 -0800
+
+    [exception] Paragraph two is no longer universally true
+
+    We recently added `bad_expected_access<void>` to the Standard Library, which derives from `exception`, but does not have "the following publicly accessible member functions, each of them having a non-throwing exception specification." For clarity, we should point out that this provision is not universal.
+
+commit 2055c2feabee6ec9df24ea07f8451ad33618be45
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Jan 16 09:20:44 2024 +0100
+
+    [zombie.names] Remove superfluous period (#6774)
+
+commit 8410aac1b84ec161b6990441acde53185f958135
+Author: Daniel Krügler <daniel.kruegler@gmail.com>
+Date:   Sun Jan 21 22:39:02 2024 +0100
+
+    [tuple.helper] Paragraph 1 not universally true (#6777)
+
+    [tuple.helper] p1 defines a general requirement that all specializations of `tuple_size`
+    shall meet the *Cpp17UnaryTypeTrait* requirements, but p4 actually defines a
+    special situation where this requirement is not met ("Otherwise, it has no member value").
+    We have the same seemingly contradiction in [depr.tuple] p2. For clarity, we should
+    point out that this provision is not universal.
+
+commit 4fe9190fa05c4fb4e83c1a1ba68aa12aa49542e9
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Sat Jan 27 14:38:55 2024 +0800
+
+    [locale.ctype.members] Add missing parameter name
+
+commit 74f5f61cac56a4eca5389a51754fe7e60e6b7449
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Sat Jan 27 11:26:37 2024 +0000
+
+    [tuple.cnstr] Do not use code font for cardinal number 1 (#6785)
+
+commit cb8ff12806b67990665100baaacb9a16040bce8c
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Jan 27 17:11:23 2024 +0100
+
+    [container.alloc.reqmts] End note with period (#6787)
+
+commit 70b99af0dfcb9cae82bcd97c7b24a2e84edfb2cd
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Jan 27 18:03:16 2024 +0100
+
+    [class.mem.general,class.mfct.non.static] End note with period (#6778)
+
+commit db80a4612af561e8473fd8fb3724ae9db2c72578
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Mon Feb 5 15:51:03 2024 +0000
+
+    [rand.dist.samp.plinear] Fix copy & paste error in Mandates (#6794)
+
+    This error was present in the incoming P1719R2 paper (Mandating the
+    Standard Library: Clause 26 - Numerics Library), but is obviously bogus.
+    There is no UnaryOperation type in that constructor. The correct
+    requirement is taken from the corresponding constructor in
+    [rand.dist.samp.pconst].
+
+commit e51d5733b1bd1531d6e3b63617d12414a56678c0
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Wed Feb 7 10:37:06 2024 -0500
+
+    [temp.res.general] Grammatical parallelism: remove a stray "a" (#6796)
+
+commit 8238252bcec14f76e97133db32721beaec5c749b
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Feb 8 06:59:10 2024 +0100
+
+    [iterator.concept.winc] Fix typo (#6800)
+
+commit 19caa61068d3f3aa2453e1ba7256536b8464c25c
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Dec 28 10:07:15 2023 +0800
+
+    [mem.res.private] Say `*this` instead of improper  `this`
+
+commit 419190062806ae257e5efe7057551fd626bd9516
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Dec 28 10:08:04 2023 +0800
+
+    [mem.res.monotonic.buffer.mem] Say `*this` instead of improper `this`
+
+commit 6ecda0b20664fc6b8450157e1cd9f0580c32e5e1
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Dec 28 10:09:08 2023 +0800
+
+    [re.traits] Say `*this` instead of improper `this`
+
+commit 9305893dfd250d876edf4555cf96c665e2e71e75
+Author: Casey Carter <Casey@Carter.net>
+Date:   Thu Feb 15 13:16:33 2024 -0800
+
+    [thread.once.callonce] INVOKE is evaluated, not called (#6810)
+
+commit 3616a40ded794e94181a5405672b1c36f7774684
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Feb 21 19:05:13 2024 +0100
+
+    [temp.pre] Add comma after introductory clause (#6814)
+
+commit 30debb0c5d5dc42fa36864aac76b82f49319ad84
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 21 21:39:56 2024 +0100
+
+    [temp.constr.order] Move index entry to correct paragraph (#6812)
+
+commit fb0277664fd53efea93d95202784f78aea610f31
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Feb 22 20:28:15 2024 +0100
+
+    [semaphore.syn] Add binary_semaphore to index (#6781)
+
+commit 090840673ee58d3c1e8d2844d3c716ee5ce245bc
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Feb 22 20:31:19 2024 +0100
+
+    [format.parse.ctx] Improve readability of paragraphs 12 and 14 (#6815)
+
+commit a5825b1905b06d730a46e64fb5b379f48cbc6e51
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Feb 22 20:33:18 2024 +0100
+
+    [format.parse.ctx] Add comma (#6817)
+
+commit 8c8e05d7ff6cda6329ca898e7a270547a85675d7
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Feb 22 20:35:21 2024 +0100
+
+    [format.parse.ctx] Move non-normative explanations of errors into notes (#6816)
+
+commit 48f90026631638c91b3d8138bed49cd0450380c7
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Feb 28 10:23:51 2024 +0100
+
+    [stmt.while] Add comma after introductory phrase
+
+commit d5ad3794937429b1410071037af9ddfb0aa8c861
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Feb 28 10:24:26 2024 +0100
+
+    [stmt.do] Add comma after introductory phrase
+
+commit 78ecd23f22f00be4bffaf806a6747417ce2150a2
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Feb 28 18:06:26 2024 +0100
+
+    [stmt.jump] Add cross-reference to [stmt.dcl] for destruction of local variables (#6829)
+
+commit 66b6b97c8f3969f96e3ca8df1180c18b1c57af8c
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Feb 28 21:50:50 2024 +0100
+
+    [expr.dynamic.cast] Add comma after conditional clause (#6830)
+
+commit 23430d7e605d62f5a4a1769611e3c415d6510b65
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Mar 1 11:06:34 2024 +0100
+
+    [bibliography] Replace HTTP link with HTTPS link (#6831)
+
+commit 20c2851a3c8f480a017cef6602b1b6a4d32bc5e4
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Mar 1 16:03:04 2024 +0100
+
+    [time.parse] Hyphenate argument-dependent lookup
+
+commit e0287d17110f86e3724bda5ebe74de249508490f
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Mar 1 16:04:02 2024 +0100
+
+    [diff.cpp17.temp] Hyphenate argument-dependent lookup
+
+commit ceff4ea83b511be01a8e1756386ce6a2e06e323c
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Mar 1 18:06:00 2024 +0100
+
+    [headers] Strike incorrect quote of subclause heading (#6832)
+
+commit 9878cfbea12b517d32c5af1bbfa7c8b8c4ff9cab
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Mar 3 08:42:45 2024 +0100
+
+    [handler.functions] Add cross-reference to [intro.races] (#6845)
+
+commit 9ec133c8e51aae98297255563250a2f6656e4636
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Mar 19 15:36:51 2024 +0000
+
+    [time.hash] Fix spelling of 'Cpp17Hash'
+
+commit 2b7cd6e8be2bc8a9ae97da9bf03ae4efa7fe1a9c
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Tue Apr 16 20:03:29 2024 +0800
+
+    [expos.only.entity] Add/fix \expos for exposition-only names (#6924)
+
+commit aa21c812f629975d5d25d4639053482f346751a8
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Tue Apr 16 08:07:44 2024 -0400
+
+    [dcl.type.elab] Move note to separate paragraph
+
+    Also clarify that the next paragraph is talking about any elaborated-type-specifier at all, not just the ones in p4.
+
+commit 397384c90e3ead9f832a3a269335fbfe53328180
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Feb 16 06:51:03 2024 +0100
+
+    [rand.adapt.ibits,rand.dist.pois.poisson] Add namespace std in class template
+
+    [rand.adapt.ibits] 28.5.5.3-4
+    [rand.dist.pois.poisson] 28.5.9.4.1-1
+
+commit fbf3d76683d269a0a5313fb69b5aa483ddd3a18a
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Feb 22 21:41:42 2024 +0100
+
+    [expr.unary.op] remove redundant value category wording
+
+commit 498cd7720bb2e53fb323144f956e67900a054e34
+Author: Daniel Krügler <daniel.kruegler@gmail.com>
+Date:   Sun Feb 4 17:57:38 2024 +0100
+
+    [iterator.requirements.general] Clarify that "constexpr iterator" is a requirement to be met
+
+    [iterator.requirements.general] p16 says "Iterators are called _constexpr iterators_ [..]", but all referencing sections say "meet the constexpr iterator requirements". For clarity, we should reword the definition to make it clear that this is a named requirement.
+
+commit 89cd1467f354a2b9b05ac57ad1f90f483aab22b9
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Sun Jan 28 13:54:17 2024 +0800
+
+    [range.drop.overview] Remove redundant \iref for subrange
+
+    ..which already existed in the previous bullet.
+
+commit bee055de1c5e23ce0b301138998633dc64169b4a
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Nov 23 09:33:39 2023 +0800
+
+    [dcl.init.ref] Change "function lvalue" to "lvalue of function type"
+
+commit ce31d424ba6753be1c87a4cf3face42f89b9e010
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Nov 23 09:36:28 2023 +0800
+
+    [over.ics.ref] Simplify wording by not using "function lvalue"
+
+commit 2a07c133732dcc7ea57aeb32612b15b50837a4df
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Nov 23 09:38:41 2023 +0800
+
+    [over.ics.rank] Change "function lvalue" to "lvalue of function type"
+
+commit 7675c4c1abf1986241e8a20463fd71f2841d3c39
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Sep 1 10:27:25 2023 +0200
+
+    [res.on.exception.handling] use grammarterm instead of informal term and add ref
+
+ + diff --git a/papers/n4982.md b/papers/n4982.md new file mode 100644 index 0000000000..92a68b0900 --- /dev/null +++ b/papers/n4982.md @@ -0,0 +1,472 @@ +# N4982 Editors' Report -- Programming Languages -- C++ + +Date: 2024-04-16 + +Thomas Köppe (editor, Google DeepMind) +Jens Maurer (co-editor) +Dawn Perchik (co-editor, Bright Side Computing, LLC) +Richard Smith (co-editor, Google Inc) + +Email: `cxxeditor@gmail.com` + +## Acknowledgements + +Thanks to all those who have [submitted editorial +issues](https://github.com/cplusplus/draft/wiki/How-to-submit-an-editorial-issue) +and to those who have provided pull requests with fixes. + +## New papers + + * [N4981](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4981.pdf) is the + current working draft for C++26. It replaces + [N4971](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4971.pdf). + * N4982 is this Editors' Report. + +## Motions incorporated into working draft + +### Notes on motions + +All motions were applied cleanly. + +### Core working group polls + +CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues in +[P3196R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3196r0.html) +(Core Language Working Group "ready" Issues for the March, 2024 meeting) to the C++ Working Paper. + +CWG Poll 2. Apply the changes in +[P2748R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2748r5.html) +(Disallow Binding a Returned Glvalue to a Temporary) to the C++ Working Paper. + +CWG Poll 3. Accept as a Defect Report and apply the changes in [P3106R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3106r1.html) (Clarifying rules for brace elision in aggregate initialization) to the C++ Working Paper, resolving core issue 2149. + +CWG Poll 4. Apply the changes in +[P0609R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0609r3.pdf) +(Attributes for Structured Bindings) to the C++ Working Paper. + +CWG Poll 5. Accept as a Defect Report and apply the changes in +[P3034R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3034r1.html) +(Module Declarations Shouldn’t be Macros) to the C++ Working Paper. + +CWG Poll 6. Accept as a Defect Report and apply the changes in +[P2809R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2809r3.html) +(Trivial infinite loops are not Undefined Behavior) to the C++ Working Paper. + +CWG Poll 7. Apply the changes in +[P2795R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2795r5.html) +(Erroneous behaviour for uninitialized reads) to the C++ Working Paper. + +CWG Poll 9. Apply the changes in +[P2573R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2573r2.html) +(`= delete("should have a reason");`) to the C++ Working Paper. + +CWG Poll 10. Apply the changes in +[P2893R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2893r3.html) +(Variadic friends) to the C++ Working Paper. + +CWG Poll 8 was withdrawn. + +### Library working group polls + +LWG Poll 1: Apply the changes for all Ready and Tentatively Ready issues in +[P3180R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3180r0.html) +(C++ Standard Library Ready Issues to be moved in Tokyo, Mar. 2024) to the C++ working paper. + +LWG Poll 2: Apply the changes in +[P2875R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2875r4.pdf) +(Undeprecate `polymorphic_allocator::destroy` for C++26) to the C++ working paper. + +LWG Poll 3: Apply the changes in +[P2867R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2867r2.html) +(Remove Deprecated `strstream`s From C++26) to the C++ working paper. + +LWG Poll 4: Apply the changes in +[P2869R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2869r4.pdf) +(Remove Deprecated `shared_ptr` Atomic Access APIs from C++26) to the C++ working paper. + +LWG Poll 5: Apply the changes in +[P2872R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2872r3.pdf) +(Remove `wstring_convert` From C++26) to the C++ working paper. + +LWG Poll 6: Accept as a Defect Report and apply the changes in +[P3107R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3107r5.html) +(Permit an efficient implementation of `std::print`) to the C++ working paper. + +LWG Poll 7: Apply the changes in +[P3142R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3142r0.pdf) +(Printing Blank Lines with `println`) to the C++ working paper. + +LWG Poll 8: Apply the changes in +[P2845R8](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2845r8.html) +(Formatting of `std::filesystem::path`) to the C++ working paper. + +LWG Poll 9: Apply the changes in +[P0493R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0493r5.pdf) +(Atomic minimum/maximum) to the C++ working paper. + +LWG Poll 10: Apply the changes in +[P2542R8](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2542r8.html) +(`views::concat`) to the C++ working paper. + +LWG Poll 11: Apply the changes in +[P2591R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2591r5.html) +(Concatenation of strings and string views) to the C++ working paper. + +LWG Poll 12: Apply the changes in +[P2248R8](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2248r8.html) +(Enabling list-initialization for algorithms) to the C++ working paper. + +LWG Poll 13: Apply the changes in +[P2810R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2810r4.html) +(`is_debugger_present` `is_replaceable`) to the C++ working paper. + +LWG Poll 14: Apply the changes in +[P1068R11](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p1068r11.html) +(Vector API for random number generation) to the C++ working paper. + +LWG Poll 16: Apply the changes in +[P2944R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2944r3.html) +(Comparisons for `reference_wrapper`) to the C++ working paper. + +LWG Poll 17: Apply the changes in +[P2642R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2642r6.pdf) +(Padded `mdspan` layouts) to the C++ working paper. + +LWG Poll 18: Apply the changes in +[P3029R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3029r1.html) +(Better `mdspan`'s CTAD) to the C++ working paper. + +LWG Poll 15 was withdrawn. + +## Editorial changes + +### Major editorial changes + +There have not been any major editorial changes since the last working draft. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4971 is below. This +list excludes changes that do not affect the body text or only affect whitespace +or typeface. For a complete list including such changes (or for the actual +deltas applied by these changes), consult the +[draft sources on GitHub](https://github.com/cplusplus/draft/compare/n4971...n4981). + + commit 08649a5a81ba91d8597c263b99dc80ed71767940 + Author: Jan Schultke + Date: Fri Dec 22 11:33:39 2023 +0100 + + [stmt.expr] Use \grammarterm for expression (#6469) + + commit acb68797051c9a6a5f51e4adb5091b376f1ba13a + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jan 1 16:23:56 2024 +0100 + + [basic.life] Fix indentation in example (#6727) + + commit f6692f25130834672ba5a212f739100669abbbe8 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Jan 2 20:21:54 2024 +0100 + + [basic.scope.pdecl,basic.types.general] Remove extra whitespace (#6756) + + commit 7ddcd43c96589fc13342ac4cee549da75360fde7 + Author: Alisdair Meredith + Date: Fri Jan 5 15:41:01 2024 -0500 + + [basic.scope.param] Add missing \grammarterm for requires-expression (#6759) + + commit 29c0e4882a1ae62e7cd5f8d3fabcb22ae6153219 + Author: Jens Maurer + Date: Mon Dec 18 17:22:30 2023 +0100 + + [std] Remove problematic 'requires' phrases from notes. + + Only specific phrases involving the word "required" are problematic, + namely when they appear to establish a normative requirement. They + have been reworded, often by replacing "is required" with "needs", + sometimes with slightly larger edits. + + commit 43fc5a16147e720568b68ecae77f12fa3fb15102 + Author: Thomas Köppe + Date: Fri Jan 5 15:32:55 2024 +0000 + + [std] Reword "necessary", "permitted", "allowed", "may" in notes. + + This is so that notes do not (inappropriately) state requirements or + permissions. + + commit 74433025763f83bbccfb001dab8aa084647ffb2f + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Jan 11 19:11:17 2024 +0100 + + [basic.def] Fix punctuation (#6766) + + commit b67e0b70e88abf65d9b49875133c68d55744b1de + Author: Jonathan Wakely + Date: Fri Jan 12 12:53:10 2024 +0000 + + [text.encoding.overview] Use same parameter names as detailed description (#6768) + + commit bc5a56b6e9cadd030d48066601fc8098382c7469 + Author: Casey Carter + Date: Mon Jan 15 11:19:13 2024 -0800 + + [exception] Paragraph two is no longer universally true + + We recently added `bad_expected_access` to the Standard Library, which derives from `exception`, but does not have "the following publicly accessible member functions, each of them having a non-throwing exception specification." For clarity, we should point out that this provision is not universal. + + commit 2055c2feabee6ec9df24ea07f8451ad33618be45 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Jan 16 09:20:44 2024 +0100 + + [zombie.names] Remove superfluous period (#6774) + + commit 8410aac1b84ec161b6990441acde53185f958135 + Author: Daniel Krügler + Date: Sun Jan 21 22:39:02 2024 +0100 + + [tuple.helper] Paragraph 1 not universally true (#6777) + + [tuple.helper] p1 defines a general requirement that all specializations of `tuple_size` + shall meet the *Cpp17UnaryTypeTrait* requirements, but p4 actually defines a + special situation where this requirement is not met ("Otherwise, it has no member value"). + We have the same seemingly contradiction in [depr.tuple] p2. For clarity, we should + point out that this provision is not universal. + + commit 4fe9190fa05c4fb4e83c1a1ba68aa12aa49542e9 + Author: S. B. Tam + Date: Sat Jan 27 14:38:55 2024 +0800 + + [locale.ctype.members] Add missing parameter name + + commit 74f5f61cac56a4eca5389a51754fe7e60e6b7449 + Author: Jonathan Wakely + Date: Sat Jan 27 11:26:37 2024 +0000 + + [tuple.cnstr] Do not use code font for cardinal number 1 (#6785) + + commit cb8ff12806b67990665100baaacb9a16040bce8c + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Jan 27 17:11:23 2024 +0100 + + [container.alloc.reqmts] End note with period (#6787) + + commit 70b99af0dfcb9cae82bcd97c7b24a2e84edfb2cd + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Jan 27 18:03:16 2024 +0100 + + [class.mem.general,class.mfct.non.static] End note with period (#6778) + + commit db80a4612af561e8473fd8fb3724ae9db2c72578 + Author: Jonathan Wakely + Date: Mon Feb 5 15:51:03 2024 +0000 + + [rand.dist.samp.plinear] Fix copy & paste error in Mandates (#6794) + + This error was present in the incoming P1719R2 paper (Mandating the + Standard Library: Clause 26 - Numerics Library), but is obviously bogus. + There is no UnaryOperation type in that constructor. The correct + requirement is taken from the corresponding constructor in + [rand.dist.samp.pconst]. + + commit e51d5733b1bd1531d6e3b63617d12414a56678c0 + Author: Arthur O'Dwyer + Date: Wed Feb 7 10:37:06 2024 -0500 + + [temp.res.general] Grammatical parallelism: remove a stray "a" (#6796) + + commit 8238252bcec14f76e97133db32721beaec5c749b + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Feb 8 06:59:10 2024 +0100 + + [iterator.concept.winc] Fix typo (#6800) + + commit 19caa61068d3f3aa2453e1ba7256536b8464c25c + Author: A. Jiang + Date: Thu Dec 28 10:07:15 2023 +0800 + + [mem.res.private] Say `*this` instead of improper `this` + + commit 419190062806ae257e5efe7057551fd626bd9516 + Author: A. Jiang + Date: Thu Dec 28 10:08:04 2023 +0800 + + [mem.res.monotonic.buffer.mem] Say `*this` instead of improper `this` + + commit 6ecda0b20664fc6b8450157e1cd9f0580c32e5e1 + Author: A. Jiang + Date: Thu Dec 28 10:09:08 2023 +0800 + + [re.traits] Say `*this` instead of improper `this` + + commit 9305893dfd250d876edf4555cf96c665e2e71e75 + Author: Casey Carter + Date: Thu Feb 15 13:16:33 2024 -0800 + + [thread.once.callonce] INVOKE is evaluated, not called (#6810) + + commit 3616a40ded794e94181a5405672b1c36f7774684 + Author: Jan Schultke + Date: Wed Feb 21 19:05:13 2024 +0100 + + [temp.pre] Add comma after introductory clause (#6814) + + commit 30debb0c5d5dc42fa36864aac76b82f49319ad84 + Author: Jens Maurer + Date: Wed Feb 21 21:39:56 2024 +0100 + + [temp.constr.order] Move index entry to correct paragraph (#6812) + + commit fb0277664fd53efea93d95202784f78aea610f31 + Author: Jan Schultke + Date: Thu Feb 22 20:28:15 2024 +0100 + + [semaphore.syn] Add binary_semaphore to index (#6781) + + commit 090840673ee58d3c1e8d2844d3c716ee5ce245bc + Author: Jan Schultke + Date: Thu Feb 22 20:31:19 2024 +0100 + + [format.parse.ctx] Improve readability of paragraphs 12 and 14 (#6815) + + commit a5825b1905b06d730a46e64fb5b379f48cbc6e51 + Author: Jan Schultke + Date: Thu Feb 22 20:33:18 2024 +0100 + + [format.parse.ctx] Add comma (#6817) + + commit 8c8e05d7ff6cda6329ca898e7a270547a85675d7 + Author: Jan Schultke + Date: Thu Feb 22 20:35:21 2024 +0100 + + [format.parse.ctx] Move non-normative explanations of errors into notes (#6816) + + commit 48f90026631638c91b3d8138bed49cd0450380c7 + Author: Eisenwave + Date: Wed Feb 28 10:23:51 2024 +0100 + + [stmt.while] Add comma after introductory phrase + + commit d5ad3794937429b1410071037af9ddfb0aa8c861 + Author: Eisenwave + Date: Wed Feb 28 10:24:26 2024 +0100 + + [stmt.do] Add comma after introductory phrase + + commit 78ecd23f22f00be4bffaf806a6747417ce2150a2 + Author: Jan Schultke + Date: Wed Feb 28 18:06:26 2024 +0100 + + [stmt.jump] Add cross-reference to [stmt.dcl] for destruction of local variables (#6829) + + commit 66b6b97c8f3969f96e3ca8df1180c18b1c57af8c + Author: Jan Schultke + Date: Wed Feb 28 21:50:50 2024 +0100 + + [expr.dynamic.cast] Add comma after conditional clause (#6830) + + commit 23430d7e605d62f5a4a1769611e3c415d6510b65 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Mar 1 11:06:34 2024 +0100 + + [bibliography] Replace HTTP link with HTTPS link (#6831) + + commit 20c2851a3c8f480a017cef6602b1b6a4d32bc5e4 + Author: Eisenwave + Date: Fri Mar 1 16:03:04 2024 +0100 + + [time.parse] Hyphenate argument-dependent lookup + + commit e0287d17110f86e3724bda5ebe74de249508490f + Author: Eisenwave + Date: Fri Mar 1 16:04:02 2024 +0100 + + [diff.cpp17.temp] Hyphenate argument-dependent lookup + + commit ceff4ea83b511be01a8e1756386ce6a2e06e323c + Author: Jan Schultke + Date: Fri Mar 1 18:06:00 2024 +0100 + + [headers] Strike incorrect quote of subclause heading (#6832) + + commit 9878cfbea12b517d32c5af1bbfa7c8b8c4ff9cab + Author: Jan Schultke + Date: Sun Mar 3 08:42:45 2024 +0100 + + [handler.functions] Add cross-reference to [intro.races] (#6845) + + commit 9ec133c8e51aae98297255563250a2f6656e4636 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Mar 19 15:36:51 2024 +0000 + + [time.hash] Fix spelling of 'Cpp17Hash' + + commit 2b7cd6e8be2bc8a9ae97da9bf03ae4efa7fe1a9c + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Tue Apr 16 20:03:29 2024 +0800 + + [expos.only.entity] Add/fix \expos for exposition-only names (#6924) + + commit aa21c812f629975d5d25d4639053482f346751a8 + Author: Arthur O'Dwyer + Date: Tue Apr 16 08:07:44 2024 -0400 + + [dcl.type.elab] Move note to separate paragraph + + Also clarify that the next paragraph is talking about any elaborated-type-specifier at all, not just the ones in p4. + + commit 397384c90e3ead9f832a3a269335fbfe53328180 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Feb 16 06:51:03 2024 +0100 + + [rand.adapt.ibits,rand.dist.pois.poisson] Add namespace std in class template + + [rand.adapt.ibits] 28.5.5.3-4 + [rand.dist.pois.poisson] 28.5.9.4.1-1 + + commit fbf3d76683d269a0a5313fb69b5aa483ddd3a18a + Author: Jan Schultke + Date: Thu Feb 22 21:41:42 2024 +0100 + + [expr.unary.op] remove redundant value category wording + + commit 498cd7720bb2e53fb323144f956e67900a054e34 + Author: Daniel Krügler + Date: Sun Feb 4 17:57:38 2024 +0100 + + [iterator.requirements.general] Clarify that "constexpr iterator" is a requirement to be met + + [iterator.requirements.general] p16 says "Iterators are called _constexpr iterators_ [..]", but all referencing sections say "meet the constexpr iterator requirements". For clarity, we should reword the definition to make it clear that this is a named requirement. + + commit 89cd1467f354a2b9b05ac57ad1f90f483aab22b9 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Sun Jan 28 13:54:17 2024 +0800 + + [range.drop.overview] Remove redundant \iref for subrange + + ..which already existed in the previous bullet. + + commit bee055de1c5e23ce0b301138998633dc64169b4a + Author: A. Jiang + Date: Thu Nov 23 09:33:39 2023 +0800 + + [dcl.init.ref] Change "function lvalue" to "lvalue of function type" + + commit ce31d424ba6753be1c87a4cf3face42f89b9e010 + Author: A. Jiang + Date: Thu Nov 23 09:36:28 2023 +0800 + + [over.ics.ref] Simplify wording by not using "function lvalue" + + commit 2a07c133732dcc7ea57aeb32612b15b50837a4df + Author: A. Jiang + Date: Thu Nov 23 09:38:41 2023 +0800 + + [over.ics.rank] Change "function lvalue" to "lvalue of function type" + + commit 7675c4c1abf1986241e8a20463fd71f2841d3c39 + Author: Eisenwave + Date: Fri Sep 1 10:27:25 2023 +0200 + + [res.on.exception.handling] use grammarterm instead of informal term and add ref diff --git a/papers/wd-index.md b/papers/wd-index.md index 5ea3d75a59..19b0d4c6a9 100644 --- a/papers/wd-index.md +++ b/papers/wd-index.md @@ -48,3 +48,4 @@ * [N4958](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4958.pdf) 2023-08 C++ Working Draft * [N4964](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4964.pdf) 2023-10 C++ Working Draft * [N4971](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4971.pdf) 2023-12 C++ Working Draft + * [N4981](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4981.pdf) 2024-03 C++ Working Draft diff --git a/source/algorithms.tex b/source/algorithms.tex index ff4c3b38ed..ec47564de5 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -24,6 +24,7 @@ \ref{alg.sorting} & Sorting and related operations & \\ \rowsep \ref{numeric.ops} & Generalized numeric operations & \tcode{} \\ \rowsep \ref{specialized.algorithms} & Specialized \tcode{} algorithms & \tcode{} \\ \rowsep +\ref{alg.rand} & Specialized \tcode{} algorithms & \tcode{} \\ \rowsep \ref{alg.c.library} & C library algorithms & \tcode{} \\ \end{libsumtab} @@ -707,10 +708,12 @@ // \ref{alg.contains}, contains namespace ranges { - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr bool contains(I first, S last, const T& value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T, class Proj = identity> + template<@\libconcept{input_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr bool contains(R&& r, const T& value, Proj proj = {}); @@ -766,10 +769,11 @@ } // \ref{alg.find}, find - template + template::value_type> constexpr InputIterator find(InputIterator first, InputIterator last, const T& value); - template + template::value_type> ForwardIterator find(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& value); @@ -789,10 +793,12 @@ Predicate pred); namespace ranges { - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr I find(I first, S last, const T& value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T, class Proj = identity> + template<@\libconcept{input_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr borrowed_iterator_t @@ -943,10 +949,11 @@ } // \ref{alg.count}, count - template + template::value_type> constexpr typename iterator_traits::difference_type count(InputIterator first, InputIterator last, const T& value); - template + template::value_type> typename iterator_traits::difference_type count(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& value); @@ -959,11 +966,13 @@ ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr iter_difference_t count(I first, S last, const T& value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T, class Proj = identity> + template<@\libconcept{input_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr range_difference_t @@ -1157,21 +1166,24 @@ Proj1 proj1 = {}, Proj2 proj2 = {}); } - template + template::value_type> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value); - template + template::value_type, class BinaryPredicate> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred); - template + template::value_type> ForwardIterator search_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Size count, const T& value); - template + template::value_type, class BinaryPredicate> ForwardIterator search_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, @@ -1179,14 +1191,15 @@ BinaryPredicate pred); namespace ranges { - template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, - class Pred = ranges::equal_to, class Proj = identity> + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, + class Pred = ranges::equal_to, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirectly_comparable}@ constexpr subrange search_n(I first, S last, iter_difference_t count, const T& value, Pred pred = {}, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Pred = ranges::equal_to, - class Proj = identity> + template<@\libconcept{forward_range}@ R, class Pred = ranges::equal_to, + class Proj = identity, class T = projected_value_t> requires @\libconcept{indirectly_comparable}@, const T*, Pred, Proj> constexpr borrowed_subrange_t search_n(R&& r, range_difference_t count, @@ -1255,11 +1268,12 @@ concept @\defexposconcept{indirectly-binary-right-foldable}@ = // \expos @\exposconcept{indirectly-binary-left-foldable}@<@\exposid{flipped}@, T, I>; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, @\exposconcept{indirectly-binary-left-foldable}@ F> constexpr auto fold_left(I first, S last, T init, F f); - template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> + template<@\libconcept{input_range}@ R, class T = range_value_t, + @\exposconcept{indirectly-binary-left-foldable}@> F> constexpr auto fold_left(R&& r, T init, F f); template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @@ -1271,11 +1285,11 @@ requires @\libconcept{constructible_from}@, range_reference_t> constexpr auto fold_left_first(R&& r, F f); - template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, + template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, @\exposconcept{indirectly-binary-right-foldable}@ F> constexpr auto fold_right(I first, S last, T init, F f); - template<@\libconcept{bidirectional_range}@ R, class T, + template<@\libconcept{bidirectional_range}@ R, class T = range_value_t, @\exposconcept{indirectly-binary-right-foldable}@> F> constexpr auto fold_right(R&& r, T init, F f); @@ -1294,11 +1308,12 @@ template using fold_left_first_with_iter_result = in_value_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, @\exposconcept{indirectly-binary-left-foldable}@ F> constexpr @\seebelow@ fold_left_with_iter(I first, S last, T init, F f); - template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> + template<@\libconcept{input_range}@ R, class T = range_value_t, + @\exposconcept{indirectly-binary-left-foldable}@> F> constexpr @\seebelow@ fold_left_with_iter(R&& r, T init, F f); template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @@ -1532,35 +1547,41 @@ template constexpr void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); - template + template::value_type> void replace(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); - template + template::value_type> constexpr void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); - template + template::value_type> void replace_if(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); namespace ranges { - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T1, class T2, class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T1 = projected_value_t, class T2 = T1> requires @\libconcept{indirectly_writable}@ && @\libconcept{indirect_binary_predicate}@, const T1*> constexpr I replace(I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T1, class T2, class Proj = identity> + template<@\libconcept{input_range}@ R, class Proj = identity, + class T1 = projected_value_t, Proj>, class T2 = T1> requires @\libconcept{indirectly_writable}@, const T2&> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> constexpr borrowed_iterator_t replace(R&& r, const T1& old_value, const T2& new_value, Proj proj = {}); - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_writable}@ constexpr I replace_if(I first, S last, Pred pred, const T& new_value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T, class Proj = identity, + template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> constexpr borrowed_iterator_t @@ -1576,12 +1597,13 @@ ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& old_value, const T& new_value); - template + template::value_type> constexpr OutputIterator replace_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred, const T& new_value); template + class Predicate, class T = iterator_traits::value_type> ForwardIterator2 replace_copy_if(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, @@ -1591,18 +1613,21 @@ template using replace_copy_result = in_out_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T1, class T2, - @\libconcept{output_iterator}@ O, class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class O, + class Proj = identity, + class T1 = projected_value_t, class T2 = iter_value_t> requires @\libconcept{indirectly_copyable}@ && - @\libconcept{indirect_binary_predicate}@, const T1*> + @\libconcept{indirect_binary_predicate}@, const T1*> && + @\libconcept{output_iterator}@ constexpr replace_copy_result replace_copy(I first, S last, O result, const T1& old_value, const T2& new_value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T1, class T2, @\libconcept{output_iterator}@ O, - class Proj = identity> + template<@\libconcept{input_range}@ R, class O, class Proj = identity, + class T1 = projected_value_t, Proj>, class T2 = iter_value_t> requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> + projected, Proj>, const T1*> && + @\libconcept{output_iterator}@ constexpr replace_copy_result, O> replace_copy(R&& r, O result, const T1& old_value, const T2& new_value, Proj proj = {}); @@ -1610,39 +1635,44 @@ template using replace_copy_if_result = in_out_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, @\libconcept{output_iterator}@ O, + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class O, class T = iter_value_t class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> - requires @\libconcept{indirectly_copyable}@ + requires @\libconcept{indirectly_copyable}@ && @\libconcept{output_iterator}@ constexpr replace_copy_if_result replace_copy_if(I first, S last, O result, Pred pred, const T& new_value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T, @\libconcept{output_iterator}@ O, class Proj = identity, + template<@\libconcept{input_range}@ R, class O, class T = iter_value_t, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> - requires @\libconcept{indirectly_copyable}@, O> + requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{output_iterator}@ constexpr replace_copy_if_result, O> replace_copy_if(R&& r, O result, Pred pred, const T& new_value, Proj proj = {}); } // \ref{alg.fill}, fill - template + template::value_type> constexpr void fill(ForwardIterator first, ForwardIterator last, const T& value); - template + template::value_type> void fill(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& value); - template + template::value_type> constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value); // freestanding template + class Size, class T = iterator_traits::value_type> ForwardIterator fill_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, Size n, const T& value); namespace ranges { - template O, @\libconcept{sentinel_for}@ S> + template S, class T = iter_value_t> + requires @\libconcept{output_iterator}@ constexpr O fill(O first, S last, const T& value); - template R> + template> + requires @\libconcept{output_range}@ constexpr borrowed_iterator_t fill(R&& r, const T& value); - template O> + template> + requires @\libconcept{output_iterator}@ O> constexpr O fill_n(O first, iter_difference_t n, const T& value); } @@ -1673,10 +1703,11 @@ } // \ref{alg.remove}, remove - template + template::value_type> constexpr ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value); - template + template::value_type> ForwardIterator remove(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& value); @@ -1689,10 +1720,12 @@ Predicate pred); namespace ranges { - template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> + template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr subrange remove(I first, S last, const T& value, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Proj = identity> + template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{permutable}@> && @\libconcept{indirect_binary_predicate}@, Proj>, const T*> @@ -1708,12 +1741,13 @@ remove_if(R&& r, Pred pred, Proj proj = {}); } - template + template::value_type> constexpr OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value); template + class T = iterator_traits::value_type> ForwardIterator2 remove_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, @@ -1733,13 +1767,14 @@ template using remove_copy_result = in_out_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, class T, - class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, + class Proj = identity, class T = projected_value_t> requires @\libconcept{indirectly_copyable}@ && @\libconcept{indirect_binary_predicate}@, const T*> constexpr remove_copy_result remove_copy(I first, S last, O result, const T& value, Proj proj = {}); - template<@\libconcept{input_range}@ R, @\libconcept{weakly_incrementable}@ O, class T, class Proj = identity> + template<@\libconcept{input_range}@ R, @\libconcept{weakly_incrementable}@ O, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{indirect_binary_predicate}@, Proj>, const T*> @@ -2192,83 +2227,95 @@ } // \ref{alg.binary.search}, binary search - template + template::value_type> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value); - template + template::value_type, + class Compare> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { - template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr I lower_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Proj = identity, + template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t lower_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {}); } - template + template::value_type> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value); - template + template::value_type, + class Compare> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { - template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr I upper_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Proj = identity, + template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t upper_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {}); } - template + template::value_type> constexpr pair equal_range(ForwardIterator first, ForwardIterator last, const T& value); - template + template::value_type, + class Compare> constexpr pair equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { - template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> Comp = ranges::less> constexpr subrange equal_range(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Proj = identity, + template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_subrange_t equal_range(R&& r, const T& value, Comp comp = {}, Proj proj = {}); } - template + template::value_type> constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value); - template + template::value_type, + class Compare> constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { - template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr bool binary_search(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Proj = identity, + template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr bool binary_search(R&& r, const T& value, Comp comp = {}, @@ -3363,10 +3410,11 @@ \indexlibraryglobal{contains}% \begin{itemdecl} -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr bool ranges::contains(I first, S last, const T& value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T, class Proj = identity> +template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr bool ranges::contains(R&& r, const T& value, Proj proj = {}); \end{itemdecl} @@ -3643,10 +3691,11 @@ \indexlibraryglobal{find_if}% \indexlibraryglobal{find_if_not}% \begin{itemdecl} -template +template::value_type> constexpr InputIterator find(InputIterator first, InputIterator last, const T& value); -template +template::value_type> ForwardIterator find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); @@ -3665,10 +3714,11 @@ ForwardIterator first, ForwardIterator last, Predicate pred); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr I ranges::find(I first, S last, const T& value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T, class Proj = identity> +template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr borrowed_iterator_t ranges::find(R&& r, const T& value, Proj proj = {}); @@ -3982,10 +4032,11 @@ \indexlibraryglobal{count}% \indexlibraryglobal{count_if}% \begin{itemdecl} -template +template::value_type> constexpr typename iterator_traits::difference_type count(InputIterator first, InputIterator last, const T& value); -template +template::value_type> typename iterator_traits::difference_type count(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); @@ -3998,11 +4049,12 @@ count_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr iter_difference_t ranges::count(I first, S last, const T& value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T, class Proj = identity> +template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr range_difference_t ranges::count(R&& r, const T& value, Proj proj = {}); @@ -4462,23 +4514,25 @@ \indexlibraryglobal{search_n}% \begin{itemdecl} -template +template::value_type> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value); -template +template::value_type> ForwardIterator search_n(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Size count, const T& value); -template::value_type, class BinaryPredicate> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred); -template::value_type, class BinaryPredicate> ForwardIterator search_n(ExecutionPolicy&& exec, @@ -4509,14 +4563,15 @@ \indexlibraryglobal{search_n}% \begin{itemdecl} -template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, - class Pred = ranges::equal_to, class Proj = identity> +template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, + class Pred = ranges::equal_to, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirectly_comparable}@ constexpr subrange ranges::search_n(I first, S last, iter_difference_t count, const T& value, Pred pred = {}, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Pred = ranges::equal_to, - class Proj = identity> +template<@\libconcept{forward_range}@ R, class Pred = ranges::equal_to, + class Proj = identity, class T = projected_value_t, Proj>> requires @\libconcept{indirectly_comparable}@, const T*, Pred, Proj> constexpr borrowed_subrange_t ranges::search_n(R&& r, range_difference_t count, @@ -4635,9 +4690,11 @@ \indexlibraryglobal{fold_left}% \begin{itemdecl} -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, @\exposconcept{indirectly-binary-left-foldable}@ F> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, + @\exposconcept{indirectly-binary-left-foldable}@ F> constexpr auto ranges::fold_left(I first, S last, T init, F f); -template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> +template<@\libconcept{input_range}@ R, class T = range_value_t, + @\exposconcept{indirectly-binary-left-foldable}@> F> constexpr auto ranges::fold_left(R&& r, T init, F f); \end{itemdecl} @@ -4670,10 +4727,10 @@ \indexlibraryglobal{fold_right}% \begin{itemdecl} -template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, +template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, @\exposconcept{indirectly-binary-right-foldable}@ F> constexpr auto ranges::fold_right(I first, S last, T init, F f); -template<@\libconcept{bidirectional_range}@ R, class T, +template<@\libconcept{bidirectional_range}@ R, class T = range_value_t, @\exposconcept{indirectly-binary-right-foldable}@> F> constexpr auto ranges::fold_right(R&& r, T init, F f); \end{itemdecl} @@ -4725,10 +4782,11 @@ \indexlibraryglobal{fold_left_with_iter}% \begin{itemdecl} -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, @\exposconcept{indirectly-binary-left-foldable}@ F> constexpr @\seebelow@ ranges::fold_left_with_iter(I first, S last, T init, F f); -template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> +template<@\libconcept{input_range}@ R, class T = range_value_t, + @\exposconcept{indirectly-binary-left-foldable}@> F> constexpr @\seebelow@ ranges::fold_left_with_iter(R&& r, T init, F f); \end{itemdecl} @@ -5424,37 +5482,43 @@ \indexlibraryglobal{replace}% \indexlibraryglobal{replace_if}% \begin{itemdecl} -template +template::value_type> constexpr void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); -template +template::value_type> void replace(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); -template +template::value_type> constexpr void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); -template +template::value_type> void replace_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T1, class T2, class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T1 = projected_value_t, class T2 = T1> requires @\libconcept{indirectly_writable}@ && @\libconcept{indirect_binary_predicate}@, const T1*> constexpr I ranges::replace(I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T1, class T2, class Proj = identity> +template<@\libconcept{input_range}@ R, class Proj = identity, + class T1 = projected_value_t, Proj>, class T2 = T1> requires @\libconcept{indirectly_writable}@, const T2&> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> constexpr borrowed_iterator_t ranges::replace(R&& r, const T1& old_value, const T2& new_value, Proj proj = {}); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_writable}@ constexpr I ranges::replace_if(I first, S last, Pred pred, const T& new_value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T, class Proj = identity, +template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, Proj>, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> constexpr borrowed_iterator_t @@ -5495,12 +5559,14 @@ \indexlibraryglobal{replace_copy}% \indexlibraryglobal{replace_copy_if}% \begin{itemdecl} -template +template::value_type> constexpr OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value); -template +template::value_type> ForwardIterator2 replace_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, @@ -5520,30 +5586,32 @@ ForwardIterator2 result, Predicate pred, const T& new_value); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T1, class T2, @\libconcept{output_iterator}@ O, - class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class O, + class Proj = identity, class T1 = projected_value_t, class T2 = iter_value_t> requires @\libconcept{indirectly_copyable}@ && - @\libconcept{indirect_binary_predicate}@, const T1*> + @\libconcept{indirect_binary_predicate}@, const T1*> && + @\libconcept{output_iterator}@ constexpr ranges::replace_copy_result ranges::replace_copy(I first, S last, O result, const T1& old_value, const T2& new_value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T1, class T2, @\libconcept{output_iterator}@ O, - class Proj = identity> +template<@\libconcept{input_range}@ R, class O, class Proj = identity, + class T1 = projected_value_t, Proj>, class T2 = iter_value_t> requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> + && @\libconcept{output_iterator}@ constexpr ranges::replace_copy_result, O> ranges::replace_copy(R&& r, O result, const T1& old_value, const T2& new_value, Proj proj = {}); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, @\libconcept{output_iterator}@ O, +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S,class O, class T = iter_value_t, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> - requires @\libconcept{indirectly_copyable}@ + requires @\libconcept{indirectly_copyable}@ && @\libconcept{output_iterator}@ constexpr ranges::replace_copy_if_result ranges::replace_copy_if(I first, S last, O result, Pred pred, const T& new_value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T, @\libconcept{output_iterator}@ O, class Proj = identity, +template<@\libconcept{input_range}@ R, class O, class T = iter_value_t, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> - requires @\libconcept{indirectly_copyable}@, O> + requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{output_iterator}@ constexpr ranges::replace_copy_if_result, O> ranges::replace_copy_if(R&& r, O result, Pred pred, const T& new_value, Proj proj = {}); @@ -5606,23 +5674,28 @@ \indexlibraryglobal{fill}% \indexlibraryglobal{fill_n}% \begin{itemdecl} -template +template::value_type> constexpr void fill(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type> void fill(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type> constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value); -template +template::value_type> ForwardIterator fill_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, const T& value); -template O, @\libconcept{sentinel_for}@ S> +template S, class T = iter_value_t> + requires @\libconcept{output_iterator}@ constexpr O ranges::fill(O first, S last, const T& value); -template R> +template> + requires @\libconcept{output_range}@> constexpr borrowed_iterator_t ranges::fill(R&& r, const T& value); -template O> +template> + requires @\libconcept{output_iterator}@> constexpr O ranges::fill_n(O first, iter_difference_t n, const T& value); \end{itemdecl} @@ -5711,10 +5784,11 @@ \indexlibraryglobal{remove}% \indexlibraryglobal{remove_if}% \begin{itemdecl} -template +template::value_type> constexpr ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type> ForwardIterator remove(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); @@ -5727,10 +5801,12 @@ ForwardIterator first, ForwardIterator last, Predicate pred); -template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> +template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr subrange ranges::remove(I first, S last, const T& value, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Proj = identity> +template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{permutable}@> && @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr borrowed_subrange_t @@ -5796,12 +5872,13 @@ \indexlibraryglobal{remove_copy}% \indexlibraryglobal{remove_copy_if}% \begin{itemdecl} -template +template::value_type> constexpr OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value); template + class T = iterator_traits::value_type> ForwardIterator2 remove_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, @@ -5818,13 +5895,14 @@ ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, class T, - class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, + class Proj = identity, class T = projected_value_t> requires @\libconcept{indirectly_copyable}@ && @\libconcept{indirect_binary_predicate}@, const T*> constexpr ranges::remove_copy_result ranges::remove_copy(I first, S last, O result, const T& value, Proj proj = {}); -template<@\libconcept{input_range}@ R, @\libconcept{weakly_incrementable}@ O, class T, class Proj = identity> +template<@\libconcept{input_range}@ R, @\libconcept{weakly_incrementable}@ O, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr ranges::remove_copy_result, O> @@ -7196,21 +7274,24 @@ \indexlibraryglobal{lower_bound}% \begin{itemdecl} -template +template::value_type> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type, + class Compare> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); -template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, +template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr I ranges::lower_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Proj = identity, +template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t @@ -7244,20 +7325,23 @@ \indexlibraryglobal{upper_bound}% \begin{itemdecl} -template +template::value_type> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type, + class Compare> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); -template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, +template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr I ranges::upper_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Proj = identity, +template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t @@ -7291,22 +7375,25 @@ \indexlibraryglobal{equal_range}% \begin{itemdecl} -template +template::value_type> constexpr pair equal_range(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type, + class Compare> constexpr pair equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); -template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, +template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr subrange ranges::equal_range(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Proj = identity, +template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_subrange_t @@ -7356,21 +7443,24 @@ \indexlibraryglobal{binary_search}% \begin{itemdecl} -template +template::value_type> constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type, + class Compare> constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); -template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, +template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr bool ranges::binary_search(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Proj = identity, +template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr bool ranges::binary_search(R&& r, const T& value, Comp comp = {}, @@ -10773,11 +10863,9 @@ \rSec3[numeric.sat.func]{Arithmetic functions} \pnum -\begin{note} In the following descriptions, an arithmetic operation is performed as a mathematical operation with infinite range and then it is determined whether the mathematical result fits into the result type. -\end{note} \indexlibraryglobal{add_sat}% \begin{itemdecl} @@ -11580,6 +11668,138 @@ \end{codeblock} \end{itemdescr} +\rSec1[alg.rand]{Specialized \tcode{} algorithms} + +\rSec2[alg.rand.general]{General} + +\pnum +The contents specified in \ref{alg.rand} +are declared in the header \libheaderrefx{random}{rand.synopsis}. + +\rSec2[alg.rand.generate]{\tcode{generate_random}} + +\begin{itemdecl} +template + requires @\libconcept{output_range}@> && @\libconcept{uniform_random_bit_generator}@> +constexpr borrowed_iterator_t ranges::generate_random(R&& r, G&& g); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +Calls \tcode{g.generate_random(std::forward(r))} +if this expression is well-formed. +\item +Otherwise, if \tcode{R} models \tcode{sized_range}, +fills \tcode{r} with \tcode{ranges::size(r)} values of +type \tcode{invoke_result_t} by performing +an unspecified number of invocations of +the form \tcode{g()} or \tcode{g.generate_random(s)}, +if such an expression is well-formed for a value \tcode{N} and +an object \tcode{s} of type \tcode{span, N>}. +\begin{note} +Values of \tcode{N} can differ between invocations. +\end{note} +\item +Otherwise, calls \tcode{ranges::generate(std::forward(r), ref(g))}. +\end{itemize} + +\pnum +\returns +\tcode{ranges::end(r)}. + +\pnum +\remarks +The effects of \tcode{generate_random(r, g)} shall be equivalent to +\tcode{ranges::generate(std::for\-ward(r), ref(g))}. +\begin{note} +This implies that \tcode{g.generate_random(a)} fills \tcode{a} +with the same values as produced by invocation of \tcode{g()}. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +template> O, @\libconcept{sentinel_for}@ S> + requires @\libconcept{uniform_random_bit_generator}@> +constexpr O ranges::generate_random(O first, S last, G&& g); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return generate_random(subrange(std::move(first), last), g); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{output_range}@> && @\libconcept{invocable}@ && + @\libconcept{uniform_random_bit_generator}@> +constexpr borrowed_iterator_t ranges::generate_random(R&& r, G&& g, D&& d); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +Calls \tcode{d.generate_random(std::forward(r), g)} +if this expression is well-formed. +\item +Otherwise, if \tcode{R} models \tcode{sized_range}, +fills \tcode{r} with \tcode{ranges::size(r)} values of +type \tcode{invoke_result_t} +by performing an unspecified number of invocations of +the form \tcode{invoke(d, g)} or \tcode{d.generate_random(s, g)}, +if such an expression is well-formed +for a value \tcode{N} and +an object \tcode{s} of type \tcode{span, N>}. +\begin{note} +Values of N can differ between invocations. +\end{note} +\item +Otherwise, calls +\begin{codeblock} +ranges::generate(std::forward(r), [&d, &g] { return invoke(d, g); }); +\end{codeblock} +\end{itemize} + +\pnum +\returns +\tcode{ranges::end(r)} + +\pnum +\remarks +The effects of \tcode{generate_random(r, g, d)} shall be equivalent to +\begin{codeblock} +ranges::generate(std::forward(r), [&d, &g] { return invoke(d, g); })} +\end{codeblock} +\begin{note} +This implies that \tcode{d.generate_random(a, g)} +fills \tcode{a} with the values with the same random distribution +as produced by invocation of \tcode{invoke(d, g)}. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +template> O, @\libconcept{sentinel_for}@ S> + requires @\libconcept{invocable}@ && @\libconcept{uniform_random_bit_generator}@> +constexpr O ranges::generate_random(O first, S last, G&& g, D&& d); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return generate_random(subrange(std::move(first), last), g, d); +\end{codeblock} +\end{itemdescr} + \rSec1[alg.c.library]{C library algorithms} \pnum diff --git a/source/back.tex b/source/back.tex index 335f834a90..4d9a27a1ec 100644 --- a/source/back.tex +++ b/source/back.tex @@ -25,7 +25,7 @@ \bibitem{unicode-charmap} Unicode Character Mapping Markup Language [online]. Edited by Mark Davis and Markus Scherer. Revision 5.0.1; 2017-05-31 - Available from: \url{http://www.unicode.org/reports/tr22/tr22-8.html} + Available from: \url{https://www.unicode.org/reports/tr22/tr22-8.html} % Literature references. \bibitem{cpp-r} Bjarne Stroustrup, diff --git a/source/basic.tex b/source/basic.tex index aa5ea9413a..1343ca29f2 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -228,7 +228,7 @@ a \grammarterm{template-declaration}\iref{temp.pre} whose \grammarterm{template-head} is not followed by either a \grammarterm{concept-definition} or a \grammarterm{declaration} -that defines a function, a class, a variable, or a static data member. +that defines a function, a class, a variable, or a static data member, \item it is an explicit instantiation declaration\iref{temp.explicit}, or \item it is @@ -465,8 +465,8 @@ \pnum \tcode{*\keyword{this}} is odr-used if \keyword{this} appears as a potentially-evaluated expression -(including as the result of the implicit transformation in the body of a non-static -member function\iref{class.mfct.non.static}). +(including as the result of any implicit transformation to +a class member access expression\iref{expr.prim.id.general}). \pnum A virtual member @@ -537,6 +537,27 @@ \end{codeblock} \end{example} +\pnum +\begin{example} +\begin{codeblock} +void g() { + constexpr int x = 1; + auto lambda = [] {}; // OK + lambda.operator()(); // OK, does not consider \tcode{x} at all + lambda.operator()(); // OK, does not odr-use \tcode{x} + lambda.operator()(); // error: odr-uses \tcode{x} from a context where \tcode{x} is not odr-usable +} + +void h() { + constexpr int x = 1; + auto lambda = [] { (T)x; }; // OK + lambda.operator()(); // OK, does not odr-use \tcode{x} + lambda.operator()(); // OK, does not odr-use \tcode{x} + lambda.operator()(); // error: odr-uses \tcode{x} from a context where \tcode{x} is not odr-usable +} +\end{codeblock} +\end{example} + \pnum Every program shall contain at least one definition of every function or variable that is odr-used in that program @@ -1129,8 +1150,8 @@ the locus of the declaration that hides it. \begin{example} \begin{codeblock} -const int i = 2; -{ int i[i]; } +const int i = 2; +{ int i[i]; } \end{codeblock} declares a block-scope array of two integers. \end{example} @@ -1351,7 +1372,7 @@ in the \grammarterm{lambda-expression}. \item If $P$ is associated with a \grammarterm{requirement-parameter-list}, -its scope extends to the end of the \grammarterm{requirement-body} of the requires-expression. +its scope extends to the end of the \grammarterm{requirement-body} of the \grammarterm{requires-expression}. \item If $P$ is associated with a \grammarterm{deduction-guide}, its scope extends to the end of the \grammarterm{deduction-guide}. @@ -2034,7 +2055,7 @@ its associated entities are: the class itself; the class of which it is a member, if any; -and its direct and indirect base classes. +and, if it is a complete type, its direct and indirect base classes. Furthermore, if \tcode{T} is a class template specialization, its associated entities also include: the entities @@ -3682,12 +3703,12 @@ \begin{codeblock} class T { }; struct B { - ~B(); + ~B(); }; void h() { - B b; - new (&b) T; + B b; + new (&b) T; } // undefined behavior at block exit \end{codeblock} \end{example} @@ -3723,26 +3744,49 @@ \end{note} \indextext{object lifetime|)} -\rSec2[basic.indet]{Indeterminate values} +\rSec2[basic.indet]{Indeterminate and erroneous values} \pnum \indextext{value!indeterminate}% \indextext{indeterminate value}% When storage for an object with automatic or dynamic storage duration -is obtained, the object has an \defnadj{indeterminate}{value}, and if -no initialization is performed for the object, that object retains an -indeterminate value until that value is replaced\iref{expr.ass}. +is obtained, +the bytes comprising the storage for the object +have the following initial value: +\begin{itemize} +\item +If the object has dynamic storage duration, or +is the object associated with a variable or function parameter +whose first declaration is marked with +the \tcode{[[indeterminate]]} attribute\iref{dcl.attr.indet}, +the bytes have \defnadjx{indeterminate}{values}{value}; +\item +otherwise, the bytes have erroneous values, +where each value is determined by the implementation +independently of the state of the program. +\end{itemize} +If no initialization is performed for an object (including subobjects), +such a byte retains its initial value +until that value is replaced\iref{dcl.init.general,expr.ass}. +If any bit in the value representation has an indeterminate value, +the object has an indeterminate value; +otherwise, if any bit in the value representation has an erroneous value, +the object has an erroneous value\iref{conv.lval}. \begin{note} Objects with static or thread storage duration are zero-initialized, see~\ref{basic.start.static}. \end{note} \pnum -If an indeterminate value is produced by an evaluation, -the behavior is undefined except in the following cases: +Except in the following cases, +if an indeterminate value is produced by an evaluation, +the behavior is undefined, and +if an erroneous value is produced by an evaluation, +the behavior is erroneous and +the result of the evaluation is the value so produced but is not erroneous: \begin{itemize} \item - If an indeterminate value of + If an indeterminate or erroneous value of unsigned ordinary character type\iref{basic.fundamental} or \tcode{std::byte} type\iref{cstddef.syn} is produced by the evaluation of: @@ -3759,37 +3803,69 @@ \item a discarded-value expression\iref{expr.context}, \end{itemize} - then the result of the operation is an indeterminate value. + then the result of the operation is an indeterminate value or + that errorneous value, respectively. \item - If an indeterminate value of + If an indeterminate or erroneous value of unsigned ordinary character type or \tcode{std::byte} type is produced by the evaluation of the right operand of a simple assignment operator\iref{expr.ass} whose first operand is an lvalue of unsigned ordinary character type or \tcode{std::byte} type, - an indeterminate value replaces + an indeterminate value or that erroneous value, respectively, replaces the value of the object referred to by the left operand. \item - If an indeterminate value of unsigned ordinary character type + If an indeterminate or erroneous value of unsigned ordinary character type is produced by the evaluation of the initialization expression when initializing an object of unsigned ordinary character type, that object is initialized to an indeterminate - value. + value or that erroneous value, respectively. \item If an indeterminate value of unsigned ordinary character type or \tcode{std::byte} type is produced by the evaluation of the initialization expression when initializing an object of \tcode{std::byte} type, - that object is initialized to an indeterminate value. + that object is initialized to an indeterminate value or + that erroneous value, respectively. \end{itemize} +Converting an indeterminate or erroneous value of +unsigned ordinary character type or \tcode{std::byte} type +produces an indeterminate or erroneous value, respectively. +In the latter case, +the result of the conversion is the value of the converted operand. \begin{example} \begin{codeblock} int f(bool b) { - unsigned char c; - unsigned char d = c; // OK, \tcode{d} has an indeterminate value + unsigned char *c = new unsigned char; + unsigned char d = *c; // OK, \tcode{d} has an indeterminate value int e = d; // undefined behavior return b ? d : 0; // undefined behavior if \tcode{b} is \tcode{true} } + +int g(bool b) { + unsigned char c; + unsigned char d = c; // no erroneous behavior, but \tcode{d} has an erroneous value + + assert(c == d); // holds, both integral promotions have erroneous behavior + + int e = d; // erroneous behavior + return b ? d : 0; // erroneous behavior if \tcode{b} is \tcode{true} +} + +void h() { + int d1, d2; + + int e1 = d1; // erroneous behavior + int e2 = d1; // erroneous behavior + + assert(e1 == e2); // holds + assert(e1 == d1); // holds, erroneous behavior + assert(e2 == d1); // holds, erroneous behavior + + std::memcpy(&d2, &d1, sizeof(int)); // no erroneous behavior, but \tcode{d2} has an erroneous value + assert(e1 == d2); // holds, erroneous behavior + assert(e2 == d2); // holds, erroneous behavior +} \end{codeblock} \end{example} @@ -3809,6 +3885,10 @@ \item automatic storage duration \item dynamic storage duration \end{itemize} +\begin{note} +After the duration of a region of storage has ended, +the use of pointers to that region of storage is limited\iref{basic.compound}. +\end{note} \pnum \indextext{storage duration!static}% @@ -3816,31 +3896,16 @@ \indextext{storage duration!automatic}% \indextext{storage duration!dynamic}% Static, thread, and automatic storage durations are associated with objects -introduced by declarations\iref{basic.def} and implicitly created by -the implementation\iref{class.temporary}. The dynamic storage duration +introduced by declarations\iref{basic.def} and +with temporary objects\iref{class.temporary}. +The dynamic storage duration is associated with objects created by a -\grammarterm{new-expression}\iref{expr.new}. +\grammarterm{new-expression}\iref{expr.new} or +with implicitly created objects\iref{intro.object}. \pnum The storage duration categories apply to references as well. -\pnum -When the end of the duration of a region of storage is reached, -the values of all pointers -representing the address of any part of that region of storage -become invalid pointer values\iref{basic.compound}. -Indirection through an invalid pointer value and -passing an invalid pointer value to a deallocation function -have undefined behavior. -Any other use of an invalid pointer value has -\impldef{any use of an invalid pointer other than to perform indirection or deallocate} -behavior. -\begin{footnote} -Some implementations might define that -copying an invalid pointer value -causes a system-generated runtime fault. -\end{footnote} - \rSec3[basic.stc.static]{Static storage duration} \pnum @@ -3897,15 +3962,16 @@ \pnum \indextext{storage duration!local object}% -Variables that belong to a block or parameter scope and are +Variables that belong to a block scope and are not explicitly declared \keyword{static}, \keyword{thread_local}, or \keyword{extern} have \defnadj{automatic}{storage duration}. The storage -for these entities lasts until the block in which they are created exits. - -\pnum +for such variables lasts until the block in which they are created exits. \begin{note} These variables are initialized and destroyed as described in~\ref{stmt.dcl}. \end{note} +Variables that belong to a parameter scope also have automatic storage duration. +The storage for a function parameter lasts until +immediately after its destruction\iref{expr.call}. \pnum If a variable with automatic storage duration has initialization or a destructor with side @@ -4285,15 +4351,9 @@ Temporary objects are created \begin{itemize} \item -when a prvalue is converted to an xvalue\iref{conv.rval}, +when a prvalue is converted to an xvalue\iref{conv.rval} and \item -when needed by the implementation to pass or return an object of trivially copyable type (see below), -and -\item -when throwing an exception\iref{except.throw}. -\begin{note} -The lifetime of exception objects is described in~\ref{except.throw}. -\end{note} +when needed by the implementation to pass or return an object of trivially copyable type (see below). \end{itemize} Even when the creation of the temporary object is unevaluated\iref{expr.context}, @@ -4318,7 +4378,9 @@ when binding a reference to a prvalue\iref{dcl.init.ref,expr.type.conv, expr.dynamic.cast,expr.static.cast,expr.const.cast,expr.cast}, \item -when performing member access on a class prvalue\iref{expr.ref,expr.mptr.oper}, +when performing certain member accesses on a class prvalue\iref{expr.ref,expr.mptr.oper}, +\item +when invoking an implicit object member function on a class prvalue\iref{expr.call}, \item when performing an array-to-pointer conversion or subscripting on an array prvalue\iref{conv.array,expr.sub}, \item @@ -4525,8 +4587,6 @@ persists until the completion of the full-expression containing the \grammarterm{expression-list}. -\item The lifetime of a temporary bound to the returned value in a function \tcode{return} statement\iref{stmt.return} is not extended; the temporary is destroyed at the end of the full-expression in the \tcode{return} statement. - \item A temporary bound to a reference in a \grammarterm{new-initializer}\iref{expr.new} persists until the completion of the full-expression containing the \grammarterm{new-initializer}. \begin{note} This might introduce a dangling reference. @@ -4541,7 +4601,7 @@ \end{itemize} \pnum -The fourth context is when a temporary object other than a function parameter object +The fourth context is when a temporary object is created in the \grammarterm{for-range-initializer} of a range-based \keyword{for} statement. If such a temporary object would otherwise be destroyed at the end of the \grammarterm{for-range-initializer} full-expression, @@ -4549,10 +4609,13 @@ initialized by the \grammarterm{for-range-initializer}. \pnum -The destruction of a temporary whose lifetime is not extended -beyond the full-expression in which it was created -is sequenced before the destruction of every -temporary which is constructed earlier in the same full-expression. +Let \tcode{x} and \tcode{y} each be either +a temporary object whose lifetime is not extended, or +a function parameter. +If the lifetimes of \tcode{x} and \tcode{y} end at +the end of the same full-expression, and +\tcode{x} is initialized before \tcode{y}, then +the destruction of \tcode{y} is sequenced before that of \tcode{x}. If the lifetime of two or more temporaries with lifetimes extending beyond the full-expressions in which they were created ends at the same point, @@ -4812,7 +4875,7 @@ } struct X { int i; }; // now \tcode{X} is a complete type -int arr[10]; // now the type of \tcode{arr} is complete +int arr[10]; // now the type of \tcode{arr} is complete X x; void bar() { @@ -5207,6 +5270,7 @@ to type \cv{}~\keyword{void}. \pnum +The types denoted by \cv~\tcode{std::nullptr_t} are distinct types. A value of type \tcode{std::nullptr_t} is a null pointer constant\iref{conv.ptr}. Such values participate in the pointer and the pointer-to-member conversions\iref{conv.ptr,conv.mem}. @@ -5416,10 +5480,6 @@ is not considered to point to an unrelated object of the object's type, even if the unrelated object is located at that address. -A pointer value becomes invalid -when the storage it denotes -reaches the end of its storage duration; -see \ref{basic.stc}. \end{note} For purposes of pointer arithmetic\iref{expr.add} and comparison\iref{expr.rel,expr.eq}, @@ -5440,6 +5500,31 @@ alignment requirement. \end{note} +\pnum +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 it is a pointer to or past the end of an object $O$ and +$E$ happens before the end of the duration of the region of storage for $O$. +If a pointer value $P$ is used in an evaluation $E$ and +$P$ is not valid in the context of $E$, +then the behavior is undefined if $E$ is +an indirection\iref{expr.unary.op} or +an invocation of a deallocation function\iref{basic.stc.dynamic.deallocation}, +and \impldef{invalid pointer value in the context of an evaluation} otherwise. +\begin{footnote} +Some implementations might define that +copying such a pointer value causes a system-generated runtime fault. +\end{footnote} +\begin{note} +$P$ can be valid in the context of $E$ even +if it points to a type unrelated to that of $O$ or +if $O$ is not within its lifetime, +although further restrictions apply +to such pointer values\iref{basic.life, basic.lval, expr.add}. +\end{note} + \pnum Two objects \placeholder{a} and \placeholder{b} are \defn{pointer-interconvertible} if: \begin{itemize} @@ -6202,15 +6287,15 @@ The ``inter-thread happens before'' relation describes arbitrary concatenations of ``sequenced before'', ``synchronizes with'' and ``dependency-ordered before'' relationships, with two exceptions. The first -exception is that a concatenation is not permitted to end with +exception is that a concatenation never ends with ``dependency-ordered before'' followed by ``sequenced before''. The reason for this limitation is that a consume operation participating in a ``dependency-ordered before'' relationship provides ordering only with respect to operations to which this consume operation actually carries a dependency. The reason that this limitation applies only to the end of such a concatenation is that any subsequent release operation will provide the required ordering for a -prior consume operation. The second exception is that a concatenation is not -permitted to consist entirely of ``sequenced before''. The reasons for this +prior consume operation. The second exception is that a concatenation never +consist entirely of ``sequenced before''. The reasons for this limitation are (1) to permit ``inter-thread happens before'' to be transitively closed and (2) the ``happens before'' relation, defined below, provides for relationships consisting entirely of ``sequenced before''. @@ -6290,7 +6375,7 @@ \begin{note} This states that operations on ordinary objects are not visibly reordered. This is not actually detectable -without data races, but it is necessary to ensure that data races, as defined +without data races, but is needed to ensure that data races, as defined below, and with suitable restrictions on the use of atomics, correspond to data races in a simple interleaved (sequentially consistent) execution. \end{note} @@ -6401,7 +6486,7 @@ However, this applies only to data-race-free programs, and data-race-free programs cannot observe most program transformations that do not change single-threaded program semantics. In fact, most single-threaded program -transformations continue to be allowed, since any program that behaves +transformations remain possible, since any program that behaves differently as a result has undefined behavior. \end{note} @@ -6448,13 +6533,18 @@ following: \begin{itemize} \item terminate, +\item invoke the function \tcode{std::this_thread::yield}\iref{thread.thread.this}, \item make a call to a library I/O function, -\item perform an access through a volatile glvalue, or -\item perform a synchronization operation or an atomic operation. +\item perform an access through a volatile glvalue, +\item perform a synchronization operation or an atomic operation, or +\item continue execution of a trivial infinite loop\iref{stmt.iter.general}. \end{itemize} \begin{note} -This is intended to allow compiler transformations such as removal of -empty loops, even when termination cannot be proven. +This is intended to allow compiler transformations +such as removal, merging, and reordering of empty loops, +even when termination cannot be proven. +An affordance is made for trivial infinite loops, +which cannot be removed nor reordered. \end{note} \pnum @@ -6538,7 +6628,7 @@ the implementation ensures that the thread will eventually make progress for as long as it has not terminated. \begin{note} -This is required regardless of whether or not other threads of execution (if any) +This applies regardless of whether or not other threads of execution (if any) have been or are making progress. To eventually fulfill this requirement means that this will happen in an unspecified but finite amount of time. \end{note} @@ -6703,8 +6793,7 @@ Any further (optional) parameters should be added after \tcode{argv}. \pnum -The function \tcode{main} shall not be used within -a program. +The function \tcode{main} shall not be named by an expression. \indextext{\idxcode{main} function!implementation-defined linkage of}% The linkage\iref{basic.link} of \tcode{main} is \impldef{linkage of \tcode{main}}. A program that defines \tcode{main} as diff --git a/source/classes.tex b/source/classes.tex index 65231de79a..1472b94a64 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -72,7 +72,8 @@ it is not looked up, and the \grammarterm{class-specifier} introduces it. \pnum -The +\indextext{component name}% +The component name of the \grammarterm{class-name} is also bound in the scope of the class (template) itself; this is known as the \defn{injected-class-name}. For purposes of access checking, the injected-class-name is treated as @@ -461,6 +462,7 @@ \nontermdef{member-declaration}\br \opt{attribute-specifier-seq} \opt{decl-specifier-seq} \opt{member-declarator-list} \terminal{;}\br function-definition\br + friend-type-declaration\br using-declaration\br using-enum-declaration\br static_assert-declaration\br @@ -482,7 +484,7 @@ \nontermdef{member-declarator}\br declarator \opt{virt-specifier-seq} \opt{pure-specifier}\br declarator requires-clause\br - declarator \opt{brace-or-equal-initializer}\br + declarator brace-or-equal-initializer\br \opt{identifier} \opt{attribute-specifier-seq} \terminal{:} constant-expression \opt{brace-or-equal-initializer} \end{bnf} @@ -503,6 +505,36 @@ \terminal{=} \terminal{0} \end{bnf} +\begin{bnf} +\nontermdef{friend-type-declaration}\br + \keyword{friend} friend-type-specifier-list \terminal{;} +\end{bnf} + +\begin{bnf} +\nontermdef{friend-type-specifier-list}\br + friend-type-specifier \opt{\terminal{...}}\br + friend-type-specifier-list \terminal{,} friend-type-specifier \opt{\terminal{...}} +\end{bnf} + +\begin{bnf} +\nontermdef{friend-type-specifier}\br + simple-type-specifier\br + elaborated-type-specifier\br + typename-specifier +\end{bnf} + +\pnum +In the absence of a \grammarterm{virt-specifier-seq}, +the token sequence \tcode{= 0} is treated as a \grammarterm{pure-specifier} +if the type of the \grammarterm{declarator-id}\iref{dcl.meaning.general} +is a function type, and +is otherwise treated as a \grammarterm{brace-or-equal-initializer}. +\begin{note} +If the member declaration acquires a function type through +template instantiation, +the program is ill-formed; see~\ref{temp.spec.general}. +\end{note} + \pnum \indextext{definition!class}% The \grammarterm{member-specification} in a class definition declares the @@ -610,6 +642,11 @@ or if $P$ is in a complete-class context of \tcode{C}. Otherwise, \tcode{C} is incomplete at $P$. +\pnum +If a \grammarterm{member-declaration} matches +the syntactic requirements of \grammarterm{friend-type-declaration}, +it is a \grammarterm{friend-type-declaration}. + \pnum In a \grammarterm{member-declarator}, an \tcode{=} immediately following the \grammarterm{declarator} @@ -765,7 +802,7 @@ \item every member function of class \tcode{T}; \begin{note} This restriction does not apply to constructors, which do not have -names\iref{class.ctor} +names\iref{class.ctor}. \end{note}% \item every member of class \tcode{T} that is itself a type; @@ -943,66 +980,6 @@ its class or a class derived from its class, or a member thereof, as described below. -\pnum -When an \grammarterm{id-expression}\iref{expr.prim.id} that is -neither part of a class member access syntax\iref{expr.ref} -nor the unparenthesized operand of -the unary \tcode{\&} operator\iref{expr.unary.op} is used -where the current class is \tcode{X}\iref{expr.prim.this}, -if name -lookup\iref{basic.lookup} resolves the name in the -\grammarterm{id-expression} to a non-static non-type member of some class -\tcode{C}, -and if either the \grammarterm{id-expression} is potentially evaluated or -\tcode{C} is \tcode{X} or a base class of \tcode{X}, -the \grammarterm{id-expression} is transformed into a class -member access expression\iref{expr.ref} using -\tcode{(*this)} as the \grammarterm{postfix-expression} -to the left of the \tcode{.} operator. -\begin{note} -If \tcode{C} is not \tcode{X} or a base class of \tcode{X}, the class -member access expression is ill-formed. -\end{note} -This transformation does not apply in the -template definition context\iref{temp.dep.type}. -\begin{example} -\begin{codeblock} -struct tnode { - char tword[20]; - int count; - tnode* left; - tnode* right; - void set(const char*, tnode* l, tnode* r); -}; - -void tnode::set(const char* w, tnode* l, tnode* r) { - count = strlen(w)+1; - if (sizeof(tword)<=count) - perror("tnode string too long"); - strcpy(tword,w); - left = l; - right = r; -} - -void f(tnode n1, tnode n2) { - n1.set("abc",&n2,0); - n2.set("def",0,0); -} -\end{codeblock} - -In the body of the member function \tcode{tnode::set}, the member names -\tcode{tword}, \tcode{count}, \tcode{left}, and \tcode{right} refer to -members of the object for which the function is called. Thus, in the -call \tcode{n1.set("abc",\&n2,0)}, \tcode{tword} refers to -\tcode{n1.tword}, and in the call \tcode{n2.set("def",0,0)}, it refers -to \tcode{n2.tword}. The functions \tcode{strlen}, \tcode{perror}, and -\tcode{strcpy} are not members of the class \tcode{tnode} and should be -declared elsewhere. -\begin{footnote} -See, for example, \libheaderref{cstring}. -\end{footnote} -\end{example} - \pnum \indextext{member function!const}% \indextext{member function!volatile}% @@ -1012,7 +989,7 @@ \grammarterm{cv-qualifier}{s}, which affect the type of the \keyword{this} pointer\iref{expr.prim.this}, and/or a \grammarterm{ref-qualifier}\iref{dcl.fct}; -both affect overload resolution\iref{over.match.funcs} +both affect overload resolution\iref{over.match.funcs}. \end{note} \pnum @@ -1330,7 +1307,7 @@ \indextext{constructor!implicitly invoked}% A default constructor is implicitly invoked to initialize a class object when no initializer is specified\iref{dcl.init.general}. -Such a default constructor is required to be accessible\iref{class.access}. +Such a default constructor needs to be accessible\iref{class.access}. \end{note} \pnum @@ -2435,10 +2412,9 @@ its \grammarterm{declarator} shall be a function declarator\iref{dcl.fct} of the form \begin{ncsimplebnf} -ptr-declarator \terminal{(} parameter-declaration-clause \terminal{)} \opt{cv-qualifier-seq}\br -\bnfindent \opt{ref-qualifier} \opt{noexcept-specifier} \opt{attribute-specifier-seq} +noptr-declarator parameters-and-qualifiers \end{ncsimplebnf} -where the \grammarterm{ptr-declarator} consists solely of +where the \grammarterm{noptr-declarator} consists solely of an \grammarterm{id-expression}, an optional \grammarterm{attribute-specifier-seq}, and optional surrounding parentheses, and @@ -2457,6 +2433,7 @@ \pnum A conversion function shall have no non-object parameters and shall be a non-static member function of a class or class template \tcode{X}; +its declared return type is the \grammarterm{conversion-type-id} and it specifies a conversion from \tcode{X} to the type specified by the \grammarterm{conversion-type-id}, interpreted as a \grammarterm{type-id}\iref{dcl.name}. @@ -2464,13 +2441,6 @@ of a conversion function (if any) shall not be a \grammarterm{defining-type-specifier}. -\pnum -\indextext{conversion!type of}% -The type of the conversion function is -``\opt{\tcode{noexcept}} function taking no parameter -\opt{\grammarterm{cv-qualifier-seq}} \opt{\grammarterm{ref-qualifier}} -returning \grammarterm{conversion-type-id}''. - \pnum \begin{note} A conversion function is never invoked for @@ -3074,8 +3044,7 @@ structs that share a common initial sequence\iref{class.mem}, and if a non-static data member of an object of this standard-layout union type is active and is one of the standard-layout structs, -it is permitted to inspect the common initial sequence -of any of the standard-layout struct members; +the common initial sequence of any of the standard-layout struct members can be inspected; see~\ref{class.mem}. \end{note} @@ -4842,27 +4811,22 @@ \pnum A friend declaration that does not declare a function -shall have one of the following forms: - -\begin{ncsimplebnf} -\keyword{friend} elaborated-type-specifier \terminal{;}\br -\keyword{friend} simple-type-specifier \terminal{;}\br -\keyword{friend} typename-specifier \terminal{;} -\end{ncsimplebnf} +shall be a \grammarterm{friend-type-declaration}. \begin{note} A friend declaration can be the \grammarterm{declaration} in a \grammarterm{template-declaration}\iref{temp.pre,temp.friend}. \end{note} -If the -type specifier in a friend declaration designates a (possibly +If a \grammarterm{friend-type-specifier} in a friend declaration +designates a (possibly cv-qualified) class type, that class is declared as a friend; otherwise, the -friend declaration is ignored. +\grammarterm{friend-type-specifier} is ignored. \begin{example} \begin{codeblock} class C; typedef C Ct; +class E; class X1 { friend C; // OK, \tcode{class C} is a friend @@ -4874,12 +4838,22 @@ friend class D; // OK, elaborated-type-specifier declares new class }; -template class R { - friend T; +template class R { + friend Ts...; +}; + +template +class R, R> { + friend Ts::Nested..., Us...; }; R rc; // \tcode{class C} is a friend of \tcode{R} -R Ri; // OK, \tcode{"friend int;"} is ignored +R rce; // classes \tcode{C} and \tcode{E} are friends of \tcode{R} +R Ri; // OK, ``\tcode{friend int;}'' is ignored + +struct E { struct Nested; }; + +R, R> rr; // \tcode{E::Nested} and \tcode{C} are friends of \tcode{R, R>} \end{codeblock} \end{example} @@ -5560,7 +5534,7 @@ is neither initialized nor given a value during execution of the \grammarterm{compound-statement} of the body of the constructor, -the member has an indeterminate value. +the member has an indeterminate or erroneous value\iref{basic.indet}. \end{note} \begin{example} \begin{codeblock} @@ -5576,7 +5550,7 @@ C() { } // initializes members as follows: A a; // OK, calls \tcode{A::A()} const B b; // error: \tcode{B} has no default constructor - int i; // OK, \tcode{i} has indeterminate value + int i; // OK, \tcode{i} has indeterminate or erroneous value int j = 5; // OK, \tcode{j} has the value \tcode{5} }; \end{codeblock} @@ -6408,12 +6382,15 @@ \pnum A defaulted comparison operator function\iref{over.binary} -for some class \tcode{C} shall be a non-template function -that is +that \begin{itemize} \item -a non-static member or friend of \tcode{C} and +is a non-static member or friend of some class \tcode{C}, + +\item +is defined as defaulted in \tcode{C} or in +a context where \tcode{C} is complete, and \item either has @@ -6422,13 +6399,28 @@ where the implicit object parameter (if any) is considered to be the first parameter. \end{itemize} -Name lookups in the implicit definition\iref{dcl.fct.def.default} +Such a comparison operator function is termed +\indextext{operator!defaulted comparison operator function}% +a defaulted comparison operator function for class \tcode{C}. +Name lookups and access checks in +the implicit definition\iref{dcl.fct.def.default} of a comparison operator function are performed from a context equivalent to its \grammarterm{function-body}. A definition of a comparison operator as defaulted that appears in a class shall be the first declaration of that function. +\begin{example} +\begin{codeblock} +struct S; +bool operator==(S, S) = default; // error: \tcode{S} is not complete +struct S { + friend bool operator==(S, const S&) = default; // error: parameters of different types +}; +enum E { }; +bool operator==(E, E) = default; // error: not a member or friend of a class +\end{codeblock} +\end{example} \pnum A defaulted \tcode{<=>} or \tcode{==} operator function for class \tcode{C} @@ -6696,18 +6688,29 @@ is defined as deleted if \begin{itemize} \item -overload resolution\iref{over.match}, +a first overload resolution\iref{over.match}, as applied to \tcode{x @ y}, +\begin{itemize} +\item does not result in a usable candidate, or - \item -the candidate selected by overload resolution -is not a rewritten candidate. +the selected candidate is not a rewritten candidate, or \end{itemize} +\item +a second overload resolution for +the expression resulting from the interpretation of \tcode{x @ y} +using the selected rewritten candidate\iref{over.match.oper} +does not result in a usable candidate +(for example, that expression might be \tcode{(x <=> y) @ 0}), or + +\item +\tcode{x @ y} cannot be implicitly converted to \tcode{bool}. +\end{itemize} +In any of the two overload resolutions above, +the defaulted operator function is not considered as +a candidate for the \tcode{@} operator. Otherwise, the operator function yields \tcode{x @ y}. -The defaulted operator function is not considered as a candidate -in the overload resolution for the \tcode{@} operator. \pnum \begin{example} diff --git a/source/compatibility.tex b/source/compatibility.tex index 4e1948add1..e3ff48606f 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -155,6 +155,18 @@ // OK in \CppXXVI{} \end{codeblock} +\nodiffref +\change +Removal of atomic access API for \tcode{shared_ptr} objects. +\rationale +The old behavior was brittle. \tcode{shared_ptr} objects using the old API were +not protected by the type system, and certain interactions with code not using +this API would, in some cases, silently produce undefined behavior. A complete +type-safe replacement is provided in the form of \tcode{atomic>}. +\effect +A valid \CppXXIII{} program that relies on the presence of the removed functions +may fail to compile. + \nodiffref \change Remove the \tcode{basic_string::reserve()} overload with no parameters. @@ -190,6 +202,37 @@ \item \tcode{little_endian}. \end{itemize} +\nodiffref +\change +Remove header \libnoheader{strstream} and all its contents. +\rationale +The header has been deprecated since the original \Cpp{} standard; the +\libheader{spanstream} header provides an updated, safer facility. +Ongoing support is at implementer's discretion, +exercising freedoms granted by \ref{zombie.names}. +\effect +A valid \CppXXIII{} program \tcode{\#include}-ing the header or importing the +header unit may become ill-formed. Code that uses any of the following classes +by importing one of the standard library modules may become ill-formed: +\begin{itemize} +\item \tcode{istrstream} +\item \tcode{ostrstream} +\item \tcode{strstream} +\item \tcode{strstreambuf} +\end{itemize} + +\nodiffref +\change +Remove convenience interfaces \tcode{wstring_convert} and +\tcode{wbuffer_convert}. +\rationale +These features were underspecified with no clear error reporting mechanism and +were deprecated for the last three editions of this standard. +Ongoing support is at implementer's discretion, +exercising freedoms granted by \ref{zombie.names}. +\effect +A valid \CppXXIII{} program using these interfaces may become ill-formed. + \rSec1[diff.cpp20]{\Cpp{} and ISO \CppXX{}} \rSec2[diff.cpp20.general]{General} @@ -984,11 +1027,11 @@ and for which name lookup finds nothing or finds a function will be treated as a \grammarterm{template-name} -in order to potentially cause argument dependent lookup to be performed. +in order to potentially cause argument-dependent lookup to be performed. \rationale It was problematic to call a function template with an explicit template argument list -via argument dependent lookup +via argument-dependent lookup because of the need to have a template with the same name visible via normal lookup. \effect @@ -2881,8 +2924,8 @@ \end{codeblock} \rationale -This is to avoid erroneous function calls (i.e., function calls -with the wrong number or type of arguments). +This is to avoid function calls +with the wrong number or type of arguments. \effect Change to semantics of well-defined feature. This feature was marked as ``obsolescent'' in C. diff --git a/source/config.tex b/source/config.tex index e80dc71ea2..bac1ee788a 100644 --- a/source/config.tex +++ b/source/config.tex @@ -1,8 +1,8 @@ %!TEX root = std.tex %%-------------------------------------------------- %% Version numbers -\newcommand{\docno}{N4971} -\newcommand{\prevdocno}{N4964} +\newcommand{\docno}{N4981} +\newcommand{\prevdocno}{N4971} \newcommand{\cppver}{202302L} %% Release date diff --git a/source/containers.tex b/source/containers.tex index 3644b97916..ece8bdea92 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -958,7 +958,7 @@ and its evaluation causes the following postcondition to hold: The value of \tcode{*p} is equivalent to the value of \tcode{rv} before the evaluation. \begin{note} -\tcode{rv} remains a valid object. Its state is unspecified +\tcode{rv} remains a valid object. Its state is unspecified. \end{note} \item @@ -2719,7 +2719,7 @@ and \tcode{mapped_type}. \begin{note} For example, in some cases \tcode{key_type} and \tcode{mapped_type} -are required to be \oldconcept{CopyAssignable} even though the associated +need to be \oldconcept{CopyAssignable} even though the associated \tcode{value_type}, \tcode{pair}, is not \oldconcept{CopyAssignable}. \end{note} @@ -4217,7 +4217,7 @@ apply instead to \tcode{key_type} and \tcode{mapped_type}. \begin{note} For example, \tcode{key_type} and \tcode{mapped_type} -are sometimes required to be \oldconcept{CopyAssignable} +sometimes need to be \oldconcept{CopyAssignable} even though the associated \tcode{value_type}, \tcode{pair}, is not \oldconcept{CopyAssignable}. @@ -6039,7 +6039,7 @@ noexcept(noexcept(x.swap(y))); // \ref{deque.erasure}, erasure - template + template typename deque::size_type erase(deque& c, const U& value); template @@ -6075,7 +6075,7 @@ noexcept(noexcept(x.swap(y))); // \ref{forward.list.erasure}, erasure - template + template typename forward_list::size_type erase(forward_list& c, const U& value); template @@ -6111,7 +6111,7 @@ noexcept(noexcept(x.swap(y))); // \ref{list.erasure}, erasure - template + template typename list::size_type erase(list& c, const U& value); template @@ -6147,7 +6147,7 @@ noexcept(noexcept(x.swap(y))); // \ref{vector.erasure}, erasure - template + template constexpr typename vector::size_type erase(vector& c, const U& value); template @@ -6919,7 +6919,7 @@ \indexlibrarymember{erase}{deque}% \begin{itemdecl} -template +template typename deque::size_type erase(deque& c, const U& value); \end{itemdecl} @@ -7832,7 +7832,7 @@ \indexlibrarymember{erase}{forward_list}% \begin{itemdecl} -template +template typename forward_list::size_type erase(forward_list& c, const U& value); \end{itemdecl} @@ -8581,7 +8581,7 @@ \indexlibrarymember{erase}{list}% \begin{itemdecl} -template +template typename list::size_type erase(list& c, const U& value); \end{itemdecl} @@ -9164,7 +9164,7 @@ \indexlibrarymember{erase}{vector}% \begin{itemdecl} -template +template constexpr typename vector::size_type erase(vector& c, const U& value); \end{itemdecl} @@ -18228,6 +18228,20 @@ // constants inline constexpr size_t @\libglobal{dynamic_extent}@ = numeric_limits::max(); + template + concept @\defexposconcept{integral-constant-like}@ = // \expos + is_integral_v && + !is_same_v> && + @\libconcept{convertible_to}@ && + @\libconcept{equality_comparable_with}@ && + bool_constant::value && + bool_constant(T()) == T::value>::value; + + template + constexpr size_t @\defexposconcept{maybe-static-ext}@ = dynamic_extent; // \expos + template<@\exposconcept{integral-constant-like}@ T> + constexpr size_t @\exposconcept{maybe-static-ext}@ = {T::value}; + // \ref{views.span}, class template \tcode{span} template class span; // partially freestanding @@ -18343,7 +18357,8 @@ }; template - span(It, EndOrSize) -> span>>; + span(It, EndOrSize) -> span>, + @\exposconcept{maybe-static-ext}@>; template span(T (&)[N]) -> span; template @@ -18635,7 +18650,8 @@ \indexlibrary{\idxcode{span}!deduction guide}% \begin{itemdecl} template - span(It, EndOrSize) -> span>>; + span(It, EndOrSize) -> span>, + @\exposconcept{maybe-static-ext}@>; \end{itemdecl} \begin{itemdescr} @@ -18837,8 +18853,12 @@ \tcode{idx < size()} is \tcode{true}. \pnum -\effects -Equivalent to: \tcode{return *(data() + idx);} +\returns +\tcode{*(data() + idx)}. + +\pnum +\throws +Nothing. \end{itemdescr} \indexlibrarymember{span}{at}% @@ -18867,8 +18887,12 @@ \tcode{empty()} is \tcode{false}. \pnum -\effects -Equivalent to: \tcode{return *data();} +\returns +\tcode{*data()}. + +\pnum +\throws +Nothing. \end{itemdescr} \indexlibrarymember{span}{back}% @@ -18882,8 +18906,12 @@ \tcode{empty()} is \tcode{false}. \pnum -\effects -Equivalent to: \tcode{return *(data() + (size() - 1));} +\returns +\tcode{*(data() + (size() - 1))}. + +\pnum +\throws +Nothing. \end{itemdescr} \indexlibrarymember{span}{data}% @@ -18893,8 +18921,8 @@ \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{data_};} +\returns +\exposid{data_}. \end{itemdescr} \rSec4[span.iterators]{Iterator support} @@ -19052,6 +19080,10 @@ struct layout_left; struct layout_right; struct layout_stride; + template + struct layout_left_padded; + template + struct layout_right_padded; // \ref{mdspan.accessor.default}, class template \tcode{default_accessor} template @@ -19062,7 +19094,7 @@ class AccessorPolicy = default_accessor> class mdspan; - // \ref{mdspan.submdspan}, \tcode{submdspan} creation + // \ref{mdspan.sub}, \tcode{submdspan} creation template struct strided_slice; @@ -19075,22 +19107,13 @@ template constexpr auto submdspan_extents(const extents&, SliceSpecifiers...); - // \ref{mdspan.submdspan.submdspan}, \tcode{submdspan} function template + // \ref{mdspan.sub.sub}, \tcode{submdspan} function template template constexpr auto submdspan( const mdspan& src, SliceSpecifiers... slices) -> @\seebelow@; - template - concept @\defexposconcept{integral-constant-like}@ = // \expos - is_integral_v && - !is_same_v> && - @\libconcept{convertible_to}@ && - @\libconcept{equality_comparable_with}@ && - bool_constant::value && - bool_constant(T()) == T::value>::value; - template concept @\defexposconcept{index-pair-like}@ = // \expos @\exposconcept{pair-like}@ && @@ -19442,7 +19465,7 @@ \pnum \remarks -The deduced type is \tcode{dextents}. +The deduced type is \tcode{extents...>}. \end{itemdescr} \rSec4[mdspan.extents.obs]{Observers of the multidimensional index space} @@ -19543,13 +19566,47 @@ \end{itemize} \pnum -In subclauses \ref{mdspan.layout.reqmts} through \ref{mdspan.layout.stride}, -let \exposid{is-mapping-of} be the exposition-only variable template defined as follows: +In subclauses \ref{mdspan.layout.reqmts} through \ref{mdspan.layout.stride}: +\begin{itemize} +\item +Let \exposid{is-mapping-of} be the exposition-only variable template defined as follows: \begin{codeblock} template constexpr bool @\exposid{is-mapping-of}@ = // \expos is_same_v, Mapping>; \end{codeblock} +\item +Let \exposid{is-layout-left-padded-mapping-of} be +the exposition-only variable template defined as follows: +\begin{codeblock} +template +constexpr bool @\exposid{is-layout-left-padded-mapping-of}@ = @\seebelow@; // \expos +\end{codeblock} +where \tcode{\exposid{is-layout-left-padded-mapping-of}} is \tcode{true} +if and only if \tcode{Mapping} denotes +a specialization of \tcode{layout_left_padded::mapping} +for some value \tcode{S} of type \tcode{size_t}. +\item +Let \exposid{is-layout-right-padded-mapping-of} be +the exposition-only variable template defined as follows: +\begin{codeblock} +template +constexpr bool @\exposid{is-layout-right-padded-mapping-of}@ = @\seebelow@; // \expos +\end{codeblock} +where \tcode{\exposid{is-layout-right-padded-mapping-of}} is \tcode{true} +if and only if \tcode{Mapping} denotes +a specialization of \tcode{layout_right_padded::mapping} +for some value \tcode{S} of type \tcode{size_t}. +\item +For nonnegative integers $x$ and $y$, +let $\exposid{LEAST-MULTIPLE-AT-LEAST}(x, y)$ denote +\begin{itemize} +\item +$y$ if $x$ is zero, +\item +otherwise, the least multiple of $x$ that is greater than or equal to $y$. +\end{itemize} +\end{itemize} \rSec4[mdspan.layout.reqmts]{Requirements} @@ -19843,6 +19900,15 @@ template class mapping; }; + + template + struct layout_left_padded { + template class mapping; + }; + template + struct layout_right_padded { + template class mapping; + }; } \end{codeblock} @@ -19850,6 +19916,11 @@ 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. + \rSec4[mdspan.layout.left]{Class template \tcode{layout_left::mapping}} \rSec5[mdspan.layout.left.overview]{Overview} @@ -19880,6 +19951,10 @@ template constexpr explicit(!is_convertible_v) mapping(const layout_right::mapping&) noexcept; + template + constexpr explicit(!is_convertible_v) + mapping(const LayoutLeftPaddedMapping&) noexcept; template constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping&); @@ -19908,12 +19983,12 @@ friend constexpr bool operator==(const mapping&, const mapping&) noexcept; private: - extents_type @\exposid{extents_}@{}; // \expos + extents_type @\exposid{extents_}@{}; // \expos - // \ref{mdspan.submdspan.mapping}, \tcode{submdspan} mapping specialization + // \ref{mdspan.sub.map}, \tcode{submdspan} mapping specialization template - constexpr auto @\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; + constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const // \expos + -> @\seebelow@; template friend constexpr auto submdspan_mapping( @@ -20005,6 +20080,56 @@ Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \end{itemdescr} +\indexlibraryctor{layout_left::mapping}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) + mapping(const LayoutLeftPaddedMapping&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{\exposid{is-layout-left-padded-mapping-of}} is \tcode{true}. +\item +\tcode{is_constructible_v}\newline is \tcode{true}. +\end{itemize} + +\pnum +\mandates +If +\begin{itemize} +\item +\tcode{Extents::rank()} is greater than one, +\item +\tcode{Extents::static_extent(0)} does not equal \tcode{dynamic_extent}, and +\item +\tcode{LayoutLeftPaddedMapping::\exposid{static-padding-stride}} +does not equal \tcode{dynamic_extent}, +\end{itemize} +then \tcode{Extents::static_extent(0)} equals +\tcode{LayoutLeftPaddedMapping::\exposid{static-padding-stride}}. + +\pnum +\expects +\begin{itemize} +\item +If \tcode{extents_type::rank() > 1} is \tcode{true}, +then \tcode{other.stride(1)} equals \tcode{other.extents(0)}. +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +Effects: Direct-non-list-initializes +\tcode{extents_} with \tcode{other.extents()}. +\end{itemdescr} + \indexlibraryctor{layout_left::mapping}% \begin{itemdecl} template @@ -20149,6 +20274,10 @@ template constexpr explicit(!is_convertible_v) mapping(const layout_left::mapping&) noexcept; + template + constexpr explicit(!is_convertible_v) + mapping(const LayoutRightPaddedMapping&) noexcept; template constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping&) noexcept; @@ -20179,10 +20308,10 @@ private: extents_type @\exposid{extents_}@{}; // \expos - // \ref{mdspan.submdspan.mapping}, \tcode{submdspan} mapping specialization + // \ref{mdspan.sub.map}, \tcode{submdspan} mapping specialization template - constexpr auto @\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; + constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const // \expos + -> @\seebelow@; template friend constexpr auto submdspan_mapping( @@ -20274,6 +20403,59 @@ Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \end{itemdescr} +\indexlibraryctor{layout_right::mapping}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) + mapping(const LayoutRightPaddedMapping&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{\exposid{is-layout-right-padded-mapping-of}} +is \tcode{true}. +\item +\tcode{is_constructible_v} +is \tcode{true}. +\end{itemize} + +\pnum +\mandates +If +\begin{itemize} +\item +\tcode{Extents::rank()} is greater than one, +\item +\tcode{Extents::static_extent(Extents::rank() - 1)} +does not equal \tcode{dynamic_extent}, and +\item +\tcode{LayoutRightPaddedMapping::\exposid{static-padding-stride}} +does not equal \tcode{dynamic_extent}, +\end{itemize} +then \tcode{Extents::static_extent(Extents::rank() - 1)} equals +\tcode{LayoutRightPaddedMapping::\exposid{sta\-tic-padding-stride}}. + +\pnum +\expects +\begin{itemize} +\item +If \tcode{extents_type::rank() > 1} is \tcode{true}, +then \tcode{other.stride(extents_type::rank() - 2)}\newline equals +\tcode{other.extents().extent(extents_type::rank() - 1)}. +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +Direct-non-list-initializes \tcode{extents_} with \tcode{other.extents()}. +\end{itemdescr} + \indexlibraryctor{layout_right::mapping}% \begin{itemdecl} template @@ -20450,10 +20632,10 @@ extents_type @\exposid{extents_}@{}; // \expos array @\exposid{strides_}@{}; // \expos - // \ref{mdspan.submdspan.mapping}, \tcode{submdspan} mapping specialization + // \ref{mdspan.sub.map}, \tcode{submdspan} mapping specialization template - constexpr auto @\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; + constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const // \expos + -> @\seebelow@; template friend constexpr auto submdspan_mapping( @@ -20662,6 +20844,8 @@ !(is_convertible_v && (@\exposid{is-mapping-of}@ || @\exposid{is-mapping-of}@ || + @\exposid{is-layout-left-padded-mapping-of}@ || + @\exposid{is-layout-right-padded-mapping-of}@ || @\exposid{is-mapping-of}@)) \end{codeblock} \end{itemdescr} @@ -20769,109 +20953,1365 @@ Otherwise, \tcode{false}. \end{itemdescr} -\rSec3[mdspan.accessor]{Accessor policy} +\rSec4[mdspan.layout.leftpad]{Class template \tcode{layout_left_padded::mapping}} -\rSec4[mdspan.accessor.general]{General} +\rSec5[mdspan.layout.leftpad.overview]{Overview} \pnum -An \defn{accessor policy} defines types and operations by which -a reference to a single object is created -from an abstract data handle to a number of such objects and an index. +\tcode{layout_left_padded} provides a layout mapping +that behaves like \tcode{layout_left::mapping}, +except that the padding stride \tcode{stride(1)} +can be greater than or equal to \tcode{extent(0)}. + +\begin{codeblock} +namespace std { + template + template + class layout_left_padded::mapping { + public: + static constexpr size_t padding_value = PaddingValue; + + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_left_padded; + + private: + static constexpr size_t @\exposid{rank_}@ = extents_type::rank(); // \expos + static constexpr size_t @\exposid{first-static-extent}@ = // \expos + extents_type::static_extent(0); + + // \ref{mdspan.layout.leftpad.expo}, exposition-only members + static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; // \expos + + public: + // \ref{mdspan.layout.leftpad.cons}, constructors + constexpr mapping() noexcept : mapping(extents_type{}) {} + constexpr mapping(const mapping&) noexcept = default; + constexpr mapping(const extents_type&); + template + constexpr mapping(const extents_type&, OtherIndexType); + template + constexpr explicit(!is_convertible_v) + mapping(const layout_left::mapping&); + template + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping&); + template + constexpr explicit( @\seebelow@ ) + mapping(const LayoutLeftPaddedMapping&); + template + constexpr explicit( @\seebelow@ ) + mapping(const LayoutRightPaddedMapping&) noexcept; + + constexpr mapping& operator=(const mapping&) noexcept = default; + + // \ref{mdspan.layout.leftpad.obs}, observers + constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } + constexpr array strides() const noexcept; + + constexpr index_type required_span_size() const noexcept; + template + constexpr index_type operator()(Indices...) const noexcept; + + static constexpr bool is_always_unique() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept; + static constexpr bool is_always_strided() noexcept { return true; } + + static constexpr bool is_unique() noexcept { return true; } + constexpr bool is_exhaustive() const noexcept; + static constexpr bool is_strided() noexcept { return true; } + + constexpr index_type stride(rank_type) const noexcept; + + template + friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept; + + private: + // \ref{mdspan.layout.leftpad.expo}, exposition-only members + index_type @\exposid{stride-1}@ = @\exposid{static-padding-stride}@; // \expos + extents_type @\exposid{extents_}@{}; // \expos + // \ref{mdspan.sub.map}, submdspan mapping specialization + template + constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const // \expos + -> @\seebelow@; + + template + friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) { + return src.@\exposid{submdspan-mapping-impl}@(slices...); + } + }; +} +\end{codeblock} \pnum -A range of indices $[0, N)$ is an \defnadj{accessible}{range} of -a given data handle and an accessor -if, for each $i$ in the range, -the accessor policy's \tcode{access} function produces a valid reference to an object. +If \tcode{Extents} is not a specialization of \tcode{extents}, +then the program is ill-formed. \pnum -In subclause \ref{mdspan.accessor.reqmts}, +\tcode{layout_left_padded::mapping} is a trivially copyable type +that models \libconcept{regular} for each \tcode{E}. +\pnum +Throughout \ref{mdspan.layout.leftpad}, +let \tcode{P_rank} be the following +size \exposid{rank_} parameter pack of \tcode{size_}t values: \begin{itemize} \item -\tcode{A} denotes an accessor policy. -\item -\tcode{a} denotes a value of type \tcode{A} or \tcode{const A}. +the empty parameter pack, if \exposid{rank_} equals zero; \item -\tcode{p} denotes a value of type \tcode{A::data_handle_type} or \tcode{const A::data_handle_type}. -\begin{note} -The type \tcode{A::data_handle_type} need not be dereferenceable. -\end{note} +\tcode otherwise, {0zu}, if \exposid{rank_} equals one; \item -\tcode{n}, \tcode{i}, and \tcode{j} each denote values of type \tcode{size_t}. +otherwise, the parameter pack \tcode{0zu}, \tcode{1zu}, \ldots, \tcode{\exposid{rank_}- 1}. \end{itemize} -\rSec4[mdspan.accessor.reqmts]{Requirements} - \pnum -A type \tcode{A} meets the accessor policy requirements if +\mandates \begin{itemize} \item -\tcode{A} models \libconcept{copyable}, +If \tcode{rank_dynamic() == 0} is \tcode{true}, +then the size of the multidimensional index space \tcode{Extents()} +is representable as a value of type \tcode{index_type}. \item -\tcode{is_nothrow_move_constructible_v} is \tcode{true}, +\tcode{padding_value} is representable as a value of type \tcode{index_type}. \item -\tcode{is_nothrow_move_assignable_v} is \tcode{true}, +If +\begin{itemize} \item -\tcode{is_nothrow_swappable_v} is \tcode{true}, and +\exposid{rank_} is greater than one, \item -the following types and expressions -are well-formed and have the specified semantics. +\tcode{padding_value} does not equal \tcode{dynamic_extent}, and +\item +\exposid{first-static-extent} does not equal \tcode{dynamic_extent}, +\end{itemize} +then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{first-static-extent})} +is representable as a val\-ue of type \tcode{size_t}, and +is representable as a value of type \tcode{index_type}. +\item +If +\begin{itemize} +\item +\exposid{rank_} is greater than one, +\item +\tcode{padding_value} does not equal \tcode{dynamic_extent}, and +\item +\tcode{extents_type::static_extent($k$)} does not equal \tcode{dynamic_extent} +for all $k$ in the range \range{0}{extents_type::rank()}, +\end{itemize} +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.static_extent(0))} and +all values \tcode{ext.static_extent($k$)} +with $k$ in the range of \range{1}{\exposid{rank_}} +is representable as a value of type \tcode{size_t}, and +is representable as a value of type \tcode{index_type}. \end{itemize} -\begin{itemdecl} -typename A::element_type -\end{itemdecl} - -\begin{itemdescr} -\pnum -\result -A complete object type that is not an abstract class type. -\end{itemdescr} +\rSec5[mdspan.layout.leftpad.expo]{Exposition-only members} \begin{itemdecl} -typename A::data_handle_type +static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\result -A type that models \libconcept{copyable}, and -for which \tcode{is_nothrow_move_constructible_v} is \tcode{true}, -\tcode{is_nothrow_move_assignable_v} is \tcode{true}, and -\tcode{is_nothrow_swappable_v} is \tcode{true}. -\begin{note} -The type of \tcode{data_handle_type} need not be \tcode{element_type*}. -\end{note} +The value is +\begin{itemize} +\item +\tcode{0}, if \exposid{rank_} equals zero or one; +\item +otherwise, \tcode{dynamic_extent}, +if \tcode{padding_value} or \exposid{first-static-extent} equals +\tcode{dynamic_extent}; +\item +otherwise, the \tcode{size_t} value which is +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{first-sta\-tic-extent})}. +\end{itemize} \end{itemdescr} \begin{itemdecl} -typename A::reference +index_type @\exposid{stride-1}@ = @\exposid{static-padding-stride}@; \end{itemdecl} \begin{itemdescr} \pnum -\result -A type that models -\tcode{\libconcept{common_reference_with}}. +\recommended +Implementations should not store this value +if \exposid{static-padding-stride} is not \tcode{dynamic_extent}. \begin{note} -The type of \tcode{reference} need not be \tcode{element_type\&}. +Using \tcode{extents} instead of +\tcode{index_type} as the type of \exposid{stride-1} would achieve this. \end{note} \end{itemdescr} +\rSec5[mdspan.layout.leftpad.cons]{Constructors} + +\indexlibraryctor{layout_left_padded::mapping}% \begin{itemdecl} -typename A::offset_policy +constexpr mapping(const extents_type& ext); \end{itemdecl} \begin{itemdescr} \pnum -\result -A type \tcode{OP} such that: - +\expects \begin{itemize} \item -\tcode{OP} meets the accessor policy requirements, -\item +The size of the multidimensional index space \tcode{ext} is representable as +a value of type \tcode{index_type}. +\item +If \exposid{rank_} is greater than one and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{\exposid{LEAST-MUL\-TIPLE-AT-LEAST}(padding_value, ext.extent(0))} +is representable as a value of type \exposid{index_type}. +\item +If \exposid{rank_} is greater than one and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(0))} and +all values \tcode{ext.extent($k$)} +with $k$ in the range of \range{1}{\exposid{rank_}} +is representable as a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{ext}; and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-1} +\begin{itemize} +\item +with \tcode{ext.extent(0)} if padding_value is \tcode{dynamic_extent}, +\item +otherwise with +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(0))}. +\end{itemize} +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{layout_left_padded::mapping}% +\begin{itemdecl} +template +constexpr mapping(const extents_type& ext, OtherIndexType pad); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v} is \tcode{true}. +\item +\tcode{is_nothrow_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{pad} is representable as a value of type \tcode{index_type}. +\item +\tcode{extents_type::index-cast(pad)} is greater than zero. +\item +If \exposid{rank_} is greater than one, +then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(0))} +is representable as a value of type \tcode{index_type.} +\item +If \exposid{rank_} is greater than one, +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\linebreak 0))} and +all values \tcode{ext.extent($k$)} +with $k$ in the range of \range{1}{\exposid{rank_}} +is representable as a value of type \tcode{index_type}. +\item +If \tcode{padding_value} is not equal to \tcode{dynamic_extent}, +\tcode{padding_value} equals \tcode{extents_type::\exposid{in\-dex-cast}(pad)}. +\end{itemize} + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{ext}, and +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-1} with +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(0))}. +\end{itemdescr} + +\indexlibraryctor{layout_left_padded::mapping}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) + mapping(const layout_left::mapping& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\mandates +If \tcode{OtherExtents::rank()} is greater than \tcode{1}, then +\begin{codeblock} +(static-padding-stride== dynamic_extent) || +(OtherExtents::static_extent(0) == dynamic_extent) || +(static-padding-stride== OtherExtents::static_extent(0)) +\end{codeblock} +is \tcode{true}. + +\pnum +\expects +\begin{itemize} +\item +If \tcode{extents_type::rank() > 1} is \tcode{true} and +\tcode{padding_value} == \tcode{dynamic_extent} is \tcode{false}, +then \tcode{other.stride(1)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extents().extent(0))) +\end{codeblock} +and +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +Equivalent to \tcode{mapping(other.extents())}. +\end{itemdescr} + +\indexlibraryctor{layout_left_padded::mapping}% +\begin{itemdecl} +template + constexpr explicit(rank_ > 0) + mapping(const layout_stride::mapping& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\expects +\begin{itemize} +\item +If \exposid{rank_} is greater than \tcode{1} and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{other.\linebreak stride(1)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extents().extent(0))) +\end{codeblock} +\item +If \exposid{rank_} is greater than 0, +then \tcode{other.stride(0)} equals 1. +\item +If \exposid{rank_} is greater than 2, +then for all $r$ in the range \range{2}{\exposid{rank_}}, +\tcode{other.stride(r)} equals +\begin{codeblock} +(other.extents().@\exposid{fwd-prod-of-extents}@(r) / other.extents().extent(0)) * other.stride(1) +\end{codeblock} +\item +\tcode{other.required_span_size()} is representable as +a value of type \exposid{index_type}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()} and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-1} with +\tcode{other.stride(1)}. +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{layout_left_padded::mapping}% +\begin{itemdecl} +template + constexpr explicit(@\seebelow@) + mapping(const LayoutLeftPaddedMapping& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{\exposid{is-layout-left-padded-mapping-of}} +is \tcode{true}. +\item +\tcode{is_constructible_v} +\newline is \tcode{true}. +\end{itemize} + +\pnum +\mandates +If \exposid{rank_} is greater than 1, +then +\begin{codeblock} +padding_value == dynamic_extent || +LayoutLeftPaddedMapping::padding_value == dynamic_extent || +padding_value == LayoutLeftPaddedMapping::padding_value +\end{codeblock} +is true. + +\pnum +\begin{itemize} +\item +If \exposid{rank_} is greater than 1 and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{other.\linebreak stride(1)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extent(0))) +\end{codeblock} +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()} and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-1} with \tcode{other.stride(1)}. +\end{itemize} + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +rank_> 1 && +(padding_value != dynamic_extent || + LayoutLeftPaddedMapping::padding_value == dynamic_extent) +\end{codeblock} +\end{itemdescr} + +\indexlibraryctor{layout_left_padded::mapping}% +\begin{itemdecl} +template + constexpr explicit(@\seebelow@) + mapping(const LayoutRightPaddedMapping& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{\exposid{is-layout-right-padded-mapping-of}} +is \tcode{true} or\newline +\tcode{\exposid{is-mapping-of}} +is \tcode{true}. +\item +\exposid{rank_} equals zero or one. +\item +\tcode{is_constructible_v} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!is_convertible_v +\end{codeblock} + +\begin{note} +Neither the input mapping nor the mapping to be constructed +uses the padding stride in the rank-0 or rank-1 case, +so the padding stride does not affect +either the constraints or the preconditions. +\end{note} +\end{itemdescr} + +\rSec5[mdspan.layout.leftpad.obs]{Observers} + +\begin{itemdecl} +constexpr array strides() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{array(\{stride(P_rank)...\})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr index_type required_span_size() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{0} if the multidimensional index space \exposid{extents_} is empty, +\item +otherwise, \tcode{*this(((\exposid{extents_}(P_rank) - index_type(1))...)) + 1}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template +constexpr size_t operator()(Indices... idxs) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{sizeof...(Indices) == \exposid{rank_}} is \tcode{true}. +\item +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}. +\item +\item +\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{extents_type::\exposid{index-cast}(idxs)} is +a multidimensional index in \tcode{extents()}\iref{mdspan.overview}. + +\pnum +\returns +\tcode{((static_cast(idxs) * stride(P_rank)) + ... + 0)}. +\end{itemdescr} + +\begin{itemdecl} +static constexpr bool is_always_exhaustive() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +If \exposid{rank_} equals zero or one, then \tcode{true}; +\item +otherwise, if +neither \exposid{static-padding-stride} nor \exposid{first-static-extent} +equal \tcode{dynamic_extent}, +then \tcode{\exposid{static-padding-stride} == \exposid{first-static-extent}}; +\item +otherwise, \tcode{false}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +constexpr bool is_exhaustive() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \exposid{rank_} equals zero or one; +otherwise, \tcode{extents_.extent(0) == stride(1)}. +\end{itemdescr} + +\begin{itemdecl} +constexpr index_type stride(rank_type r) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{r} is smaller than \exposid{rank_}. + +\pnum +\returns +\begin{itemize} +\item +If \tcode{r} equals zero: 1; +\item +otherwise, if \tcode{r} equals one: \exposid{stride-1}; +\item +otherwise, the product of \exposid{stride-1} and +all values \tcode{extents_.extent($k$)} with $k$ in the range \range{1}{r}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{\exposid{is-layout-left-padded-mapping-of}} +is \tcode{true}. +\item +\tcode{LayoutLeftPaddedMapping::extents_type::rank() == rank_} is \tcode{true}. +\end{itemize} + +\pnum +\returns +\tcode{true} if \tcode{x.extents() == y.extents()} is \tcode{true} and +\tcode{\exposid{rank_} < 2 || x.stride(1) == y.\newline stride(1)} is \tcode{true}. +Otherwise, \tcode{false}. +\end{itemdescr} + +\rSec4[mdspan.layout.rightpad]{Class template \tcode{layout_right_padded::mapping}} + +\rSec5[mdspan.layout.rightpad.overview]{Overview} + +\pnum +\tcode{layout_right_padded} provides a layout mapping +that behaves like \tcode{layout_right::mapping}, +except that the padding stride \tcode{stride(extents_type::rank() - 2)} +can be greater than or equal to +\tcode{extents_type::ex\-tent(extents_type::rank() - 1)}. + +\begin{codeblock} +namespace std { + template + template + class layout_right_padded::mapping { + public: + static constexpr size_t padding_value = PaddingValue; + + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_right_padded; + + private: + static constexpr size_t @\exposid{rank_}@ = extents_type::rank(); // \expos + static constexpr size_t @\exposid{last-static-extent}@ = // \expos + extents_type::static_extent(@\exposid{rank_}@ - 1); + + // \ref{mdspan.layout.rightpad.expo}, exposition-only members + static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; // \expos + + public: + // \ref{mdspan.layout.rightpad.cons}, constructors + constexpr mapping() noexcept : mapping(extents_type{}) {} + constexpr mapping(const mapping&) noexcept = default; + constexpr mapping(const extents_type&); + template + constexpr mapping(const extents_type&, OtherIndexType); + + template + constexpr explicit(!is_convertible_v) + mapping(const layout_right::mapping&); + template + constexpr explicit(rank_ > 0) + mapping(const layout_stride::mapping&); + template + constexpr explicit( @\seebelow@ ) + mapping(const LayoutRightPaddedMapping&); + template + constexpr explicit( @\seebelow@ ) + mapping(const LayoutLeftPaddedMapping&) noexcept; + + constexpr mapping& operator=(const mapping&) noexcept = default; + + // \ref{mdspan.layout.rightpad.obs}, observers + constexpr const extents_type& extents() const noexcept { return extents_; } + constexpr array strides() const noexcept; + + constexpr index_type required_span_size() const noexcept; + + template + constexpr index_type operator()(Indices...) const noexcept; + + static constexpr bool is_always_unique() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept; + static constexpr bool is_always_strided() noexcept { return true; } + + static constexpr bool is_unique() noexcept { return true; } + constexpr bool is_exhaustive() const noexcept; + static constexpr bool is_strided() noexcept { return true; } + + constexpr index_type stride(rank_type) const noexcept; + + template + friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept; + + private: + // \ref{mdspan.layout.rightpad.expo}, exposition-only members + index_type @\exposid{stride-rm2}@ = @\exposid{static-padding-stride}@; // \expos + extents_type @\exposid{extents_}@{}; // \expos + + // \ref{mdspan.sub.map}, submdspan mapping specialization + template + constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const // \expos + -> @\seebelow@; + + template + friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) { + return src.@\exposid{submdspan-mapping-impl}@(slices...); + } + }; +} +\end{codeblock} + +\pnum +If \tcode{Extents} is not a specialization of \tcode{extents}, +then the program is ill-formed. + +\pnum +\tcode{layout_right_padded::mapping} is a trivially copyable type +that models \libconcept{regular} for each \tcode{E}. + +\pnum +Throughout \ref{mdspan.layout.rightpad}, +let \tcode{P_rank} be the following +size \exposid{rank_} parameter pack of \tcode{size_}t values: +\begin{itemize} +\item +the empty parameter pack, if \exposid{rank_} equals zero; +\item +\tcode otherwise, \tcode{0zu}, if \exposid{rank_} equals one; +\item +otherwise, the parameter pack \tcode{0zu}, \tcode{1zu}, \ldots, \tcode{\exposid{rank_}- 1}. +\end{itemize} + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{rank_dynamic() == 0} is \tcode{true}, +then the size of the multidimensional index space \tcode{Extents()} +is representable as a value of type \tcode{index_type}. +\item +\tcode{padding_value} is representable as a value of type \tcode{index_type}. +\item +If +\begin{itemize} +\item +\exposid{rank_} is greater than one, +\item +\tcode{padding_value} does not equal \tcode{dynamic_extent}, and +\item +\exposid{last-static-extent} does not equal \tcode{dynamic_extent}, +\end{itemize} +then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{last-static-extent})} +is representable as a value of type \tcode{size_t}, and +is representable as a value of type \tcode{index_type}. +\item +If +\begin{itemize} +\item +\exposid{rank_} is greater than one, +\item +\tcode{padding_value} does not equal \tcode{dynamic_extent}, and +\item +\tcode{extents_type::static_extent($k$)} does not equal \tcode{dynamic_extent} +for all $k$ in the range \range{0}{\exposid{rank_}}, +\end{itemize} +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.static_extent(\exposid{rank_} - 1))} and +all values \tcode{ext.static_extent($k$)} +with $k$ in the range of \range{0}{\exposid{rank_} - 1} +is representable as a value of type \tcode{size_t}, and +is representable as a value of type \tcode{index_type}. +\end{itemize} + +\rSec5[mdspan.layout.rightpad.expo]{Exposition-only members} + +\begin{itemdecl} +static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The value is +\begin{itemize} +\item +\tcode{0}, if \exposid{rank_} equals zero or one; +\item +otherwise, \tcode{dynamic_extent}, +if \tcode{padding_value} or \exposid{last-static-extent} equals +\tcode{dynamic_extent}; +\item +otherwise, the \tcode{size_t} value which is +\tcode{LEAST-MULTIPLE-AT-LEAST(padding_value, \exposid{last-sta\-tic-extent})}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +index_type @\exposid{stride-rm2}@ = @\exposid{static-padding-stride}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\recommended +Implementations should not store this value +if \exposid{static-padding-stride} is not \tcode{dynamic_extent}. +\begin{note} +Using \tcode{extents} +instead of \tcode{index_type} as the type of \exposid{stride-\linebreak rm2} +would achieve this. +\end{note} +\end{itemdescr} + +\rSec5[mdspan.layout.rightpad.cons]{Constructors} + +\indexlibraryctor{layout_right_padded::mapping}% +\begin{itemdecl} +constexpr mapping(const extents_type& ext); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +The size of the multidimensional index space \tcode{ext} +is representable as a value of type \tcode{index_type}. +\item +If \exposid{rank_} is greater than one and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{\exposid{LEAST-MUL\-TIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))} +is representable as a value of type \exposid{index_type}. +\item +If \exposid{rank_} is greater than one and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))} and +all values \tcode{ext.extent($k$)} +with $k$ in the range of \range{0}{\exposid{rank_} - 1} +is representable as a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{ext}; and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-rm2} +\begin{itemize} +\item +with \tcode{ext.extent(\exposid{rank_} - 1)} +if \tcode{padding_value} is \tcode{dynamic_extent}, +\item +otherwise with +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))}. +\end{itemize} +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{layout_right_padded::mapping}% +\begin{itemdecl} +template +constexpr mapping(const extents_type& ext, OtherIndexType pad); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v} is \tcode{true}. +\item +\tcode{is_nothrow_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{pad} is representable as a value of type \tcode{index_type}. +\item +\tcode{extents_type::\exposid{index-cast}(pad)} is greater than zero. +\item +If \exposid{rank_} is greater than one, +then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\exposid{rank_} - 1))} +is representable as a value of type \tcode{index_type}. +\item +If \exposid{rank_} is greater than one, +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\exposid{\linebreak rank_} - 1))} and +all values \tcode{ext.extent($k$)} +with $k$ in the range of \range{0}{\exposid{rank_} - 1} +is representable as a value of type \tcode{index_type}. +\item +If \tcode{padding_value} is not equal to \tcode{dynamic_extent}, +\tcode{padding_value} equals \tcode{extents_type::\linebreak \exposid{index-cast}(pad)}. +\end{itemize} + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{ext}, and +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-rm2} with +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\exposid{rank_} - 1))}. +\end{itemdescr} + +\indexlibraryctor{layout_right_padded::mapping}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) + mapping(const layout_right::mapping& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\mandates +If \tcode{OtherExtents::rank()} is greater than 1, then +\begin{codeblock} +(@\exposid{static-padding-stride}@ == dynamic_extent) || +(OtherExtents::static_extent(@\exposid{rank_}@ - 1) == dynamic_extent) || +(@\exposid{static-padding-stride}@ == OtherExtents::static_extent(@\exposid{rank_}@ - 1)) +\end{codeblock} +is \tcode{true}. + +\pnum +\expects +\begin{itemize} +\item +If \tcode{\exposid{rank_} > 1} is \tcode{true} and +\tcode{padding_value == dynamic_extent} is \tcode{false}, then +\tcode{other.stride(\newline \exposid{rank_} - 2)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extents().extent(rank_ - 1))) +\end{codeblock} +and +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +Equivalent to \tcode{mapping(other.extents())}. +\end{itemdescr} + +\indexlibraryctor{layout_right_padded::mapping}% +\begin{itemdecl} +template + constexpr explicit(rank_ > 0) + mapping(const layout_stride::mapping& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\expects +\begin{itemize} +\item +If \exposid{rank_} is greater than 1 and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{other.\linebreak stride(\exposid{rank_} - 2)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extents().extent(@\exposid{rank_}@ - 1))) +\end{codeblock} +\item +If \exposid{rank_} is greater than 0, +then other.stride(\exposid{rank_} - 1) equals 1. +\item +If \exposid{rank_} is greater than 2, +then for all $r$ in the range \range{0}{\exposid{rank_} - 2}, +\tcode{other.stride($r$)} equals +\begin{codeblock} +(other.extents().@\exposid{rev-prod-of-extents}@(r) / other.extents().extent(@\exposid{rank_}@ - 1)) * + other.stride(@\exposid{rank_}@ - 2) +\end{codeblock} +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}; and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-rm2} +with \tcode{other.stride(\exposid{rank_} - 2)}. +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{layout_right_padded::mapping}% +\begin{itemdecl} +template + constexpr explicit( @\seebelow@ ) + mapping(const LayoutRightPaddedMapping& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{\exposid{is-layout-right-padded-mapping-of}} +is \tcode{true}. +\item +\tcode{is_constructible_v} +is \tcode{true}. +\end{itemize} + +\pnum +\mandates +If \exposid{rank_} is greater than 1, then +\begin{codeblock} +padding_value == dynamic_extent || +LayoutRightPaddedMapping::padding_value == dynamic_extent || +padding_value == LayoutRightPaddedMapping::padding_value +\end{codeblock} +is \tcode{true}. + +\pnum +\expects +\begin{itemize} +\item +If \exposid{rank_} is greater than 1 and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{other.\linebreak stride(\exposid{rank_} - 2)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extent(@\exposid{rank_}@ - 1))) +\end{codeblock} +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}; and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-rm2} +with \tcode{other.stride(rank_ - 2)}. +\end{itemize} + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +@\exposid{rank_}@ > 1 && +(padding_value != dynamic_extent || + LayoutRightPaddedMapping::padding_value == dynamic_extent) +\end{codeblock} +\end{itemdescr} + +\indexlibraryctor{layout_right_padded::mapping}% +\begin{itemdecl} +template + constexpr explicit( @\seebelow@ ) + mapping(const LayoutLeftPaddedMapping& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{\exposid{is-layout-left-padded-mapping-of}} +is \tcode{true} or\newline +\tcode{\exposid{is-mapping-of}} +is \tcode{true}. +\item +\exposid{rank_} equals zero or one. +\item +\tcode{is_constructible_v}\newline +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!is_convertible_v +\end{codeblock} +\begin{note} +Neither the input mapping nor the mapping to be constructed +uses the padding stride in the rank-0 or rank-1 case, +so the padding stride affects neither the constraints nor the preconditions. +\end{note} +\end{itemdescr} + +\rSec5[mdspan.layout.rightpad.obs]{Observers} + +\indexlibrarymember{layout_right_padded::mapping}{strides}% +\begin{itemdecl} +constexpr array strides() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{array({stride(P_rank)...})}. +\end{itemdescr} + +\indexlibrarymember{layout_right_padded::mapping}{required_span_size}% +\begin{itemdecl} +constexpr index_type required_span_size() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{0} if the multidimensional index space \exposid{extents_} is empty, +otherwise \tcode{*this(((\exposid{extents_}(P_rank) - index_type(1))...)) + 1}. +\end{itemdescr} + +\indexlibrarymember{layout_right_padded::mapping}{operator()}% +\begin{itemdecl} +template +constexpr size_t operator()(Indices... idxs) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{sizeof...(Indices) == \exposid{rank_}} is \tcode{true}. +\item +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}. +\item +\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{extents_type::\exposid{index-cast}(idxs)} is +a multidimensional index in \tcode{extents()}\iref{mdspan.overview}. + +\pnum +\returns +\tcode{((static_cast(idxs) * stride(P_rank)) + ... + 0)}. +\end{itemdescr} + +\indexlibrarymember{layout_right_padded::mapping}{is_always_exhaustive}% +\begin{itemdecl} +static constexpr bool is_always_exhaustive() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +If \exposid{rank_} equals zero or one, then \tcode{true}; +\item +otherwise, +if neither \exposid{static-padding-stride} nor \exposid{last-static-extent} +equal \tcode{dynamic_extent}, +then \tcode{\exposid{static-padding-stride} == \exposid{last-static-extent}}; +\item +otherwise, \tcode{false}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{layout_right_padded::mapping}{is_exhaustive}% +\begin{itemdecl} +constexpr bool is_exhaustive() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \exposid{rank_} equals zero or one; +otherwise, +\begin{codeblock} +@\exposid{extents_}@.extent(@\exposid{rank_}@ - 1) == stride(@\exposid{rank_}@ - 2) +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr index_type stride(rank_type r) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{r} is smaller than \exposid{rank_}. +\pnum +\returns +\begin{itemize} +\item +If \tcode{r} equals \tcode{\exposid{rank_} - 1}: \tcode{1}; +\item +otherwise, if \tcode{r} equals \tcode{\exposid{rank_} - 2}: \exposid{stride-rm2}; +\item +otherwise, +the product of \exposid{stride-rm2} and +all values \tcode{extents_.extent($k$)} +with $k$ in the range of \range{r + 1}{\exposid{rank_} - 1}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{layout_right_padded::mapping}{operator==}% +\begin{itemdecl} +template + friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{\exposid{is-layout-right-padded-mapping-of}} +is \tcode{true}. +\item +\tcode{LayoutRightPaddedMapping::extents_type::rank() == \exposid{rank_}} +is \tcode{true}. +\end{itemize} + +\pnum +\returns +\tcode{true} if \tcode{x.extents() == y.extents()} is \tcode{true} and +\tcode{\exposid{rank_} < 2 || x.stride(\exposid{rank_} - 2) == y.stride(\exposid{rank_} - 2)} is \tcode{true}. +Otherwise, \tcode{false}. +\end{itemdescr} + +\rSec3[mdspan.accessor]{Accessor policy} + +\rSec4[mdspan.accessor.general]{General} + +\pnum +An \defn{accessor policy} defines types and operations by which +a reference to a single object is created +from an abstract data handle to a number of such objects and an index. + +\pnum +A range of indices $[0, N)$ is an \defnadj{accessible}{range} of +a given data handle and an accessor +if, for each $i$ in the range, +the accessor policy's \tcode{access} function produces a valid reference to an object. + +\pnum +In subclause \ref{mdspan.accessor.reqmts}, + +\begin{itemize} +\item +\tcode{A} denotes an accessor policy. +\item +\tcode{a} denotes a value of type \tcode{A} or \tcode{const A}. +\item +\tcode{p} denotes a value of type \tcode{A::data_handle_type} or \tcode{const A::data_handle_type}. +\begin{note} +The type \tcode{A::data_handle_type} need not be dereferenceable. +\end{note} +\item +\tcode{n}, \tcode{i}, and \tcode{j} each denote values of type \tcode{size_t}. +\end{itemize} + +\rSec4[mdspan.accessor.reqmts]{Requirements} + +\pnum +A type \tcode{A} meets the accessor policy requirements if +\begin{itemize} +\item +\tcode{A} models \libconcept{copyable}, +\item +\tcode{is_nothrow_move_constructible_v} is \tcode{true}, +\item +\tcode{is_nothrow_move_assignable_v} is \tcode{true}, +\item +\tcode{is_nothrow_swappable_v} is \tcode{true}, and +\item +the following types and expressions +are well-formed and have the specified semantics. +\end{itemize} + +\begin{itemdecl} +typename A::element_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A complete object type that is not an abstract class type. +\end{itemdescr} + +\begin{itemdecl} +typename A::data_handle_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A type that models \libconcept{copyable}, and +for which \tcode{is_nothrow_move_constructible_v} is \tcode{true}, +\tcode{is_nothrow_move_assignable_v} is \tcode{true}, and +\tcode{is_nothrow_swappable_v} is \tcode{true}. +\begin{note} +The type of \tcode{data_handle_type} need not be \tcode{element_type*}. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +typename A::reference +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A type that models +\tcode{\libconcept{common_reference_with}}. +\begin{note} +The type of \tcode{reference} need not be \tcode{element_type\&}. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +typename A::offset_policy +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A type \tcode{OP} such that: + +\begin{itemize} +\item +\tcode{OP} meets the accessor policy requirements, +\item \tcode{\libconcept{constructible_from}} is modeled, and \item \tcode{is_same_v} is \tcode{true}. @@ -21116,7 +22556,7 @@ template requires ((is_convertible_v && ...) && sizeof...(Integrals) > 0) explicit mdspan(ElementType*, Integrals...) - -> mdspan>; + -> mdspan...>>; template mdspan(ElementType*, span) @@ -21565,9 +23005,9 @@ \end{codeblock} \end{itemdescr} -\rSec3[mdspan.submdspan]{\tcode{submdspan}} +\rSec3[mdspan.sub]{\tcode{submdspan}} -\rSec4[mdspan.submdspan.overview]{Overview} +\rSec4[mdspan.sub.overview]{Overview} \pnum The \tcode{submdspan} facilities create a new \tcode{mdspan} @@ -21576,7 +23016,7 @@ the \tcode{SliceSpecifier} arguments. \pnum -For each function defined in subclause \ref{mdspan.submdspan} that +For each function defined in subclause \ref{mdspan.sub} that takes a parameter pack named \tcode{slices} as an argument: \begin{itemize} @@ -21610,7 +23050,7 @@ \end{itemize} \end{itemize} -\rSec4[mdspan.submdspan.strided.slice]{\tcode{strided_slice}} +\rSec4[mdspan.sub.strided.slice]{\tcode{strided_slice}} \pnum \tcode{strided_slice} represents a set of @@ -21649,7 +23089,7 @@ Indices are selected from the half-open interval \range{1}{1 + 10}. \end{note} -\rSec4[mdspan.submdspan.submdspan.mapping.result]{\tcode{submdspan_mapping_result}} +\rSec4[mdspan.sub.map.result]{\tcode{submdspan_mapping_result}} \pnum Specializations of \tcode{submdspan_mapping_result} @@ -21675,7 +23115,7 @@ \tcode{LayoutMapping} shall meet the layout mapping requirements\iref{mdspan.layout.policy.reqmts}. -\rSec4[mdspan.submdspan.helpers]{Exposition-only helpers} +\rSec4[mdspan.sub.helpers]{Exposition-only helpers} \indexlibraryglobal{\exposid{de-ice}}% \indexlibraryglobal{\exposid{first_}}% @@ -21798,7 +23238,7 @@ \end{itemize} \end{itemdescr} -\rSec4[mdspan.submdspan.extents]{\tcode{submdspan_extents} function} +\rSec4[mdspan.sub.extents]{\tcode{submdspan_extents} function} \indexlibraryglobal{submdspan_extents}% \begin{itemdecl} @@ -21905,45 +23345,30 @@ \end{itemize} \end{itemdescr} -\rSec4[mdspan.submdspan.mapping]{Layout specializations of \tcode{submdspan_mapping}} - -\indexlibrarymemberexpos{layout_stride::mapping}{submdspan-mapping-impl}% -\indexlibrarymemberexpos{layout_left::mapping}{submdspan-mapping-impl}% -\indexlibrarymemberexpos{layout_right::mapping}{submdspan-mapping-impl}% -\begin{itemdecl} -template - template - constexpr auto layout_left::mapping::@\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; - -template - template - constexpr auto layout_right::mapping::@\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; +\rSec4[mdspan.sub.map]{Specializations of \tcode{submdspan_mapping}} -template - template - constexpr auto layout_stride::mapping::@\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; -\end{itemdecl} +\rSec5[mdspan.sub.map.common]{Common} -\begin{itemdescr} \pnum -Let \tcode{index_type} be \tcode{typename Extents::index_type}. +The following elements apply to all functions in \ref{mdspan.sub.map}. \pnum \constraints -\tcode{sizeof...(slices)} equals \tcode{Extents::rank()}. +\tcode{sizeof...(slices)} equals \tcode{extents_type::rank()}. \pnum \mandates For each rank index $k$ of \tcode{extents()}, exactly one of the following is true: \begin{itemize} -\item $S_k$ models \tcode{\libconcept{convertible_to}}, -\item $S_k$ models \tcode{\exposconcept{index-pair-like}}, -\item \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}, or -\item $S_k$ is a specialization of \tcode{strided_slice}. +\item +$S_k$ models \tcode{\libconcept{convertible_to}}, +\item +$S_k$ models \tcode{\exposconcept{index-pair-like}}, +\item +\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}, or +\item +$S_k$ is a specialization of \tcode{strided_slice}. \end{itemize} \pnum @@ -21952,64 +23377,71 @@ all of the following are \tcode{true}: \begin{itemize} \item -if $S_k$ is a specialization of \tcode{strided_slice} - \begin{itemize} - \item $\tcode{$s_k$.extent} = 0$, or - \item $\tcode{$s_k$.stride} > 0$ - \end{itemize} +if $S_k$ is a specialization of \tcode{strided_slice}, +\tcode{$s_k$.extent} is equal to zero or +\tcode{$s_k$.stride} is greater than zero; and \item -$0 \le \tcode{\exposid{first_}(slices...)} \\ -\hphantom{0 } \le \tcode{\exposid{last_}<$k$>(extents(), slices...)} \\ -\hphantom{0 } \le \tcode{extents().extent($k$)}$ +$0 \leq \tcode{\exposid{first_}(slices...)} \\ +\hphantom{0 } \leq \tcode{\exposid{last_}<$k$>(extents(), slices...)} \\ +\hphantom{0 } \leq \tcode{extents().extent($k$)}$ \end{itemize} \pnum -Let \tcode{sub_ext} be the result of -\tcode{submdspan_extents(extents(), slices...)} and -let \tcode{SubExtents} be \tcode{decltype(sub_ext)}. +Let \tcode{sub_ext} be +the result of \tcode{submdspan_extents(extents(), slices...)} and +let \tcode{SubExtents} be \tcode{decl\-type(sub_ext)}. \pnum Let \tcode{sub_strides} be -an \tcode{array} such that -for each rank index $k$ of \tcode{extents()} -for which \tcode{\placeholder{map-rank}[$k$]} is not \tcode{dynamic_extent}, -\tcode{sub_strides[\placeholder{map-rank}[\linebreak{}$k$]]} equals: - +an \tcode{array} +such that for each rank index $k$ of \tcode{extents()} +for which \tcode{\exposid{map-rank}[$k$]} is not \tcode{dynamic_extent}, +\tcode{sub_strides[\exposid{map-rank}[$k$]]} equals: \begin{itemize} \item -\tcode{stride($k$) * \exposid{de-ice}($s_k$.stride)} +\tcode{stride(k) * \exposid{de-ice}($s_k$.stride)} if $S_k$ is a specialization of \tcode{strided_slice} and -\tcode{$s_k$.stride < $s_k$.extent}; - +\tcode{$s_k$.stride < $s_k$.\linebreak extent} is \tcode{true}; \item -otherwise, -\tcode{stride($k$)}. +otherwise, \tcode{stride($k$)}. \end{itemize} \pnum -Let \tcode{P} be a parameter pack such that -\tcode{is_same_v, index_sequence<\linebreak{}P...>>} +Let \tcode{P} be a parameter pack +such that \tcode{is_same_v, index_sequence>} is \tcode{true}. \pnum -Let \tcode{offset} be a value of type \tcode{size_t} -equal to \tcode{(*this)(\exposid{first_}(slices...)...)}. +Let \tcode{offset} be a value of type \tcode{size_t} equal to +\tcode{(*this)(\exposid{first_}(slices...)...)}. + +\rSec5[mdspan.sub.map.left]{\tcode{layout_left} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_left::mapping}{submdspan-mapping-impl}% +\begin{itemdecl} +template +template +constexpr auto layout_left::mapping::@\exposid{submdspan-mapping-impl}@( + SliceSpecifiers... slices) const -> @\seebelow@; +\end{itemdecl} +\begin{itemdescr} \pnum \returns \begin{itemize} \item \tcode{submdspan_mapping_result\{*this, 0\}}, if \tcode{Extents::rank() == 0} is \tcode{true}; - +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}}, +if \tcode{SubEx\-tents::rank() == 0} is \tcode{true}; \item otherwise, \tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}}, if \begin{itemize} \item - \tcode{layout_type} is \tcode{layout_left}; and - \item for each $k$ in the range \range{0}{SubExtents::rank() - 1)}, \tcode{is_convertible_v<$S_k$, full_ext\-ent_t>} is \tcode{true}; and \item @@ -22022,36 +23454,313 @@ all $S_k$ with $k$ larger than \tcode{SubExtents::rank() - 1} are convertible to \tcode{index_type}. \end{note} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_left_padded::mapping(sub_ext, stride(@$u$@ + 1)), + offset} +\end{codeblock} +if for a value $u$ for which $u+1$ is +the smallest value $p$ larger than zero +for which $S_p$ models +\tcode{\exposconcept{index-pair-like}} or +\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true}, +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 +\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}; +\end{itemize} +and where \tcode{S_static} is: +\begin{itemize} +\item +\tcode{dynamic_extent}, +if \tcode{static_extent($k$)} is \tcode{dynamic_extent} +for any $k$ in the range \range{0}{$u$ + 1}, +\item +otherwise, the product of all values +\tcode{static_extent($k$)} for $k$ in the range \range{0}{$u$ + 1}; +\end{itemize} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec5[mdspan.sub.map.right]{\tcode{layout_right} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_right::mapping}{submdspan-mapping-impl}% +\begin{itemdecl} +template +template +constexpr auto layout_right::mapping::@\exposid{submdspan-mapping-impl}@( + SliceSpecifiers... slices) const -> @\seebelow@; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{Extents::rank() == 0} is \tcode{true}; \item otherwise, \tcode{submdspan_mapping_result\{layout_right::mapping(sub_ext), offset\}}, +if \tcode{Sub\-Extents::rank() == 0} is \tcode{true}; +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}}, if \begin{itemize} \item - \tcode{layout_type} is \tcode{layout_right}; and - \item - for each $k$ in the range - \range{Extents::rank() - SubExtents::rank() + 1}{Extents::rank()}, + for each $k$ in the range \range{\exposid{rank_} - SubExtents::rank() + 1}{\exposid{rank_}}, \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and \item - for $k$ equal to \tcode{Extents::rank() - SubExtents::rank()}, - $S_k$ models \tcode{\exposconcept{index-pair-like}} or + 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}; \end{itemize} \begin{note} If the above conditions are true, -all $S_k$ with $k < \tcode{Extents::rank() - SubExtents::rank()}$ +all $S_k$ with $k < \tcode{\exposid{_rank} - SubExtents::rank()}$ are convertible to \tcode{index_type}. \end{note} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_right_padded::mapping(sub_ext, + stride(@\exposid{rank_}@ - @$u$@ - 2)), offset} +\end{codeblock} +if for a value $u$ for which $\exposid{rank_} - u - 2$ is +the largest value $p$ smaller than \tcode{\exposid{rank_} - 1} +for which $S_p$ models +\tcode{\exposconcept{index-pair-like}} or +\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true}, +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 +\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}; +\end{itemize} +and where \tcode{S_static} is: +\begin{itemize} +\item +\tcode{dynamic_extent}, +if \tcode{static_extent($k$)} is \tcode{dynamic_extent} +for any $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_}}, +\item +otherwise, the product of all values +\tcode{static_extent($k$)} +for $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_}}; +\end{itemize} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec5[mdspan.sub.map.stride]{\tcode{layout_stride} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_stride::mapping}{submdspan-mapping-impl}% +\begin{itemdecl} +template +template +constexpr auto layout_stride::mapping::@\exposid{submdspan-mapping-impl}@( + SliceSpecifiers... slices) const -> @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{Extents::rank() == 0} is \tcode{true}; +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec5[mdspan.sub.map.leftpad]{\tcode{layout_left_padded} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_left_padded::mapping}{submdspan-mapping-impl}% +\begin{itemdecl} +template +template +constexpr auto layout_left_padded::mapping::@\exposid{submdspan-mapping-impl}@( + SliceSpecifiers... slices) const -> @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{Extents::rank() == 0} is \tcode{true}; +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}}, +if \tcode{\exposid{rank_} == 1} is \tcode{true} or +\tcode{SubExtents::rank() == 0} is \tcode{true}; +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}}, +if +\begin{itemize} +\item +\tcode{SubExtents::rank() == 1} is \tcode{true} and +\item +$S_0$ models \tcode{\exposconcept{index-pair-like}} or +\tcode{is_convertible_v<$S_0$ , full_extent_t>} is \tcode{true}; +\end{itemize} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_left_padded::mapping(sub_ext, stride(@$u$@ + 1)), + offset} +\end{codeblock} +if for a value $u$ +for which \tcode{$u$ + 1} is the smallest value $p$ larger than zero +for which $S_p$ models \tcode{\exposconcept{index-pair-like}} or +\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true}, +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 +\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}; +\end{itemize} +where \tcode{S_static} is: +\begin{itemize} +\item +\tcode{dynamic_extent}, +if \exposid{static-padding-stride} is \tcode{dynamic_extent} or +\tcode{static_extent($k$)} is \tcode{dynamic_extent} +for any $k$ in the range \range{1}{$u$ + 1}, +\item +otherwise, the product of \exposid{static-padding-stride} and +all values \tcode{static_extent($k$)} for $k$ in the range \range{1}{$u$ + 1}; +\end{itemize} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec5[mdspan.sub.map.rightpad]{\tcode{layout_right_padded} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_right_padded::mapping}{submdspan-mapping-impl}% +\begin{itemdecl} +template +template +constexpr auto layout_right_padded::mapping::submdspan-mapping-impl( + SliceSpecifiers... slices) const -> @\seebelow@; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{\exposid{rank_} == 0} is \tcode{true}; +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_right::mapping(sub_ext), offset\}},\newline +if \tcode{\exposid{rank_} == 1} is \tcode{true} or +\tcode{SubExtents::rank() == 0} is \tcode{true}; +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_right::mapping(sub_ext), offset\}}, +if +\begin{itemize} +\item +\tcode{SubExtents::rank() == 1} is \tcode{true} and +\item +for $k$ equal to \tcode{\exposid{rank_} - 1}, +$S_k$ models \tcode{\exposconcept{index-pair-like}} or +\tcode{is_convertible_v<$S_k$ , full_extent_t>} is \tcode{true}; +\end{itemize} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_right_padded::mapping(sub_ext, + stride(@\exposid{rank_}@ - @$u$@ - 2)), offset} +\end{codeblock} +if for a value $u$ +for which \tcode{\exposid{rank_} - $u$ - 2} +is the largest value p smaller than \tcode{\exposid{rank_} - 1} +for which $S_p$ models \tcode{\exposconcept{index-pair-like}} or +\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true}, +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 +\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}; +\end{itemize} +and where \tcode{S_static} is: +\begin{itemize} +\item +\tcode{dynamic_extent} +if \exposid{static-padding-stride} is \tcode{dynamic_extent} or +for any $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_} - 1} +\tcode{static_extent($k$)} is \tcode{dynamic_extent}, +\item +otherwise, the product of \exposid{static-padding-stride} and +all values \tcode{static_extent($k$)} +with $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_} - 1}; +\end{itemize} \item otherwise, -\tcode{submdspan_mapping_result\{layout_stride::mapping(sub_ext, sub_strides),\linebreak{}offset\}}. +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} +\end{codeblock} \end{itemize} \end{itemdescr} -\rSec4[mdspan.submdspan.submdspan]{\tcode{submdspan} function template} +\rSec4[mdspan.sub.sub]{\tcode{submdspan} function template} \indexlibraryglobal{submdspan}% \begin{itemdecl} diff --git a/source/declarations.tex b/source/declarations.tex index 709ee00a69..2079217bac 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -28,6 +28,7 @@ block-declaration\br nodeclspec-function-declaration\br function-definition\br + friend-type-declaration\br template-declaration\br deduction-guide\br linkage-specification\br @@ -67,11 +68,27 @@ \keyword{using} identifier \opt{attribute-specifier-seq} \terminal{=} defining-type-id \terminal{;} \end{bnf} +\begin{bnf} +\nontermdef{attributed-identifier}\br + identifier \opt{attribute-specifier-seq} +\end{bnf} + +\begin{bnf} +\nontermdef{attributed-identifier-list}\br + attributed-identifier\br + attributed-identifier-list \terminal{,} attributed-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{]} +\end{bnf} + \begin{bnf} \nontermdef{simple-declaration}\br decl-specifier-seq \opt{init-declarator-list} \terminal{;}\br attribute-specifier-seq decl-specifier-seq init-declarator-list \terminal{;}\br - \opt{attribute-specifier-seq} decl-specifier-seq \opt{ref-qualifier} \terminal{[} identifier-list \terminal{]} initializer \terminal{;} + structured-binding-declaration initializer \terminal{;} \end{bnf} \begin{bnf} @@ -117,6 +134,11 @@ the declaration that are \emph{not} nested within scopes nested within the declaration. +\pnum +If a \grammarterm{name-declaration} matches +the syntactic requirements of \grammarterm{friend-type-declaration}, +it is a \grammarterm{friend-type-declaration}. + \pnum A \grammarterm{simple-declaration} or @@ -186,7 +208,7 @@ \end{example} \pnum -A \grammarterm{simple-declaration} with an \grammarterm{identifier-list} is called +A \grammarterm{simple-declaration} with a \grammarterm{structured-binding-declaration} is called a \defn{structured binding declaration}\iref{dcl.struct.bind}. Each \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq} shall be @@ -1268,10 +1290,10 @@ \indextext{\idxcode{volatile}!implementation-defined}% \begin{note} \tcode{volatile} is a hint to the implementation to avoid aggressive -optimization involving the object because the value of the object might -be changed by means undetectable by an implementation. -Furthermore, for some implementations, \tcode{volatile} might indicate that -special hardware instructions are required to access the object. +optimization involving the object because it is possible for the value of the object +to change by means undetectable by an implementation. +Furthermore, for some implementations, \tcode{volatile} can indicate that +special hardware instructions are needed to access the object. See~\ref{intro.execution} for detailed semantics. In general, the semantics of \tcode{volatile} are intended to be the same in \Cpp{} as they are in C. @@ -1520,30 +1542,34 @@ The target scope of $E$ is the nearest enclosing namespace or block scope. \pnum -If an \grammarterm{elaborated-type-specifier} appears with -the \keyword{friend} specifier as an entire \grammarterm{member-declaration}, -the \grammarterm{member-declaration} shall have one of the following forms: +A \grammarterm{friend-type-specifier} +that is an \grammarterm{elaborated-type-specifier} +shall have one of the following forms: \begin{ncsimplebnf} -\keyword{friend} class-key \opt{nested-name-specifier} identifier \terminal{;}\br -\keyword{friend} class-key simple-template-id \terminal{;}\br -\keyword{friend} class-key nested-name-specifier \opt{\keyword{template}} simple-template-id \terminal{;} +class-key \opt{nested-name-specifier} identifier\br +class-key simple-template-id\br +class-key nested-name-specifier \opt{\keyword{template}} simple-template-id \end{ncsimplebnf} Any unqualified lookup for the \grammarterm{identifier} (in the first case) -does not consider scopes that contain the target scope; no name is bound. +does not consider scopes that contain +the nearest enclosing namespace or block scope; no name is bound. \begin{note} A \grammarterm{using-directive} in the target scope is ignored if it refers to a namespace not contained by that scope. -\ref{basic.lookup.elab} describes how name lookup proceeds -in an \grammarterm{elaborated-type-specifier}. \end{note} \pnum \begin{note} +\ref{basic.lookup.elab} describes how name lookup proceeds +in an \grammarterm{elaborated-type-specifier}. An \grammarterm{elaborated-type-specifier} can be used to refer to a previously declared \grammarterm{class-name} or \grammarterm{enum-name} even if the name has been hidden by a non-type declaration. \end{note} + +\pnum If the \grammarterm{identifier} or \grammarterm{simple-template-id} +in an \grammarterm{elaborated-type-specifier} resolves to a \grammarterm{class-name} or \grammarterm{enum-name}, the \grammarterm{elaborated-type-specifier} introduces it into the declaration the same way a @@ -1558,12 +1584,12 @@ \begin{codeblock} friend class T; \end{codeblock} -is ill-formed. However, the similar declaration \tcode{friend T;} is allowed\iref{class.friend}. +is ill-formed. However, the similar declaration \tcode{friend T;} is well-formed.\iref{class.friend}. \end{note} \pnum The \grammarterm{class-key} or \keyword{enum} keyword -present in the +present in an \grammarterm{elaborated-type-specifier} shall agree in kind with the declaration to which the name in the \grammarterm{elaborated-type-specifier} refers. This rule also applies to @@ -1716,20 +1742,31 @@ \pnum A \grammarterm{placeholder-type-specifier} -designates a placeholder type that will be replaced later by deduction +designates a placeholder type that will be replaced later, +typically by deduction from an initializer. \pnum -A \grammarterm{placeholder-type-specifier} of the form -\opt{\grammarterm{type-constraint}} \keyword{auto} -can be used as a \grammarterm{decl-specifier} of -the \grammarterm{decl-specifier-seq} of -a \grammarterm{parameter-declaration} of -a function declaration or \grammarterm{lambda-expression} and, -if it is not the \keyword{auto} \grammarterm{type-specifier} -introducing a \grammarterm{trailing-return-type} (see below), +The type of a \grammarterm{parameter-declaration} of a +function declaration\iref{dcl.fct}, +\grammarterm{lambda-expression}\iref{expr.prim.lambda}, or +\grammarterm{template-parameter}\iref{temp.param} +can be declared using +a \grammarterm{placeholder-type-specifier} of the form +\opt{\grammarterm{type-constraint}} \keyword{auto}. +The placeholder type shall appear +as one of the \grammarterm{decl-specifier}{s} in +the \grammarterm{decl-specifier-seq} or +as one of the \grammarterm{type-specifier}{s} in +a \grammarterm{trailing-return-type} +that specifies the type that replaces such +a \grammarterm{decl-specifier} (see below); +the placeholder type is a \defn{generic parameter type placeholder} -of the function declaration or \grammarterm{lambda-expression}. +of the +function declaration, +\grammarterm{lambda-expression}, or +\grammarterm{template-parameter}, respectively. \begin{note} Having a generic parameter type placeholder signifies that the function is @@ -1738,15 +1775,15 @@ \end{note} \pnum -A placeholder type can appear with a function declarator in the -\grammarterm{decl-specifier-seq}, \grammarterm{type-specifier-seq}, -\grammarterm{conversion-function-id}, or \grammarterm{trailing-return-type}, -in any context where such a declarator is valid. If the function declarator -includes a \grammarterm{trailing-return-type}\iref{dcl.fct}, that -\grammarterm{trailing-return-type} specifies -the declared return type of the function. Otherwise, the function declarator -shall declare a function. If the declared return type of the -function contains a placeholder type, the return type of the function is +A placeholder type can appear in +the \grammarterm{decl-specifier-seq} for a function declarator +that includes a \grammarterm{trailing-return-type}\iref{dcl.fct}. + +\pnum +A placeholder type can appear in +the \grammarterm{decl-specifier-seq} or \grammarterm{type-specifier-seq} +in the declared return type of a function declarator that declares a function; +the return type of the function is deduced from non-discarded \tcode{return} statements, if any, in the body of the function\iref{stmt.if}. @@ -1756,9 +1793,11 @@ This use is allowed in an initializing declaration\iref{dcl.init} of a variable. The placeholder type shall appear as one of the -\grammarterm{decl-specifier}{s} in the -\grammarterm{decl-specifier-seq} and the -\grammarterm{decl-specifier-seq} +\grammarterm{decl-specifier}{s} in the \grammarterm{decl-specifier-seq} +or as one of the +\grammarterm{type-specifier}{s} in a \grammarterm{trailing-return-type} +that specifies the type that replaces such a \grammarterm{decl-specifier}; +the \grammarterm{decl-specifier-seq} shall be followed by one or more \grammarterm{declarator}{s}, each of which shall @@ -1772,6 +1811,7 @@ auto int r; // error: \keyword{auto} is not a \grammarterm{storage-class-specifier} auto f() -> int; // OK, \tcode{f} returns \tcode{int} auto g() { return 0.0; } // OK, \tcode{g} returns \tcode{double} +auto (*fp)() -> auto = f; // OK auto h(); // OK, \tcode{h}'s return type will be deduced when it is defined \end{codeblock} \end{example} @@ -1781,13 +1821,19 @@ \pnum A placeholder type can also be used -in the \grammarterm{type-specifier-seq} in -the \grammarterm{new-type-id} or \grammarterm{type-id} of a -\grammarterm{new-expression}\iref{expr.new} -and as a \grammarterm{decl-specifier} -of the \grammarterm{parameter-declaration}{'s} -\grammarterm{decl-specifier-seq} -in a \grammarterm{template-parameter}\iref{temp.param}. +in the \grammarterm{type-specifier-seq} of +the \grammarterm{new-type-id} or +in the \grammarterm{type-id} of a +\grammarterm{new-expression}\iref{expr.new}. +In such a \grammarterm{type-id}, +the placeholder type shall appear +as one of the \grammarterm{type-specifier}{s} in +the \grammarterm{type-specifier-seq} or +as one of the \grammarterm{type-specifier}{s} in +a \grammarterm{trailing-return-type} +that specifies the type that replaces such a \grammarterm{type-specifier}. + +\pnum The \tcode{auto} \grammarterm{type-specifier} can also be used as the \grammarterm{simple-type-specifier} in an explicit type conversion (functional notation)\iref{expr.type.conv}. @@ -3069,16 +3115,46 @@ specifier\iref{dcl.stc}, is a class member\iref{class.mem} declaration within a class definition, or is the declaration of a parameter or a return type\iref{dcl.fct}; see~\ref{basic.def}. -A reference shall be initialized to refer to a valid object or function. + +\pnum +Attempting to bind a reference to a function where +the converted initializer is a glvalue whose +type is not call-compatible\iref{expr.call} +with the type of the function's definition +results in undefined behavior. +Attempting to bind a reference to an object where +the converted initializer is a glvalue through which +the object is not type-accessible\iref{basic.lval} +results in undefined behavior. \begin{note} \indextext{reference!null}% -In particular, a null reference cannot exist in a well-defined program, -because the only way to create such a reference would be to bind it to -the ``object'' obtained by indirection through a null pointer, -which causes undefined behavior. +The object designated by such a glvalue can be +outside its lifetime\iref{basic.life}. +Because a null pointer value or a pointer past the end of an object +does not point to an object, +a reference in a well-defined program cannot refer to such things; +see~\ref{expr.unary.op}. As described in~\ref{class.bit}, a reference cannot be bound directly to a bit-field. \end{note} +The behavior of an evaluation of a reference\iref{expr.prim.id, expr.ref} that +does not happen after\iref{intro.races} the initialization of the reference +is undefined. +\begin{example} +\begin{codeblock} +int &f(int&); +int &g(); +extern int &ir3; +int *ip = 0; +int &ir1 = *ip; // undefined behavior: null pointer +int &ir2 = f(ir3); // undefined behavior: \tcode{ir3} not yet initialized +int &ir3 = g(); +int &ir4 = f(ir4); // undefined behavior: \tcode{ir4} used in its own initializer + +char x alignas(int); +int &ir5 = *reinterpret_cast(&x); // undefined behavior: initializer refers to char object +\end{codeblock} +\end{example} \pnum \indextext{reference collapsing}% @@ -3436,60 +3512,44 @@ \tcode{T} \tcode{D} where +\tcode{T} may be empty and \tcode{D} has the form \begin{ncsimplebnf} \terminal{D1} \terminal{(} parameter-declaration-clause \terminal{)} \opt{cv-qualifier-seq}\br -\bnfindent\opt{ref-qualifier} \opt{noexcept-specifier} \opt{attribute-specifier-seq} +\bnfindent\opt{ref-qualifier} \opt{noexcept-specifier} \opt{attribute-specifier-seq} \opt{trailing-return-type} \end{ncsimplebnf} -and the type of the contained +a \placeholder{derived-declarator-type-list} is determined as follows: +\begin{itemize} +\item +If the \grammarterm{unqualified-id} of the \grammarterm{declarator-id} +is a \grammarterm{conversion-function-id}, +the \placeholder{derived-declarator-type-list} is empty. + +\item +Otherwise, the \placeholder{derived-declarator-type-list} is as appears in +the type ``\placeholder{derived-declarator-type-list} \tcode{T}'' +of the contained \grammarterm{declarator-id} in the declaration \tcode{T} -\tcode{D1} -is -``\placeholder{derived-declarator-type-list} -\tcode{T}'', -the type of the -\grammarterm{declarator-id} -in -\tcode{D} -is -``\placeholder{derived-declarator-type-list} -\opt{\keyword{noexcept}} -function of parameter-type-list -\opt{\grammarterm{cv-qualifier-seq}} \opt{\grammarterm{ref-qualifier}} -returning \tcode{T}'', where +\tcode{D1}. +\end{itemize} +The declared return type \tcode{U} of the function type +is determined as follows: \begin{itemize} \item -the parameter-type-list is derived from -the \grammarterm{parameter-declaration-clause} as described below and +If the \grammarterm{trailing-return-type} is present, +\tcode{T} shall be the single \grammarterm{type-specifier} \keyword{auto}, and +\tcode{U} is the type specified by the \grammarterm{trailing-return-type}. + \item -the optional \keyword{noexcept} is present if and only if -the exception specification\iref{except.spec} is non-throwing. -\end{itemize} -The optional \grammarterm{attribute-specifier-seq} -appertains to the function type. +Otherwise, if the declaration declares a conversion function, +see~\ref{class.conv.fct}. -\pnum -In a declaration -\tcode{T} -\tcode{D} -where -\tcode{D} -has the form -\begin{ncsimplebnf} -\terminal{D1} \terminal{(} parameter-declaration-clause \terminal{)} \opt{cv-qualifier-seq}\br -\bnfindent\opt{ref-qualifier} \opt{noexcept-specifier} \opt{attribute-specifier-seq} trailing-return-type -\end{ncsimplebnf} -and the type of the contained -\grammarterm{declarator-id} -in the declaration -\tcode{T} -\tcode{D1} -is -``\placeholder{derived-declarator-type-list} \tcode{T}'', -\tcode{T} shall be the single \grammarterm{type-specifier} \keyword{auto}. +\item +Otherwise, \tcode{U} is \tcode{T}. +\end{itemize} The type of the \grammarterm{declarator-id} in @@ -3503,12 +3563,10 @@ \begin{itemize} \item the parameter-type-list is derived from -the \grammarterm{parameter-declaration-clause} as described below, -\item -\tcode{U} is the type specified by the \grammarterm{trailing-return-type}, and +the \grammarterm{parameter-declaration-clause} as described below and \item the optional \keyword{noexcept} is present if and only if -the exception specification is non-throwing. +the exception specification\iref{except.spec} is non-throwing. \end{itemize} The optional \grammarterm{attribute-specifier-seq} appertains to the function type. @@ -3652,11 +3710,15 @@ a \grammarterm{parameter-declaration} with a \keyword{this} specifier. An explicit-object-parameter-declaration shall appear only as the first \grammarterm{parameter-declaration} of -a \grammarterm{parameter-declaration-list} of either: +a \grammarterm{parameter-declaration-list} of one of: \begin{itemize} \item -a \grammarterm{member-declarator} -that declares a member function\iref{class.mem}, or +a declaration of +a member function or member function template\iref{class.mem}, or +\item +an explicit instantiation\iref{temp.explicit} or +explicit specialization\iref{temp.expl.spec} of +a templated member function, or \item a \grammarterm{lambda-declarator}\iref{expr.prim.lambda}. \end{itemize} @@ -4574,9 +4636,7 @@ constructor that is user-provided or deleted, then the object is default-initialized; \item otherwise, -the object is zero-initialized and the semantic constraints for -default-initialization are checked, and if \tcode{T} has a -non-trivial default constructor, the object is default-initialized. +the object is zero-initialized and then default-initialized. \end{itemize} \item @@ -4684,13 +4744,15 @@ \tcode{X}. The form \tcode{()} -is permitted in certain other initialization contexts\iref{expr.new, +can appear in certain other initialization contexts\iref{expr.new, expr.type.conv,class.base.init}. \end{note} \item Otherwise, if the destination type is an array, the object is initialized as follows. +The \grammarterm{initializer} shall be of the form +\tcode{(} \grammarterm{expression-list} \tcode{)}. Let $x_1$, $\dotsc$, $x_k$ be the elements of the \grammarterm{expression-list}. If the destination type is an array of unknown bound, @@ -4752,7 +4814,7 @@ is sequenced before those associated with the initialization of $e_j$. \begin{note} By contrast with direct-list-initialization, -narrowing conversions\iref{dcl.init.list} are permitted, +narrowing conversions\iref{dcl.init.list} can appear, designators are not permitted, a temporary object bound to a reference does not have its lifetime extended\iref{class.temporary}, and @@ -4960,8 +5022,8 @@ \item If the initializer list is a brace-enclosed \grammarterm{initializer-list}, the explicitly initialized elements of the aggregate -are the first $n$ elements of the aggregate, -where $n$ is the number of elements in the initializer list. +are those for which an element of the initializer list +appertains to the aggregate element or to a subobject thereof (see below). \item Otherwise, the initializer list must be \tcode{\{\}}, and there are no explicitly initialized elements. @@ -4992,21 +5054,30 @@ initializes \tcode{c.a} with 1 and \tcode{c.x} with 3. \end{example} \item -Otherwise, the element is copy-initialized -from the corresponding \grammarterm{initializer-clause} -or is initialized with the \grammarterm{brace-or-equal-initializer} +Otherwise, if the initializer list is +a brace-enclosed \grammarterm{designated-initializer-list}, +the element is initialized with the \grammarterm{brace-or-equal-initializer} of the corresponding \grammarterm{designated-initializer-clause}. If that initializer is of the form -\grammarterm{assignment-expression} or \tcode{= }\grammarterm{assignment-expression} and a narrowing conversion\iref{dcl.init.list} is required to convert the expression, the program is ill-formed. \begin{note} -If the initialization is by \grammarterm{designated-initializer-clause}, -its form determines whether copy-initialization or direct-initialization -is performed. +The form of the initializer determines +whether copy-initialization or direct-initialization is performed. \end{note} +\item +Otherwise, +the initializer list is a brace-enclosed \grammarterm{initializer-list}. +If an \grammarterm{initializer-clause} appertains to the aggregate element, +then the aggregate element is copy-initialized from the \grammarterm{initializer-clause}. +Otherwise, +the aggregate element is copy-initialized +from a brace-enclosed \grammarterm{initializer-list} +consisting of all of the \grammarterm{initializer-clause}s +that appertain to subobjects of the aggregate element, +in the order of appearance. \begin{note} If an initializer is itself an initializer list, the element is list-initialized, which will result in a recursive application @@ -5096,13 +5167,7 @@ with the value of an expression of the form \tcode{int\{\}} (that is, \tcode{0}), and \tcode{ss.d} with the value of \tcode{ss.b[ss.a]} -(that is, \tcode{'s'}), and in -\begin{codeblock} -struct X { int i, j, k = 42; }; -X a[] = { 1, 2, 3, 4, 5, 6 }; -X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } }; -\end{codeblock} -\tcode{a} and \tcode{b} have the same value +(that is, \tcode{'s'}). \begin{codeblock} struct A { @@ -5144,15 +5209,9 @@ \end{note} \pnum -An array of unknown bound initialized with a -brace-enclosed -\grammarterm{initializer-list} -containing -\tcode{n} -\grammarterm{initializer-clause}{s} -is defined as having -\tcode{n} -elements\iref{dcl.array}. +The number of elements\iref{dcl.array} in an array of unknown bound +initialized with a brace-enclosed \grammarterm{initializer-list} +is the number of explicitly initialized elements of the array. \begin{example} \begin{codeblock} int x[] = { 1, 3, 5 }; @@ -5162,6 +5221,15 @@ as a one-dimensional array that has three elements since no size was specified and there are three initializers. \end{example} +\begin{example} +In +\begin{codeblock} +struct X { int i, j, k; }; +X a[] = { 1, 2, 3, 4, 5, 6 }; +X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } }; +\end{codeblock} +\tcode{a} and \tcode{b} have the same value. +\end{example} An array of unknown bound shall not be initialized with an empty \grammarterm{braced-init-list} \tcode{\{\}}. \begin{footnote} @@ -5209,19 +5277,6 @@ \end{example} \end{note} -\pnum -An -\grammarterm{initializer-list} -is ill-formed if the number of -\grammarterm{initializer-clause}{s} -exceeds the number of elements of the aggregate. -\begin{example} -\begin{codeblock} -char cv[4] = { 'a', 's', 'd', 'f', 0 }; // error -\end{codeblock} -is ill-formed. -\end{example} - \pnum If a member has a default member initializer and a potentially-evaluated subexpression thereof is an aggregate @@ -5243,32 +5298,6 @@ \end{codeblock} \end{example} -\pnum -If an aggregate class \tcode{C} contains a subaggregate element -\tcode{e} with no elements, -the \grammarterm{initializer-clause} for \tcode{e} shall not be -omitted from an \grammarterm{initializer-list} for an object of type -\tcode{C} unless the \grammarterm{initializer-clause}{s} for all -elements of \tcode{C} following \tcode{e} are also omitted. -\begin{example} -\begin{codeblock} -struct S { } s; -struct A { - S s1; - int i1; - S s2; - int i2; - S s3; - int i3; -} a = { - { }, // Required initialization - 0, - s, // Required initialization - 0 -}; // Initialization not required for \tcode{A::s3} because \tcode{A::i3} is also not initialized -\end{codeblock} -\end{example} - \pnum When initializing a multidimensional array, the @@ -5306,28 +5335,71 @@ \end{example} \pnum -Braces can be elided in an -\grammarterm{initializer-list} -as follows. -If the -\grammarterm{initializer-list} -begins with a left brace, -then the succeeding comma-separated list of -\grammarterm{initializer-clause}{s} -initializes the elements of a subaggregate; -it is erroneous for there to be more -\grammarterm{initializer-clause}{s} -than elements. -If, however, the -\grammarterm{initializer-list} -for a subaggregate does not begin with a left brace, -then only enough -\grammarterm{initializer-clause}{s} -from the list are taken to initialize the elements of the subaggregate; -any remaining -\grammarterm{initializer-clause}{s} -are left to initialize the next element of the aggregate -of which the current subaggregate is an element. +Each \grammarterm{initializer-clause} in +a brace-enclosed \grammarterm{initializer-list} +is said to \defn{appertain} +to an element of the aggregate being initialized or +to an element of one of its subaggregates. +Considering the sequence of \grammarterm{initializer-clause}s, +and the sequence of aggregate elements +initially formed as the sequence of elements of the aggregate being initialized +and potentially modified as described below, +each \grammarterm{initializer-clause} appertains to +the corresponding aggregate element if +\begin{itemize} +\item +the aggregate element is not an aggregate, or +\item +the \grammarterm{initializer-clause} begins with a left brace, or +\item +the \grammarterm{initializer-clause} is an expression and +an implicit conversion sequence can be formed +that converts the expression to the type of the aggregate element, or +\item +the aggregate element is an aggregate that itself has no aggregate elements. +\end{itemize} +Otherwise, +the aggregate element is an aggregate and +that subaggregate is replaced in the list of aggregate elements by +the sequence of its own aggregate elements, and +the appertainment analysis resumes with +the first such element and the same \grammarterm{initializer-clause}. +\begin{note} +These rules apply recursively to the aggregate's subaggregates. +\begin{example} +In +\begin{codeblock} +struct S1 { int a, b; }; +struct S2 { S1 s, t; }; + +S2 x[2] = { 1, 2, 3, 4, 5, 6, 7, 8 }; +S2 y[2] = { + { + { 1, 2 }, + { 3, 4 } + }, + { + { 5, 6 }, + { 7, 8 } + } +}; +\end{codeblock} +\tcode{x} and \tcode{y} have the same value. +\end{example} +\end{note} +This process continues +until all \grammarterm{initializer-clause}s have been exhausted. +If any \grammarterm{initializer-clause} remains +that does not appertain to +an element of the aggregate or one of its subaggregates, +the program is ill-formed. +\begin{example} +\begin{codeblock} +char cv[4] = { 'a', 's', 'd', 'f', 0 }; // error: too many initializers +\end{codeblock} +\end{example} + +\pnum \begin{example} \begin{codeblock} float y[4][3] = { @@ -5382,22 +5454,30 @@ \end{example} \pnum -All implicit type conversions\iref{conv} are considered when -initializing the element with an \grammarterm{assignment-expression}. -If the -\grammarterm{assignment-expression} -can initialize an element, the element is initialized. -Otherwise, if the element is itself a subaggregate, -brace elision is assumed and the -\grammarterm{assignment-expression} -is considered for the initialization of the first element of the subaggregate. \begin{note} -As specified above, brace elision cannot apply to -subaggregates with no elements; an -\grammarterm{initializer-clause} for the entire subobject is -required. +The initializer for an empty subaggregate is needed +if any initializers are provided for subsequent elements. +\begin{example} +\begin{codeblock} +struct S { } s; +struct A { + S s1; + int i1; + S s2; + int i2; + S s3; + int i3; +} a = { + { }, // Required initialization + 0, + s, // Required initialization + 0 +}; // Initialization not required for \tcode{A::s3} because \tcode{A::i3} is also not initialized +\end{codeblock} +\end{example} \end{note} +\pnum \begin{example} \begin{codeblock} struct A { @@ -5411,7 +5491,6 @@ A a; B b = { 4, a, a }; \end{codeblock} - Braces are elided around the \grammarterm{initializer-clause} for @@ -5667,13 +5746,14 @@ \item Otherwise, if the initializer expression \begin{itemize} -\item is an rvalue (but not a bit-field) or function lvalue and +\item is an rvalue (but not a bit-field) or an lvalue of function type and ``\cvqual{cv1} \tcode{T1}'' is reference-compatible with ``\cvqual{cv2} \tcode{T2}'', or \item has a class type (i.e., \tcode{T2} is a class type), where \tcode{T1} is not reference-related to \tcode{T2}, and can be converted to -an rvalue or function lvalue of type ``\cvqual{cv3} \tcode{T3}'', +an rvalue of type ``\cvqual{cv3} \tcode{T3}'' or +an lvalue of function type ``\cvqual{cv3} \tcode{T3}'', where ``\cvqual{cv1} \tcode{T1}'' is reference-compatible with ``\cvqual{cv3} \tcode{T3}'' (see~\ref{over.match.ref}), \end{itemize} @@ -5682,8 +5762,10 @@ the converted expression in the second case is called the converted initializer. If the converted initializer is a prvalue, -its type \tcode{T4} is adjusted to type ``\cvqual{cv1} \tcode{T4}''\iref{conv.qual} -and the temporary materialization conversion\iref{conv.rval} is applied. +let its type be denoted by \tcode{T4}; +the temporary materialization conversion\iref{conv.rval} is applied, +considering the type of the prvalue to be +``\cvqual{cv1} \tcode{T4}''\iref{conv.qual}. In any case, the reference binds to the resulting glvalue (or to an appropriate base class subobject). @@ -5703,6 +5785,13 @@ int i2 = 42; int&& rri = static_cast(i2); // binds directly to \tcode{i2} B&& rrb = x; // binds directly to the result of \tcode{operator B} + +constexpr int f() { + const int &x = 42; + const_cast(x) = 1; // undefined behavior + return x; +} +constexpr int z = f(); // error: not a constant expression \end{codeblock} \end{example} @@ -5741,7 +5830,7 @@ Banana &&banana3 = Alaska(); // error } -const double& rcd2 = 2; // \tcode{rcd2} refers to temporary with value \tcode{2.0} +const double& rcd2 = 2; // \tcode{rcd2} refers to temporary with type \tcode{const double} and value \tcode{2.0} double&& rrd = 2; // \tcode{rrd} refers to temporary with value \tcode{2.0} const volatile int cvi = 1; const int& r2 = cvi; // error: cv-qualifier dropped @@ -5841,7 +5930,7 @@ the program is ill-formed. \pnum -List-initialization of an object or reference of type \tcode{T} is defined as follows: +List-initialization of an object or reference of type \cvqual{cv} \tcode{T} is defined as follows: \begin{itemize} \item If the \grammarterm{braced-init-list} @@ -5864,7 +5953,7 @@ \end{example} \item If \tcode{T} is an aggregate class and the initializer list has a single element -of type \cvqual{cv} \tcode{U}, +of type \cvqual{cv1} \tcode{U}, where \tcode{U} is \tcode{T} or a class derived from \tcode{T}, the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for @@ -5909,12 +5998,14 @@ struct S { S(std::initializer_list); // \#1 S(std::initializer_list); // \#2 - S(); // \#3 + S(std::initializer_list); // \#3 + S(); // \#4 // ... }; S s1 = { 1.0, 2.0, 3.0 }; // invoke \#1 S s2 = { 1, 2, 3 }; // invoke \#2 -S s3 = { }; // invoke \#3 +S s3{s2}; // invoke \#3 (not the copy constructor) +S s4 = { }; // invoke \#4 \end{codeblock} \end{example} @@ -6084,7 +6175,7 @@ corresponding element of the initializer list, and the \tcode{std::initializer_list} object is constructed to refer to that array. \begin{note} -A constructor or conversion function selected for the copy is required to be +A constructor or conversion function selected for the copy needs to be accessible\iref{class.access} in the context of the initializer list. \end{note} If a narrowing conversion is required to initialize any of the elements, @@ -6250,7 +6341,13 @@ \opt{ctor-initializer} compound-statement\br function-try-block\br \terminal{=} \keyword{default} \terminal{;}\br - \terminal{=} \keyword{delete} \terminal{;} + deleted-function-body +\end{bnf} + +\begin{bnf} +\nontermdef{deleted-function-body}\br + \terminal{=} \keyword{delete} \terminal{;}\br + \terminal{=} \keyword{delete} \terminal{(} unevaluated-string \terminal{)} \terminal{;} \end{bnf} Any informal reference to the body of a function should be interpreted as a reference to @@ -6262,8 +6359,10 @@ a \grammarterm{mem-initializer-id}\iref{class.base.init}. The optional \grammarterm{attribute-specifier-seq} in a \grammarterm{function-definition} appertains to the function. -A \grammarterm{virt-specifier-seq} can be part of a \grammarterm{function-definition} -only if it is a \grammarterm{member-declaration}\iref{class.mem}. +A \grammarterm{function-definition} with a \grammarterm{virt-specifier-seq} +shall be a \grammarterm{member-declaration}\iref{class.mem}. +A \grammarterm{function-definition} with a \grammarterm{requires-clause} +shall define a templated function. \pnum In a \grammarterm{function-definition}, @@ -6372,9 +6471,9 @@ is called an \defnx{explicitly-defaulted}{definition!function!explicitly-defaulted} definition. A function that is explicitly defaulted shall \begin{itemize} -\item be a special member function or -a comparison operator function\iref{over.binary}, and -\item not have default arguments. +\item be a special member function\iref{special} or +a comparison operator function\iref{over.binary, class.compare.default}, and +\item not have default arguments\iref{dcl.fct.default}. \end{itemize} \pnum @@ -6469,15 +6568,18 @@ (i.e., explicitly defaulted after its first declaration) is implicitly defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. +\begin{note} +Declaring a function as defaulted after its first declaration +can provide efficient execution and concise definition +while enabling a stable binary interface to an evolving code base. +\end{note} A non-user-provided defaulted function (i.e., implicitly declared or explicitly defaulted in the class) that is not defined as deleted is implicitly defined when it is odr-used\iref{basic.def.odr} or needed for constant evaluation\iref{expr.const}. \begin{note} -Declaring a function as defaulted after its first declaration can provide -efficient execution and concise -definition while enabling a stable binary interface to an evolving code -base. +The implicit definition of a non-user-provided defaulted function +does not bind any names. \end{note} \pnum @@ -6503,11 +6605,8 @@ \indextext{definition!function!deleted}% \pnum -A \defnadj{deleted}{definition} of a function is -a function definition whose -\grammarterm{function-body} -is of the form -\tcode{= delete ;} +A \defnadj{deleted}{definition} of a function is a function definition +whose \grammarterm{function-body} is a \grammarterm{deleted-function-body} or an explicitly-defaulted definition of the function where the function is defined as deleted. A \defnadj{deleted}{function} is @@ -6517,6 +6616,12 @@ \pnum A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. + +\recommended +The resulting diagnostic message should include +the text of the \grammarterm{unevaluated-string}, +if one is supplied. + \begin{note} This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the @@ -6525,6 +6630,9 @@ function selected by overload resolution is referenced. The implicit odr-use\iref{term.odr.use} of a virtual function does not, by itself, constitute a reference. +The \grammarterm{unevaluated-string}, if present, +can be used to explain the rationale for deletion and/or +to suggest an alternative. \end{note} \pnum @@ -6898,8 +7006,11 @@ A structured binding declaration introduces the \grammarterm{identifier}{s} $\tcode{v}_0$, $\tcode{v}_1$, $\tcode{v}_2, \dotsc$ of the -\grammarterm{identifier-list} as names +\grammarterm{attributed-identifier-list} as names of \defn{structured binding}{s}. +The optional \grammarterm{attribute-specifier-seq} of +an \grammarterm{attributed-identifier} +appertains to the structured binding so introduced. 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 @@ -6938,7 +7049,7 @@ \pnum If \tcode{E} is an array type with element type \tcode{T}, the number -of elements in the \grammarterm{identifier-list} shall be equal to the +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 lvalue that refers to the element $i$ of the array and whose type is \tcode{T}; the referenced type is \tcode{T}. @@ -6961,7 +7072,7 @@ shall be a well-formed integral constant expression and the number of elements in -the \grammarterm{identifier-list} shall be equal to the value of that +the \grammarterm{attributed-identifier-list} shall be 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$. @@ -7003,7 +7114,7 @@ well-formed when named as \tcode{\exposidnc{e}.\placeholder{name}} in the context of the structured binding, \tcode{E} shall not have an anonymous union member, and -the number of elements in the \grammarterm{identifier-list} shall be +the number of elements in the \grammarterm{attributed-identifier-list} shall be 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$ @@ -9100,6 +9211,52 @@ \end{codeblock} \end{example} +\rSec2[dcl.attr.indet]{Indeterminate storage} +\indextext{attribute!indeterminate} + +\pnum +The \grammarterm{attribute-token} \tcode{indeterminate} may be applied +to the definition of a block variable with automatic storage duration or +to a \grammarterm{parameter-declaration} of a function declaration. +No \grammarterm{attribute-argument-clause} shall be present. +The attribute specifies +that the storage of an object with automatic storage duration +is initially indeterminate rather than erroneous\iref{basic.indet}. + +\pnum +If a function parameter is declared with the \tcode{indeterminate} attribute, +it shall be so declared in the first declaration of its function. +If a function parameter is declared with +the \tcode{indeterminate} attribute in the first declaration of its function +in one translation unit and +the same function is declared without the \tcode{indeterminate} attribute +on the same parameter in its first declaration in another translation unit, +the program is ill-formed, no diagnostic required. + +\pnum +\begin{note} +Reading from an uninitialized variable +that is marked \tcode{[[indeterminate]]} can cause undefined behavior. +\begin{codeblock} +void f(int); +void g() { + int x [[indeterminate]], y; + f(y); // erroneous behavior\iref{basic.indet} + f(x); // undefined behavior +} + +struct T { + T() {} + int x; +}; +int h(T t [[indeterminate]]) { + f(t.x); // undefined behavior when called below + return 0; +} +int _ = h(T()); +\end{codeblock} +\end{note} + \rSec2[dcl.attr.likelihood]{Likelihood attributes}% \indextext{attribute!likely} \indextext{attribute!unlikely} @@ -9176,6 +9333,7 @@ The attribute may be applied to the declaration of a class, \grammarterm{typedef-name}, variable (including a structured binding declaration), +structured binding, non-static data member, function, enumeration, or @@ -9333,7 +9491,7 @@ 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. \begin{note} -The function may +The function can terminate by throwing an exception. \end{note} diff --git a/source/exceptions.tex b/source/exceptions.tex index 8dc2fcbc05..22fc97a325 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -257,7 +257,7 @@ \pnum Throwing an exception -initializes a temporary object, +initializes an object with dynamic storage duration, called the \defnx{exception object}{exception handling!exception object}. If the type of the exception object would be @@ -309,12 +309,13 @@ \pnum \indextext{exception handling!exception object!constructor}% \indextext{exception handling!exception object!destructor}% -When the thrown object is a class object, the constructor selected for -the copy-initialization as well as the constructor selected for -a copy-initialization considering the thrown object as an lvalue -shall be non-deleted and accessible, even if the copy/move operation is -elided\iref{class.copy.elision}. -The destructor is potentially invoked\iref{class.dtor}. +Let \tcode{T} denote the type of the exception object. +Copy-initialization of an object of type \tcode{T} from +an lvalue of type \tcode{const T} in a context unrelated to \tcode{T} +shall be well-formed. +If \tcode{T} is a class type, +the selected constructor is odr-used\iref{basic.def.odr} and +the destructor of \tcode{T} is potentially invoked\iref{class.dtor}. \pnum \indextext{exception handling!rethrow}% diff --git a/source/expressions.tex b/source/expressions.tex index e4c80eef64..683b30137f 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -300,23 +300,24 @@ \end{note} \pnum +An object of dynamic type $\tcode{T}_\text{obj}$ is +\defn{type-accessible} through a glvalue of type $\tcode{T}_\text{ref}$ +if $\tcode{T}_\text{ref}$ is similar\iref{conv.qual} to: +\begin{itemize} +\item $\tcode{T}_\text{obj}$, + +\item a type that is the signed or unsigned type corresponding to $\tcode{T}_\text{obj}$, or + +\item a \keyword{char}, \tcode{\keyword{unsigned} \keyword{char}}, or \tcode{std::byte} type. +\end{itemize} If a program attempts to access\iref{defns.access} the stored value of an object through a glvalue -whose type is not similar\iref{conv.qual} to -one of the following types the behavior is -undefined: +through which it is not type-accessible, +the behavior is undefined. \begin{footnote} The intent of this list is to specify those circumstances in which an object can or cannot be aliased. \end{footnote} -\begin{itemize} -\item the dynamic type of the object, - -\item a type that is the signed or unsigned type corresponding to the -dynamic type of the object, or - -\item a \keyword{char}, \tcode{\keyword{unsigned} \keyword{char}}, or \tcode{std::byte} type. -\end{itemize} If a program invokes a defaulted copy/move constructor or copy/move assignment operator for a union of type \tcode{U} with a glvalue argument @@ -674,6 +675,9 @@ \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. \end{itemize} \pnum @@ -1335,14 +1339,43 @@ operators\iref{expr.ref}. \end{note} +\pnum +If an \grammarterm{id-expression} $E$ denotes +a non-static non-type member of some class \tcode{C} at a point where +the current class\iref{expr.prim.this} is \tcode{X} and +\begin{itemize} +\item +$E$ is potentially evaluated or +\tcode{C} is \tcode{X} or a base class of \tcode{X}, and +\item +$E$ is not the \grammarterm{id-expression} of +a class member access expression\iref{expr.ref}, and +\item +if $E$ is a \grammarterm{qualified-id}, +$E$ is not the un-parenthesized operand of +the unary \tcode{\&} operator\iref{expr.unary.op}, +\end{itemize} +the \grammarterm{id-expression} is transformed into +a class member access expression using \tcode{(*this)} as the object expression. +\begin{note} +If \tcode{C} is not \tcode{X} or a base class of \tcode{X}, +the class member access expression is ill-formed. +Also, if the \grammarterm{id-expression} occurs within +a static or explicit object member function, +the class member access is ill-formed. +\end{note} +This transformation does not apply in +the template definition context\iref{temp.dep.type}. + \pnum If an \grammarterm{id-expression} $E$ denotes a member $M$ of an anonymous union\iref{class.union.anon} $U$: \begin{itemize} \item If $U$ is a non-static data member, -$E$ refers to $M$ as a member of the lookup context of the terminal name of $E$ (after any transformation to -a class member access expression\iref{class.mfct.non.static}). +$E$ refers to $M$ as a member of the lookup context of the terminal name of $E$ +(after any implicit transformation to +a class member access expression). \begin{example} \tcode{o.x} is interpreted as \tcode{o.$u$.x}, where $u$ names the anonymous union member. @@ -1364,13 +1397,11 @@ An \grammarterm{id-expression} that denotes a non-static data member or implicit object member function of a class can only be used: \begin{itemize} -\item as part of a class member access\iref{expr.ref} in which the +\item as part of a class member access +(after any implicit transformation (see above)) +in which the object expression refers to the member's class -\begin{footnote} -This also applies when the object expression -is an implicit \tcode{(*\keyword{this})}\iref{class.mfct.non.static}. -\end{footnote} or a class derived from that class, or @@ -1412,7 +1443,7 @@ \end{codeblock} In each case, the constraints of \tcode{f} are not satisfied. In the declaration of \tcode{p2}, -those constraints are required to be satisfied +those constraints need to be satisfied even though \tcode{f} is an unevaluated operand\iref{term.unevaluated.operand}. \end{example} @@ -1447,9 +1478,6 @@ A \grammarterm{type-name} or \grammarterm{computed-type-specifier} prefixed by \tcode{\~} denotes the destructor of the type so named; see~\ref{expr.prim.id.dtor}. -Within the definition of a non-static member function, an -\grammarterm{identifier} that names a non-static member is transformed to a -class member access expression\iref{class.mfct.non.static}. \end{note} \pnum @@ -1502,11 +1530,10 @@ is in $E$'s \grammarterm{parameter-declaration-clause}), the type of the expression is the type of the result. \end{itemize} -\begin{note} If the entity is a template parameter object for a template parameter of type \tcode{T}\iref{temp.param}, the type of the expression is \tcode{const T}. -\end{note} +In all other cases, the type of the expression is the type of the entity. \begin{note} The type will be adjusted as described in \ref{expr.type} if it is cv-qualified or is a reference type. @@ -1899,8 +1926,9 @@ \end{note} \pnum -The closure type is not an aggregate type\iref{dcl.init.aggr} and -not a structural type\iref{term.structural.type}. +The closure type is not an aggregate type\iref{dcl.init.aggr}; +it is a structural type\iref{term.structural.type} if and only if +the lambda has no \grammarterm{lambda-capture}. An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than by changing: @@ -2182,7 +2210,7 @@ if the function call operator template specialization is an immediate function. \begin{note} This will result in the implicit instantiation of the generic lambda's body. -The instantiated generic lambda's return type and parameter types are required to match +The instantiated generic lambda's return type and parameter types need to match the return type and parameter types of the pointer to function. \end{note} \begin{example} @@ -2875,9 +2903,11 @@ \pnum A \grammarterm{requires-expression} may introduce local parameters using a -\grammarterm{parameter-declaration-clause}\iref{dcl.fct}. +\grammarterm{parameter-declaration-clause}. A local parameter of a \grammarterm{requires-expression} shall not have a default argument. +The type of such a parameter is determined as specified for +a function parameter in~\ref{dcl.fct}. These parameters have no linkage, storage, or lifetime; they are only used as notation for the purpose of defining \grammarterm{requirement}s. The \grammarterm{parameter-declaration-clause} of a @@ -2889,6 +2919,10 @@ concept C = requires(T t, ...) { // error: terminates with an ellipsis t; }; +template +concept C2 = requires(T p[2]) { + (decltype(p))nullptr; // OK, \tcode{p} has type ``pointer to \tcode{T}'' +}; \end{codeblock} \end{example} @@ -3270,14 +3304,20 @@ of the class member access\iref{expr.ref,basic.life}. \pnum +A type $\tcode{T}_\text{call}$ is +\defn{call-compatible} with a function type $\tcode{T}_\text{func}$ +if $\tcode{T}_\text{call}$ is the same type as $\tcode{T}_\text{func}$ or +if the type ``pointer to $\tcode{T}_\text{func}$'' can be +converted to type ``pointer to $\tcode{T}_\text{call}$'' +via a function pointer conversion\iref{conv.fctptr}. Calling a function through an -expression whose function type \tcode{E} is different -from the function type \tcode{F} of the called function's -definition results in undefined behavior -unless the type ``pointer to \tcode{F}'' can be converted -to the type ``pointer to \tcode{E}'' via a function pointer conversion\iref{conv.fctptr}. +expression whose function type +is not call-compatible with the +type of the called function's +definition results in undefined behavior. \begin{note} -The exception applies when the expression has the type of a +This requirement allows the case +when the expression has the type of a potentially-throwing function, but the called function has a non-throwing exception specification, and the function types are otherwise the same. @@ -3303,7 +3343,9 @@ \end{codeblock} \end{example} If the function is an implicit object member -function, the \keyword{this} parameter of the function\iref{expr.prim.this} +function, +the object expression of the class member access shall be a glvalue and +the \keyword{this} parameter of the function\iref{expr.prim.this} is initialized with a pointer to the object of the call, converted as if by an explicit type conversion\iref{expr.cast}. \begin{note} @@ -3320,10 +3362,12 @@ a type. However, it prevents a passed-by-value parameter to have an incomplete or abstract class type. \end{note} -It is \impldef{whether the lifetime of a parameter ends when the callee -returns or at the end of the enclosing full-expression} whether the -lifetime of a parameter ends when the function in which it is defined -returns or at the end of the enclosing full-expression. +It is \impldef{whether a parameter is destroyed when the function +exits or at the end of the enclosing full-expression} +whether a parameter is destroyed +when the function in which it is defined exits\iref{stmt.return, except.ctor} +or at the end of the enclosing full-expression; +parameters are always destroyed in the reverse order of their construction. The initialization and destruction of each parameter occurs within the context of the full-expression\iref{intro.execution} where the function call appears. @@ -3404,7 +3448,7 @@ A function can change the values of its non-const parameters, but these changes cannot affect the values of the arguments except where a parameter is of a reference type\iref{dcl.ref}; if the reference is to -a const-qualified type, \keyword{const_cast} is required to be used to +a const-qualified type, \keyword{const_cast} needs to be used to cast away the constness in order to modify the argument's value. Where a parameter is of \keyword{const} reference type a temporary object is introduced if @@ -3543,18 +3587,7 @@ A postfix expression followed by a dot \tcode{.} or an arrow \tcode{->}, optionally followed by the keyword \keyword{template}, and then followed by an -\grammarterm{id-expression}, is a postfix expression. The postfix -expression before the dot or arrow is evaluated; -\begin{footnote} -If the class member -access expression is evaluated, the subexpression evaluation happens even if the -result is unnecessary to determine -the value of the entire postfix expression, for example if the -\grammarterm{id-expression} denotes a static member. -\end{footnote} -the result of that evaluation, together with the -\grammarterm{id-expression}, determines the result of the entire postfix -expression. +\grammarterm{id-expression}, is a postfix expression. \begin{note} If the keyword \keyword{template} is used, the following unqualified name @@ -3565,8 +3598,12 @@ \pnum \indextext{type!incomplete}% -For the first option (dot) the first expression shall be a glvalue. -For the second option (arrow) the first expression +For the first option (dot), +if the \grammarterm{id-expression} names a static member or an enumerator, +the first expression is a discarded-value expression\iref{expr.context}; +if the \grammarterm{id-expression} names a non-static data member, +the first expression shall be a glvalue. +For the second option (arrow), the first expression shall be a prvalue having pointer type. The expression \tcode{E1->E2} is converted to the equivalent form \tcode{(*(E1)).E2}; the remainder of @@ -3576,6 +3613,19 @@ \tcode{(*(E1))} is an lvalue. \end{footnote} +\pnum +The postfix expression before the dot is evaluated; +\begin{footnote} +If the class member +access expression is evaluated, the subexpression evaluation happens even if the +result is unnecessary to determine +the value of the entire postfix expression, for example if the +\grammarterm{id-expression} denotes a static member. +\end{footnote} +the result of that evaluation, +together with the \grammarterm{id-expression}, +determines the result of the entire postfix expression. + \pnum Abbreviating \grammarterm{postfix-expression}\tcode{.}\grammarterm{id-expression} @@ -3717,7 +3767,7 @@ An operand with volatile-qualified type is deprecated; see~\ref{depr.volatile.type}. The value of the operand object is modified\iref{defns.access} -by adding \tcode{1} to it. +as if it were the operand of the prefix \tcode{++} operator\iref{expr.pre.incr}. The \indextext{value computation}% value computation of the \tcode{++} expression is sequenced before the @@ -3732,11 +3782,6 @@ \end{note} The result is a prvalue. The type of the result is the cv-unqualified version of the type of the operand. -If the operand is a bit-field that cannot represent the incremented value, the -resulting value of the bit-field is -\impldefplain{value of bit-field that cannot represent!incremented value}. -See also~\ref{expr.add} -and~\ref{expr.ass}. \pnum \indextext{expression!decrement}% @@ -3827,7 +3872,8 @@ \item If, in the most derived object pointed (referred) to by \tcode{v}, \tcode{v} points (refers) to a public base class subobject of a \tcode{C} object, and if only one object of type \tcode{C} is derived -from the subobject pointed (referred) to by \tcode{v} the result points (refers) to that \tcode{C} object. +from the subobject pointed (referred) to by \tcode{v}, +the result points (refers) to that \tcode{C} object. \item Otherwise, if \tcode{v} points (refers) to a public base class subobject of the most derived object, and the type of the most @@ -3906,26 +3952,27 @@ a reference to (possibly cv-qualified) class type, that class shall be completely defined. +\pnum +If an \grammarterm{expression} operand of \keyword{typeid} is +a possibly-parenthesized \grammarterm{unary-expression} +whose \grammarterm{unary-operator} is \tcode{*} and +whose operand evaluates to a null pointer value\iref{basic.compound}, +the \keyword{typeid} expression throws an exception\iref{except.throw} +of a type that would match a handler of type +\indextext{\idxcode{bad_typeid}}% +\indexlibraryglobal{bad_typeid}% +\tcode{std::bad_typeid}\iref{bad.typeid}. +\begin{note} +In other contexts, evaluating such a \grammarterm{unary-expression} +results in undefined behavior\iref{expr.unary.op}. +\end{note} + \pnum When \keyword{typeid} is applied to a glvalue whose type is a polymorphic class type\iref{class.virtual}, the result refers to a \tcode{std::type_info} object representing the type of the most derived object\iref{intro.object} (that is, the dynamic type) to which the -glvalue refers. If the glvalue is obtained by applying the -unary \tcode{*} operator to a pointer -\begin{footnote} -If \tcode{p} is an expression of -pointer type, then \tcode{*p}, -\tcode{(*p)}, \tcode{*(p)}, \tcode{((*p))}, \tcode{*((p))}, and so on -all meet this requirement. -\end{footnote} -and the pointer is a null pointer value\iref{basic.compound}, the -\keyword{typeid} expression throws an exception\iref{except.throw} of -a type that would match a handler of type -\indextext{\idxcode{bad_typeid}}% -\indexlibraryglobal{bad_typeid}% -\tcode{std::bad_typeid} -exception\iref{bad.typeid}. +glvalue refers. \pnum When \keyword{typeid} is applied to an expression other than a glvalue of @@ -4219,7 +4266,7 @@ If the original pointer value represents the address \tcode{A} of a byte in memory and \tcode{A} does not satisfy the alignment requirement of \tcode{T}, -then the resulting pointer value is unspecified. +then the resulting pointer value\iref{basic.compound} is unspecified. Otherwise, if the original pointer value points to an object \placeholder{a}, and there is an object \placeholder{b} of type similar to \tcode{T} that is pointer-interconvertible\iref{basic.compound} with \placeholder{a}, @@ -4289,7 +4336,7 @@ A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type -will have its original value; +will have its original value\iref{basic.compound}; \indextext{conversion!implementation-defined pointer integer}% mappings between pointers and integers are otherwise \impldef{conversions between pointers and integers}. @@ -4603,7 +4650,6 @@ \indextext{expression!pointer-to-member constant}% The operand of the unary \tcode{\&} operator shall be an lvalue of some type \tcode{T}. -The result is a prvalue. \begin{itemize} \item If the operand is a \grammarterm{qualified-id} naming a non-static or variant member \tcode{m} @@ -4736,32 +4782,16 @@ \pnum \indextext{expression!increment}% \indextext{expression!decrement}% -The operand of prefix \tcode{++} \indextext{operator!increment}% +\indextext{operator!decrement}% \indextext{prefix \tcode{++}}% -is modified\iref{defns.access} by adding \tcode{1}. \indextext{prefix \tcode{--}}% -The operand shall be a modifiable lvalue. The type of the operand shall -be an arithmetic type other than \cv{}~\tcode{bool}, -or a pointer to a completely-defined object type. +The operand of prefix \tcode{++} or \tcode{--} +shall not be of type \cv{}~\tcode{bool}. An operand with volatile-qualified type is deprecated; see~\ref{depr.volatile.type}. -The result is the updated operand; it is an lvalue, and it is a -bit-field if the operand is a bit-field. -The expression \tcode{++x} is equivalent to \tcode{x+=1}. -\indextext{operator!\idxcode{+=}}% -\begin{note} -See the discussions of addition\iref{expr.add} and assignment -operators\iref{expr.ass} for information on conversions. -\end{note} - -\pnum -The operand of prefix -\indextext{operator!decrement}% -\tcode{--} is modified\iref{defns.access} by subtracting \tcode{1}. -The requirements on the operand of prefix -\tcode{--} and the properties of its result are otherwise the same as -those of prefix \tcode{++}. +The expression \tcode{++x} is otherwise equivalent to \tcode{x+=1} and +the expression \tcode{--x} is otherwise equivalent to \tcode{x-=1}\iref{expr.ass}. \begin{note} For postfix increment and decrement, see~\ref{expr.post.incr}. \end{note} @@ -4783,9 +4813,11 @@ \end{bnf} \pnum -An \grammarterm{await-expression} shall appear only in a potentially-evaluated +An \grammarterm{await-expression} shall appear only as a potentially-evaluated expression within the \grammarterm{compound-statement} of a -\grammarterm{function-body} outside of a \grammarterm{handler}\iref{except.pre}. +\grammarterm{function-body} or \grammarterm{lambda-expression}, +in either case +outside of a \grammarterm{handler}\iref{except.pre}. In a \grammarterm{declaration-statement} or in the \grammarterm{simple-declaration} (if any) of an \grammarterm{init-statement}, an \grammarterm{await-expression} @@ -5269,7 +5301,7 @@ If the \grammarterm{expression} in a \grammarterm{noptr-new-declarator} is present, it is implicitly converted to \tcode{std::size_t}. \indextext{function!allocation}% -The \grammarterm{expression} is erroneous if: +The value of the \grammarterm{expression} is invalid if: \begin{itemize} \item the expression is of non-class type and its value before converting to @@ -5297,7 +5329,7 @@ number of elements to initialize. \end{itemize} -If the \grammarterm{expression} is erroneous after converting to \tcode{std::size_t}: +If the value of the \grammarterm{expression} is invalid after converting to \tcode{std::size_t}: \begin{itemize} \item if the \grammarterm{expression} is a potentially-evaluated core constant expression, @@ -5378,7 +5410,7 @@ and the deallocation function's name is \tcode{\keyword{operator} \keyword{delete}[]}. \begin{note} -An implementation is required to provide default definitions for the global +An implementation is expected to provide default definitions for the global allocation functions\iref{basic.stc.dynamic,new.delete.single,new.delete.array}. A \Cpp{} program can provide alternative definitions of @@ -6054,8 +6086,9 @@ If a conversion can be interpreted in more than one of the ways listed above, the interpretation that appears first in the list is used, even if a cast resulting from that interpretation is ill-formed. If a -conversion can be interpreted in more than one way as a -\keyword{static_cast} followed by a \keyword{const_cast}, the conversion is +\keyword{static_cast} followed by a \keyword{const_cast} is used and +the conversion can be interpreted in more than one way as such, +the conversion is ill-formed. \begin{example} \begin{codeblock} @@ -6066,6 +6099,15 @@ A* foo( D* p ) { return (A*)( p ); // ill-formed \keyword{static_cast} interpretation } + +int*** ptr = 0; +auto t = (int const*const*const*)ptr; // OK, \keyword{const_cast} interpretation + +struct S { + operator const int*(); + operator volatile int*(); +}; +int *p = (int*)S(); // error: two possible interpretations using \keyword{static_cast} followed by \keyword{const_cast} \end{codeblock} \end{example} @@ -6080,7 +6122,7 @@ inheritance relationship between the two classes. \begin{note} For example, if the classes were defined later in the translation unit, -a multi-pass compiler would be permitted to interpret a cast between +a multi-pass compiler could validly interpret a cast between pointers to the classes as if the class types were complete at the point of the cast. \end{note} @@ -6296,7 +6338,7 @@ \begin{itemize} \item If \tcode{P} evaluates to a null pointer value and \tcode{J} evaluates to 0, the result is a null pointer value. -\item Otherwise, if \tcode{P} points to an array element $i$ +\item Otherwise, if \tcode{P} points to a (possibly-hypothetical) array element $i$ of an array object \tcode{x} with $n$ elements\iref{dcl.array}, \begin{footnote} As specified in \ref{basic.compound}, @@ -7479,7 +7521,7 @@ limits (see \ref{implimits}); \item -an operation that would have undefined behavior +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}; \begin{footnote} @@ -7860,6 +7902,9 @@ \item qualification conversions\iref{conv.qual}, \item integral promotions\iref{conv.prom}, \item integral conversions\iref{conv.integral} other than narrowing conversions\iref{dcl.init.list}, +\item floating-point promotions\iref{conv.fpprom}, +\item floating-point conversions\iref{conv.double} where + the source value can be represented exactly in the destination type, \item null pointer conversions\iref{conv.ptr} from \tcode{std::nullptr_t}, \item null member pointer conversions\iref{conv.mem} from \tcode{std::nullptr_t}, and \item function pointer conversions\iref{conv.fctptr}, @@ -7894,7 +7939,7 @@ \item if the value is an object of scalar type, - it does not have an indeterminate value\iref{basic.indet}, + it does not have an indeterminate or erroneous value\iref{basic.indet}, \item if the value is of pointer type, it contains @@ -7930,6 +7975,14 @@ constexpr int r = h(); // OK constexpr auto e = g(); // error: a pointer to an immediate function is // not a permitted result of a constant expression + +struct S { + int x; + constexpr S() {} +}; +int i() { + constexpr S s; // error: \tcode{s.x} has erroneous value +} \end{codeblock} \end{example} diff --git a/source/future.tex b/source/future.tex index 34173964ff..04ed0e5eee 100644 --- a/source/future.tex +++ b/source/future.tex @@ -232,6 +232,7 @@ \indexlibraryglobal{__alignas_is_defined}% \begin{codeblock} #define @\xname{alignas_is_defined}@ 1 +#define @\xname{alignof_is_defined}@ 1 \end{codeblock} \pnum @@ -323,1676 +324,355 @@ \tcode{!(x < y)}. \end{itemdescr} -\rSec1[depr.str.strstreams]{\tcode{char*} streams} - -\rSec2[depr.strstream.syn]{Header \tcode{} synopsis} +\rSec1[depr.cerrno]{Deprecated error numbers} \pnum -The header \libheaderdef{strstream} -defines types that associate stream buffers with -character array objects and assist reading and writing such objects. +The following macros are defined in addition to those +specified in \ref{cerrno.syn}: +\indexlibraryglobal{ENODATA}% +\indexlibraryglobal{ENOSR}% +\indexlibraryglobal{ENOSTR}% +\indexlibraryglobal{ETIME}% \begin{codeblock} -namespace std { - class strstreambuf; - class istrstream; - class ostrstream; - class strstream; -} +#define ENODATA @\seebelow@ +#define ENOSR @\seebelow@ +#define ENOSTR @\seebelow@ +#define ETIME @\seebelow@ \end{codeblock} -\rSec2[depr.strstreambuf]{Class \tcode{strstreambuf}} +\pnum +The meaning of these macros is defined by the POSIX standard. -\rSec3[depr.strstreambuf.general]{General} +\pnum +The following \tcode{enum errc} enumerators are defined +in addition to those specified in \ref{system.error.syn}: -\indexlibraryglobal{strstreambuf}% \begin{codeblock} -namespace std { - class strstreambuf : public basic_streambuf { - public: - strstreambuf() : strstreambuf(0) {} - explicit strstreambuf(streamsize alsize_arg); - strstreambuf(void* (*palloc_arg)(size_t), void (*pfree_arg)(void*)); - strstreambuf(char* gnext_arg, streamsize n, char* pbeg_arg = nullptr); - strstreambuf(const char* gnext_arg, streamsize n); - - strstreambuf(signed char* gnext_arg, streamsize n, - signed char* pbeg_arg = nullptr); - strstreambuf(const signed char* gnext_arg, streamsize n); - strstreambuf(unsigned char* gnext_arg, streamsize n, - unsigned char* pbeg_arg = nullptr); - strstreambuf(const unsigned char* gnext_arg, streamsize n); - - virtual ~strstreambuf(); - - void freeze(bool freezefl = true); - char* str(); - int pcount(); - - protected: - int_type overflow (int_type c = EOF) override; - int_type pbackfail(int_type c = EOF) override; - int_type underflow() override; - pos_type seekoff(off_type off, ios_base::seekdir way, - ios_base::openmode which = ios_base::in | ios_base::out) override; - pos_type seekpos(pos_type sp, - ios_base::openmode which = ios_base::in | ios_base::out) override; - streambuf* setbuf(char* s, streamsize n) override; - - private: - using strstate = T1; // \expos - static const strstate allocated; // \expos - static const strstate constant; // \expos - static const strstate dynamic; // \expos - static const strstate frozen; // \expos - strstate strmode; // \expos - streamsize alsize; // \expos - void* (*palloc)(size_t); // \expos - void (*pfree)(void*); // \expos - }; -} +no_message_available, // \tcode{ENODATA} +no_stream_resources, // \tcode{ENOSR} +not_a_stream, // \tcode{ENOSTR} +stream_timeout, // \tcode{ETIME} \end{codeblock} \pnum -The class -\tcode{strstreambuf} -associates the input sequence, and possibly the output sequence, with an object of some -\textit{character} -array type, whose elements store arbitrary values. -The array object has several attributes. +The value of each \tcode{enum errc} enumerator above +is the same as the value of the \libheader{cerrno} macro +shown in the above synopsis. -\pnum -\begin{note} -For the sake of exposition, these are represented as elements of a bitmask type -(indicated here as \tcode{T1}) called \tcode{strstate}. -The elements are: -\begin{itemize} -\item -\tcode{allocated}, set when a dynamic array object has been -allocated, and hence will be freed by the destructor for the -\tcode{strstreambuf} object; -\item -\tcode{constant}, set when the array object has -\keyword{const} elements, so the output sequence cannot be written; -\item -\tcode{dynamic}, set when the array object is allocated -(or reallocated) -as necessary to hold a character sequence that can change in length; -\item -\tcode{frozen}, set when the program has requested that the -array object not be altered, reallocated, or freed. -\end{itemize} -\end{note} +\rSec1[depr.meta.types]{Deprecated type traits} \pnum -\begin{note} -For the sake of exposition, the maintained data is presented here as: -\begin{itemize} -\item -\tcode{strstate strmode}, the attributes of the array object -associated with the \tcode{strstreambuf} object; -\item -\tcode{int alsize}, the suggested minimum size for a -dynamic array object; -\item -\tcode{void* (*palloc)(size_t)}, points to the function -to call to allocate a dynamic array object; -\item -\tcode{void (*pfree)(void*)}, points to the function to -call to free a dynamic array object. -\end{itemize} -\end{note} +The header \libheaderrefx{type_traits}{meta.type.synop} +has the following addition: + +\begin{codeblock} +namespace std { + template struct is_pod; + template constexpr bool is_pod_v = is_pod::value; + template // \seebelow + struct aligned_storage; + template // \seebelow + using @\libglobal{aligned_storage_t}@ = typename aligned_storage::type; + template + struct aligned_union; + template + using @\libglobal{aligned_union_t}@ = typename aligned_union::type; +} +\end{codeblock} \pnum -Each object of class -\tcode{strstreambuf} -has a -\term{seekable area}, -delimited by the pointers \tcode{seeklow} and \tcode{seekhigh}. -If \tcode{gnext} is a null pointer, the seekable area is undefined. -Otherwise, \tcode{seeklow} equals \tcode{gbeg} and -\tcode{seekhigh} is either \tcode{pend}, -if \tcode{pend} is not a null pointer, or \tcode{gend}. +The behavior of a program that adds specializations for +any of the templates defined in this subclause is undefined, +unless explicitly permitted by the specification of the corresponding template. -\rSec3[depr.strstreambuf.cons]{\tcode{strstreambuf} constructors} +\pnum +\indextext{POD}% +A \term{POD class} is a class that is both a trivial class and a +standard-layout class, and has no non-static data members of type non-POD class +(or array thereof). A \term{POD type} is a scalar type, a POD class, an array +of such a type, or a cv-qualified version of one of these types. -\indexlibraryctor{strstreambuf}% +\indexlibraryglobal{is_pod}% \begin{itemdecl} -explicit strstreambuf(streamsize alsize_arg); +template struct is_pod; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes the base class with \tcode{streambuf()}. -The postconditions of this function are indicated in \tref{depr.strstreambuf.cons.sz}. -\end{itemdescr} - -\begin{libtab2}{\tcode{strstreambuf(streamsize)} effects}{depr.strstreambuf.cons.sz} -{ll} -{Element}{Value} -\tcode{strmode} & \tcode{dynamic} \\ -\tcode{alsize} & \tcode{alsize_arg} \\ -\tcode{palloc} & a null pointer \\ -\tcode{pfree} & a null pointer \\ -\end{libtab2} +\expects +\tcode{remove_all_extents_t} shall be a complete type or \cv{} \keyword{void}. -\indexlibraryctor{strstreambuf}% -\begin{itemdecl} -strstreambuf(void* (*palloc_arg)(size_t), void (*pfree_arg)(void*)); -\end{itemdecl} +\pnum +\remarks +\tcode{is_pod} is a \oldconcept{UnaryTypeTrait}\iref{meta.rqmts} +with a base characteristic of \tcode{true_type} +if \tcode{T} is a POD type, +and \tcode{false_type} otherwise. -\begin{itemdescr} \pnum -\effects -Initializes the base class with \tcode{streambuf()}. -The postconditions of this function are indicated in \tref{depr.strstreambuf.cons.alloc}. - -\begin{libtab2}{\tcode{strstreambuf(void* (*)(size_t), void (*)(void*))} effects} -{depr.strstreambuf.cons.alloc} -{ll} -{Element}{Value} -\tcode{strmode} & \tcode{dynamic} \\ -\tcode{alsize} & an unspecified value \\ -\tcode{palloc} & \tcode{palloc_arg} \\ -\tcode{pfree} & \tcode{pfree_arg} \\ -\end{libtab2} +\begin{note} +It is unspecified whether a closure type\iref{expr.prim.lambda.closure} is a POD type. +\end{note} \end{itemdescr} -\indextext{unspecified}% -\indexlibraryctor{strstreambuf}% +\indexlibraryglobal{aligned_storage}% \begin{itemdecl} -strstreambuf(char* gnext_arg, streamsize n, char* pbeg_arg = nullptr); -strstreambuf(signed char* gnext_arg, streamsize n, - signed char* pbeg_arg = nullptr); -strstreambuf(unsigned char* gnext_arg, streamsize n, - unsigned char* pbeg_arg = nullptr); +template + struct aligned_storage; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes the base class with \tcode{streambuf()}. -The postconditions of this function are indicated in \tref{depr.strstreambuf.cons.ptr}. - -\begin{libtab2}{\tcode{strstreambuf(charT*, streamsize, charT*)} effects} -{depr.strstreambuf.cons.ptr} -{ll} -{Element}{Value} -\tcode{strmode} & 0 \\ -\tcode{alsize} & an unspecified value \\ -\tcode{palloc} & a null pointer \\ -\tcode{pfree} & a null pointer \\ -\end{libtab2} - -\pnum -\tcode{gnext_arg} shall point to the first element of an array -object whose number of elements \tcode{N} is determined as follows: -\begin{itemize} -\item -If -\tcode{n > 0}, -\tcode{N} is \tcode{n}. -\item -If -\tcode{n == 0}, -\tcode{N} is -\tcode{std::strlen(gnext_arg)}. -\indexlibraryglobal{strlen}% -\item -If -\tcode{n < 0}, -\tcode{N} is -\tcode{INT_MAX}. -\begin{footnote} -The function signature -\indexlibraryglobal{strlen}% -\tcode{strlen(const char*)} -is declared in \libheaderref{cstring}. -The macro \tcode{INT_MAX} is defined in \libheaderref{climits}. -\end{footnote} -\end{itemize} +The value of \exposid{default-alignment} is the most +stringent alignment requirement for any object type whose size +is no greater than \tcode{Len}\iref{basic.types}. \pnum -If \tcode{pbeg_arg} is a null pointer, the function executes: +\mandates +\tcode{Len} is not zero. +\tcode{Align} is equal to \tcode{alignof(T)} for some type \tcode{T} or +to \exposid{default-alignment}. -\begin{codeblock} -setg(gnext_arg, gnext_arg, gnext_arg + N); -\end{codeblock} +\pnum +The member typedef \tcode{type} denotes a trivial standard-layout type +suitable for use as uninitialized storage for any object +whose size is at most \tcode{Len} and +whose alignment is a divisor of \tcode{Align}. \pnum -Otherwise, the function executes: +\begin{note} +Uses of \tcode{aligned_storage::type} can be replaced +by an array \tcode{std::byte[Len]} declared with \tcode{alignas(Align)}. +\end{note} +\pnum +\begin{note} +A typical implementation would define \tcode{aligned_storage} as: \begin{codeblock} -setg(gnext_arg, gnext_arg, pbeg_arg); -setp(pbeg_arg, pbeg_arg + N); +template +struct aligned_storage { + typedef struct { + alignas(Alignment) unsigned char __data[Len]; + } type; +}; \end{codeblock} -\end{itemdescr} - - -\indexlibraryctor{strstreambuf}% -\begin{itemdecl} -strstreambuf(const char* gnext_arg, streamsize n); -strstreambuf(const signed char* gnext_arg, streamsize n); -strstreambuf(const unsigned char* gnext_arg, streamsize n); -\end{itemdecl} +\end{note} -\begin{itemdescr} -\pnum -\effects -Behaves the same as -\tcode{strstreambuf((char*)gnext_arg,n)}, -except that the constructor also sets \tcode{constant} in \tcode{strmode}. \end{itemdescr} -\indexlibrarydtor{strstreambuf}% +\indexlibraryglobal{aligned_union}% \begin{itemdecl} -virtual ~strstreambuf(); +template + struct aligned_union; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Destroys an object of class -\tcode{strstreambuf}. -The function frees the dynamically allocated array object only if -\tcode{(strmode \& allocated) != 0} -and -\tcode{(strmode \& frozen) == 0}. -(\ref{depr.strstreambuf.virtuals} describes how a dynamically allocated array object is freed.) -\end{itemdescr} - -\rSec3[depr.strstreambuf.members]{Member functions} - -\indexlibrarymember{freeze}{strstreambuf}% -\begin{itemdecl} -void freeze(bool freezefl = true); -\end{itemdecl} +\mandates +At least one type is provided. +Each type in the template parameter pack \tcode{Types} +is a complete object type. -\begin{itemdescr} \pnum -\effects -If \tcode{strmode \& dynamic} is nonzero, alters the -freeze status of the dynamic array object as follows: -\begin{itemize} -\item -If \tcode{freezefl} is -\tcode{true}, -the function sets \tcode{frozen} in \tcode{strmode}. -\item -Otherwise, it clears \tcode{frozen} in \tcode{strmode}. -\end{itemize} +The member typedef \tcode{type} denotes a trivial standard-layout type +suitable for use as uninitialized storage for any object +whose type is listed in \tcode{Types}; +its size shall be at least \tcode{Len}. +The static member \tcode{alignment_value} +is an integral constant of type \tcode{size_t} +whose value is the strictest alignment of all types listed in \tcode{Types}. \end{itemdescr} -\indexlibrarymember{str}{strstreambuf}% -\begin{itemdecl} -char* str(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls -\tcode{freeze()}, -then returns the beginning pointer for the input sequence, \tcode{gbeg}. +\rSec1[depr.tuple]{Tuple} \pnum -\remarks -The return value can be a null pointer. -\end{itemdescr} - -\indexlibrarymember{pcount}{strstreambuf}% -\begin{itemdecl} -int pcount() const; -\end{itemdecl} +The header \libheaderref{tuple} has the following additions: -\begin{itemdescr} -\pnum -\effects -If the next pointer for the output sequence, \tcode{pnext}, is -a null pointer, returns zero. -Otherwise, returns the current -effective length of the array object as the next pointer minus the beginning -pointer for the output sequence, \tcode{pnext - pbeg}. -\end{itemdescr} +\begin{codeblock} +namespace std { + template struct tuple_size; + template struct tuple_size; -\rSec3[depr.strstreambuf.virtuals]{\tcode{strstreambuf} overridden virtual functions} + template struct tuple_element; + template struct tuple_element; +} +\end{codeblock} -\indexlibrarymember{overflow}{strstreambuf}% \begin{itemdecl} -int_type overflow(int_type c = EOF) override; +template struct tuple_size; +template struct tuple_size; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Appends the character designated by \tcode{c} to the output -sequence, if possible, in one of two ways: -\begin{itemize} -\item -If -\tcode{c != EOF} -and if either the output sequence has a write position available or -the function makes a write position available -(as described below), -assigns \tcode{c} to -\tcode{*pnext++}. - -Returns -\tcode{(unsigned char)c}. - -\item -If -\tcode{c == EOF}, -there is no character to append. - -Returns a value other than \tcode{EOF}. -\end{itemize} +Let \tcode{TS} denote \tcode{tuple_size} of the cv-unqualified type \tcode{T}. +If the expression \tcode{TS::value} is well-formed +when treated as an unevaluated operand\iref{term.unevaluated.operand}, +then specializations of each of the two templates meet +the \oldconcept{TransformationTrait} requirements with a base characteristic of +\tcode{integral_constant}. +Otherwise, they have no member \tcode{value}. \pnum -Returns -\tcode{EOF} -to indicate failure. +Access checking is performed as if +in a context unrelated to \tcode{TS} and \tcode{T}. +Only the validity of the immediate context of the expression is considered. \pnum -\remarks -The function can alter the number of write positions available as a -result of any call. - -\pnum -To make a write position available, the function reallocates -(or initially allocates) -an array object with a sufficient number of elements -\tcode{n} to hold the current array object (if any), -plus at least one additional write position. -How many additional write positions are made -available is otherwise unspecified.% -\indextext{unspecified}% -If \tcode{palloc} is not a null pointer, the function calls -\tcode{(*palloc)(n)} -to allocate the new dynamic array object. -Otherwise, it evaluates the expression -\tcode{new charT[n]}. -In either case, if the allocation fails, the function returns -\tcode{EOF}. -Otherwise, it sets \tcode{allocated} in \tcode{strmode}. - -\pnum -To free a previously existing dynamic array object whose first -element address is \tcode{p}: -If \tcode{pfree} is not a null pointer, -the function calls -\tcode{(*pfree)(p)}. -Otherwise, it evaluates the expression \tcode{delete[]p}. - -\pnum -If -\tcode{(strmode \& dynamic) == 0}, -or if -\tcode{(strmode \& frozen) != 0}, -the function cannot extend the array (reallocate it with greater length) to make a write position available. - -\pnum -\recommended -An implementation should consider \tcode{alsize} in making the -decision how many additional write positions to make available. +In addition to being available via inclusion of the \libheaderref{tuple} header, +the two templates are available when any of the headers +\libheaderref{array}, +\libheaderref{ranges}, or +\libheaderref{utility} +are included. \end{itemdescr} -\indexlibrarymember{pbackfail}{strstreambuf}% \begin{itemdecl} -int_type pbackfail(int_type c = EOF) override; +template struct tuple_element; +template struct tuple_element; \end{itemdecl} \begin{itemdescr} \pnum -Puts back the character designated by \tcode{c} to the input -sequence, if possible, in one of three ways: +Let \tcode{TE} denote \tcode{tuple_element_t} +of the cv-unqualified type \tcode{T}. +Then specializations of each of the two templates meet +the \oldconcept{TransformationTrait} requirements +with a member typedef \tcode{type} that names the following type: \begin{itemize} -\item -If -\tcode{c != EOF}, -if the input sequence has a putback position available, and if -\tcode{(char)c == gnext[-1]}, -assigns -\tcode{gnext - 1} -to \tcode{gnext}. - -Returns \tcode{c}. -\item -If -\tcode{c != EOF}, -if the input sequence has a putback position available, and if -\tcode{strmode \& constant} is zero, -assigns \tcode{c} to -\tcode{*--gnext}. - -Returns -\tcode{c}. -\item -If -\tcode{c == EOF} -and if the input sequence has a putback position available, -assigns -\tcode{gnext - 1} -to \tcode{gnext}. - -Returns a value other than -\tcode{EOF}. +\item for the first specialization, \tcode{add_volatile_t}, and +\item for the second specialization, \tcode{add_cv_t}. \end{itemize} \pnum -Returns -\tcode{EOF} -to indicate failure. - -\pnum -\remarks -If the function can succeed in more than one of these ways, it is -unspecified which way is chosen. -\indextext{unspecified}% -The function can alter the number of putback -positions available as a result of any call. +In addition to being available via inclusion of the \libheaderref{tuple} header, +the two templates are available when any of the headers +\libheaderref{array}, +\libheaderref{ranges}, or +\libheaderref{utility} +are included. \end{itemdescr} -\indexlibrarymember{underflow}{strstreambuf}% -\begin{itemdecl} -int_type underflow() override; -\end{itemdecl} +\rSec1[depr.variant]{Variant} -\begin{itemdescr} \pnum -\effects -Reads a character from the -\term{input sequence}, -if possible, without moving the stream position past it, as follows: -\begin{itemize} -\item -If the input sequence has a read position available, the function -signals success by returning -\tcode{(unsigned char)\brk*gnext}. -\item -Otherwise, if -the current write next pointer \tcode{pnext} is not a null pointer and -is greater than the current read end pointer \tcode{gend}, -makes a -\term{read position} -available by -assigning to \tcode{gend} a value greater than \tcode{gnext} and -no greater than \tcode{pnext}. - -Returns \tcode{(unsigned char)*gnext}. -\end{itemize} +The header \libheaderref{variant} has the following additions: -\pnum -Returns -\tcode{EOF} -to indicate failure. +\begin{codeblock} +namespace std { + template struct variant_size; + template struct variant_size; -\pnum -\remarks -The function can alter the number of read positions available as a -result of any call. -\end{itemdescr} + template struct variant_alternative; + template struct variant_alternative; +} +\end{codeblock} -\indexlibrarymember{seekoff}{strstreambuf}% \begin{itemdecl} -pos_type seekoff(off_type off, seekdir way, openmode which = in | out) override; +template struct variant_size; +template struct variant_size; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Alters the stream position within one of the -controlled sequences, if possible, as indicated in \tref{depr.strstreambuf.seekoff.pos}. - -\begin{libtab2}{\tcode{seekoff} positioning}{depr.strstreambuf.seekoff.pos} -{p{2.5in}l}{Conditions}{Result} -\tcode{(which \& ios::in) != 0} & - positions the input sequence \\ \rowsep -\tcode{(which \& ios::out) != 0} & - positions the output sequence \\ \rowsep -\tcode{(which \& (ios::in | ios::out)) ==}\br -\tcode{(ios::in | ios::out)} and either\br -\tcode{way == ios::beg} or \tcode{way == ios::end} & - positions both the input and the output sequences \\ \rowsep -Otherwise & - the positioning operation fails. \\ -\end{libtab2} - -\pnum -For a sequence to be positioned, if its next pointer is a null pointer, -the positioning operation fails. -Otherwise, the function determines \tcode{newoff} as indicated in -\tref{depr.strstreambuf.seekoff.newoff}. - -\begin{libtab2}{\tcode{newoff} values}{depr.strstreambuf.seekoff.newoff} -{p{2.0in}p{2.0in}}{Condition}{\tcode{newoff} Value} -\tcode{way == ios::beg} & - 0 \\ \rowsep -\tcode{way == ios::cur} & - the next pointer minus the beginning pointer (\tcode{xnext - xbeg}). \\ \rowsep -\tcode{way == ios::end} & - \tcode{seekhigh} minus the beginning pointer (\tcode{seekhigh - xbeg}). \\ -\end{libtab2} - -\pnum -If \tcode{(newoff + off) < (seeklow - xbeg)} -or \tcode{(seekhigh - xbeg) < (newoff + off)}, -the positioning operation fails. -Otherwise, the function assigns -\tcode{xbeg + newoff + off} -to the next pointer \tcode{xnext}. - -\pnum -\returns -\tcode{pos_type(newoff)}, -constructed from the resultant offset -\tcode{newoff} (of type -\tcode{off_type}), -that stores the resultant stream position, if possible. -If the positioning operation fails, or -if the constructed object cannot represent the resultant stream position, -the return value is -\tcode{pos_type(off_type(-1))}. +Let \tcode{VS} denote \tcode{variant_size} +of the cv-unqualified type \tcode{T}. +Then specializations of each of the two templates meet +the \oldconcept{UnaryTypeTrait} requirements +with a base characteristic of \tcode{integral_constant}. \end{itemdescr} -\indexlibrarymember{seekpos}{strstreambuf}% \begin{itemdecl} -pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override; +template struct variant_alternative; +template struct variant_alternative; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Alters the stream position within one of the -controlled sequences, if possible, to correspond to the -stream position stored in \tcode{sp} -(as described below). +Let \tcode{VA} denote \tcode{variant_alternative} +of the cv-unqualified type \tcode{T}. +Then specializations of each of the two templates meet +the \oldconcept{TransformationTrait} requirements +with a member typedef \tcode{type} that names the following type: \begin{itemize} -\item -If -\tcode{(which \& ios::in) != 0}, -positions the input sequence. -\item -If -\tcode{(which \& ios::out) != 0}, -positions the output sequence. -\item -If the function positions neither sequence, the positioning operation fails. -\end{itemize} - -\pnum -For a sequence to be positioned, if its next pointer is a null pointer, -the positioning operation fails. -Otherwise, the function determines \tcode{newoff} from -\tcode{sp.offset()}: -\begin{itemize} -\item -If \tcode{newoff} is an invalid stream position, -has a negative value, or -has a value greater than (\tcode{seekhigh - seeklow}), -the positioning operation fails -\item -Otherwise, the function -adds \tcode{newoff} to the beginning pointer \tcode{xbeg} and -stores the result in the next pointer \tcode{xnext}. -\end{itemize} - -\pnum -\returns -\tcode{pos_type(newoff)}, -constructed from the resultant offset \tcode{newoff} -(of type -\tcode{off_type}), -that stores the resultant stream position, if possible. -If the positioning operation fails, or -if the constructed object cannot represent the resultant stream position, -the return value is -\tcode{pos_type(off_type(-1))}. -\end{itemdescr} - -\indexlibrarymember{setbuf}{strstreambuf}% -\begin{itemdecl} -streambuf* setbuf(char* s, streamsize n) override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Behavior is \impldef{behavior of \tcode{strstreambuf::setbuf}}, -except that -\tcode{setbuf(0, 0)} -has no effect.% -\end{itemdescr} - -\rSec2[depr.istrstream]{Class \tcode{istrstream}} - -\rSec3[depr.istrstream.general]{General} - -\indexlibraryglobal{istrstream}% -\begin{codeblock} -namespace std { - class istrstream : public basic_istream { - public: - explicit istrstream(const char* s); - explicit istrstream(char* s); - istrstream(const char* s, streamsize n); - istrstream(char* s, streamsize n); - virtual ~istrstream(); - - strstreambuf* rdbuf() const; - char* str(); - private: - strstreambuf sb; // \expos - }; -} -\end{codeblock} - -\pnum -The class -\tcode{istrstream} -supports the reading of objects of class -\tcode{strstreambuf}. -It supplies a -\tcode{strstreambuf} -object to control the associated array object. -For the sake of exposition, the maintained data is presented here as: - -\begin{itemize} -\item -\tcode{sb}, the \tcode{strstreambuf} object. -\end{itemize} - -\rSec3[depr.istrstream.cons]{\tcode{istrstream} constructors} - -\indexlibraryctor{istrstream}% -\begin{itemdecl} -explicit istrstream(const char* s); -explicit istrstream(char* s); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the base class with \tcode{istream(\&sb)} and -\tcode{sb} with \tcode{strstreambuf(s, 0)}. -\tcode{s} shall designate the first element of an \ntbs{}.% -\indextext{NTBS@\ntbs{}} -\end{itemdescr} - -\indexlibraryctor{istrstream}% -\begin{itemdecl} -istrstream(const char* s, streamsize n); -istrstream(char* s, streamsize n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the base class with \tcode{istream(\&sb)} -and \tcode{sb} with \tcode{strstreambuf(s, n)}. -\tcode{s} shall designate the first element of an array whose length is -\tcode{n} elements, and \tcode{n} shall be greater than zero. -\end{itemdescr} - -\rSec3[depr.istrstream.members]{Member functions} - -\indexlibrarymember{rdbuf}{istrstream}% -\begin{itemdecl} -strstreambuf* rdbuf() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{const_cast(\&sb)}. -\end{itemdescr} - -\indexlibrarymember{str}{istrstream}% -\begin{itemdecl} -char* str(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{rdbuf()->str()}. -\end{itemdescr} - -\rSec2[depr.ostrstream]{Class \tcode{ostrstream}} - -\rSec3[depr.ostrstream.general]{General} - -\indexlibraryglobal{ostrstream}% -\begin{codeblock} -namespace std { - class ostrstream : public basic_ostream { - public: - ostrstream(); - ostrstream(char* s, int n, ios_base::openmode mode = ios_base::out); - virtual ~ostrstream(); - - strstreambuf* rdbuf() const; - void freeze(bool freezefl = true); - char* str(); - int pcount() const; - private: - strstreambuf sb; // \expos - }; -} -\end{codeblock} - -\pnum -The class -\tcode{ostrstream} -supports the writing of objects of class -\tcode{strstreambuf}. -It supplies a -\tcode{strstreambuf} -object to control the associated array object. -For the sake of exposition, the maintained data is presented here as: - -\begin{itemize} -\item -\tcode{sb}, the \tcode{strstreambuf} object. -\end{itemize} - -\rSec3[depr.ostrstream.cons]{\tcode{ostrstream} constructors} - -\indexlibraryctor{ostrstream}% -\begin{itemdecl} -ostrstream(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the base class with \tcode{ostream(\&sb)} and -\tcode{sb} with \tcode{strstreambuf()}. -\end{itemdescr} - -\indexlibraryctor{ostrstream}% -\begin{itemdecl} -ostrstream(char* s, int n, ios_base::openmode mode = ios_base::out); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the base class with \tcode{ostream(\&sb)}, -and \tcode{sb} with one of two constructors: - -\begin{itemize} -\item -If -\tcode{(mode \& app) == 0}, -then \tcode{s} shall designate the first element of an array of \tcode{n} elements. - -The constructor is -\tcode{strstreambuf(s, n, s)}. -\item -If -\tcode{(mode \& app) != 0}, -then \tcode{s} shall designate the first element of an array of \tcode{n} elements that -contains an \ntbs{} whose first element is designated by \tcode{s}. -\indextext{NTBS@\ntbs{}}% -The constructor is -\tcode{strstreambuf(s, n, s + std::strlen(s))}. -\begin{footnote} -The function signature -\indexlibraryglobal{strlen}% -\tcode{strlen(const char*)} -is declared in \libheaderref{cstring}. -\end{footnote} -\end{itemize} -\end{itemdescr} - -\rSec3[depr.ostrstream.members]{Member functions} - -\indexlibrarymember{rdbuf}{ostrstream}% -\begin{itemdecl} -strstreambuf* rdbuf() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{(strstreambuf*)\&sb}. -\end{itemdescr} - -\indexlibrarymember{freeze}{ostrstream}% -\begin{itemdecl} -void freeze(bool freezefl = true); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls -\tcode{rdbuf()->freeze(freezefl)}. -\end{itemdescr} - -\indexlibrarymember{str}{ostrstream}% -\begin{itemdecl} -char* str(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{rdbuf()->str()}. -\end{itemdescr} - -\indexlibrarymember{pcount}{ostrstream}% -\begin{itemdecl} -int pcount() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{rdbuf()->pcount()}. -\end{itemdescr} - -\rSec2[depr.strstream]{Class \tcode{strstream}} - -\rSec3[depr.strstream.general]{General} - -\indexlibraryglobal{strstream}% -\begin{codeblock} -namespace std { - class strstream - : public basic_iostream { - public: - // types - using char_type = char; - using int_type = char_traits::int_type; - using pos_type = char_traits::pos_type; - using off_type = char_traits::off_type; - - // constructors/destructor - strstream(); - strstream(char* s, int n, - ios_base::openmode mode = ios_base::in|ios_base::out); - virtual ~strstream(); - - // members - strstreambuf* rdbuf() const; - void freeze(bool freezefl = true); - int pcount() const; - char* str(); - - private: - strstreambuf sb; // \expos - }; -} -\end{codeblock} - -\pnum -The class -\tcode{strstream} -supports reading and writing from objects of class -\tcode{strstreambuf}. -It supplies a -\tcode{strstreambuf} -object to control the associated array object. -For the sake of exposition, the maintained data is presented here as: - -\begin{itemize} -\item -\tcode{sb}, the \tcode{strstreambuf} object. -\end{itemize} - -\rSec3[depr.strstream.cons]{\tcode{strstream} constructors} - -\indexlibraryctor{strstream}% -\begin{itemdecl} -strstream(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the base class with \tcode{iostream(\&sb)}. -\end{itemdescr} - -\indexlibraryctor{strstream}% -\begin{itemdecl} -strstream(char* s, int n, - ios_base::openmode mode = ios_base::in|ios_base::out); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the base class with \tcode{iostream(\&sb)}, -and \tcode{sb} with one of the two constructors: -\begin{itemize} -\item -If -\tcode{(mode \& app) == 0}, -then \tcode{s} shall designate the first element of an array of \tcode{n} elements. -The constructor is -\tcode{strstreambuf(s,n,s)}. -\item -If -\tcode{(mode \& app) != 0}, -then \tcode{s} shall -designate the first element of an array of \tcode{n} elements that contains -an \ntbs{} whose first element is designated by \tcode{s}. -The constructor is -\tcode{strstreambuf(s,n,s + std::strlen(s))}. -\indexlibrarydtor{strstream}% -\end{itemize} -\end{itemdescr} - -\rSec3[depr.strstream.dest]{\tcode{strstream} destructor} - -\indexlibrarydtor{strstream}% -\begin{itemdecl} -virtual ~strstream(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Destroys an object of class -\tcode{strstream}. -\end{itemdescr} - -\rSec3[depr.strstream.oper]{\tcode{strstream} operations} - -\indexlibrarymember{rdbuf}{strstream}% -\begin{itemdecl} -strstreambuf* rdbuf() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{const_cast(\&sb)}. -\end{itemdescr} - -\indexlibrarymember{freeze}{strstream}% -\begin{itemdecl} -void freeze(bool freezefl = true); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls -\tcode{rdbuf()->freeze(freezefl)}. -\end{itemdescr} - -\indexlibrarymember{str}{strstream}% -\begin{itemdecl} -char* str(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{rdbuf()->str()}. -\end{itemdescr} - -\indexlibrarymember{pcount}{strstream}% -\begin{itemdecl} -int pcount() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{rdbuf()->pcount()}. -\end{itemdescr} - -\rSec1[depr.cerrno]{Deprecated error numbers} - -\pnum -The following macros are defined in addition to those -specified in \ref{cerrno.syn}: - -\indexlibraryglobal{ENODATA}% -\indexlibraryglobal{ENOSR}% -\indexlibraryglobal{ENOSTR}% -\indexlibraryglobal{ETIME}% -\begin{codeblock} -#define ENODATA @\seebelow@ -#define ENOSR @\seebelow@ -#define ENOSTR @\seebelow@ -#define ETIME @\seebelow@ -\end{codeblock} - -\pnum -The meaning of these macros is defined by the POSIX standard. - -\pnum -The following \tcode{enum errc} enumerators are defined -in addition to those specified in \ref{system.error.syn}: - -\begin{codeblock} -no_message_available, // \tcode{ENODATA} -no_stream_resources, // \tcode{ENOSR} -not_a_stream, // \tcode{ENOSTR} -stream_timeout, // \tcode{ETIME} -\end{codeblock} - -\pnum -The value of each \tcode{enum errc} enumerator above -is the same as the value of the \libheader{cerrno} macro -shown in the above synopsis. - -\rSec1[depr.mem.poly.allocator.mem]{Deprecated \tcode{polymorphic_allocator} member function} - -\pnum -The following member is declared in addition to those members -specified in \ref{mem.poly.allocator.mem}: - -\begin{codeblock} -namespace std::pmr { - template - class polymorphic_allocator { - public: - template - void destroy(T* p); - }; -} -\end{codeblock} - -\indexlibrarymember{destroy}{polymorphic_allocator}% -\begin{itemdecl} -template - void destroy(T* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by \tcode{p->\~T()}. -\end{itemdescr} - -\rSec1[depr.meta.types]{Deprecated type traits} - -\pnum -The header \libheaderrefx{type_traits}{meta.type.synop} -has the following addition: - -\begin{codeblock} -namespace std { - template struct is_pod; - template constexpr bool is_pod_v = is_pod::value; - template // \seebelow - struct aligned_storage; - template // \seebelow - using @\libglobal{aligned_storage_t}@ = typename aligned_storage::type; - template - struct aligned_union; - template - using @\libglobal{aligned_union_t}@ = typename aligned_union::type; -} -\end{codeblock} - -\pnum -The behavior of a program that adds specializations for -any of the templates defined in this subclause is undefined, -unless explicitly permitted by the specification of the corresponding template. - -\pnum -\indextext{POD}% -A \term{POD class} is a class that is both a trivial class and a -standard-layout class, and has no non-static data members of type non-POD class -(or array thereof). A \term{POD type} is a scalar type, a POD class, an array -of such a type, or a cv-qualified version of one of these types. - -\indexlibraryglobal{is_pod}% -\begin{itemdecl} -template struct is_pod; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{remove_all_extents_t} shall be a complete type or \cv{} \keyword{void}. - -\pnum -\remarks -\tcode{is_pod} is a \oldconcept{UnaryTypeTrait}\iref{meta.rqmts} -with a base characteristic of \tcode{true_type} -if \tcode{T} is a POD type, -and \tcode{false_type} otherwise. - -\pnum -\begin{note} -It is unspecified whether a closure type\iref{expr.prim.lambda.closure} is a POD type. -\end{note} -\end{itemdescr} - -\indexlibraryglobal{aligned_storage}% -\begin{itemdecl} -template - struct aligned_storage; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The value of \exposid{default-alignment} is the most -stringent alignment requirement for any object type whose size -is no greater than \tcode{Len}\iref{basic.types}. - -\pnum -\mandates -\tcode{Len} is not zero. -\tcode{Align} is equal to \tcode{alignof(T)} for some type \tcode{T} or -to \exposid{default-alignment}. - -\pnum -The member typedef \tcode{type} denotes a trivial standard-layout type -suitable for use as uninitialized storage for any object -whose size is at most \tcode{Len} and -whose alignment is a divisor of \tcode{Align}. - -\pnum -\begin{note} -Uses of \tcode{aligned_storage::type} can be replaced -by an array \tcode{std::byte[Len]} declared with \tcode{alignas(Align)}. -\end{note} - -\pnum -\begin{note} -A typical implementation would define \tcode{aligned_storage} as: -\begin{codeblock} -template -struct aligned_storage { - typedef struct { - alignas(Alignment) unsigned char __data[Len]; - } type; -}; -\end{codeblock} -\end{note} - -\end{itemdescr} - -\indexlibraryglobal{aligned_union}% -\begin{itemdecl} -template - struct aligned_union; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -At least one type is provided. -Each type in the template parameter pack \tcode{Types} -is a complete object type. - -\pnum -The member typedef \tcode{type} denotes a trivial standard-layout type -suitable for use as uninitialized storage for any object -whose type is listed in \tcode{Types}; -its size shall be at least \tcode{Len}. -The static member \tcode{alignment_value} -is an integral constant of type \tcode{size_t} -whose value is the strictest alignment of all types listed in \tcode{Types}. -\end{itemdescr} - -\rSec1[depr.tuple]{Tuple} - -\pnum -The header \libheaderref{tuple} has the following additions: - -\begin{codeblock} -namespace std { - template struct tuple_size; - template struct tuple_size; - - template struct tuple_element; - template struct tuple_element; -} -\end{codeblock} - -\begin{itemdecl} -template struct tuple_size; -template struct tuple_size; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{TS} denote \tcode{tuple_size} of the cv-unqualified type \tcode{T}. -If the expression \tcode{TS::value} is well-formed -when treated as an unevaluated operand\iref{term.unevaluated.operand}, -then specializations of each of the two templates meet -the \oldconcept{TransformationTrait} requirements with a base characteristic of -\tcode{integral_constant}. -Otherwise, they have no member \tcode{value}. - -\pnum -Access checking is performed as if -in a context unrelated to \tcode{TS} and \tcode{T}. -Only the validity of the immediate context of the expression is considered. - -\pnum -In addition to being available via inclusion of the \libheaderref{tuple} header, -the two templates are available when any of the headers -\libheaderref{array}, -\libheaderref{ranges}, or -\libheaderref{utility} -are included. -\end{itemdescr} - -\begin{itemdecl} -template struct tuple_element; -template struct tuple_element; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{TE} denote \tcode{tuple_element_t} -of the cv-unqualified type \tcode{T}. -Then specializations of each of the two templates meet -the \oldconcept{TransformationTrait} requirements -with a member typedef \tcode{type} that names the following type: -\begin{itemize} -\item for the first specialization, \tcode{add_volatile_t}, and -\item for the second specialization, \tcode{add_cv_t}. -\end{itemize} - -\pnum -In addition to being available via inclusion of the \libheaderref{tuple} header, -the two templates are available when any of the headers -\libheaderref{array}, -\libheaderref{ranges}, or -\libheaderref{utility} -are included. -\end{itemdescr} - -\rSec1[depr.variant]{Variant} - -\pnum -The header \libheaderref{variant} has the following additions: - -\begin{codeblock} -namespace std { - template struct variant_size; - template struct variant_size; - - template struct variant_alternative; - template struct variant_alternative; -} -\end{codeblock} - -\begin{itemdecl} -template struct variant_size; -template struct variant_size; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VS} denote \tcode{variant_size} -of the cv-unqualified type \tcode{T}. -Then specializations of each of the two templates meet -the \oldconcept{UnaryTypeTrait} requirements -with a base characteristic of \tcode{integral_constant}. -\end{itemdescr} - -\begin{itemdecl} -template struct variant_alternative; -template struct variant_alternative; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VA} denote \tcode{variant_alternative} -of the cv-unqualified type \tcode{T}. -Then specializations of each of the two templates meet -the \oldconcept{TransformationTrait} requirements -with a member typedef \tcode{type} that names the following type: -\begin{itemize} -\item for the first specialization, \tcode{add_volatile_t}, and -\item for the second specialization, \tcode{add_cv_t}. -\end{itemize} -\end{itemdescr} - -\rSec1[depr.iterator]{Deprecated \tcode{iterator} class template} - -\pnum -The header \libheaderrefx{iterator}{iterator.synopsis} has the following addition: - -\indexlibraryglobal{iterator}% -\begin{codeblock} -namespace std { - template - struct iterator { - using iterator_category = Category; - using value_type = T; - using difference_type = Distance; - using pointer = Pointer; - using reference = Reference; - }; -} -\end{codeblock} - -\pnum -The -\tcode{iterator} -template may be used as a base class to ease the definition of required types -for new iterators. - -\pnum -\begin{note} -If the new iterator type is a class template, then these aliases -will not be visible from within the iterator class's template definition, but -only to callers of that class. -\end{note} - -\pnum -\begin{example} -If a \Cpp{} program wants to define a bidirectional iterator for some data -structure containing \tcode{double} and such that it works on a large memory -model of the implementation, it can do so with: - -\begin{codeblock} -class MyIterator : - public iterator { - // code implementing \tcode{++}, etc. -}; -\end{codeblock} -\end{example} - -\rSec1[depr.move.iter.elem]{Deprecated \tcode{move_iterator} access} - -\pnum -The following member is declared in addition to those members -specified in \ref{move.iter.elem}: - -\begin{codeblock} -namespace std { - template - class move_iterator { - public: - constexpr pointer operator->() const; - }; -} -\end{codeblock} - -\indexlibrarymember{operator->}{move_iterator}% -\begin{itemdecl} -constexpr pointer operator->() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{current}. -\end{itemdescr} - -\rSec1[depr.util.smartptr.shared.atomic]{Deprecated \tcode{shared_ptr} atomic access} - -\pnum -The header \libheaderref{memory} has the following additions: - -\indexlibraryglobal{shared_ptr}% -\begin{codeblock} -namespace std { - template - bool atomic_is_lock_free(const shared_ptr* p); - - template - shared_ptr atomic_load(const shared_ptr* p); - template - shared_ptr atomic_load_explicit(const shared_ptr* p, memory_order mo); - - template - void atomic_store(shared_ptr* p, shared_ptr r); - template - void atomic_store_explicit(shared_ptr* p, shared_ptr r, memory_order mo); - - template - shared_ptr atomic_exchange(shared_ptr* p, shared_ptr r); - template - shared_ptr atomic_exchange_explicit(shared_ptr* p, shared_ptr r, memory_order mo); - - template - bool atomic_compare_exchange_weak(shared_ptr* p, shared_ptr* v, shared_ptr w); - template - bool atomic_compare_exchange_strong(shared_ptr* p, shared_ptr* v, shared_ptr w); - template - bool atomic_compare_exchange_weak_explicit( - shared_ptr* p, shared_ptr* v, shared_ptr w, - memory_order success, memory_order failure); - template - bool atomic_compare_exchange_strong_explicit( - shared_ptr* p, shared_ptr* v, shared_ptr w, - memory_order success, memory_order failure); -} -\end{codeblock} - -\pnum -Concurrent access to a \tcode{shared_ptr} object from multiple threads does not -introduce a data race if the access is done exclusively via the functions in -this subclause and the instance is passed as their first argument. - -\pnum -The meaning of the arguments of type \tcode{memory_order} is explained in~\ref{atomics.order}. - -\indexlibrarymember{atomic_is_lock_free}{shared_ptr}% -\begin{itemdecl} -template bool atomic_is_lock_free(const shared_ptr* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. - -\pnum -\returns -\tcode{true} if atomic access to \tcode{*p} is lock-free, \tcode{false} otherwise. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_load}{shared_ptr}% -\begin{itemdecl} -template shared_ptr atomic_load(const shared_ptr* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. - -\pnum -\returns -\tcode{atomic_load_explicit(p, memory_order::seq_cst)}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_load_explicit}{shared_ptr}% -\begin{itemdecl} -template shared_ptr atomic_load_explicit(const shared_ptr* p, memory_order mo); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. -\tcode{mo} is neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\returns -\tcode{*p}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_store}{shared_ptr}% -\begin{itemdecl} -template void atomic_store(shared_ptr* p, shared_ptr r); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. - -\pnum -\effects -As if by \tcode{atomic_store_explicit(p, r, memory_order::seq_cst)}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_store_explicit}{shared_ptr}% -\begin{itemdecl} -template void atomic_store_explicit(shared_ptr* p, shared_ptr r, memory_order mo); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. -\tcode{mo} is neither \tcode{memory_order::acquire} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -As if by \tcode{p->swap(r)}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_exchange}{shared_ptr}% -\begin{itemdecl} -template shared_ptr atomic_exchange(shared_ptr* p, shared_ptr r); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. - -\pnum -\returns -\tcode{atomic_exchange_explicit(p, r, memory_order::seq_cst)}. - -\pnum -\throws -Nothing. +\item for the first specialization, \tcode{add_volatile_t}, and +\item for the second specialization, \tcode{add_cv_t}. +\end{itemize} \end{itemdescr} -\indexlibrarymember{atomic_exchange_explicit}{shared_ptr}% -\begin{itemdecl} -template - shared_ptr atomic_exchange_explicit(shared_ptr* p, shared_ptr r, memory_order mo); -\end{itemdecl} +\rSec1[depr.iterator]{Deprecated \tcode{iterator} class template} -\begin{itemdescr} \pnum -\expects -\tcode{p} is not null. +The header \libheaderrefx{iterator}{iterator.synopsis} has the following addition: -\pnum -\effects -As if by \tcode{p->swap(r)}. +\indexlibraryglobal{iterator}% +\begin{codeblock} +namespace std { + template + struct iterator { + using iterator_category = Category; + using value_type = T; + using difference_type = Distance; + using pointer = Pointer; + using reference = Reference; + }; +} +\end{codeblock} \pnum -\returns -The previous value of \tcode{*p}. +The +\tcode{iterator} +template may be used as a base class to ease the definition of required types +for new iterators. \pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_compare_exchange_weak}{shared_ptr}% -\begin{itemdecl} -template - bool atomic_compare_exchange_weak(shared_ptr* p, shared_ptr* v, shared_ptr w); -\end{itemdecl} +\begin{note} +If the new iterator type is a class template, then these aliases +will not be visible from within the iterator class's template definition, but +only to callers of that class. +\end{note} -\begin{itemdescr} \pnum -\expects -\tcode{p} is not null and \tcode{v} is not null. +\begin{example} +If a \Cpp{} program wants to define a bidirectional iterator for some data +structure containing \tcode{double} and such that it works on a large memory +model of the implementation, it can do so with: -\pnum -\returns \begin{codeblock} -atomic_compare_exchange_weak_explicit(p, v, w, memory_order::seq_cst, memory_order::seq_cst) +class MyIterator : + public iterator { + // code implementing \tcode{++}, etc. +}; \end{codeblock} +\end{example} -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_compare_exchange_strong}{shared_ptr}% -\begin{itemdecl} -template - bool atomic_compare_exchange_strong(shared_ptr* p, shared_ptr* v, shared_ptr w); -\end{itemdecl} +\rSec1[depr.move.iter.elem]{Deprecated \tcode{move_iterator} access} -\begin{itemdescr} \pnum -\returns +The following member is declared in addition to those members +specified in \ref{move.iter.elem}: + \begin{codeblock} -atomic_compare_exchange_strong_explicit(p, v, w, memory_order::seq_cst, - memory_order::seq_cst) +namespace std { + template + class move_iterator { + public: + constexpr pointer operator->() const; + }; +} \end{codeblock} -\end{itemdescr} -\indexlibrarymember{atomic_compare_exchange_weak_explicit}{shared_ptr}% -\indexlibrarymember{atomic_compare_exchange_strong_explicit}{shared_ptr}% +\indexlibrarymember{operator->}{move_iterator}% \begin{itemdecl} -template - bool atomic_compare_exchange_weak_explicit( - shared_ptr* p, shared_ptr* v, shared_ptr w, - memory_order success, memory_order failure); -template - bool atomic_compare_exchange_strong_explicit( - shared_ptr* p, shared_ptr* v, shared_ptr w, - memory_order success, memory_order failure); +constexpr pointer operator->() const; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{p} is not null and \tcode{v} is not null. -The \tcode{failure} argument is neither \tcode{memory_order::release} nor -\tcode{memory_order::acq_rel}. - -\pnum -\effects -If \tcode{*p} is equivalent to \tcode{*v}, assigns \tcode{w} to -\tcode{*p} and has synchronization semantics corresponding to the value of -\tcode{success}, otherwise assigns \tcode{*p} to \tcode{*v} and has -synchronization semantics corresponding to the value of \tcode{failure}. - \pnum \returns -\tcode{true} if \tcode{*p} was equivalent to \tcode{*v}, \tcode{false} otherwise. - -\pnum -\throws -Nothing. - -\pnum -\remarks -Two \tcode{shared_ptr} objects are equivalent if they store the same -pointer value and share ownership. -The weak form may fail spuriously. See~\ref{atomics.types.operations}. +\tcode{current}. \end{itemdescr} \rSec1[depr.format]{Deprecated formatting} @@ -2023,383 +703,6 @@ Equivalent to: \tcode{return visit(std::forward(vis), arg.value);} \end{itemdescr} -\rSec1[depr.conversions]{Deprecated convenience conversion interfaces} - -\rSec2[depr.conversions.general]{General} - -\pnum -The header \libheaderref{locale} has the following additions: - -\begin{codeblock} -namespace std { - template, - class ByteAlloc = allocator> - class wstring_convert; - - template> - class wbuffer_convert; -} -\end{codeblock} - -\rSec2[depr.conversions.string]{Class template \tcode{wstring_convert}} - -\pnum -Class template \tcode{wstring_convert} performs conversions between a wide -string and a byte string. It lets you specify a code conversion facet -(like class template \tcode{codecvt}) to perform the conversions, without -affecting any streams or locales. -\begin{example} -If you want to use a code -conversion facet, \tcode{codecvt_for_utf8}, to output to \tcode{cout} a UTF-8 -multibyte sequence corresponding to a wide string, but you don't want to -alter the locale for \tcode{cout}, you can write something like: -\begin{codeblock} -std::wstring_convert> myconv; -std::string mbstring = myconv.to_bytes(L"Hello\n"); -std::cout << mbstring; -\end{codeblock} -\end{example} - -\indexlibraryglobal{wstring_convert}% -\indexlibrarymember{byte_string}{wstring_convert}% -\indexlibrarymember{int_type}{wstring_convert}% -\indexlibrarymember{state_type}{wstring_convert}% -\indexlibrarymember{wide_string}{wstring_convert}% -\begin{codeblock} -namespace std { - template, - class ByteAlloc = allocator> - class wstring_convert { - public: - using byte_string = basic_string, ByteAlloc>; - using wide_string = basic_string, WideAlloc>; - using state_type = typename Codecvt::state_type; - using int_type = typename wide_string::traits_type::int_type; - - wstring_convert() : wstring_convert(new Codecvt) {} - explicit wstring_convert(Codecvt* pcvt); - wstring_convert(Codecvt* pcvt, state_type state); - explicit wstring_convert(const byte_string& byte_err, - const wide_string& wide_err = wide_string()); - ~wstring_convert(); - - wstring_convert(const wstring_convert&) = delete; - wstring_convert& operator=(const wstring_convert&) = delete; - - wide_string from_bytes(char byte); - wide_string from_bytes(const char* ptr); - wide_string from_bytes(const byte_string& str); - wide_string from_bytes(const char* first, const char* last); - - byte_string to_bytes(Elem wchar); - byte_string to_bytes(const Elem* wptr); - byte_string to_bytes(const wide_string& wstr); - byte_string to_bytes(const Elem* first, const Elem* last); - - size_t converted() const noexcept; - state_type state() const; - - private: - byte_string byte_err_string; // \expos - wide_string wide_err_string; // \expos - Codecvt* cvtptr; // \expos - state_type cvtstate; // \expos - size_t cvtcount; // \expos - }; -} -\end{codeblock} - -\pnum -The class template describes an object that controls conversions between wide -string objects of class \tcode{basic_string, -WideAlloc>} and byte string objects of class \tcode{basic_string, ByteAlloc>}. The class template defines the types -\tcode{wide_string} and \tcode{byte_string} as synonyms for these two types. -Conversion between a sequence of \tcode{Elem} values (stored in a -\tcode{wide_string} object) and multibyte sequences (stored in a -\tcode{byte_string} object) is performed by an object of class -\tcode{Codecvt}, which meets the -requirements of the standard code-conversion facet \tcode{codecvt}. - -\pnum -An object of this class template stores: - -\begin{itemize} -\item \tcode{byte_err_string} --- a byte string to display on errors -\item \tcode{wide_err_string} --- a wide string to display on errors -\item \tcode{cvtptr} --- a pointer to the allocated conversion object -(which is freed when the \tcode{wstring_convert} object is destroyed) -\item \tcode{cvtstate} --- a conversion state object -\item \tcode{cvtcount} --- a conversion count -\end{itemize} - -\indexlibrarymember{converted}{wstring_convert}% -\begin{itemdecl} -size_t converted() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{cvtcount}. -\end{itemdescr} - -\indexlibrarymember{from_bytes}{wstring_convert}% -\begin{itemdecl} -wide_string from_bytes(char byte); -wide_string from_bytes(const char* ptr); -wide_string from_bytes(const byte_string& str); -wide_string from_bytes(const char* first, const char* last); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The first member function converts the single-element sequence \tcode{byte} to a -wide string. The second member function converts the null-terminated -sequence beginning at \tcode{ptr} to a wide string. The third member function -converts the sequence stored in \tcode{str} to a wide string. The fourth member -function converts the sequence defined by the range \range{first}{last} to a -wide string. - -\pnum -In all cases: - -\begin{itemize} -\item If the \tcode{cvtstate} object was not constructed with an explicit value, it -is set to its default value (the initial conversion state) before the -conversion begins. Otherwise it is left unchanged. - -\item The number of input elements successfully converted is stored in \tcode{cvtcount}. -\end{itemize} - -\pnum -\returns -If no conversion error occurs, the member function returns the converted wide string. -Otherwise, if the object was constructed with a wide-error string, the -member function returns the wide-error string. -Otherwise, the member function throws an object of class \tcode{range_error}. -\end{itemdescr} - -\indexlibrarymember{state}{wstring_convert}% -\begin{itemdecl} -state_type state() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{cvtstate}. -\end{itemdescr} - -\indexlibrarymember{to_bytes}{wstring_convert}% -\begin{itemdecl} -byte_string to_bytes(Elem wchar); -byte_string to_bytes(const Elem* wptr); -byte_string to_bytes(const wide_string& wstr); -byte_string to_bytes(const Elem* first, const Elem* last); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The first member function converts the single-element sequence \tcode{wchar} to a byte string. -The second member function converts the null-terminated sequence beginning at \tcode{wptr} to -a byte string. The third member function converts the sequence stored in \tcode{wstr} to a -byte string. The fourth member function converts the sequence defined by the -range \range{first}{last} to a byte string. - -\pnum -In all cases: - -\begin{itemize} -\item If the \tcode{cvtstate} object was not constructed with an explicit value, -it is set to its default value (the initial conversion state) before the -conversion begins. Otherwise it is left unchanged. -\item The number of input elements successfully converted is stored -in \tcode{cvtcount}. -\end{itemize} - -\pnum -\returns -If no conversion error occurs, the member function returns the converted byte string. -Otherwise, if the object was constructed with a byte-error string, the -member function returns the byte-error string. -Otherwise, the member function throws an object of class \tcode{range_error}. -\end{itemdescr} - -\indexlibraryctor{wstring_convert}% -\begin{itemdecl} -explicit wstring_convert(Codecvt* pcvt); -wstring_convert(Codecvt* pcvt, state_type state); -explicit wstring_convert(const byte_string& byte_err, - const wide_string& wide_err = wide_string()); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -For the first and second constructors, \tcode{pcvt} is not null. - -\pnum -\effects -The first constructor stores \tcode{pcvt} in \tcode{cvtptr} and -default values in \tcode{cvtstate}, \tcode{byte_err_string}, and -\tcode{wide_err_string}. -The second constructor stores \tcode{pcvt} in \tcode{cvtptr}, -\tcode{state} in \tcode{cvtstate}, and default values in -\tcode{byte_err_string} and \tcode{wide_err_string}; moreover the -stored state is retained between calls to \tcode{from_bytes} and -\tcode{to_bytes}. -The third constructor stores \tcode{new Codecvt} in \tcode{cvtptr}, -\tcode{state_type()} in \tcode{cvtstate}, \tcode{byte_err} -in \tcode{byte_err_string}, and \tcode{wide_err} in -\tcode{wide_err_string}. -\end{itemdescr} - -\indexlibrarydtor{wstring_convert}% -\begin{itemdecl} -~wstring_convert(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -\tcode{delete cvtptr}. -\end{itemdescr} - -\rSec2[depr.conversions.buffer]{Class template \tcode{wbuffer_convert}} - -\pnum -Class template \tcode{wbuffer_convert} looks like a wide stream buffer, but -performs all its I/O through an underlying byte stream buffer that you -specify when you construct it. Like class template \tcode{wstring_convert}, it -lets you specify a code conversion facet to perform the conversions, -without affecting any streams or locales. - -\indexlibraryglobal{wbuffer_convert}% -\indexlibrarymember{state_type}{wbuffer_convert}% -\begin{codeblock} -namespace std { - template> - class wbuffer_convert : public basic_streambuf { - public: - using state_type = typename Codecvt::state_type; - - wbuffer_convert() : wbuffer_convert(nullptr) {} - explicit wbuffer_convert(streambuf* bytebuf, - Codecvt* pcvt = new Codecvt, - state_type state = state_type()); - - ~wbuffer_convert(); - - wbuffer_convert(const wbuffer_convert&) = delete; - wbuffer_convert& operator=(const wbuffer_convert&) = delete; - - streambuf* rdbuf() const; - streambuf* rdbuf(streambuf* bytebuf); - - state_type state() const; - - private: - streambuf* bufptr; // \expos - Codecvt* cvtptr; // \expos - state_type cvtstate; // \expos - }; -} -\end{codeblock} - -\pnum -The class template describes a stream buffer that controls the -transmission of elements of type \tcode{Elem}, whose character traits are -described by the class \tcode{Tr}, to and from a byte stream buffer of type -\tcode{streambuf}. Conversion between a sequence of \tcode{Elem} values and -multibyte sequences is performed by an object of class -\tcode{Codecvt}, which shall meet the requirements -of the standard code-conversion facet \tcode{codecvt}. - -\pnum -An object of this class template stores: - -\begin{itemize} -\item \tcode{bufptr} --- a pointer to its underlying byte stream buffer -\item \tcode{cvtptr} --- a pointer to the allocated conversion object -(which is freed when the \tcode{wbuffer_convert} object is destroyed) -\item \tcode{cvtstate} --- a conversion state object -\end{itemize} - -\indexlibrarymember{state}{wbuffer_convert}% -\begin{itemdecl} -state_type state() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{cvtstate}. -\end{itemdescr} - -\indexlibrarymember{rdbuf}{wbuffer_convert}% -\begin{itemdecl} -streambuf* rdbuf() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{bufptr}. -\end{itemdescr} - -\indexlibrarymember{rdbuf}{wbuffer_convert}% -\begin{itemdecl} -streambuf* rdbuf(streambuf* bytebuf); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Stores \tcode{bytebuf} in \tcode{bufptr}. - -\pnum -\returns -The previous value of \tcode{bufptr}. -\end{itemdescr} - -\indexlibraryctor{wbuffer_convert}% -\begin{itemdecl} -explicit wbuffer_convert( - streambuf* bytebuf, - Codecvt* pcvt = new Codecvt, - state_type state = state_type()); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{pcvt} is not null. - -\pnum -\effects -The constructor constructs a stream buffer object, initializes -\tcode{bufptr} to \tcode{bytebuf}, initializes \tcode{cvtptr} -to \tcode{pcvt}, and initializes \tcode{cvtstate} to \tcode{state}. -\end{itemdescr} - -\indexlibrarydtor{wbuffer_convert}% -\begin{itemdecl} -~wbuffer_convert(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -\tcode{delete cvtptr}. -\end{itemdescr} - \rSec1[depr.locale.category]{Deprecated locale category facets} \pnum @@ -2410,6 +713,8 @@ \begin{codeblock} codecvt codecvt +codecvt +codecvt \end{codeblock} \pnum @@ -2420,6 +725,8 @@ \begin{codeblock} codecvt_byname codecvt_byname +codecvt_byname +codecvt_byname \end{codeblock} \pnum @@ -2427,11 +734,13 @@ in addition to those specified in~\ref{locale.codecvt}. \indextext{UTF-8}% \indextext{UTF-16}% -The specialization \tcode{codecvt} -converts between the UTF-16 and UTF-8 encoding forms, and +The specializations \tcode{codecvt} and +\tcode{codecvt} +convert between the UTF-16 and UTF-8 encoding forms, and \indextext{UTF-32}% -the specialization \tcode{codecvt} -converts between the UTF-32 and UTF-8 encoding forms. +the specializations \tcode{codecvt} and +\tcode{codecvt} +convert between the UTF-32 and UTF-8 encoding forms. \rSec1[depr.fs.path.factory]{Deprecated filesystem path factory functions} diff --git a/source/intro.tex b/source/intro.tex index a4fff15300..506c912ee4 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -253,6 +253,16 @@ \definition{dynamic type}{defns.dynamic.type.prvalue} \defncontext{prvalue} \termref{defns.static.type}{static type}{} of the prvalue expression +\definition{erroneous behavior}{defns.erroneous} +well-defined behavior that the implementation is recommended to diagnose +\begin{defnote} +Erroneous behavior is always the consequence of incorrect program code. +Implementations are allowed, but not required, +to diagnose it\iref{intro.compliance.general}. +Evaluation of a constant expression\iref{expr.const} +never exhibits behavior specified as erroneous in \ref{intro} through \ref{cpp}. +\end{defnote} + \definition{expression-equivalent}{defns.expression.equivalent} \defncontext{library} \indexdefn{expression-equivalent}% @@ -629,13 +639,13 @@ \begin{defnote} Undefined behavior may be expected when this document omits any explicit -definition of behavior or when a program uses an erroneous construct or erroneous data. +definition of behavior or when a program uses an incorrect construct or invalid data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a \termref{defns.diagnostic}{diagnostic message}{}), to terminating a translation or execution (with the -issuance of a diagnostic message). Many erroneous program constructs do +issuance of a diagnostic message). Many incorrect program constructs do not engender undefined behavior; they are required to be diagnosed. Evaluation of a constant expression\iref{expr.const} never exhibits behavior explicitly specified as undefined in \ref{intro} through \ref{cpp}. @@ -721,7 +731,8 @@ within its resource limits as described in \ref{implimits}, accept and correctly execute \begin{footnote} -``Correct execution'' can include undefined behavior, depending on +``Correct execution'' can include undefined behavior +and erroneous behavior, depending on the data being processed; see \ref{intro.defs} and~\ref{intro.execution}. \end{footnote} that program. @@ -730,11 +741,22 @@ If a program contains a violation of a rule for which no diagnostic is required, this document places no requirement on implementations with respect to that program. + \item \indextext{message!diagnostic}% -Otherwise, if a program contains a violation of any diagnosable rule or an occurrence +Otherwise, if a program contains +\begin{itemize} +\item +a violation of any diagnosable rule, +\item +a preprocessing translation unit with +a \tcode{\#warning} preprocessing directive\iref{cpp.error}, or +\item +an occurrence of a construct described in this document as ``conditionally-supported'' when -the implementation does not support that construct, a conforming implementation +the implementation does not support that construct, +\end{itemize} +a conforming implementation shall issue at least one diagnostic message. \end{itemize} \begin{note} @@ -744,17 +766,13 @@ see~\ref{temp.deduct}. \end{note} Furthermore, a conforming implementation +shall not accept \begin{itemize} \item -shall not accept a preprocessing translation unit containing -a \tcode{\#error} preprocessing directive\iref{cpp.error}, +a preprocessing translation unit containing +a \tcode{\#error} preprocessing directive\iref{cpp.error} or \item -shall issue at least one diagnostic message for -each \tcode{\#warning} or \tcode{\#error} preprocessing directive -not following a \tcode{\#error} preprocessing directive in -a preprocessing translation unit, and -\item -shall not accept a translation unit with +a translation unit with a \grammarterm{static_assert-declaration} that fails\iref{dcl.pre}. \end{itemize} @@ -893,6 +911,20 @@ requirement on the implementation executing that program with that input (not even with regard to operations preceding the first undefined operation). +If the execution contains an operation specified as having erroneous behavior, +the implementation is permitted to issue a diagnostic and +is permitted to terminate the execution +at an unspecified time after that operation. + +\pnum +\recommended +An implementation should issue a diagnostic when such an operation is executed. +\begin{note} +An implementation can issue a diagnostic +if it can determine that erroneous behavior is reachable +under an implementation-specific set of assumptions about the program behavior, +which can result in false positives. +\end{note} \pnum \indextext{conformance requirements}% diff --git a/source/iostreams.tex b/source/iostreams.tex index 39833d60d3..e865cd8211 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -918,7 +918,7 @@ to class \tcode{ios_base::failure} shown in this subclause. \begin{note} When \tcode{ios_base::failure} is a synonym for another type, -that type is required to provide a nested type \tcode{failure} +that type needs to provide a nested type \tcode{failure} to emulate the injected-class-name. \end{note} The class @@ -3513,6 +3513,11 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\range{gbeg}{gnext}, \range{gbeg}{gend}, and \range{gnext}{gend} +are all valid ranges. + \pnum \ensures \tcode{gbeg == eback()}, @@ -3573,6 +3578,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\range{pbeg}{pend} is a valid range. + \pnum \ensures \tcode{pbeg == pbase()}, @@ -4196,6 +4205,7 @@ void print(ostream& os, format_string fmt, Args&&... args); template void println(ostream& os, format_string fmt, Args&&... args); + void println(ostream& os); void vprint_unicode(ostream& os, string_view fmt, format_args args); void vprint_nonunicode(ostream& os, string_view fmt, format_args args); @@ -4248,8 +4258,10 @@ // \ref{print.fun}, print functions template void print(format_string fmt, Args&&... args); + void println(); template void print(FILE* stream, format_string fmt, Args&&... args); + void println(FILE* stream); template void println(format_string fmt, Args&&... args); @@ -6813,6 +6825,20 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{println}% +\begin{itemdecl} +void println(ostream& os); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +print(os, "\n"); +\end{codeblock} +\end{itemdescr} + \indexlibraryglobal{vprint_unicode}% \indexlibraryglobal{vprint_nonunicode}% \begin{itemdecl} @@ -7697,13 +7723,19 @@ \begin{itemdescr} \pnum \effects +Let \tcode{locksafe} be +\tcode{(enable_nonlocking_formatter_optimization> \&\& ...)}. If the ordinary literal encoding\iref{lex.charset} is UTF-8, equivalent to: \begin{codeblock} -vprint_unicode(stream, fmt.@\exposid{str}@, make_format_args(args...)); +locksafe + ? vprint_unicode_locking(stream, fmt.str, make_format_args(args...)) + : vprint_unicode(stream, fmt.str, make_format_args(args...)); \end{codeblock} Otherwise, equivalent to: \begin{codeblock} -vprint_nonunicode(stream, fmt.@\exposid{str}@, make_format_args(args...)); +locksafe + ? vprint_nonunicode_locking(stream, fmt.str, make_format_args(args...)) + : vprint_nonunicode(stream, fmt.str, make_format_args(args...)); \end{codeblock} \end{itemdescr} @@ -7722,6 +7754,20 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{println}% +\begin{itemdecl} +void println(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +println(stdout); +\end{codeblock} +\end{itemdescr} + \indexlibraryglobal{println}% \begin{itemdecl} template @@ -7733,7 +7779,21 @@ \effects Equivalent to: \begin{codeblock} -print(stream, "{}\n", format(fmt, std::forward(args)...)); +print(stream, runtime_format(string(fmt.get()) + '\n'), std::forward(args)...); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{println}% +\begin{itemdecl} +void println(FILE* stream); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +print(stream, "\n"); \end{codeblock} \end{itemdescr} @@ -7756,6 +7816,21 @@ void vprint_unicode(FILE* stream, string_view fmt, format_args args); \end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +string out = vformat(fmt, args); +vprint_unicode_locking(stream, "{}", make_format_args(out)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{vprint_unicode_locking}% +\begin{itemdecl} +void vprint_unicode_locking(FILE* stream, string_view fmt, format_args args); +\end{itemdecl} + \begin{itemdescr} \pnum \expects @@ -7763,10 +7838,10 @@ \pnum \effects -The function initializes an automatic variable via -\begin{codeblock} -string out = vformat(fmt, args); -\end{codeblock} +Locks \tcode{stream}. +Let \tcode{out} denote the character representation of +formatting arguments provided by \tcode{args} +formatted according to specifications given in \tcode{fmt}. If \tcode{stream} refers to a terminal capable of displaying Unicode, writes \tcode{out} to the terminal using the native Unicode API; if \tcode{out} contains invalid code units, @@ -7776,6 +7851,10 @@ Otherwise writes \tcode{out} to \tcode{stream} unchanged. If the native Unicode API is used, the function flushes \tcode{stream} before writing \tcode{out}. +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, @@ -7820,6 +7899,21 @@ void vprint_nonunicode(FILE* stream, string_view fmt, format_args args); \end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +string out = vformat(fmt, args); +vprint_nonunicode_locking("{}", make_format_args(out)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{vprint_nonunicode_locking}% +\begin{itemdecl} +void vprint_nonunicode_locking(FILE* stream, string_view fmt, format_args args); +\end{itemdecl} + \begin{itemdescr} \pnum \expects @@ -7827,7 +7921,10 @@ \pnum \effects -Writes the result of \tcode{vformat(fmt, args)} to \tcode{stream}. +While holding the lock on \tcode{stream}, +writes the character representation of +formatting arguments provided by \tcode{args} +formatted according to specifications given in \tcode{fmt} to \tcode{stream}. \pnum \throws @@ -8081,7 +8178,7 @@ \indexlibraryctor{basic_stringbuf}% \begin{itemdecl} -basic_stringbuf(ios_base::openmode which, const Allocator &a); +basic_stringbuf(ios_base::openmode which, const Allocator& a); \end{itemdecl} \begin{itemdescr} @@ -8119,7 +8216,7 @@ template basic_stringbuf( const basic_string& s, - ios_base::openmode which, const Allocator &a); + ios_base::openmode which, const Allocator& a); \end{itemdecl} \begin{itemdescr} @@ -13359,8 +13456,11 @@ path weakly_canonical(const path& p, error_code& ec); } -// \ref{fs.path.hash}, hash support namespace std { + // \ref{fs.path.fmtr}, formatting support + template struct formatter; + + // \ref{fs.path.hash}, hash support template struct hash; template<> struct hash; } @@ -13839,8 +13939,8 @@ \begin{note} Some operating systems have no unambiguous way to distinguish between native format and generic format arguments. This is by design as it simplifies use for operating systems that do not require -disambiguation. An implementation for an operating system where disambiguation -is required is permitted to distinguish between the formats. +disambiguation. It is possible that an implementation for an operating system +where disambiguation is needed distinguishes between the formats. \end{note} \pnum @@ -14384,7 +14484,7 @@ \effects Each \grammarterm{directory-separator} of the pathname in the generic format - is converted to \grammarterm{preferred-separator}. +is converted to \grammarterm{preferred-separator}. \pnum \returns @@ -15161,8 +15261,8 @@ \item The \grammarterm{root-name} element, if present. \item The \grammarterm{root-directory} element, if present. \begin{note} -The generic format is required to ensure lexicographical -comparison works correctly. +It is possible that the use of the generic format is needed +to ensure correct lexicographical comparison. \end{note} \item Each successive \grammarterm{filename} element, if present. \item An empty element, if a trailing non-root \grammarterm{directory-separator} @@ -15315,6 +15415,102 @@ Equivalent to: \tcode{return path(lhs) /= rhs;} \end{itemdescr} +\rSec3[fs.path.fmtr]{Formatting support} + +\rSec4[fs.path.fmtr.general]{Formatting support overview} + +\indexlibraryglobal{formatter}% +\begin{codeblock} +namespace std { + template struct formatter { + constexpr void set_debug_format(); + + constexpr typename basic_format_parse_context::iterator + parse(basic_format_parse_context& ctx); + + template + typename FormatContext::iterator + format(const filesystem::path& path, FormatContext& ctx) const; + }; +} +\end{codeblock} + +\rSec4[fs.path.fmtr.funcs]{Formatting support functions} + +\pnum +Formatting of paths uses formatting specifiers of the form +\begin{ncbnf} +\nontermdef{path-format-spec}\br + \opt{fill-and-align} \opt{width} \opt{\terminal{?}} \opt{\terminal{g}} +\end{ncbnf} +where the productions \fmtgrammarterm{fill-and-align} and \fmtgrammarterm{width} +are described in \ref{format.string}. +If the \tcode{?} option is used then +the path is formatted as an escaped string\iref{format.string.escaped}. + +\indexlibrarymember{formatter}{set_debug_format}% +\begin{itemdecl} +constexpr void set_debug_format(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Modifies the state of the \tcode{formatter} to be as if +the \fmtgrammarterm{path-format-spec} parsed by the last call to \tcode{parse} +contained the \tcode{?} option. +\end{itemdescr} + +\indexlibrarymember{formatter}{basic_format_parse_context}% +\begin{itemdecl} +constexpr typename basic_format_parse_context::iterator + parse(basic_format_parse_context& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Parses the format specifier as a \fmtgrammarterm{path-format-spec} and +stores the parsed specifiers in \tcode{*this}. + +\pnum +\returns +An iterator past the end of the \fmtgrammarterm{path-format-spec}. +\end{itemdescr} + +\indexlibrarymember{formatter}{format}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(const filesystem::path& p, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{s} be \tcode{p.generic_string()} +if the \tcode{g} option is used, +otherwise \tcode{p.native()}. +Writes \tcode{s} into \tcode{ctx.out()}, +adjusted according to the \fmtgrammarterm{path-format-spec}. +If \tcode{charT} is \keyword{char}, +\tcode{path::value_type} is \keyword{wchar_t}, and +the literal encoding is UTF-8, +then the escaped path is transcoded from the native encoding for +wide character strings to UTF-8 with +maximal subparts of ill-formed subsequences +substituted with \ucode{fffd} \uname{replacement character} +per the Unicode Standard, Chapter 3.9 \ucode{fffd} Substitution in Conversion. +If \tcode{charT} and \tcode{path::value_type} are the same +then no transcoding is performed. +Otherwise, transcoding is +\impldef{transcoding of a formatted path when \tcode{charT} and \tcode{path::value_type} differ}. + +\pnum +\returns +An iterator past the end of the output range. +\end{itemdescr} + \rSec3[fs.path.hash]{Hash support} \begin{itemdecl} diff --git a/source/iterators.tex b/source/iterators.tex index 1a7b67109a..c59e2264c3 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -173,6 +173,11 @@ template<@\libconcept{weakly_incrementable}@ I, class Proj> struct incrementable_traits>; // freestanding + + template<@\libconcept{indirectly_readable}@ I, @\libconcept{indirectly_regular_unary_invocable}@ Proj> + using projected_value_t = // freestanding + remove_cvref_t&>>; + // \ref{alg.req}, common algorithm requirements // \ref{alg.req.ind.move}, concept \libconcept{indirectly_movable} template @@ -709,12 +714,12 @@ \pnum \indextext{iterator!constexpr}% -Iterators are called \defn{constexpr iterators} +Iterators meet the \defn{constexpr iterator} requirements if all operations provided to meet iterator category requirements are constexpr functions. \begin{note} For example, the types ``pointer to \tcode{int}'' and -\tcode{reverse_iterator} are constexpr iterators. +\tcode{reverse_iterator} meet the constexpr iterator requirements. \end{note} \rSec2[iterator.assoc.types]{Associated types} @@ -1551,7 +1556,7 @@ \pnum \recommended -The implementaton of an algorithm on a weakly incrementable type +The implementation of an algorithm on a weakly incrementable type should never attempt to pass through the same incrementable value twice; such an algorithm should be a single-pass algorithm. \begin{note} diff --git a/source/lex.tex b/source/lex.tex index 41d0e4702d..03d086d26a 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -32,7 +32,10 @@ A source file together with all the headers\iref{headers} and source files included\iref{cpp.include} via the preprocessing directive \tcode{\#include}, less any source lines skipped by any of the -conditional inclusion\iref{cpp.cond} preprocessing directives, is +conditional inclusion\iref{cpp.cond} preprocessing directives, +as modified by the implementation-defined behavior of any +conditionally-supported-directives\iref{cpp.pre} and pragmas\iref{cpp.pragma}, +if any, is called a \defnadj{preprocessing}{translation unit}. \begin{note} A \Cpp{} program need not all be translated at the same time. @@ -665,8 +668,7 @@ (collectively, ``whitespace''), as described below, are ignored except as they serve to separate tokens. \begin{note} -Some whitespace is -required to separate otherwise adjacent identifiers, keywords, numeric +Whitespace can separate otherwise adjacent identifiers, keywords, numeric literals, and alternative tokens containing alphabetic characters. \end{note} \indextext{token|)} @@ -1851,7 +1853,7 @@ \pnum \begin{note} -The characters \tcode{'('} and \tcode{')'} are permitted in a +The characters \tcode{'('} and \tcode{')'} can appear in a \grammarterm{raw-string}. Thus, \tcode{R"delimiter((a|b))delimiter"} is equivalent to \tcode{"(a|b)"}. \end{note} diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 0594db6039..2cc47ecbcc 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -499,11 +499,11 @@ namespace std { template requires @\libconcept{convertible_to}@> - constexpr decay_t @\placeholdernc{decay-copy}@(T&& v) - noexcept(is_nothrow_convertible_v>) // \expos + constexpr decay_t @\placeholdernc{decay-copy}@(T&& v) // \expos + noexcept(is_nothrow_convertible_v>) { return std::forward(v); } - constexpr auto @\placeholdernc{synth-three-way}@ = + constexpr auto @\placeholdernc{synth-three-way}@ = // \expos [](const T& t, const U& u) requires requires { { t < u } -> @\exposconcept{boolean-testable}@; @@ -520,7 +520,8 @@ }; template - using @\placeholdernc{synth-three-way-result}@ = decltype(@\placeholdernc{synth-three-way}@(declval(), declval())); + using @\placeholdernc{synth-three-way-result}@ = // \expos + decltype(@\placeholdernc{synth-three-way}@(declval(), declval())); } \end{codeblock} @@ -1139,8 +1140,8 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\columnbreak \tcode{} \\ +\columnbreak \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1163,8 +1164,8 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \columnbreak +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1186,15 +1187,14 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \columnbreak +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1313,7 +1313,7 @@ \end{footnote} \pnum -\ref{support.c.headers}, C standard library headers, describes the effects of using +Subclause \ref{support.c.headers} describes the effects of using the \tcode{\placeholder{name}.h} (C header) form in a \Cpp{} program. \begin{footnote} The @@ -1455,7 +1455,7 @@ It is unspecified to which module a declaration in the standard library is attached. \begin{note} -Implementations are required to ensure that mixing +Conforming implementations ensure that mixing \tcode{\#include} and \tcode{import} does not result in conflicting attachments\iref{basic.link}. \end{note} @@ -1939,10 +1939,10 @@ \pnum A value-initialized object of type \tcode{P} produces the null value of the type. The null value shall be equivalent only to itself. A default-initialized object -of type \tcode{P} may have an indeterminate value. +of type \tcode{P} may have an indeterminate or erroneous value. \begin{note} -Operations involving -indeterminate values can cause undefined behavior. +Operations involving indeterminate values can cause undefined behavior, and +operations involving erroneous values can cause erroneous behavior\iref{basic.indet}. \end{note} \pnum @@ -3049,6 +3049,7 @@ \item \indexlibraryzombie{gets} \tcode{gets}, \item \indexlibraryzombie{is_literal_type} \tcode{is_literal_type}, \item \indexlibraryzombie{is_literal_type_v} \tcode{is_literal_type_v}, +\item \indexlibraryzombie{istrstream} \tcode{istrstream}, \item \indexlibraryzombie{little_endian} \tcode{little_endian}, \item \indexlibraryzombie{mem_fun1_ref_t} \tcode{mem_fun1_ref_t}, \item \indexlibraryzombie{mem_fun1_t} \tcode{mem_fun1_t}, @@ -3058,6 +3059,7 @@ \item \indexlibraryzombie{mem_fun} \tcode{mem_fun}, \item \indexlibraryzombie{not1} \tcode{not1}, \item \indexlibraryzombie{not2} \tcode{not2}, +\item \indexlibraryzombie{ostrstream} \tcode{ostrstream}, \item \indexlibraryzombie{pointer_safety} \tcode{pointer_safety}, \item \indexlibraryzombie{pointer_to_binary_function} \tcode{pointer_to_binary_function}, \item \indexlibraryzombie{pointer_to_unary_function} \tcode{pointer_to_unary_function}, @@ -3068,13 +3070,17 @@ \item \indexlibraryzombie{result_of_t} \tcode{result_of_t}, \item \indexlibraryzombie{return_temporary_buffer} \tcode{return_temporary_buffer}, \item \indexlibraryzombie{set_unexpected} \tcode{set_unexpected}, +\item \indexlibraryzombie{strstream} \tcode{strstream}, +\item \indexlibraryzombie{strstreambuf} \tcode{strstreambuf}, \item \indexlibraryzombie{unary_function} \tcode{unary_function}, \item \indexlibraryzombie{unary_negate} \tcode{unary_negate}, \item \indexlibraryzombie{uncaught_exception} \tcode{uncaught_exception}, \item \indexlibraryzombie{undeclare_no_pointers} \tcode{undeclare_no_pointers}, \item \indexlibraryzombie{undeclare_reachable} \tcode{undeclare_reachable}, +\item \indexlibraryzombie{unexpected_handler} \tcode{unexpected_handler}, +\item \indexlibraryzombie{wbuffer_convert} \tcode{wbuffer_convert}, and -\item \indexlibraryzombie{unexpected_handler} \tcode{unexpected_handler}. +\item \indexlibraryzombie{wstring_convert} \tcode{wstring_convert}. \end{itemize} \pnum @@ -3088,24 +3094,34 @@ \item \indexlibraryzombie{open_mode} \tcode{open_mode}, \item \indexlibraryzombie{preferred} \tcode{preferred}, \item \indexlibraryzombie{second_argument_type} \tcode{second_argument_type}, -\item \indexlibraryzombie{seek_dir} \tcode{seek_dir}, and. +\item \indexlibraryzombie{seek_dir} \tcode{seek_dir}, and \item \indexlibraryzombie{strict} \tcode{strict}. \end{itemize} \pnum -The name \indexlibraryzombie{stossc} \tcode{stossc} is reserved as a -member function for previous standardization, and may not be used as a name for -function-like macros in portable code. +The following names are reserved as member functions for previous +standardization, and may not be used as a name for function-like macros in +portable code: +\begin{itemize} +\item \indexlibraryzombie{converted} \tcode{converted}, +\item \indexlibraryzombie{from_bytes} \tcode{from_bytes}, +\item \indexlibraryzombie{freeze} \tcode{freeze}, +\item \indexlibraryzombie{pcount} \tcode{pcount}, +\item \indexlibraryzombie{stossc} \tcode{stossc}, and +\item \indexlibraryzombie{to_bytes} \tcode{to_bytes}. +\end{itemize} \pnum -The header names -\libnoheader{ccomplex}, -\libnoheader{ciso646}, -\libnoheader{codecvt}, -\libnoheader{cstdalign}, -\libnoheader{cstdbool}, and -\libnoheader{ctgmath} -are reserved for previous standardization. +The following header names are reserved for previous standardization: +\begin{itemize} +\item \libnoheader{ccomplex}, +\item \libnoheader{ciso646}, +\item \libnoheader{codecvt}, +\item \libnoheader{cstdalign}, +\item \libnoheader{cstdbool}, +\item \libnoheader{ctgmath}, and +\item \libnoheader{strstream}. +\end{itemize} \rSec4[macro.names]{Macro names} @@ -3294,6 +3310,13 @@ operator delete[](void*, std::align_val_t, const std::nothrow_t&) \end{codeblock} +\pnum +A \Cpp{} program may provide the definition of +the following function signature declared in header \libheaderref{debugging}: +\begin{codeblock} +bool std::is_debugger_present() noexcept +\end{codeblock} + \pnum The program's definitions are used instead of the default versions supplied by the implementation\iref{new.delete}. @@ -3340,8 +3363,8 @@ \end{itemize} \pnum -Calling the \tcode{set_*} and \tcode{get_*} functions shall not incur a data race. A call to -any of the \tcode{set_*} functions shall synchronize with subsequent calls to the same +Calling the \tcode{set_*} and \tcode{get_*} functions shall not incur a data race\iref{intro.races}. +A call to any of the \tcode{set_*} functions shall synchronize with subsequent calls to the same \tcode{set_*} function and to the corresponding \tcode{get_*} function. \rSec3[res.on.functions]{Other functions} @@ -3605,8 +3628,8 @@ provided by an implementation. \begin{note} In particular, -an implementation is not allowed to provide -an additional declaration of that function or function template +a conforming implementation does not provide +any additional declarations of that function or function template at namespace scope. \end{note} \begin{note} @@ -3772,7 +3795,7 @@ can report a failure by throwing an exception of a type described in its \throws paragraph, or of a type derived from a type named in the \throws paragraph -that would be caught by an exception handler for the base type. +that would be caught by a \grammarterm{handler}\iref{except.handle} for the base type. \pnum Functions from the C standard library shall not throw exceptions% diff --git a/source/locales.tex b/source/locales.tex index b196816b96..26ea841200 100644 --- a/source/locales.tex +++ b/source/locales.tex @@ -320,8 +320,6 @@ collate & \tcode{collate}, \tcode{collate} \\ \rowsep ctype & \tcode{ctype}, \tcode{ctype} \\ & \tcode{codecvt} \\ - & \tcode{codecvt} \\ - & \tcode{codecvt} \\ & \tcode{codecvt} \\ \rowsep monetary & \tcode{moneypunct}, \tcode{moneypunct} \\ & \tcode{moneypunct}, \tcode{moneypunct} \\ @@ -356,8 +354,6 @@ collate & \tcode{collate_byname}, \tcode{collate_byname} \\ \rowsep ctype & \tcode{ctype_byname}, \tcode{ctype_byname} \\ & \tcode{codecvt_byname} \\ - & \tcode{codecvt_byname} \\ - & \tcode{codecvt_byname} \\ & \tcode{codecvt_byname} \\ \rowsep monetary & \tcode{moneypunct_byname} \\ & \tcode{moneypunct_byname} \\ @@ -978,18 +974,18 @@ using mask = @\seebelow@; // numeric values are for exposition only. - static const mask space = 1 << 0; - static const mask print = 1 << 1; - static const mask cntrl = 1 << 2; - static const mask upper = 1 << 3; - static const mask lower = 1 << 4; - static const mask alpha = 1 << 5; - static const mask digit = 1 << 6; - static const mask punct = 1 << 7; - static const mask xdigit = 1 << 8; - static const mask blank = 1 << 9; - static const mask alnum = alpha | digit; - static const mask graph = alnum | punct; + static constexpr mask space = 1 << 0; + static constexpr mask print = 1 << 1; + static constexpr mask cntrl = 1 << 2; + static constexpr mask upper = 1 << 3; + static constexpr mask lower = 1 << 4; + static constexpr mask alpha = 1 << 5; + static constexpr mask digit = 1 << 6; + static constexpr mask punct = 1 << 7; + static constexpr mask xdigit = 1 << 8; + static constexpr mask blank = 1 << 9; + static constexpr mask alnum = alpha | digit; + static constexpr mask graph = alnum | punct; }; } \end{codeblock} @@ -1096,7 +1092,7 @@ \indexlibrarymember{ctype}{toupper}% \begin{itemdecl} -charT toupper(charT) const; +charT toupper(charT c) const; const charT* toupper(charT* low, const charT* high) const; \end{itemdecl} @@ -1684,13 +1680,6 @@ convert the implementation-defined native character set. \tcode{codecvt} implements a degenerate conversion; it does not convert at all. -\indextext{UTF-8}% -\indextext{UTF-16}% -\indextext{UTF-32}% -The specialization \tcode{codecvt} -converts between the UTF-16 and UTF-8 encoding forms, and -the specialization \tcode{codecvt} -converts between the UTF-32 and UTF-8 encoding forms. \tcode{codecvt} converts between the native character sets for ordinary and wide characters. Specializations on \tcode{mbstate_t} @@ -4701,8 +4690,8 @@ struct aliases_view; constexpr aliases_view aliases() const noexcept; - friend constexpr bool operator==(const text_encoding& encoding, - const text_encoding& other) noexcept; + friend constexpr bool operator==(const text_encoding& a, + const text_encoding& b) noexcept; friend constexpr bool operator==(const text_encoding& encoding, id i) noexcept; static consteval text_encoding literal() noexcept; @@ -4751,6 +4740,7 @@ The set of aliases of a known registered character encoding is an \impldef{set of aliases of a known registered character encoding} superset of the aliases specified in the IANA Character Sets registry. +The set of aliases for US-ASCII includes ``ASCII''. No two aliases or primary names of distinct registered character encodings are equivalent when compared by \tcode{text_encoding::\exposid{comp-name}}. @@ -5048,7 +5038,7 @@ if and only if \tcode{i != id::other} is \tcode{true}. \end{itemdescr} -\rSec3[text.encoding.aliases]{Class text_encoding::aliases_view} +\rSec3[text.encoding.aliases]{Class \tcode{text_encoding::aliases_view}} \indexlibrarymember{aliases_view}{text_encoding}% \indexlibrarymember{begin}{text_encoding::aliases_view}% @@ -5073,6 +5063,11 @@ \tcode{ranges::range_value_t} and \tcode{ranges::range_reference_t} denote \tcode{const char*}. + +\pnum +%FIXME: Is this supposed to be a remark or a requirement? Same above? +\tcode{ranges::iterator_t} +is a constexpr iterator\iref{iterator.requirements.general}. \end{itemdescr} \rSec3[text.encoding.id]{Enumeration \tcode{text_encoding::id}} diff --git a/source/macros.tex b/source/macros.tex index 079b61a329..bff719918e 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -78,12 +78,12 @@ % Set the xref label for a clause to be "Clause n", not just "n". \makeatletter -\newcommand{\customlabel}[2]{% -\@bsphack \begingroup \protected@edef \@currentlabel {\protect \M@TitleReference{#2}{\M@currentTitle}}\MNR@label{#1}\endgroup \@esphack% +\newcommand{\customlabel}[3]{% +\@bsphack \protected@write\@auxout{}{\string\newlabel{#1}{{#3}{\thepage}{}{#2.\thechapter}{}}} \@esphack% } \makeatother -\newcommand{\clauselabel}[1]{\customlabel{#1}{Clause \thechapter}} -\newcommand{\annexlabel}[1]{\customlabel{#1}{Annex \thechapter}} +\newcommand{\clauselabel}[1]{\customlabel{#1}{chapter}{Clause \thechapter}} +\newcommand{\annexlabel}[1]{\customlabel{#1}{appendix}{Annex \thechapter}} % Use prefix "Annex" in the table of contents \newcommand{\annexnumberlinebox}[2]{Annex #2\space} diff --git a/source/memory.tex b/source/memory.tex index a24a3b4973..1a80d14ed0 100644 --- a/source/memory.tex +++ b/source/memory.tex @@ -5735,10 +5735,10 @@ \begin{itemdescr} \pnum \returns -A derived class shall implement this function to return \tcode{true} if memory allocated from \keyword{this} can be deallocated from \tcode{other} and vice-versa, +A derived class shall implement this function to return \tcode{true} if memory allocated from \tcode{*this} can be deallocated from \tcode{other} and vice-versa, otherwise \tcode{false}. \begin{note} -It is possible that the most-derived type of \tcode{other} does not match the type of \keyword{this}. +It is possible that the most-derived type of \tcode{other} does not match the type of \tcode{*this}. For a derived class \tcode{D}, an implementation of this function can immediately return \tcode{false} if \tcode{dynamic_cast(\&other) == nullptr}. @@ -5813,6 +5813,9 @@ template void construct(T* p, Args&&... args); + template + void destroy(T* p); + polymorphic_allocator select_on_container_copy_construction() const; memory_resource* resource() const; @@ -6023,7 +6026,7 @@ \effects Equivalent to: \begin{codeblock} -allocator_traits::destroy(*this, p); +destroy(p); deallocate_object(p); \end{codeblock} \end{itemdescr} @@ -6053,6 +6056,18 @@ Nothing unless the constructor for \tcode{T} throws. \end{itemdescr} +\indexlibrarymember{destroy}{polymorphic_allocator}% +\begin{itemdecl} +template + void destroy(T* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{p->\~T()}. +\end{itemdescr} + \indexlibrarymember{select_on_container_copy_construction}{polymorphic_allocator}% \begin{itemdecl} polymorphic_allocator select_on_container_copy_construction() const; @@ -6607,8 +6622,8 @@ \pnum \begin{note} The memory is released back to \tcode{upstream_rsrc} -even if some blocks that were allocated from \keyword{this} -have not been deallocated from \keyword{this}. +even if some blocks that were allocated from \tcode{*this} +have not been deallocated from \tcode{*this}. \end{note} \end{itemdescr} diff --git a/source/numerics.tex b/source/numerics.tex index 61c871082f..2ab8b57ecf 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -1432,6 +1432,27 @@ template RealType generate_canonical(URBG& g); + namespace ranges { + // \ref{alg.rand.generate}, \tcode{generate_random} + template + requires @\libconcept{output_range}@> && + @\libconcept{uniform_random_bit_generator}@> + constexpr borrowed_iterator_t generate_random(R&& r, G&& g); + + template> O, @\libconcept{sentinel_for}@ S> + requires @\libconcept{uniform_random_bit_generator}@> + constexpr O generate_random(O first, S last, G&& g); + + template + requires @\libconcept{output_range}@> && @\libconcept{invocable}@ && + @\libconcept{uniform_random_bit_generator}@> + 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}@> + constexpr O generate_random(O first, S last, G&& g, D&& d); + } + // \ref{rand.dist.uni.int}, class template \tcode{uniform_int_distribution} template class uniform_int_distribution; @@ -3287,7 +3308,8 @@ \indexlibraryglobal{independent_bits_engine}% \indexlibrarymember{result_type}{independent_bits_engine}% \begin{codeblock} -template +namespace std { + template class independent_bits_engine { public: // types @@ -3328,6 +3350,7 @@ private: Engine e; // \expos }; +} \end{codeblock}% \pnum @@ -4786,9 +4809,9 @@ \indexlibraryglobal{poisson_distribution}% \indexlibrarymember{result_type}{poisson_distribution}% \begin{codeblock} -template - class poisson_distribution - { +namespace std { + template + class poisson_distribution { public: // types using result_type = IntType; @@ -4824,6 +4847,7 @@ friend basic_istream& operator>>(basic_istream& is, poisson_distribution& x); }; +} \end{codeblock} \indexlibraryctor{poisson_distribution}% @@ -6395,7 +6419,12 @@ \begin{itemdescr} \pnum \mandates -\tcode{is_invocable_r_v} is \tcode{true}. +Both of +\begin{itemize} +\item{\tcode{is_convertible_v::value_type, double>}} +\item{\tcode{is_convertible_v::value_type, double>}} +\end{itemize} +are \tcode{true}. \pnum \expects @@ -9472,7 +9501,8 @@ if \tcode{X} cannot be converted to \tcode{int} by integral promotion\iref{conv.prom}, the program is ill-formed. \begin{note} -Arguments that can be promoted to \tcode{int} are permitted for compatibility with C. +Allowing arguments that can be promoted to \tcode{int} +provides compatibility with C. \end{note} \end{itemdescr} @@ -10479,6 +10509,7 @@ \rSec2[linalg.syn]{Header \tcode{} synopsis} +\indexheader{linalg}% \begin{codeblock} namespace std::linalg { // \ref{linalg.tags.order}, storage order tags @@ -11489,15 +11520,15 @@ the order of elements in an \tcode{mdspan} with \tcode{layout_blas_packed}\iref{linalg.layout.packed} layout. \begin{itemdecl} -struct column_major_t { +struct @\libglobal{column_major_t}@ { explicit column_major_t() = default; }; -inline constexpr column_major_t column_major{}; +inline constexpr column_major_t @\libglobal{column_major}@{}; -struct row_major_t { +struct @\libglobal{row_major_t}@ { explicit row_major_t() = default; }; -inline constexpr row_major_t row_major{}; +inline constexpr row_major_t @\libglobal{row_major}@{}; \end{itemdecl} \begin{itemdescr} @@ -11509,15 +11540,15 @@ \rSec3[linalg.tags.triangle]{Triangle tags} \begin{itemdecl} -struct upper_triangle_t { +struct @\libglobal{upper_triangle_t}@ { explicit upper_triangle_t() = default; }; -inline constexpr upper_triangle_t upper_triangle{}; +inline constexpr upper_triangle_t @\libglobal{upper_triangle}@{}; -struct lower_triangle_t { +struct @\libglobal{lower_triangle_t}@ { explicit lower_triangle_t() = default; }; -inline constexpr lower_triangle_t lower_triangle{}; +inline constexpr lower_triangle_t @\libglobal{lower_triangle}@{}; \end{itemdecl} \begin{itemdescr} @@ -11535,16 +11566,15 @@ \rSec3[linalg.tags.diagonal]{Diagonal tags} \begin{itemdecl} -struct implicit_unit_diagonal_t { +struct @\libglobal{implicit_unit_diagonal_t}@ { explicit implicit_unit_diagonal_t() = default; }; -inline constexpr implicit_unit_diagonal_t - implicit_unit_diagonal{}; +inline constexpr implicit_unit_diagonal_t @\libglobal{implicit_unit_diagonal}@{}; -struct explicit_diagonal_t { +struct @\libglobal{explicit_diagonal_t}@ { explicit explicit_diagonal_t() = default; }; -inline constexpr explicit_diagonal_t explicit_diagonal{}; +inline constexpr explicit_diagonal_t @\libglobal{explicit_diagonal}@{}; \end{itemdecl} \begin{itemdescr} @@ -11602,7 +11632,7 @@ \begin{codeblock} namespace std::linalg { template - class layout_blas_packed { + class @\libglobal{layout_blas_packed}@ { public: using triangle_type = Triangle; using storage_order_type = StorageOrder; @@ -11697,6 +11727,7 @@ \rSec3[linalg.layout.packed.cons]{Constructors} +\indexlibraryctor{layout_blas_packed::mapping}% \begin{itemdecl} constexpr mapping(const extents_type& e) noexcept; \end{itemdecl} @@ -11718,6 +11749,7 @@ Direct-non-list-initializes \exposid{extents_} with \tcode{e}. \end{itemdescr} +\indexlibraryctor{layout_blas_packed::mapping}% \begin{itemdecl} template explicit(!is_convertible_v) @@ -11742,6 +11774,7 @@ \rSec3[linalg.layout.packed.obs]{Observers} +\indexlibrarymember{layout_blas_packed::mapping}{required_span_size}% \begin{itemdecl} constexpr index_type required_span_size() const noexcept; \end{itemdecl} @@ -11756,6 +11789,7 @@ \end{note} \end{itemdescr} +\indexlibrarymember{layout_blas_packed::mapping}{operator()}% \begin{itemdecl} template constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept; @@ -11806,6 +11840,7 @@ \end{itemize} \end{itemdescr} +\indexlibrarymember{layout_blas_packed::mapping}{stride}% \begin{itemdecl} constexpr index_type stride(rank_type r) const noexcept; \end{itemdecl} @@ -11825,6 +11860,7 @@ \tcode{1}. \end{itemdescr} +\indexlibrarymember{layout_blas_packed::mapping}{operator==}% \begin{itemdecl} template friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; @@ -12142,7 +12178,6 @@ \rSec3[linalg.scaled.scaledaccessor]{Class template \tcode{scaled_accessor}} - \pnum The class template \tcode{scaled_accessor} is an \tcode{mdspan} accessor policy which upon access produces scaled elements. @@ -12150,7 +12185,7 @@ \begin{codeblock} namespace std::linalg { template - class scaled_accessor { + class @\libglobal{scaled_accessor}@ { public: using element_type = add_const_t() * declval())>; @@ -12193,6 +12228,7 @@ \tcode{NestedAccessor} meets the accessor policy requirements\iref{mdspan.accessor.reqmts}. \end{itemize} +\indexlibraryctor{scaled_accessor}% \begin{itemdecl} template explicit(!is_convertible_v) @@ -12216,6 +12252,7 @@ \end{itemize} \end{itemdescr} +\indexlibraryctor{scaled_accessor}% \begin{itemdecl} constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a); \end{itemdecl} @@ -12231,6 +12268,7 @@ \end{itemize} \end{itemdescr} +\indexlibrarymember{scaled_accessor}{access}% \begin{itemdecl} constexpr reference access(data_handle_type p, size_t i) const; \end{itemdecl} @@ -12243,6 +12281,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{scaled_accessor}{offset}% \begin{itemdecl} constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const; \end{itemdecl} @@ -12263,6 +12302,7 @@ that represents the elementwise product of \tcode{alpha} with each element of \tcode{x}. +\indexlibraryglobal{scaled}% \begin{itemdecl} template @@ -12317,7 +12357,7 @@ \begin{codeblock} namespace std::linalg { template - class conjugated_accessor { + class @\libglobal{conjugated_accessor}@ { public: using element_type = add_const_t()))>; @@ -12356,6 +12396,7 @@ \tcode{NestedAccessor} meets the accessor policy requirements\iref{mdspan.accessor.reqmts}. \end{itemize} +\indexlibraryctor{conjugated_accessor}% \begin{itemdecl} constexpr conjugated_accessor(const NestedAccessor& acc); \end{itemdecl} @@ -12367,6 +12408,7 @@ \exposid{nested-accessor_} with \tcode{acc}. \end{itemdescr} +\indexlibraryctor{conjugated_accessor}% \begin{itemdecl} template explicit(!is_convertible_v>) @@ -12385,6 +12427,7 @@ with \tcode{other.nested_accessor()}. \end{itemdescr} +\indexlibrarymember{conjugated_accessor}{access}% \begin{itemdecl} constexpr reference access(data_handle_type p, size_t i) const; \end{itemdecl} @@ -12395,6 +12438,7 @@ \tcode{\exposid{conj-if-needed}(NestedAccessor::element_type(\exposid{nested-accessor_}.access(p, i)))} \end{itemdescr} +\indexlibrarymember{conjugated_accessor}{offset}% \begin{itemdecl} constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const; \end{itemdecl} @@ -12409,7 +12453,7 @@ \begin{itemdecl} template - constexpr auto conjugated(mdspan a); + constexpr auto @\libglobal{conjugated}@(mdspan a); \end{itemdecl} \begin{itemdescr} @@ -12519,7 +12563,7 @@ \begin{codeblock} namespace std::linalg { template - class layout_transpose { + class @\libglobal{layout_transpose}@ { public: using nested_layout_type = Layout; @@ -12587,6 +12631,7 @@ \tcode{Extents::rank()} equals 2. \end{itemize} +\indexlibraryctor{layout_transpose::mapping}% \begin{itemdecl} constexpr explicit mapping(const @\exposid{nested-mapping-type}@& map); \end{itemdecl} @@ -12603,12 +12648,12 @@ \end{itemize} \end{itemdescr} +\indexlibrarymember{layout_transpose::mapping}{stride}% \begin{itemdecl} constexpr index_type stride(size_t r) const; \end{itemdecl} \begin{itemdescr} - \pnum \expects \begin{itemize} @@ -12623,6 +12668,7 @@ \tcode{\exposid{nested-mapping_}.stride(r == 0 ? 1 : 0)} \end{itemdescr} +\indexlibrarymember{layout_transpose::mapping}{operator==}% \begin{itemdecl} template friend constexpr bool operator==(const mapping& x, const mapping& y); @@ -12648,6 +12694,7 @@ returns a new \tcode{mdspan} representing the input matrix's transpose. The input matrix's data are not modified, and the returned \tcode{mdspan} accesses the input matrix's data in place. +\indexlibraryglobal{transposed}% \begin{itemdecl} template constexpr auto transposed(mdspan a); @@ -12771,6 +12818,7 @@ The \tcode{conjugate_transposed} function returns a conjugate transpose view of an object. This combines the effects of \tcode{transposed} and \tcode{conjugated}. +\indexlibraryglobal{conjugate_transposed}% \begin{itemdecl} template constexpr auto conjugate_transposed(mdspan a); @@ -12857,6 +12905,7 @@ \rSec4[linalg.algs.blas1.givens.lartg]{Compute Givens rotation} +\indexlibraryglobal{setup_givens_rotation}% \begin{itemdecl} template setup_givens_rotation_result setup_givens_rotation(Real a, Real b) noexcept; @@ -12910,6 +12959,7 @@ \rSec4[linalg.algs.blas1.givens.rot]{Apply a computed Givens rotation to vectors} +\indexlibraryglobal{apply_givens_rotation}% \begin{itemdecl} template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real> void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s); @@ -12948,6 +12998,7 @@ \rSec3[linalg.algs.blas1.swap]{Swap matrix or vector elements} +\indexlibraryglobal{swap_elements}% \begin{itemdecl} template<@\exposconcept{inout-object}@ InOutObj1, @\exposconcept{inout-object}@ InOutObj2> void swap_elements(InOutObj1 x, InOutObj2 y); @@ -12984,6 +13035,7 @@ \rSec3[linalg.algs.blas1.scal]{Multiply the elements of an object in place by a scalar} +\indexlibraryglobal{scale}% \begin{itemdecl} template void scale(Scalar alpha, InOutObj x); @@ -13006,6 +13058,7 @@ \rSec3[linalg.algs.blas1.copy]{Copy elements of one matrix or vector into another} +\indexlibraryglobal{copy}% \begin{itemdecl} template<@\exposconcept{in-object}@ InObj, @\exposconcept{out-object}@ OutObj> void copy(InObj x, OutObj y); @@ -13042,6 +13095,7 @@ \rSec3[linalg.algs.blas1.add]{Add vectors or matrices elementwise} +\indexlibraryglobal{add}% \begin{itemdecl} template<@\exposconcept{in-object}@ InObj1, @\exposconcept{in-object}@ InObj2, @\exposconcept{out-object}@ OutObj> void add(InObj1 x, InObj2 y, OutObj z); @@ -13095,6 +13149,8 @@ \pnum \expects \tcode{v1.extent(0)} equals \tcode{v2.extent(0)}. + +\indexlibraryglobal{dot}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> Scalar dot(InVec1 v1, InVec2 v2, Scalar init); @@ -13128,6 +13184,7 @@ then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. \end{itemdescr} +\indexlibraryglobal{dot}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2> auto dot(InVec1 v1, InVec2 v2); @@ -13160,6 +13217,7 @@ \end{itemize} \end{itemdescr} +\indexlibraryglobal{dotc}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> Scalar dotc(InVec1 v1, InVec2 v2, Scalar init); @@ -13191,6 +13249,7 @@ \end{itemize} \end{itemdescr} +\indexlibraryglobal{dotc}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2> auto dotc(InVec1 v1, InVec2 v2); @@ -13225,6 +13284,7 @@ \rSec3[linalg.algs.blas1.ssq]{Scaled sum of squares of a vector's elements} +\indexlibraryglobal{vector_sum_of_squares}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec, class Scalar> sum_of_squares_result vector_sum_of_squares(InVec v, sum_of_squares_result init); @@ -13273,6 +13333,7 @@ \rSec3[linalg.algs.blas1.nrm2]{Euclidean norm of a vector} +\indexlibraryglobal{vector_two_norm}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec, class Scalar> Scalar vector_two_norm(InVec v, Scalar init); @@ -13314,6 +13375,7 @@ \end{note} \end{itemdescr} +\indexlibraryglobal{vector_two_norm}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec> auto vector_two_norm(InVec v); @@ -13345,6 +13407,7 @@ \rSec3[linalg.algs.blas1.asum]{Sum of absolute values of vector elements} +\indexlibraryglobal{vector_abs_sum}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec, class Scalar> Scalar vector_abs_sum(InVec v, Scalar init); @@ -13397,6 +13460,7 @@ then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. \end{itemdescr} +\indexlibraryglobal{vector_abs_sum}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec> auto vector_abs_sum(InVec v); @@ -13426,6 +13490,7 @@ \rSec3[linalg.algs.blas1.iamax]{Index of maximum absolute value of vector elements} +\indexlibraryglobal{vector_idx_abs_max}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec> typename InVec::extents_type vector_idx_abs_max(InVec v); @@ -13477,6 +13542,8 @@ These functions exist in the BLAS standard\supercite{blas-std} but are not part of the reference implementation. \end{note} + +\indexlibraryglobal{matrix_frob_norm}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Scalar> Scalar matrix_frob_norm(InMat A, Scalar init); @@ -13511,6 +13578,7 @@ then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. \end{itemdescr} +\indexlibraryglobal{matrix_frob_norm}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat> auto matrix_frob_norm(InMat A); @@ -13549,6 +13617,7 @@ but are not part of the reference implementation. \end{note} +\indexlibraryglobal{matrix_one_norm}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Scalar> Scalar matrix_one_norm(InMat A, Scalar init); @@ -13585,6 +13654,7 @@ then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. \end{itemdescr} +\indexlibraryglobal{matrix_one_norm}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat> auto matrix_one_norm(InMat A); @@ -13621,6 +13691,7 @@ but are not part of the reference implementation. \end{note} +\indexlibraryglobal{matrix_inf_norm}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Scalar> Scalar matrix_inf_norm(InMat A, Scalar init); @@ -13659,6 +13730,7 @@ then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. \end{itemdescr} +\indexlibraryglobal{matrix_inf_norm}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat> auto matrix_inf_norm(InMat A); @@ -13724,6 +13796,7 @@ \complexity \bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. +\indexlibraryglobal{matrix_vector_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> void matrix_vector_product(InMat A, InVec x, OutVec y); @@ -13759,6 +13832,7 @@ \end{codeblock} \end{example} +\indexlibraryglobal{matrix_vector_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z); @@ -13835,6 +13909,7 @@ \complexity \bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. +\indexlibraryglobal{symmetric_matrix_vector_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); @@ -13856,6 +13931,7 @@ Computes $y = A x$. \end{itemdescr} +\indexlibraryglobal{symmetric_matrix_vector_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); @@ -13924,6 +14000,7 @@ \complexity \bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. +\indexlibraryglobal{hermitian_matrix_vector_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); @@ -13944,6 +14021,7 @@ Computes $y = A x$. \end{itemdescr} +\indexlibraryglobal{hermitian_matrix_vector_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); @@ -14013,6 +14091,7 @@ \tcode{A.extent(0)} equals \tcode{z.extent(0)} for those overloads that take a \tcode{z} parameter. \end{itemize} +\indexlibraryglobal{triangular_matrix_vector_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> @@ -14041,6 +14120,7 @@ \bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. \end{itemdescr} +\indexlibraryglobal{triangular_matrix_vector_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec> void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y); @@ -14072,6 +14152,7 @@ \bigoh{\tcode{y.extent(0)} \times \tcode{A.extent(1)}}. \end{itemdescr} +\indexlibraryglobal{triangular_matrix_vector_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> @@ -14144,6 +14225,7 @@ for those overloads that take an \tcode{x} parameter. \end{itemize} +\indexlibraryglobal{triangular_matrix_vector_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec, class BinaryDivideOp> @@ -14176,6 +14258,7 @@ \bigoh{\tcode{A.extent(1)} \times \tcode{b.extent(0)}}. \end{itemdescr} +\indexlibraryglobal{triangular_matrix_vector_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> @@ -14191,6 +14274,7 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{triangular_matrix_vector_solve}% \begin{itemdecl} template @@ -14208,6 +14292,7 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{triangular_matrix_vector_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec, class BinaryDivideOp> @@ -14243,6 +14328,7 @@ \bigoh{\tcode{A.extent(1)} \times \tcode{b.extent(0)}}. \end{itemdescr} +\indexlibraryglobal{triangular_matrix_vector_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec> void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b); @@ -14257,6 +14343,7 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{triangular_matrix_vector_solve}% \begin{itemdecl} template @@ -14276,6 +14363,7 @@ \rSec3[linalg.algs.blas2.rank1]{Rank-1 (outer product) update of a matrix} +\indexlibraryglobal{matrix_rank_1_update}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{inout-matrix}@ InOutMat> void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A); @@ -14311,6 +14399,7 @@ \bigoh{\tcode{x.extent(0)} \times \tcode{y.extent(0)}}. \end{itemdescr} +\indexlibraryglobal{matrix_rank_1_update}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{inout-matrix}@ InOutMat> void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A); @@ -14386,6 +14475,7 @@ \complexity \bigoh{\tcode{x.extent(0)} \times \tcode{x.extent(0)}}. +\indexlibraryglobal{symmetric_matrix_rank_1_update}% \begin{itemdecl} template void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); @@ -14409,6 +14499,7 @@ and assigns each element of $A'$ to the corresponding element of $A$. \end{itemdescr} +\indexlibraryglobal{symmetric_matrix_rank_1_update}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); @@ -14430,6 +14521,7 @@ and assigns each element of $A'$ to the corresponding element of $A$. \end{itemdescr} +\indexlibraryglobal{hermitian_matrix_rank_1_update}% \begin{itemdecl} template void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); @@ -14453,6 +14545,7 @@ and assigns each element of $A'$ to the corresponding element of $A$. \end{itemdescr} +\indexlibraryglobal{hermitian_matrix_rank_1_update}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); @@ -14513,6 +14606,7 @@ \complexity \bigoh{\tcode{x.extent(0)} \times \tcode{y.extent(0)}}. +\indexlibraryglobal{symmetric_matrix_rank_2_update}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> @@ -14536,6 +14630,7 @@ assigns each element of $A'$ to the corresponding element of $A$. \end{itemdescr} +\indexlibraryglobal{hermitian_matrix_rank_2_update}% \begin{itemdecl} template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> @@ -14586,6 +14681,7 @@ \complexity \bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. +\indexlibraryglobal{matrix_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> void matrix_product(InMat1 A, InMat2 B, OutMat C); @@ -14599,6 +14695,7 @@ Computes $C = A B$. \end{itemdescr} +\indexlibraryglobal{matrix_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C); @@ -14662,6 +14759,7 @@ \complexity \bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. +\indexlibraryglobal{symmetric_matrix_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); @@ -14711,6 +14809,7 @@ Computes $C = A B$. \end{itemdescr} +\indexlibraryglobal{symmetric_matrix_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat> void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); @@ -14763,6 +14862,7 @@ Computes $C = A B$. \end{itemdescr} +\indexlibraryglobal{symmetric_matrix_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> @@ -14825,6 +14925,7 @@ \tcode{C} may alias \tcode{E}. \end{itemdescr} +\indexlibraryglobal{symmetric_matrix_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> @@ -14900,6 +15001,7 @@ These functions correspond to the BLAS function \tcode{xTRMM}\supercite{blas3}. \end{note} +\indexlibraryglobal{triangular_matrix_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); @@ -14943,6 +15045,7 @@ \bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. \end{itemdescr} +\indexlibraryglobal{triangular_matrix_right_product}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); @@ -15030,6 +15133,7 @@ \complexity \bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. +\indexlibraryglobal{symmetric_matrix_rank_k_update}% \begin{itemdecl} template void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); @@ -15047,6 +15151,7 @@ and assigns each element of $C'$ to the corresponding element of $C$. \end{itemdescr} +\indexlibraryglobal{symmetric_matrix_rank_k_update}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); @@ -15063,6 +15168,7 @@ assigns each element of $C'$ to the corresponding element of $C$. \end{itemdescr} +\indexlibraryglobal{hermitian_matrix_rank_k_update}% \begin{itemdecl} template void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); @@ -15080,6 +15186,7 @@ and assigns each element of $C'$ to the corresponding element of $C$. \end{itemdescr} +\indexlibraryglobal{hermitian_matrix_rank_k_update}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); @@ -15135,6 +15242,7 @@ \complexity \bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. +\indexlibraryglobal{symmetric_matrix_rank_2k_update}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> @@ -15152,6 +15260,7 @@ and assigns each element of $C'$ to the corresponding element of $C$. \end{itemdescr} +\indexlibraryglobal{hermitian_matrix_rank_2k_update}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> @@ -15177,6 +15286,7 @@ These functions correspond to the BLAS function \tcode{xTRSM}\supercite{blas3}. \end{note} +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp> @@ -15242,6 +15352,7 @@ and $y^{-1}$ denotes the multiplicative inverse of $y$. \end{note} +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> @@ -15258,6 +15369,7 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% \begin{itemdecl} template @@ -15276,6 +15388,7 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp> @@ -15338,6 +15451,7 @@ \end{note} \end{itemdescr} +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> @@ -15354,6 +15468,7 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% \begin{itemdecl} template @@ -15379,6 +15494,7 @@ These functions correspond to the BLAS function \tcode{xTRSM}\supercite{blas3}. \end{note} +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp> @@ -15440,6 +15556,7 @@ \bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. \end{itemdescr} +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, @@ -15455,6 +15572,7 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{triangular_matrix_matrix_left_solve}% \begin{itemdecl} template @@ -15473,6 +15591,7 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp> @@ -15533,6 +15652,7 @@ \bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. \end{itemdescr} +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% \begin{itemdecl} template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B); @@ -15547,6 +15667,7 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{triangular_matrix_matrix_right_solve}% \begin{itemdecl} template diff --git a/source/overloading.tex b/source/overloading.tex index f46353518e..9e1292a793 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -1001,17 +1001,18 @@ or default-initialized\iref{dcl.init}, overload resolution selects the constructor. For direct-initialization or default-initialization -that is not in the context of copy-initialization, the -candidate functions are +(including default-initialization in the context of copy-list-initialization), +the candidate functions are all the constructors of the class of the object being initialized. -For copy-initialization (including default initialization -in the context of copy-initialization), the candidate functions are all +Otherwise, the candidate functions are all the converting constructors\iref{class.conv.ctor} of that class. The argument list is the \grammarterm{expression-list} or \grammarterm{assignment-expression} of the \grammarterm{initializer}. +For default-initialization in the context of copy-list-initialization, +if an explicit constructor is chosen, the initialization is ill-formed. \rSec3[over.match.copy]{Copy-initialization of class by user-defined conversion}% \indextext{overloading!resolution!initialization} @@ -1200,9 +1201,16 @@ \item The associated constraints\iref{temp.constr.decl} are the conjunction of the associated constraints of \tcode{C} and -the associated constraints of the constructor. +the associated constraints of the constructor, if any. +\begin{note} +A \grammarterm{constraint-expression} in +the \grammarterm{template-head} of \tcode{C} +is checked for satisfaction before any constraints from +the \grammarterm{template-head} or trailing \grammarterm{requires-clause} +of the constructor. +\end{note} \item -The types of the function parameters are those of the constructor. +The \grammarterm{parameter-declaration-clause} is that of the constructor. \item The return type is the class template specialization designated by \tcode{C} @@ -1228,8 +1236,8 @@ \begin{itemize} \item -The template parameters, if any, -and function parameters +The \grammarterm{template-head}, if any, +and \grammarterm{parameter-declaration-clause} are those of the \grammarterm{deduction-guide}. \item The return type @@ -2141,8 +2149,8 @@ or when converting to the left operand of an assignment operation only standard conversion sequences are allowed. \begin{note} -When converting to the explicit object parameter, if any, -user-defined conversion sequences are allowed. +When a conversion to the explicit object parameter occurs, +it can include user-defined conversion sequences. \end{note} \pnum @@ -2310,11 +2318,32 @@ \rSec4[over.ics.ref]{Reference binding} \pnum -When a parameter of reference type binds directly\iref{dcl.init.ref} to an -argument expression, the implicit conversion sequence is the identity conversion, -unless the argument expression has a type that is a derived class of the parameter -type, in which case the implicit conversion sequence is a derived-to-base +When a parameter of type ``reference to \cv \tcode{T}'' +binds directly\iref{dcl.init.ref} to an argument expression: +\begin{itemize} +\item +If the argument expression has a type that +is a derived class of the parameter type, +the implicit conversion sequence is a derived-to-base conversion\iref{over.best.ics}. + +\item +Otherwise, +if \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, the implicit conversion sequence is a qualification conversion. +\end{itemize} + \begin{example} \begin{codeblock} struct A {}; @@ -2327,9 +2356,8 @@ If the parameter binds directly to the result of applying a conversion function to the argument expression, the implicit conversion sequence is a user-defined conversion sequence\iref{over.ics.user} -whose second standard conversion sequence is either an identity conversion or, -if the conversion function returns an entity of a type that is a derived class -of the parameter type, a derived-to-base conversion. +whose second standard conversion sequence is +determined by the above rules. \pnum When a parameter of reference type is not bound directly to an argument @@ -2347,7 +2375,7 @@ binding an lvalue reference other than a reference to a non-volatile \keyword{const} type to an rvalue -or binding an rvalue reference to an lvalue other than a function lvalue. +or binding an rvalue reference to an lvalue of object type. \begin{note} This means, for example, that a candidate function cannot be a viable function if it has a non-\keyword{const} lvalue reference parameter (other than @@ -2745,8 +2773,8 @@ \item \tcode{S1} and \tcode{S2} include reference bindings\iref{dcl.init.ref} and -\tcode{S1} binds an lvalue reference to a function lvalue and \tcode{S2} binds -an rvalue reference to a function lvalue +\tcode{S1} binds an lvalue reference to an lvalue of function type and +\tcode{S2} binds an rvalue reference to an lvalue of function type \begin{example} \begin{codeblock} int f(void(&)()); // \#1 @@ -2760,14 +2788,21 @@ \item \tcode{S1} and \tcode{S2} differ only in their qualification conversion\iref{conv.qual} and -yield similar types \tcode{T1} and \tcode{T2}, respectively, -where \tcode{T1} can be converted to \tcode{T2} by a qualification conversion. +yield similar types \tcode{T1} and \tcode{T2}, respectively +(where a standard conversion sequence that is a reference binding +is considered to yield the cv-unqualified referenced type), +where \tcode{T1} and \tcode{T2} are not the same type, and +\tcode{const T2} is reference-compatible with \tcode{T1}\iref{dcl.init.ref}. \begin{example} \begin{codeblock} int f(const volatile int *); int f(const int *); int i; int j = f(&i); // calls \tcode{f(const int*)} +int g(const int*); +int g(const volatile int* const&); +int* p; +int k = g(p); // calls \tcode{g(const int*)} \end{codeblock} \end{example} or, if not that, @@ -2775,13 +2810,10 @@ \tcode{S1} and \tcode{S2} -include reference bindings\iref{dcl.init.ref}, and the types to which the references -refer are the same type except for top-level cv-qualifiers, and the type to -which the reference initialized by -\tcode{S2} -refers is more cv-qualified than the type to which the reference initialized by -\tcode{S1} -refers. +bind ``reference to \tcode{T1}'' and ``reference to \tcode{T2}'', +respectively\iref{dcl.init.ref}, +where \tcode{T1} and \tcode{T2} are not the same type, and +\tcode{T2} is reference-compatible with \tcode{T1}. \begin{example} \begin{codeblock} int f(const int &); @@ -2801,6 +2833,17 @@ a.f(); // calls \tcode{X::f() const} b.f(); // calls \tcode{X::f()} } + +int h1(int (&)[]); +int h1(int (&)[1]); +int h2(void (&)()); +int h2(void (&)() noexcept); +void g2() { + int a[1]; + h1(a); // calls \tcode{h1(int (\&)[1])} + extern void f2() noexcept; + h2(f2); // calls \tcode{h2(void (\&)() noexcept)} +} \end{codeblock} \end{example} \end{itemize} diff --git a/source/preprocessor.tex b/source/preprocessor.tex index 7ca4deabb0..913fcc20fb 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -759,6 +759,32 @@ or (if it is the first token of the \grammarterm{pp-module}) \tcode{export} is an identifier defined as an object-like macro. +\pnum +The \grammarterm{pp-tokens}, if any, of a \grammarterm{pp-module} +shall be of the form: +\begin{ncsimplebnf} +pp-module-name \opt{pp-module-partition} \opt{pp-tokens} +\end{ncsimplebnf} +where the \grammarterm{pp-tokens} (if any) shall not begin with +a \tcode{(} preprocessing token and +the grammar non-terminals are defined as: +\begin{ncbnf} +\nontermdef{pp-module-name}\br + \opt{pp-module-name-qualifier} identifier +\end{ncbnf} +\begin{ncbnf} +\nontermdef{pp-module-partition}\br + \terminal{:} \opt{pp-module-name-qualifier} identifier +\end{ncbnf} +\begin{ncbnf} +\nontermdef{pp-module-name-qualifier}\br + identifier \terminal{.}\br + pp-module-name-qualifier identifier \terminal{.} +\end{ncbnf} +No \grammarterm{identifier} in +the \grammarterm{pp-module-name} or \grammarterm{pp-module-partition} +shall currently be defined as an object-like macro. + \pnum Any preprocessing tokens after the \tcode{module} preprocessing token in the \tcode{module} directive are processed just as in normal text. @@ -1624,14 +1650,20 @@ \indextext{\idxcode{\#error}|see{preprocessing directive, error}} \pnum -A preprocessing directive of either of the following forms +A preprocessing directive of the form +\begin{ncsimplebnf} +\terminal{\# error} \opt{pp-tokens} new-line +\end{ncsimplebnf} +renders the program ill-formed. +A preprocessing directive of the form \begin{ncsimplebnf} -\terminal{\# error} \opt{pp-tokens} new-line\br \terminal{\# warning} \opt{pp-tokens} new-line \end{ncsimplebnf} -causes the implementation to produce -a diagnostic message that should include the specified sequence of preprocessing tokens; -the \tcode{\# error} directive renders the program ill-formed. +requires the implementation to produce at least one diagnostic message +for the preprocessing translation unit\iref{intro.compliance.general}. +\recommended +Any diagnostic message caused by either of these directives +should include the specified sequence of preprocessing tokens. \rSec1[cpp.pragma]{Pragma directive}% \indextext{preprocessing directive!pragma}% @@ -1825,6 +1857,7 @@ \defnxname{cpp_decltype_auto} & \tcode{201304L} \\ \rowsep \defnxname{cpp_deduction_guides} & \tcode{201907L} \\ \rowsep \defnxname{cpp_delegating_constructors} & \tcode{200604L} \\ \rowsep +\defnxname{cpp_deleted_function} & \tcode{202403L} \\ \rowsep \defnxname{cpp_designated_initializers} & \tcode{201707L} \\ \rowsep \defnxname{cpp_enumerator_attributes} & \tcode{201411L} \\ \rowsep \defnxname{cpp_explicit_this_parameter} & \tcode{202110L} \\ \rowsep @@ -1862,7 +1895,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{201606L} \\ \rowsep +\defnxname{cpp_structured_bindings} & \tcode{202403L} \\ \rowsep \defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep \defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep \defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep @@ -1870,6 +1903,7 @@ \defnxname{cpp_user_defined_literals} & \tcode{200809L} \\ \rowsep \defnxname{cpp_using_enum} & \tcode{201907L} \\ \rowsep \defnxname{cpp_variable_templates} & \tcode{201304L} \\ \rowsep +\defnxname{cpp_variadic_friend} & \tcode{202403L} \\ \rowsep \defnxname{cpp_variadic_templates} & \tcode{200704L} \\ \rowsep \defnxname{cpp_variadic_using} & \tcode{201611L} \\ \end{LongTable} diff --git a/source/ranges.tex b/source/ranges.tex index b4af1f13d4..05147c3046 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -366,6 +366,13 @@ inline constexpr @\unspecnc@ split = @\unspecnc@; // freestanding } + // \ref{range.concat}, concat view + template<@\libconcept{input_range}@... Views> + requires @\seebelow@ + class concat_view; + + namespace views { inline constexpr @\unspecnc@ concat = @\unspecnc@; } + // \ref{range.counted}, counted view namespace views { inline constexpr @\unspecnc@ counted = @\unspecnc@; } // freestanding @@ -2248,25 +2255,33 @@ \end{codeblock} \pnum -Let \exposid{container-insertable} be defined as follows: +Let \exposid{container-appendable} be defined as follows: \begin{codeblock} template -constexpr bool @\exposid{container-insertable}@ = // \expos +constexpr bool @\exposid{container-appendable}@ = // \expos requires(Container& c, Ref&& ref) { - requires (requires { c.push_back(std::forward(ref)); } || + requires (requires { c.emplace_back(std::forward(ref)); } || + requires { c.push_back(std::forward(ref)); } || + requires { c.emplace(c.end(), std::forward(ref)); } || requires { c.insert(c.end(), std::forward(ref)); }); }; \end{codeblock} \pnum -Let \exposid{container-inserter} be defined as follows: +Let \exposid{container-appendable} be defined as follows: \begin{codeblock} template -constexpr auto @\exposid{container-inserter}@(Container& c) { // \expos - if constexpr (requires { c.push_back(declval()); }) - return back_inserter(c); - else - return inserter(c, c.end()); +constexpr auto @\exposid{container-appendable}@(Container& c) { // \expos + return [&c](Ref&& ref) { + if constexpr (requires { c.emplace_back(declval()); }) + c.emplace_back(std::forward(ref)); + else if constexpr (requires { c.push_back(declval()); }) + c.push_back(std::forward(ref)); + else if constexpr (requires { c.emplace(c.end(), declval()); }) + c.emplace(c.end(), std::forward(ref)); + else + c.insert(c.end(), std::forward(ref)); + }; } \end{codeblock} @@ -2328,13 +2343,13 @@ \item \tcode{\libconcept{constructible_from}} is \tcode{true}, and \item -\tcode{\exposid{container-insertable}>} is \tcode{true}: +\tcode{\exposid{container-appendable}>} is \tcode{true}: \end{itemize} \begin{codeblock} C c(std::forward(args)...); if constexpr (@\libconcept{sized_range}@ && @\exposid{reservable-container}@) c.reserve(static_cast>(ranges::size(r))); -ranges::copy(r, @\exposid{container-inserter}@>(c)); +ranges::for_each(r, @\exposid{container-append}@(c)); \end{codeblock} \item Otherwise, the program is ill-formed. @@ -2344,7 +2359,7 @@ Otherwise, if \tcode{\libconcept{input_range}>} is \tcode{true}: \begin{codeblock} -to(r | views::transform([](auto&& elem) { +to(ref_view(r) | views::transform([](auto&& elem) { return to>(std::forward(elem)); }), std::forward(args)...); \end{codeblock} @@ -2533,6 +2548,7 @@ constexpr const T* begin() const noexcept; constexpr T* end() noexcept; constexpr const T* end() const noexcept; + static constexpr bool empty() noexcept; static constexpr size_t size() noexcept; constexpr T* data() noexcept; constexpr const T* data() const noexcept; @@ -2603,6 +2619,17 @@ Equivalent to: \tcode{return data() + 1;} \end{itemdescr} +\indexlibrarymember{empty}{single_view}% +\begin{itemdecl} +static constexpr bool empty() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return false;} +\end{itemdescr} + \indexlibrarymember{size}{single_view}% \begin{itemdecl} static constexpr size_t size() noexcept; @@ -3406,7 +3433,7 @@ Given subexpressions \tcode{E} and \tcode{F}, the expressions \tcode{views::repeat(E)} and \tcode{views::repeat(E, F)} are expression-equivalent to -\tcode{repeat_view(E)} and \tcode{repeat_view(E, F)}, respectively. +\tcode{repeat_view>(E)} and \tcode{repeat_view(E, F)}, respectively. \pnum \begin{example} @@ -3456,8 +3483,8 @@ constexpr auto size() const requires (!@\libconcept{same_as}@); }; - template - repeat_view(T, Bound) -> repeat_view; + template + repeat_view(T, Bound = Bound()) -> repeat_view; } \end{codeblock} @@ -4311,6 +4338,17 @@ constexpr T& @\exposid{as-lvalue}@(T&& t) { // \expos return static_cast(t); } + + template + concept @\defexposconceptnc{all-random-access}@ = // \expos + (@\libconcept{random_access_range}@<@\exposid{maybe-const}@> && ...); + template + concept @\defexposconceptnc{all-bidirectional}@ = // \expos + (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@> && ...); + template + concept @\defexposconceptnc{all-forward}@ = // \expos + (@\libconcept{forward_range}@<@\exposid{maybe-const}@> && ...); + } \end{codeblock} @@ -6171,7 +6209,7 @@ \item Otherwise, if \tcode{T} is -a specialization of \tcode{subrange}\iref{range.subrange} +a specialization of \tcode{subrange} that models \libconcept{random_access_range} and \libconcept{sized_range}, then \tcode{T(ranges::begin(E) + std::min(ranges::distance(E), F), ranges::\linebreak{}end(E), @@ -7909,10 +7947,9 @@ private: @\exposid{outer-iterator}@ @\exposid{i_}@ = @\exposid{outer-iterator}@(); // \expos - public: - value_type() = default; - constexpr explicit value_type(@\exposid{outer-iterator}@ i); + constexpr explicit value_type(@\exposid{outer-iterator}@ i); // \expos + public: constexpr @\exposid{inner-iterator}@ begin() const; constexpr default_sentinel_t end() const noexcept; }; @@ -8433,242 +8470,1253 @@ Equivalent to: \tcode{return x.\exposid{cur_} == y.\exposid{end_} \&\& !x.\exposid{trailing_empty_};} \end{itemdescr} -\rSec2[range.counted]{Counted view} - -\pnum -\indextext{range!counted}% -A counted view presents a view of the elements -of the counted range\iref{iterator.requirements.general} \countedrange{i}{n} -for an iterator \tcode{i} and non-negative integer \tcode{n}. - -\pnum -\indexlibrarymember{counted}{views}% -The name \tcode{views::counted} denotes -a customization point object\iref{customization.point.object}. -Let \tcode{E} and \tcode{F} be expressions, -let \tcode{T} be \tcode{decay_t}, and -let \tcode{D} be \tcode{iter_difference_t}. -If \tcode{decltype((F))} does not model -\tcode{\libconcept{convertible_to}}, -\tcode{views::counted(E, F)} is ill-formed. -\begin{note} -This case can result in substitution failure -when \tcode{views::counted(E, F)} -appears in the immediate context of a template instantiation. -\end{note} -Otherwise, \tcode{views::counted(E, F)} -is expression-equivalent to: - -\begin{itemize} -\item -If \tcode{T} models \libconcept{contiguous_iterator}, -then \tcode{span(to_address(E), static_cast(static_-\linebreak{}cast(F)))}. - -\item -Otherwise, if \tcode{T} models \libconcept{random_access_iterator}, -then \tcode{subrange(E, E + static_cast(F))}, -except that \tcode{E} is evaluated only once. - -\item -Otherwise, -\tcode{subrange(counted_iterator(E, F), default_sentinel)}. -\end{itemize} - -\rSec2[range.common]{Common view} - -\rSec3[range.common.overview]{Overview} +\rSec2[range.concat]{Concat view} -\pnum -\tcode{common_view} takes a view which has different types for -its iterator and sentinel and turns it into a view of the same -elements with an iterator and sentinel of the same type. +\rSec3[range.concat.overview]{Overview} \pnum -\begin{note} -\tcode{common_view} is useful for calling legacy algorithms that expect -a range's iterator and sentinel types to be the same. -\end{note} +\tcode{concat_view} presents a view that concatenates all the underlying ranges. \pnum -\indexlibrarymember{common}{views}% -The name \tcode{views::common} denotes a -range adaptor object\iref{range.adaptor.object}. -Given a subexpression \tcode{E}, -the expression \tcode{views::common(E)} is expression-equivalent to: +The name \tcode{views::concat} denotes +a customization point object\iref{customization.point.object}. +Given a pack of subexpressions \tcode{Es...}, +the expression \tcode{views::concat(Es...)} is expression-equivalent to \begin{itemize} -\item \tcode{views::all(E)}, - if \tcode{decltype((E))} models \libconcept{common_range} - and \tcode{views::all(E)} is a well-formed expression. - -\item Otherwise, \tcode{common_view\{E\}}. +\item \tcode{views::all(Es...)} if \tcode{Es} is a pack with only one element, +\item otherwise, \tcode{concat_view(Es...)}. \end{itemize} - -\pnum \begin{example} \begin{codeblock} -// Legacy algorithm: -template -size_t count(ForwardIterator first, ForwardIterator last); - -template<@\libconcept{forward_range}@ R> -void my_algo(R&& r) { - auto&& common = views::common(r); - auto cnt = count(common.begin(), common.end()); - // ... +std::vector v1{1, 2, 3}, v2{4, 5}, v3{}; +std::array a{6, 7, 8}; +auto s = std::views::single(9); +for (auto&& i : std::views::concat(v1, v2, v3, a, s)) { + std::print("{} ", i); // prints \tcode{1 2 3 4 5 6 7 8 9} } \end{codeblock} \end{example} -\rSec3[range.common.view]{Class template \tcode{common_view}} +\rSec3[range.concat.view]{Class template \tcode{concat_view}} -\indexlibraryglobal{common_view}% -\indexlibrarymember{base}{common_view}% -\indexlibrarymember{size}{common_view}% -\indexlibrarymember{begin}{common_view}% -\indexlibrarymember{end}{common_view}% +\indexlibraryglobal{concat_view}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{view}@ V> - requires (!@\libconcept{common_range}@ && @\libconcept{copyable}@>) - class common_view : public view_interface> { - private: - V @\exposid{base_}@ = V(); // \expos + template + using @\exposidnc{concat-reference-t}@ = common_reference_t...>; // \expos + template + using @\exposidnc{concat-value-t}@ = common_type_t...>; // \expos + template + using @\exposidnc{concat-rvalue-reference-t}@ = // \expos + common_reference_t...>; - public: - common_view() requires @\libconcept{default_initializable}@ = default; + template + concept @\exposconcept{concat-indirectly-readable}@ = @\seebelow@; // \expos + template + concept @\exposconcept{concatable}@ = @\seebelow@; // \expos + template + concept @\exposconcept{concat-is-random-access}@ = @\seebelow@; // \expos + template + concept @\exposconcept{concat-is-bidirectional}@ = @\seebelow@; // \expos - constexpr explicit common_view(V r); + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && + @\exposconcept{concatable}@ + class concat_view : public view_interface> { - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } + tuple @\exposidnc{views_}@; // \expos - constexpr auto begin() { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::begin(@\exposid{base_}@)); - } + // \ref{range.concat.iterator}, class template \tcode{concat_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos - constexpr auto begin() const requires @\libconcept{range}@ { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::begin(@\exposid{base_}@)); - } + public: + constexpr concat_view() = default; + constexpr explicit concat_view(Views... views); - constexpr auto end() { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@) + ranges::distance(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); - } + constexpr @\exposid{iterator}@ begin() requires(!(@\exposconcept{simple-view}@ && ...)); + constexpr @\exposid{iterator}@ begin() const + requires((@\libconcept{range}@ && ...) && @\exposconcept{concatable}@); - constexpr auto end() const requires @\libconcept{range}@ { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@) + ranges::distance(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); - } + constexpr auto end() requires(!(@\exposconcept{simple-view}@ && ...)); + constexpr auto end() const + requires((@\libconcept{range}@ && ...) && @\exposconcept{concatable}@); - constexpr auto size() requires @\libconcept{sized_range}@ { - return ranges::size(@\exposid{base_}@); - } - constexpr auto size() const requires @\libconcept{sized_range}@ { - return ranges::size(@\exposid{base_}@); - } + constexpr auto size() requires(@\libconcept{sized_range}@&&...); + constexpr auto size() const requires(@\libconcept{sized_range}@&&...); }; - template - common_view(R&&) -> common_view>; + template + concat_view(R&&...) -> concat_view...>; } \end{codeblock} -\indexlibraryctor{common_view}% \begin{itemdecl} -constexpr explicit common_view(V base); +template + concept @\defexposconcept{concat-indirectly-readable}@ = @\seebelow@; // \expos \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{base_} with \tcode{std::move(base)}. -\end{itemdescr} - -\rSec2[range.reverse]{Reverse view} +The exposition-only \exposconcept{concat-indirectly-readable} concept +is equivalent to: +\begin{codeblock} +template + concept @\defexposconcept{concat-indirectly-readable-impl}@ = // \expos + requires (const It it) { + { *it } -> @\libconcept{convertible_to}@; + { ranges::iter_move(it) } -> @\libconcept{convertible_to}@; + }; -\rSec3[range.reverse.overview]{Overview} +template + concept @\exposconcept{concat-indirectly-readable}@ = // \expos + @\libconcept{common_reference_with}@<@\exposid{concat-reference-t}@&&, + @\exposid{concat-value-t}@&> && + @\libconcept{common_reference_with}@<@\exposid{concat-reference-t}@&&, + @\exposid{concat-rvalue-reference-t}@&&> && + @\libconcept{common_reference_with}@<@\exposid{concat-rvalue-reference-t}@&&, + @\exposid{concat-value-t}@ const&> && + (@\exposconcept{concat-indirectly-readable-impl}@<@\exposid{concat-reference-t}@, + @\exposid{concat-rvalue-reference-t}@, + iterator_t> && ...); +\end{codeblock} +\end{itemdescr} -\pnum -\tcode{reverse_view} takes a bidirectional view and produces -another view that iterates the same elements in reverse order. +\begin{itemdecl} +template + concept @\defexposconcept{concatable}@ = @\seebelow@; // \expos +\end{itemdecl} +\begin{itemdescr} \pnum -\indexlibrarymember{reverse}{views}% -The name \tcode{views::reverse} denotes a -range adaptor object\iref{range.adaptor.object}. -Given a subexpression \tcode{E}, the expression -\tcode{views::reverse(E)} is expression-equivalent to: -\begin{itemize} -\item - If the type of \tcode{E} is - a (possibly cv-qualified) specialization of \tcode{reverse_view}, - equivalent to \tcode{E.base()}. -\item - Otherwise, if the type of \tcode{E} is \cv{} \tcode{subrange, reverse_iterator, K>} - for some iterator type \tcode{I} and - value \tcode{K} of type \tcode{subrange_kind}, - \begin{itemize} - \item - if \tcode{K} is \tcode{subrange_kind::sized}, equivalent to: -\begin{codeblock} -subrange(E.end().base(), E.begin().base(), E.size()) -\end{codeblock} - \item - otherwise, equivalent to: +The exposition-only \exposconcept{concatable} concept is equivalent to: \begin{codeblock} -subrange(E.end().base(), E.begin().base()) +template + concept @\exposconcept{concatable}@ = requires { // \expos + typename @\exposid{concat-reference-t}@; + typename @\exposid{concat-value-t}@; + typename @\exposid{concat-rvalue-reference-t}@; + } && @\exposconcept{concat-indirectly-readable}@; \end{codeblock} - \end{itemize} - However, in either case \tcode{E} is evaluated only once. -\item - Otherwise, equivalent to \tcode{reverse_view\{E\}}. -\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + concept @\defexposconcept{concat-is-random-access}@ = @\seebelow@; // \expos +\end{itemdecl} +\begin{itemdescr} \pnum -\begin{example} +Let \tcode{Fs} be the pack that consists of all elements of \tcode{Rs} +except the last element, +then \exposconceptx{concat-is-ran\-dom-access}{concat-is-random-access} +is equivalent to: \begin{codeblock} -vector is {0,1,2,3,4}; -for (int i : is | views::reverse) - cout << i << ' '; // prints \tcode{4 3 2 1 0} +template + concept @\exposconcept{concat-is-random-access}@ = // \expos + @\exposconcept{all-random-access}@ && + (@\libconcept{common_range}@<@\exposid{maybe-const}@> && ...); \end{codeblock} -\end{example} +\end{itemdescr} -\rSec3[range.reverse.view]{Class template \tcode{reverse_view}} +\begin{itemdecl} +template + concept @\defexposconcept{concat-is-bidirectional}@ = @\seebelow@; // \expos +\end{itemdecl} -\indexlibraryglobal{reverse_view}% -\indexlibrarymember{base}{reverse_view}% -\indexlibrarymember{size}{reverse_view}% +\begin{itemdescr} +\pnum +Let \tcode{Fs} be the pack that consists of all elements of \tcode{Rs} +except the last element, +then \exposconceptx{concat-is-bidirec\-tional}{concat-is-bidirectional} +is equivalent to: \begin{codeblock} -namespace std::ranges { - template<@\libconcept{view}@ V> - requires @\libconcept{bidirectional_range}@ - class reverse_view : public view_interface> { - private: - V @\exposid{base_}@ = V(); // \expos +template + concept @\exposconcept{concat-is-bidirectional}@ = // \expos + @\exposconcept{all-bidirectional}@ && + (@\libconcept{common_range}@<@\exposid{maybe-const}@> && ...); +\end{codeblock} +\end{itemdescr} - public: - reverse_view() requires @\libconcept{default_initializable}@ = default; +\indexlibraryctor{concat_view}% +\begin{itemdecl} +constexpr explicit concat_view(Views... views); +\end{itemdecl} - constexpr explicit reverse_view(V r); +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{views_} with \tcode{std::move(views)...}. +\end{itemdescr} - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } +\indexlibrarymember{begin}{concat_view}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ begin() requires(!(@\exposconcept{simple-view}@ && ...)); +constexpr @\exposid{iterator}@ begin() const + requires((@\libconcept{range}@ && ...) && @\exposconcept{concatable}@); +\end{itemdecl} - constexpr reverse_iterator> begin(); - constexpr reverse_iterator> begin() requires @\libconcept{common_range}@; - constexpr auto begin() const requires @\libconcept{common_range}@; +\begin{itemdescr} +\pnum +\effects +Let \tcode{is-const} be +\tcode{true} for the const-qualified overload, and +\tcode{false} otherwise. +Equivalent to: +\begin{codeblock} +@\exposid{iterator}@ it(this, in_place_index<0>, ranges::begin(std::get<0>(@\exposid{views_}@))); +it.template @\exposid{satisfy}@<0>(); +return it; +\end{codeblock} +\end{itemdescr} - constexpr reverse_iterator> end(); +\indexlibrarymember{end}{concat_view}% +\begin{itemdecl} +constexpr auto end() requires(!(@\exposconcept{simple-view}@ && ...)); +constexpr auto end() const + requires((@\libconcept{range}@ && ...) && @\exposconcept{concatable}@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{is-const} be +\tcode{true} for the const-qualified overload, and +\tcode{false} otherwise. +Equivalent to: +\begin{codeblock} +constexpr auto N = sizeof...(Views); +if constexpr (@\libconcept{common_range}@<@\exposid{maybe-const}@>) { + return @\exposid{iterator}@(this, in_place_index, + ranges::end(std::get(@\exposid{views_}@))); +} else { + return default_sentinel; +} +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{size}{concat_view}% +\begin{itemdecl} +constexpr auto size() requires(@\libconcept{sized_range}@&&...); +constexpr auto size() const requires(@\libconcept{sized_range}@&&...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply( + [](auto... sizes) { + using CT = make-unsigned-like-t>; + return (CT(sizes) + ...); + }, + tuple-transform(ranges::size, @\exposid{views_}@)); +\end{codeblock} +\end{itemdescr} + +\rSec3[range.concat.iterator]{Class \tcode{concat_view::\exposid{iterator}}} + +\indexlibrarymember{iterator}{concat_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && + @\exposconcept{concatable}@ + template + class concat_view::@\exposid{iterator}@ { + + public: + using iterator_category = @\seebelow@; // not always present. + using iterator_concept = @\seebelow@; + using value_type = @\exposid{concat-value-t}@<@\exposid{maybe-const}@...>; + using difference_type = common_type_t>...>; + + private: + using @\exposid{base-iter}@ = // \expos + variant>...>; + + @\exposid{maybe-const}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposid{base-iter}@ @\exposid{it_}@; // \expos + + template + constexpr void @\exposid{satisfy}@(); // \expos + template + constexpr void @\exposid{prev}@(); // \expos + + template + constexpr void @\exposid{advance-fwd}@(difference_type offset, // \expos + difference_type steps); + template + constexpr void @\exposid{advance-bwd}@(difference_type offset, // \expos + difference_type steps); + + template + constexpr explicit @\exposid{iterator}@(@\exposid{maybe-const}@* parent, // \expos + Args&&... args) + requires @\libconcept{constructible_from}@<@\exposid{base-iter}@, Args&&...>; + + public: + @\exposid{iterator}@() = default; + + constexpr @\exposid{iterator}@(iterator i) + requires Const && (@\libconcept{convertible_to}@, iterator_t> && ...); + + constexpr decltype(auto) operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); + constexpr @\exposid{iterator}@ operator++(int) + requires @\exposconcept{all-forward}@; + constexpr @\exposid{iterator}@& operator--() + requires @\exposconcept{concat-is-bidirectional}@; + constexpr @\exposid{iterator}@ operator--(int) + requires @\exposconcept{concat-is-bidirectional}@; + constexpr @\exposid{iterator}@& operator+=(difference_type n) + requires @\exposconcept{concat-is-random-access}@; + constexpr @\exposid{iterator}@& operator-=(difference_type n) + requires @\exposconcept{concat-is-random-access}@; + constexpr decltype(auto) operator[](difference_type n) const + requires @\exposconcept{concat-is-random-access}@; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires(@\libconcept{equality_comparable}@>>&&...); + friend constexpr bool operator==(const @\exposid{iterator}@& it, default_sentinel_t); + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\exposconcept{all-random-access}@ && + (@\libconcept{three_way_comparable}@>> && ...)); + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& it, difference_type n) + requires @\exposconcept{concat-is-random-access}@; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& it) + requires @\exposconcept{concat-is-random-access}@; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& it, difference_type n) + requires @\exposconcept{concat-is-random-access}@; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{concat-is-random-access}@; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t) + requires @\seebelow@; + friend constexpr difference_type operator-(default_sentinel_t, const @\exposid{iterator}@& x) + requires @\seebelow@; + friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& it) noexcept(@\seebelow@); + friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept(@\seebelow@) + requires @\seebelow@; + }; +} +\end{codeblock} + +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If +\tcode{\exposconcept{concat-is-random-access}} is modeled, +then \tcode{iterator_concept} denotes \tcode{ran\-dom_access_iterator_tag}. +\item +Otherwise, if +\tcode{\exposconcept{concat-is-bidirectional}} is modeled, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, if +\tcode{\exposconcept{all-forward}} is modeled, +then \tcode{iterator_concept} denotes \tcode{for\-ward_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. +\end{itemize} + +\pnum +The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +if and only if +\tcode{\exposconcept{all-forward}} is modeled. +In that case, +\tcode{\exposid{iterator}::iterator_category} is defined as follows: + +\begin{itemize} +\item +If +\tcode{is_reference_v<\exposid{concat-reference-t}<@\exposid{maybe-const}@...>>} +is \tcode{false}, +then \tcode{it\-erator_category} denotes \tcode{input_iterator_tag}. + +\item +Otherwise, +let \tcode{Cs} denote the pack of types +\tcode{iterator_traits>>::iterator_category...}. +\begin{itemize} +\item +If +\tcode{(\libconcept{derived_from} \&\& ...) \&\& \exposconceptx{concat-is-random-ac-\linebreak{}cess}{concat-is-random-access}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, if +\tcode{(\libconcept{derived_from} \&\& ...) \&\& \exposconceptx{concat-is--\linebreak{}bidirectional}{concat-is-bidirectional}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{bidirectional_iter\-ator_tag}. +\item +Otherwise, if +\tcode{(\libconcept{derived_from} \&\& ...)} +is \tcode{true}, +\tcode{iterator_cate\-gory} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\end{itemize} +\end{itemize} + +\indexlibrarymember{\exposid{satisfy}}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +template + constexpr void @\exposid{satisfy}@(); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if constexpr (N < (sizeof...(Views) - 1)) { + if (std::get(@\exposid{it_}@) == ranges::end(std::get(@\exposid{parent_}@->@\exposid{views_}@))) { + @\exposid{it_}@.template emplace(ranges::begin(std::get(@\exposid{parent_}@->@\exposid{views_}@))); + @\exposid{satisfy}@(); + } +} +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{\exposid{prev}}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +template + constexpr void @\exposid{prev}@(); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if constexpr (N == 0) { + --std::get<0>(@\exposid{it_}@); +} else { + if (std::get(@\exposid{it_}@) == ranges::begin(std::get(@\exposid{parent_}@->@\exposid{views_}@))) { + @\exposid{it_}@.template emplace(ranges::end(std::get(@\exposid{parent_}@->@\exposid{views_}@))); + @\exposid{prev}@(); + } else { + --std::get(@\exposid{it_}@); + } +} +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{\exposid{advance-fwd}}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +template + constexpr void @\exposid{advance-fwd}@(difference_type offset, difference_type steps); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +using underlying_diff_type = iter_difference_t>; +if constexpr (N == sizeof...(Views) - 1) { + std::get(@\exposid{it_}@) += static_cast(steps); +} else { + auto n_size = ranges::distance(std::get(@\exposid{parent_}@->@\exposid{views_}@)); + if (offset + steps < n_size) { + std::get(@\exposid{it_}@) += static_cast(steps); + } else { + @\exposid{it_}@.template emplace(ranges::begin(std::get(@\exposid{parent_}@->@\exposid{views_}@))); + @\exposid{advance-fwd}@(0, offset + steps - n_size); + } +} +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{\exposid{advance-bwd}}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +template + constexpr void @\exposid{advance-bwd}@(difference_type offset, difference_type steps); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +using underlying_diff_type = iter_difference_t>; +if constexpr (N == 0) { + std::get(@\exposid{it_}@) -= static_cast(steps); +} else { + if (offset >= steps) { + std::get(@\exposid{it_}@) -= static_cast(steps); + } else { + auto prev_size = ranges::distance(std::get(@\exposid{parent_}@->@\exposid{views_}@)); + @\exposid{it_}@.template emplace(ranges::end(std::get(@\exposid{parent_}@->@\exposid{views_}@))); + @\exposid{advance-bwd}@(prev_size, steps - offset); + } +} +\end{codeblock} +\end{itemdescr} + +\indexlibraryctor{concat_view::\exposid{iterator}}% +\begin{itemdecl} +template + constexpr explicit @\exposid{iterator}@(@\exposid{maybe-const}@* parent, // \expos + Args&&... args) + requires @\libconcept{constructible_from}@<@\exposid{base-iter}@, Args&&...>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{parent}, and +initializes \exposid{it_} with \tcode{std::forward(args)...}. +\end{itemdescr} + +\indexlibraryctor{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ it) + requires Const && + (@\libconcept{convertible_to}@, iterator_t> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{it.\exposid{parent_}}, and +let \tcode{$i$} be \tcode{it.\exposid{it_}.index()}, +initializes \exposid{it_} with +\tcode{\exposid{base-iter}(in_place_index<$i$>, std::get<$i$>(std::move(it.\exposid{it_})))}. +\end{itemdescr} + +\indexlibrarymember{operator*}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr decltype(auto) operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +using reference = @\exposid{concat-reference-t}@<@\exposid{maybe-const}@...>; +return std::visit([](auto&& it) -> reference { return *it; }, + @\exposid{it_}@); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\exposid{it_}.valueless_by_exception() is \tcode{false}. + +\pnum +\effects +Let \tcode{$i$} be \tcode{\exposid{it_}.index()}. +Equivalent to: +\begin{codeblock} +++std::get<@$i$@>(@\exposid{it_}@); +@\exposid{satisfy}@<@$i$@>(); +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +++*this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int) + requires @\exposconcept{all-forward}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() + requires @\exposconcept{concat-is-bidirectional}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +Let \tcode{$i$} be \tcode{\exposid{it_}.index()}. +Equivalent to: +\begin{codeblock} +@\exposid{prev}@<@$i$@>(); +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) + requires @\exposconcept{concat-is-bidirectional}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+=}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type n) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\exposid{it_}.valueless_by_exception() is \tcode{false}. + +\pnum +\effects +Let \tcode{$i$} be \tcode{\exposid{it_}.index()}. +Equivalent to: +\begin{codeblock} +if (n > 0) { + @\exposid{advance-fwd}@<@$i$@>(std::get<@$i$@>(@\exposid{it_}@) - ranges::begin(std::get<@$i$@>(@\exposid{parent_}@->@\exposid{views_}@)), n); +} else if (n < 0) { + @\exposid{advance-bwd}@<@$i$@>(std::get<@$i$@>(@\exposid{it_}@) - ranges::begin(std::get<@$i$@>(@\exposid{parent_}@->@\exposid{views_}@)), -n); +} +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-=}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type n) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +*this += -n; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator[]}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr decltype(auto) operator[](difference_type n) const + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return *((*this) + n); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator==}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires(@\libconcept{equality_comparable}@>>&&...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x.\exposid{it_}.valueless_by_exception()} and +\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return x.@\exposid{it_}@ == y.@\exposid{it_}@; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator==}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& it, default_sentinel_t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{it.\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +constexpr auto last_idx = sizeof...(Views) - 1; +return it.@\exposid{it_}@.index() == last_idx && + std::get(it.@\exposid{it_}@) == ranges::end(std::get(it.@\exposid{parent_}@->@\exposid{views_}@)); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator<}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\exposconcept{all-random-access}@ && + (@\libconcept{three_way_comparable}@>> && ...)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x.\exposid{it_}.valueless_by_exception()} and +\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}. + +\pnum +Let \tcode{$op$} be the operator. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return x.@\exposid{it_}@ @$op$@ y.@\exposid{it_}@; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& it, difference_type n) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = it; +temp += n; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& it) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return it + n; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& it, difference_type n) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = it; +temp -= n; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x.\exposid{it_}.valueless_by_exception()} and +\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}. + +\pnum +\effects +Let +\tcode{$i_\tcode{x}$} denote \tcode{x.\exposid{it_}.index()} and +\tcode{$i_\tcode{y}$} denote \tcode{y.\exposid{it_}.index()}. + +\begin{itemize} +\item +%FIXME This is hard to parse. +If \tcode{$i_\tcode{x}$ > $i_\tcode{y}$}, let +\tcode{$d_\tcode{y}$} be +\tcode{ranges::distance(std::get<$i_\tcode{y}$>(y.\exposid{it_}), ranges::end(std::get<$i_\tcode{y}$>(y.\linebreak{}\exposid{parent_}->\exposid{views_})))}, +\tcode{$d_\tcode{x}$} be +\tcode{ranges::distance(ranges::begin(std::get<$i_\tcode{x}$>(x.\exposid{parent_}->\linebreak{}\exposid{views_})), std::get<$i_\tcode{x}$>(x.\exposid{it_}))}. +Let \tcode{$s$} denote the sum of the sizes of all the ranges +\tcode{std::get<\linebreak{}$i$>(x.\exposid{parent_}->\exposid{views_})} +for every integer \tcode{$i$} in the range +\range{$i_\tcode{y}$ + 1}{$i_\tcode{x}$} +if there is any, and +\tcode{0} otherwise, +of type difference_type, +equivalent to: +\begin{codeblock} +return @$d_\tcode{y}$@ + @$s$@ + @$d_\tcode{x}$@; +\end{codeblock} + +\item +otherwise, if \tcode{$i_\tcode{x}$ < $i_\tcode{y}$} is \tcode{true}, +equivalent to: +\begin{codeblock} +return -(y - x); +\end{codeblock} + +\item +otherwise, equivalent to: +\begin{codeblock} +return std::get<@$i_\tcode{x}$@>(x.@\exposid{it_}@) - std::get<@$i_\tcode{y}$@>(y.@\exposid{it_}@); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t) + requires @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x.\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +%FIXME This is hard to parse. +Let +\tcode{$i_\tcode{x}$} denote \tcode{x.\exposid{it_}.index()}, +\tcode{$d_\tcode{x}$} be +\tcode{ranges::distance(std::get<$i_\tcode{x}$>(x.\exposid{it_}), ranges::\linebreak{}end(std::get<$i_\tcode{x}$>(x.\exposid{parent_}->\exposid{views_})))}. +Let \tcode{$s$} denote the sum of the sizes of all the ranges +\tcode{std::get<$i$>(x.\exposid{parent_}->\exposid{views_})} +for every integer \tcode{$i$} in the range +\range{$i_\tcode{x}$ + 1}{sizeof...(Views)} +if there is any, and +\tcode{0} otherwise, +of type difference_type, +equivalent to: +\begin{codeblock} +return -(@$d_\tcode{x}$@ + @$s$@); +\end{codeblock} + +\pnum +\remarks +Let \tcode{Fs} be the pack that consists of all elements of \tcode{Views} +except the first element, +%FIXME Do we want \grammarterm{expression} here? Same elsewhere? +the expression in the \grammarterm{requires-clause} is equivalent to: +\begin{codeblock} +(@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) && +(@\libconcept{sized_range}@<@\exposid{maybe-const}@> && ...) +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr difference_type operator-(default_sentinel_t, const @\exposid{iterator}@& x) + requires @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return -(x - default_sentinel); +\end{codeblock} + +\pnum +\remarks +Let \tcode{Fs} be the pack that consists of all elements of \tcode{Views} +except the first element, +the expression in the \grammarterm{requires-clause} is equivalent to: +\begin{codeblock} +(@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) && +(@\libconcept{sized_range}@<@\exposid{maybe-const}@> && ...) +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{iter_move}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& it) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{it.\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return std::visit([](const auto& i) + -> @\exposid{concat-rvalue-reference-t}@<@\exposid{maybe-const}@...> { + return ranges::iter_move(i); + }, + it.@\exposid{it_}@); +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to: +\begin{codeblock} +((is_nothrow_invocable_v>&> && + is_nothrow_convertible_v>, + @\exposid{concat-rvalue-reference-t}@<@\exposid{maybe-const}@...>>) && + ...) +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{iter_swap}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept(@\seebelow@) + requires @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x.\exposid{it_}.valueless_by_exception()} and +\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +std::visit([&](const auto& it1, const auto& it2) { + if constexpr (is_same_v) { + ranges::iter_swap(it1, it2); + } else { + ranges::swap(*x, *y); + } + }, + x.@\exposid{it_}@, y.@\exposid{it_}@); +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to +\begin{codeblock} +(noexcept(ranges::swap(*x, *y)) && ... && noexcept(ranges::iter_swap(its, its))) +\end{codeblock} +where \tcode{its} is a pack of lvalues of type +%FIXME "respectively" doesn't make sense here. +\tcode{const iterator_t<@\exposid{maybe-const}@>} respectively. + +\par % This paragraph is part of the \remarks clause. +The expression in the \grammarterm{requires-clause} is equivalent to +\begin{codeblock} +swappable_with, iter_reference_t> && +(... && indirectly_swappable>>) +\end{codeblock} +\end{itemdescr} + +\rSec2[range.counted]{Counted view} + +\pnum +\indextext{range!counted}% +A counted view presents a view of the elements +of the counted range\iref{iterator.requirements.general} \countedrange{i}{n} +for an iterator \tcode{i} and non-negative integer \tcode{n}. + +\pnum +\indexlibrarymember{counted}{views}% +The name \tcode{views::counted} denotes +a customization point object\iref{customization.point.object}. +Let \tcode{E} and \tcode{F} be expressions, +let \tcode{T} be \tcode{decay_t}, and +let \tcode{D} be \tcode{iter_difference_t}. +If \tcode{decltype((F))} does not model +\tcode{\libconcept{convertible_to}}, +\tcode{views::counted(E, F)} is ill-formed. +\begin{note} +This case can result in substitution failure +when \tcode{views::counted(E, F)} +appears in the immediate context of a template instantiation. +\end{note} +Otherwise, \tcode{views::counted(E, F)} +is expression-equivalent to: + +\begin{itemize} +\item +If \tcode{T} models \libconcept{contiguous_iterator}, +then \tcode{span(to_address(E), static_cast(static_-\linebreak{}cast(F)))}. + +\item +Otherwise, if \tcode{T} models \libconcept{random_access_iterator}, +then \tcode{subrange(E, E + static_cast(F))}, +except that \tcode{E} is evaluated only once. + +\item +Otherwise, +\tcode{subrange(counted_iterator(E, F), default_sentinel)}. +\end{itemize} + +\rSec2[range.common]{Common view} + +\rSec3[range.common.overview]{Overview} + +\pnum +\tcode{common_view} takes a view which has different types for +its iterator and sentinel and turns it into a view of the same +elements with an iterator and sentinel of the same type. + +\pnum +\begin{note} +\tcode{common_view} is useful for calling legacy algorithms that expect +a range's iterator and sentinel types to be the same. +\end{note} + +\pnum +\indexlibrarymember{common}{views}% +The name \tcode{views::common} denotes a +range adaptor object\iref{range.adaptor.object}. +Given a subexpression \tcode{E}, +the expression \tcode{views::common(E)} is expression-equivalent to: +\begin{itemize} +\item \tcode{views::all(E)}, + if \tcode{decltype((E))} models \libconcept{common_range} + and \tcode{views::all(E)} is a well-formed expression. + +\item Otherwise, \tcode{common_view\{E\}}. +\end{itemize} + +\pnum +\begin{example} +\begin{codeblock} +// Legacy algorithm: +template +size_t count(ForwardIterator first, ForwardIterator last); + +template<@\libconcept{forward_range}@ R> +void my_algo(R&& r) { + auto&& common = views::common(r); + auto cnt = count(common.begin(), common.end()); + // ... +} +\end{codeblock} +\end{example} + +\rSec3[range.common.view]{Class template \tcode{common_view}} + +\indexlibraryglobal{common_view}% +\indexlibrarymember{base}{common_view}% +\indexlibrarymember{size}{common_view}% +\indexlibrarymember{begin}{common_view}% +\indexlibrarymember{end}{common_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires (!@\libconcept{common_range}@ && @\libconcept{copyable}@>) + class common_view : public view_interface> { + private: + V @\exposid{base_}@ = V(); // \expos + + public: + common_view() requires @\libconcept{default_initializable}@ = default; + + constexpr explicit common_view(V r); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr auto begin() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) + return ranges::begin(@\exposid{base_}@); + else + return common_iterator, sentinel_t>(ranges::begin(@\exposid{base_}@)); + } + + constexpr auto begin() const requires @\libconcept{range}@ { + if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) + return ranges::begin(@\exposid{base_}@); + else + return common_iterator, sentinel_t>(ranges::begin(@\exposid{base_}@)); + } + + constexpr auto end() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) + return ranges::begin(@\exposid{base_}@) + ranges::distance(@\exposid{base_}@); + else + return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); + } + + constexpr auto end() const requires @\libconcept{range}@ { + if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) + return ranges::begin(@\exposid{base_}@) + ranges::distance(@\exposid{base_}@); + else + return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); + } + + constexpr auto size() requires @\libconcept{sized_range}@ { + return ranges::size(@\exposid{base_}@); + } + constexpr auto size() const requires @\libconcept{sized_range}@ { + return ranges::size(@\exposid{base_}@); + } + }; + + template + common_view(R&&) -> common_view>; +} +\end{codeblock} + +\indexlibraryctor{common_view}% +\begin{itemdecl} +constexpr explicit common_view(V base); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. +\end{itemdescr} + +\rSec2[range.reverse]{Reverse view} + +\rSec3[range.reverse.overview]{Overview} + +\pnum +\tcode{reverse_view} takes a bidirectional view and produces +another view that iterates the same elements in reverse order. + +\pnum +\indexlibrarymember{reverse}{views}% +The name \tcode{views::reverse} denotes a +range adaptor object\iref{range.adaptor.object}. +Given a subexpression \tcode{E}, the expression +\tcode{views::reverse(E)} is expression-equivalent to: +\begin{itemize} +\item + If the type of \tcode{E} is + a (possibly cv-qualified) specialization of \tcode{reverse_view}, + equivalent to \tcode{E.base()}. +\item + Otherwise, if the type of \tcode{E} is \cv{} \tcode{subrange, reverse_iterator, K>} + for some iterator type \tcode{I} and + value \tcode{K} of type \tcode{subrange_kind}, + \begin{itemize} + \item + if \tcode{K} is \tcode{subrange_kind::sized}, equivalent to: +\begin{codeblock} +subrange(E.end().base(), E.begin().base(), E.size()) +\end{codeblock} + \item + otherwise, equivalent to: +\begin{codeblock} +subrange(E.end().base(), E.begin().base()) +\end{codeblock} + \end{itemize} + However, in either case \tcode{E} is evaluated only once. +\item + Otherwise, equivalent to \tcode{reverse_view\{E\}}. +\end{itemize} + +\pnum +\begin{example} +\begin{codeblock} +vector is {0,1,2,3,4}; +for (int i : is | views::reverse) + cout << i << ' '; // prints \tcode{4 3 2 1 0} +\end{codeblock} +\end{example} + +\rSec3[range.reverse.view]{Class template \tcode{reverse_view}} + +\indexlibraryglobal{reverse_view}% +\indexlibrarymember{base}{reverse_view}% +\indexlibrarymember{size}{reverse_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{bidirectional_range}@ + class reverse_view : public view_interface> { + private: + V @\exposid{base_}@ = V(); // \expos + + public: + reverse_view() requires @\libconcept{default_initializable}@ = default; + + constexpr explicit reverse_view(V r); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr reverse_iterator> begin(); + constexpr reverse_iterator> begin() requires @\libconcept{common_range}@; + constexpr auto begin() const requires @\libconcept{common_range}@; + + constexpr reverse_iterator> end(); constexpr auto end() const requires @\libconcept{common_range}@; constexpr auto size() requires @\libconcept{sized_range}@ { @@ -9539,13 +10587,13 @@ { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), 0); } constexpr auto end() requires (!@\exposconcept{simple-view}@) { - if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) + if constexpr (@\libconcept{forward_range}@ && @\libconcept{common_range}@ && @\libconcept{sized_range}@) return @\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::distance(@\exposid{base_}@)); else return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); } constexpr auto end() const requires @\exposconcept{range-with-movable-references}@ { - if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) + if constexpr (@\libconcept{forward_range}@ && @\libconcept{common_range}@ && @\libconcept{sized_range}@) return @\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::distance(@\exposid{base_}@)); else return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); @@ -10172,16 +11220,6 @@ \begin{codeblock} namespace std::ranges { - template - concept @\defexposconceptnc{all-random-access}@ = // \expos - (@\libconcept{random_access_range}@<@\exposid{maybe-const}@> && ...); - template - concept @\defexposconceptnc{all-bidirectional}@ = // \expos - (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@> && ...); - template - concept @\defexposconceptnc{all-forward}@ = // \expos - (@\libconcept{forward_range}@<@\exposid{maybe-const}@> && ...); - template<@\libconcept{input_range}@... Views> requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) template diff --git a/source/regex.tex b/source/regex.tex index f8882f3d83..bbec2e9f78 100644 --- a/source/regex.tex +++ b/source/regex.tex @@ -1260,7 +1260,7 @@ \begin{itemdescr} \pnum \effects -Imbues \keyword{this} with a copy of the +Imbues \tcode{*this} with a copy of the locale \tcode{loc}. \begin{note} Calling \tcode{imbue} with a diff --git a/source/statements.tex b/source/statements.tex index 70d713e9ef..2b6bde2f3a 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -188,7 +188,7 @@ side effects from an expression statement are completed before the next statement is executed. \indextext{statement!empty}% -An expression statement with the expression missing is called +An expression statement with the \grammarterm{expression} missing is called a \defnadj{null}{statement}. \begin{note} Most statements are expression statements --- usually assignments or @@ -509,7 +509,7 @@ \begin{bnf} \nontermdef{for-range-declaration}\br \opt{attribute-specifier-seq} decl-specifier-seq declarator\br - \opt{attribute-specifier-seq} decl-specifier-seq \opt{ref-qualifier} \terminal{[} identifier-list \terminal{]} + structured-binding-declaration \end{bnf} \begin{bnf} @@ -546,11 +546,41 @@ Thus after the \keyword{while} statement, \tcode{i} is no longer in scope. \end{example} +\pnum +A \defnadj{trivially empty}{iteration statement} is +an iteration statement matching one of the following forms: +\begin{itemize} +\item \tcode{while (} \grammarterm{expression} \tcode{) ;} +\item \tcode{while (} \grammarterm{expression} \tcode{) \{ \}} +\item \tcode{do ; while (} \grammarterm{expression} \tcode{) ;} +\item \tcode{do \{ \} while (} \grammarterm{expression} \tcode{) ;} +\item \tcode{for (} \grammarterm{init-statement} \opt{\grammarterm{expression}} \tcode{; ) ;} +\item \tcode{for (} \grammarterm{init-statement} \opt{\grammarterm{expression}} \tcode{; ) \{ \}} +\end{itemize} +The \defnadj{controlling}{expression} of a trivially empty iteration statement +is the \grammarterm{expression} of +a \tcode{while}, \tcode{do}, or \tcode{for} statement +(or \tcode{true}, if the \tcode{for} statement has no \grammarterm{expression}). +A \defnadj{trivial infinite}{loop} is a trivially empty iteration statement +for which the converted controlling expression is a constant expression, +when interpreted as a \grammarterm{constant-expression}\iref{expr.const}, and +evaluates to \tcode{true}. +The \grammarterm{statement} of a trivial infinite loop is replaced with +a call to the function \tcode{std::this_thread::yield}\iref{thread.thread.this}; +it is implementation-defined whether this replacement occurs +on freestanding implementations. +\begin{note} +In a freestanding environment, +concurrent forward progress is not guaranteed; +such systems therefore require explicit cooperation. +A call to yield can add implicit cooperation where none is otherwise intended. +\end{note} + \rSec2[stmt.while]{The \keyword{while} statement}% \indextext{statement!\idxcode{while}} \pnum -In the \keyword{while} statement the substatement is executed repeatedly +In the \keyword{while} statement, the substatement is executed repeatedly until the value of the condition\iref{stmt.pre} becomes \tcode{false}. The test takes place before each execution of the substatement. @@ -598,7 +628,7 @@ if that conversion is ill-formed, the program is ill-formed. \pnum -In the \keyword{do} statement the substatement is executed repeatedly +In the \keyword{do} statement, the substatement is executed repeatedly until the value of the expression becomes \tcode{false}. The test takes place after each execution of the statement. @@ -677,15 +707,15 @@ \exposid{begin-expr} and \exposid{end-expr} are determined as follows: \begin{itemize} -\item if the \grammarterm{for-range-initializer} is an expression of +\item if the type of \exposid{range} is a reference to an array type \tcode{R}, \exposid{begin-expr} and \exposid{end-expr} are \exposid{range} and \exposid{range} \tcode{+} \tcode{N}, respectively, where \tcode{N} is the array bound. If \tcode{R} is an array of unknown bound or an array of incomplete type, the program is ill-formed; -\item if the \grammarterm{for-range-initializer} is -an expression of class type \tcode{C}, and +\item if the type of \exposid{range} is a reference to a +class type \tcode{C}, and searches in the scope of \tcode{C}\iref{class.member.lookup} for the names \tcode{begin} and \tcode{end} each find at least one declaration, @@ -765,7 +795,7 @@ \begin{note} On exit from a scope (however accomplished), objects with automatic storage duration\iref{basic.stc.auto} that have been constructed in that scope are destroyed -in the reverse order of their construction. +in the reverse order of their construction\iref{stmt.dcl}. For temporaries, see~\ref{class.temporary}. However, the program can be terminated (by calling \indextext{\idxcode{exit}}% @@ -905,6 +935,29 @@ before the destruction of local variables\iref{stmt.jump} of the block enclosing the \tcode{return} statement. +\pnum +In a function whose return type is a reference, +other than an invented function for \tcode{std::is_convertible}\iref{meta.rel}, +a \tcode{return} statement that binds the returned reference to +a temporary expression\iref{class.temporary} is ill-formed. +\begin{example} +\begin{codeblock} +auto&& f1() { + return 42; // ill-formed +} +const double& f2() { + static int x = 42; + return x; // ill-formed +} +auto&& id(auto&& r) { + return static_cast(r); +} +auto&& f3() { + return id(42); // OK, but probably a bug +} +\end{codeblock} +\end{example} + \rSec2[stmt.return.coroutine]{The \keyword{co_return} statement}% \indextext{\idxcode{co_return}}% \indextext{coroutine return|see{\tcode{co_return}}}% @@ -991,16 +1044,16 @@ \indextext{block (statement)!initialization in}% \indextext{initialization!automatic}% \indextext{active|see{variable, active}}% -A variable with automatic storage duration\iref{basic.stc.auto} +A block variable with automatic storage duration\iref{basic.stc.auto} is \defnx{active}{variable!active} everywhere in the scope to which it belongs after its \grammarterm{init-declarator}. \indextext{initialization!jump past}% \indextext{\idxcode{goto}!initialization and}% Upon each transfer of control (including sequential execution of statements) within a function from point $P$ to point $Q$, -all variables with automatic storage duration +all block variables with automatic storage duration that are active at $P$ and not at $Q$ are destroyed in the reverse order of their construction. -Then, all variables with automatic storage duration +Then, all block variables with automatic storage duration that are active at $Q$ but not at $P$ are initialized in declaration order; unless all such variables have vacuous initialization\iref{basic.life}, the transfer of control shall not be a jump. diff --git a/source/strings.tex b/source/strings.tex index 1d786b7099..4493b5d463 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -549,12 +549,11 @@ // \ref{string.view.comparison}, non-member comparison functions template constexpr bool operator==(basic_string_view x, - basic_string_view y) noexcept; + type_identity_t> y) noexcept; template constexpr @\seebelow@ operator<=>(basic_string_view x, - @\itcorr@ basic_string_view y) noexcept; - - // see \ref{string.view.comparison}, sufficient additional overloads of comparison functions + @\itcorr@ type_identity_t> y) noexcept; // \ref{string.view.io}, inserters and extractors template @@ -578,14 +577,14 @@ template<> struct hash; inline namespace literals { - inline namespace string_view_literals { - // \ref{string.view.literals}, suffix for \tcode{basic_string_view} literals - constexpr string_view operator""sv(const char* str, size_t len) noexcept; - constexpr u8string_view operator""sv(const char8_t* str, size_t len) noexcept; - constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept; - constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept; - constexpr wstring_view operator""sv(const wchar_t* str, size_t len) noexcept; - } + inline namespace string_view_literals { + // \ref{string.view.literals}, suffix for \tcode{basic_string_view} literals + constexpr string_view operator""sv(const char* str, size_t len) noexcept; + constexpr u8string_view operator""sv(const char8_t* str, size_t len) noexcept; + constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept; + constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept; + constexpr wstring_view operator""sv(const wchar_t* str, size_t len) noexcept; + } } } \end{codeblock} @@ -1600,47 +1599,11 @@ \rSec2[string.view.comparison]{Non-member comparison functions} -\pnum -Let \tcode{S} be \tcode{basic_string_view}, and \tcode{sv} be an instance of \tcode{S}. -Implementations shall provide sufficient additional overloads marked \keyword{constexpr} and \keyword{noexcept} -so that an object \tcode{t} with an implicit conversion to \tcode{S} can be compared according to \tref{string.view.comparison.overloads}. -\begin{libtab2}{Additional \tcode{basic_string_view} comparison overloads}{string.view.comparison.overloads}{cc}{Expression}{Equivalent to} -\tcode{t == sv} & \tcode{S(t) == sv} \\ -\tcode{sv == t} & \tcode{sv == S(t)} \\ -\tcode{t != sv} & \tcode{S(t) != sv} \\ -\tcode{sv != t} & \tcode{sv != S(t)} \\ -\tcode{t < sv} & \tcode{S(t) < sv} \\ -\tcode{sv < t} & \tcode{sv < S(t)} \\ -\tcode{t > sv} & \tcode{S(t) > sv} \\ -\tcode{sv > t} & \tcode{sv > S(t)} \\ -\tcode{t <= sv} & \tcode{S(t) <= sv} \\ -\tcode{sv <= t} & \tcode{sv <= S(t)} \\ -\tcode{t >= sv} & \tcode{S(t) >= sv} \\ -\tcode{sv >= t} & \tcode{sv >= S(t)} \\ -\tcode{t <=> sv} & \tcode{S(t) <=> sv} \\ -\tcode{sv <=> t} & \tcode{sv <=> S(t)} \\ -\end{libtab2} -\begin{example} -A sample conforming implementation for \tcode{operator==} would be: -\begin{codeblock} -template - constexpr bool operator==(basic_string_view lhs, - basic_string_view rhs) noexcept { - return lhs.compare(rhs) == 0; - } -template - constexpr bool operator==(basic_string_view lhs, - type_identity_t> rhs) noexcept { - return lhs.compare(rhs) == 0; - } -\end{codeblock} -\end{example} - \indexlibrarymember{operator==}{basic_string_view}% \begin{itemdecl} template constexpr bool operator==(basic_string_view lhs, - basic_string_view rhs) noexcept; + type_identity_t> rhs) noexcept; \end{itemdecl} \begin{itemdescr} @@ -1653,7 +1616,7 @@ \begin{itemdecl} template constexpr @\seebelow@ operator<=>(basic_string_view lhs, - @\itcorr@ basic_string_view rhs) noexcept; + @\itcorr@ type_identity_t> rhs) noexcept; \end{itemdecl} \begin{itemdescr} @@ -1669,6 +1632,15 @@ \pnum \returns \tcode{static_cast(lhs.compare(rhs) <=> 0)}. + +\pnum +\begin{note} +The usage of \tcode{type_identity_t} as parameter +ensures that an object of type \tcode{basic_string_view} +can always be compared with an object of a type \tcode{T} with +an implicit conversion to \tcode{basic_string_view}, and +vice versa, as per \ref{over.match.oper}. +\end{note} \end{itemdescr} \rSec2[string.view.io]{Inserters and extractors} @@ -1864,6 +1836,22 @@ constexpr basic_string operator+(basic_string&& lhs, charT rhs); + template + constexpr basic_string + operator+(const basic_string& lhs, + type_identity_t> rhs); + template + constexpr basic_string + operator+(basic_string&& lhs, + type_identity_t> rhs); + template + constexpr basic_string + operator+(type_identity_t> lhs, + const basic_string& rhs); + template + constexpr basic_string + operator+(type_identity_t> lhs, + basic_string&& rhs); template constexpr bool @@ -1916,7 +1904,7 @@ basic_string& str); // \ref{string.erasure}, erasure - template + template constexpr typename basic_string::size_type erase(basic_string& c, const U& value); template @@ -1987,14 +1975,14 @@ template struct hash, A>>; inline namespace literals { - inline namespace string_literals { - // \ref{basic.string.literals}, suffix for \tcode{basic_string} literals - constexpr string operator""s(const char* str, size_t len); - constexpr u8string operator""s(const char8_t* str, size_t len); - constexpr u16string operator""s(const char16_t* str, size_t len); - constexpr u32string operator""s(const char32_t* str, size_t len); - constexpr wstring operator""s(const wchar_t* str, size_t len); - } + inline namespace string_literals { + // \ref{basic.string.literals}, suffix for \tcode{basic_string} literals + constexpr string operator""s(const char* str, size_t len); + constexpr u8string operator""s(const char8_t* str, size_t len); + constexpr u16string operator""s(const char16_t* str, size_t len); + constexpr u32string operator""s(const char32_t* str, size_t len); + constexpr wstring operator""s(const wchar_t* str, size_t len); + } } } \end{codeblock} @@ -4879,6 +4867,85 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator+}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string + operator+(const basic_string& lhs, + type_identity_t> rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Equivalent to: +\begin{codeblock} +basic_string r = lhs; +r.append(rhs); +return r; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string + operator+(basic_string&& lhs, + type_identity_t> rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Equivalent to: +\begin{codeblock} +lhs.append(rhs); +return std::move(lhs); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string + operator+(type_identity_t> lhs, + const basic_string& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Equivalent to: +\begin{codeblock} +basic_string r = rhs; +r.insert(0, lhs); +return r; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string + operator+(type_identity_t> lhs, + basic_string&& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Equivalent to: +\begin{codeblock} +rhs.insert(0, lhs); +return std::move(rhs); +\end{codeblock} +\end{itemdescr} + +\pnum +\begin{note} +Using a specialization of \tcode{type_identity_t} as a parameter type ensures +that an object of type \tcode{basic_string} +can be concatenated with an object of a type \tcode{T} +having an implicit conversion to +\tcode{basic_string_view}\iref{over.match.oper}. +\end{note} + \rSec3[string.cmp]{Non-member comparison operator functions} \begin{itemdecl} template @@ -5079,7 +5146,7 @@ \indexlibrarymember{erase}{basic_string}% \begin{itemdecl} -template +template constexpr typename basic_string::size_type erase(basic_string& c, const U& value); \end{itemdecl} diff --git a/source/support.tex b/source/support.tex index 0148590585..9924cbdabd 100644 --- a/source/support.tex +++ b/source/support.tex @@ -553,6 +553,8 @@ \begin{codeblock} #define @\defnlibxname{cpp_lib_adaptor_iterator_pair_constructor}@ 202106L // also in \libheader{stack}, \libheader{queue} #define @\defnlibxname{cpp_lib_addressof_constexpr}@ 201603L // freestanding, also in \libheader{memory} +#define @\defnlibxname{cpp_lib_algorithm_default_value_type}@ 202403L + // also in \libheader{algorithm}, \libheader{ranges}, \libheader{string}, \libheader{deque}, \libheader{list}, \libheader{forward_list}, \libheader{vector} #define @\defnlibxname{cpp_lib_algorithm_iterator_requirements}@ 202207L // also in \libheader{algorithm}, \libheader{numeric}, \libheader{memory} #define @\defnlibxname{cpp_lib_allocate_at_least}@ 202302L // also in \libheader{memory} @@ -572,6 +574,7 @@ #define @\defnlibxname{cpp_lib_atomic_float}@ 201711L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_is_always_lock_free}@ 201603L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_lock_free_type_aliases}@ 201907L // also in \libheader{atomic} +#define @\defnlibxname{cpp_lib_atomic_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_shared_ptr}@ 201711L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_atomic_value_initialization}@ 201911L // freestanding, also in \libheader{atomic}, \libheader{memory} @@ -614,12 +617,14 @@ #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_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_debugging}@ 202311L // freestanding, also in \libheader{debugging} +#define @\defnlibxname{cpp_lib_debugging}@ 202403L // freestanding, also in \libheader{debugging} #define @\defnlibxname{cpp_lib_destroying_delete}@ 201806L // freestanding, also in \libheader{new} #define @\defnlibxname{cpp_lib_enable_shared_from_this}@ 201603L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_endian}@ 201907L // freestanding, also in \libheader{bit} @@ -634,6 +639,7 @@ #define @\defnlibxname{cpp_lib_flat_set}@ 202207L // also in \libheader{flat_set} #define @\defnlibxname{cpp_lib_format}@ 202311L // also in \libheader{format} #define @\defnlibxname{cpp_lib_format_ranges}@ 202207L // also in \libheader{format} +#define @\defnlibxname{cpp_lib_format_path}@ 202403L // also in \libheader{filesystem} #define @\defnlibxname{cpp_lib_format_uchar}@ 202311L // also in \libheader{format} #define @\defnlibxname{cpp_lib_formatters}@ 202302L // also in \libheader{stacktrace}, \libheader{thread} #define @\defnlibxname{cpp_lib_forward_like}@ 202207L // freestanding, also in \libheader{utility} @@ -722,7 +728,7 @@ #define @\defnlibxname{cpp_lib_out_ptr}@ 202311L // freestanding, also in \libheader{memory} #define @\defnlibxname{cpp_lib_parallel_algorithm}@ 201603L // also in \libheader{algorithm}, \libheader{numeric} #define @\defnlibxname{cpp_lib_polymorphic_allocator}@ 201902L // also in \libheader{memory_resource} -#define @\defnlibxname{cpp_lib_print}@ 202207L // also in \libheader{print}, \libheader{ostream} +#define @\defnlibxname{cpp_lib_print}@ 202403L // also in \libheader{print}, \libheader{ostream} #define @\defnlibxname{cpp_lib_quoted_string_io}@ 201304L // also in \libheader{iomanip} #define @\defnlibxname{cpp_lib_ranges}@ 202302L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} @@ -731,10 +737,12 @@ #define @\defnlibxname{cpp_lib_ranges_cartesian_product}@ 202207L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_chunk}@ 202202L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_chunk_by}@ 202202L // freestanding, also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_concat}@ 202403L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_contains}@ 202207L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_enumerate}@ 202302L // also in \libheader{ranges}, \libheader{version} #define @\defnlibxname{cpp_lib_ranges_find_last}@ 202207L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_fold}@ 202207L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_ranges_generate_random}@ 202403L // also in \libheader{random} #define @\defnlibxname{cpp_lib_ranges_iota}@ 202202L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_ranges_join_with}@ 202202L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_repeat}@ 202207L // freestanding, also in \libheader{ranges} @@ -748,6 +756,7 @@ #define @\defnlibxname{cpp_lib_raw_memory_algorithms}@ 201606L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_rcu}@ 202306L // also in \libheader{rcu} #define @\defnlibxname{cpp_lib_reference_from_temporary}@ 202202L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_reference_wrapper}@ 202403L // freestanding, also in \libheader{functional} #define @\defnlibxname{cpp_lib_remove_cvref}@ 201711L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_result_of_sfinae}@ 201210L // freestanding, also in \libheader{functional}, \libheader{type_traits} @@ -776,8 +785,8 @@ #define @\defnlibxname{cpp_lib_string_contains}@ 202011L // also in \libheader{string}, \libheader{string_view} #define @\defnlibxname{cpp_lib_string_resize_and_overwrite}@ 202110L // also in \libheader{string} #define @\defnlibxname{cpp_lib_string_udls}@ 201304L // also in \libheader{string} -#define @\defnlibxname{cpp_lib_string_view}@ 201803L // also in \libheader{string}, \libheader{string_view} -#define @\defnlibxname{cpp_lib_submdspan}@ 202306L // also in \libheader{mdspan} +#define @\defnlibxname{cpp_lib_string_view}@ 202403L // also in \libheader{string}, \libheader{string_view} +#define @\defnlibxname{cpp_lib_submdspan}@ 202403L // 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} @@ -1631,45 +1640,45 @@ \indexlibraryglobal{numeric_limits}% \begin{codeblock} namespace std { - template<> class numeric_limits { - public: - static constexpr bool is_specialized = true; - static constexpr bool min() noexcept { return false; } - static constexpr bool max() noexcept { return true; } - static constexpr bool lowest() noexcept { return false; } - - static constexpr int digits = 1; - static constexpr int digits10 = 0; - static constexpr int max_digits10 = 0; - - static constexpr bool is_signed = false; - static constexpr bool is_integer = true; - static constexpr bool is_exact = true; - static constexpr int radix = 2; - static constexpr bool epsilon() noexcept { return 0; } - static constexpr bool round_error() noexcept { return 0; } - - static constexpr int min_exponent = 0; - static constexpr int min_exponent10 = 0; - static constexpr int max_exponent = 0; - static constexpr int max_exponent10 = 0; - - static constexpr bool has_infinity = false; - static constexpr bool has_quiet_NaN = false; - static constexpr bool has_signaling_NaN = false; - static constexpr bool infinity() noexcept { return 0; } - static constexpr bool quiet_NaN() noexcept { return 0; } - static constexpr bool signaling_NaN() noexcept { return 0; } - static constexpr bool denorm_min() noexcept { return 0; } - - static constexpr bool is_iec559 = false; - static constexpr bool is_bounded = true; - static constexpr bool is_modulo = false; - - static constexpr bool traps = false; - static constexpr bool tinyness_before = false; - static constexpr float_round_style round_style = round_toward_zero; - }; + template<> class numeric_limits { + public: + static constexpr bool is_specialized = true; + static constexpr bool min() noexcept { return false; } + static constexpr bool max() noexcept { return true; } + static constexpr bool lowest() noexcept { return false; } + + static constexpr int digits = 1; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 0; + + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + static constexpr bool epsilon() noexcept { return 0; } + static constexpr bool round_error() noexcept { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr bool infinity() noexcept { return 0; } + static constexpr bool quiet_NaN() noexcept { return 0; } + static constexpr bool signaling_NaN() noexcept { return 0; } + static constexpr bool denorm_min() noexcept { return 0; } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + + static constexpr bool traps = false; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; + }; } \end{codeblock} @@ -3635,7 +3644,8 @@ expressions, to report errors detected during program execution. \pnum -Each standard library class \tcode{T} that derives from class \tcode{exception} +Except where explicitly specified otherwise, +each standard library class \tcode{T} that derives from class \tcode{exception} has the following publicly accessible member functions, each of them having a non-throwing exception specification\iref{except.spec}: \begin{itemize} @@ -3915,10 +3925,9 @@ returns an \tcode{exception_ptr} object that refers to the thrown exception or, if this is not possible, to an instance of \tcode{bad_exception}. \begin{note} -The -copy constructor of the thrown exception can also fail, so the implementation is allowed -to substitute a \tcode{bad_exception} object to avoid infinite -recursion. +The copy constructor of the thrown exception can also fail, +so the implementation can substitute a \tcode{bad_exception} object +to avoid infinite recursion. \end{note} \end{itemdescr} @@ -5197,6 +5206,7 @@ \rSec3[coroutine.traits.primary]{Class template \tcode{coroutine_traits}} +\indexlibraryglobal{coroutine_traits}% \pnum The header \libheader{coroutine} defines the primary template \tcode{coroutine_traits} such that diff --git a/source/templates.tex b/source/templates.tex index 048add70e2..3d27393946 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -59,11 +59,7 @@ \end{note} \pnum -The -\grammarterm{declaration} -in a -\grammarterm{template-declaration} -(if any) +The \grammarterm{declaration} in a \grammarterm{template-declaration} (if any) shall \begin{itemize} \item declare or define a function, a class, or a variable, or @@ -73,6 +69,8 @@ \item define a member template of a class or class template, or +\item be a \grammarterm{friend-type-declaration}, or + \item be a \grammarterm{deduction-guide}, or \item be an \grammarterm{alias-declaration}. @@ -123,7 +121,7 @@ \pnum In a \grammarterm{template-declaration}, -explicit specialization, or explicit instantiation the +explicit specialization, or explicit instantiation, the \grammarterm{init-declarator-list} in the declaration shall contain at most one declarator. When such a declaration is used to declare a class template, @@ -769,7 +767,7 @@ \keyword{typename} prefix, the \keyword{template} -prefix is allowed +prefix is well-formed even when lookup for the name would already find a template. \end{note} \begin{example} @@ -1940,9 +1938,9 @@ \indextext{constraint!normalization|)} \rSec2[temp.constr.order]{Partial ordering by constraints} -\indextext{subsume|see{constraint, subsumption}} \pnum +\indextext{subsume|see{constraint, subsumption}} A constraint $P$ \defnx{subsumes}{constraint!subsumption} a constraint $Q$ if and only if, for every disjunctive clause $P_i$ @@ -2109,6 +2107,9 @@ they both have no active member or they have the same active member and their active members are template-argument-equivalent, or +\item +they are of a closure type\iref{expr.prim.lambda.closure}, or + \item they are of class type and their corresponding direct subobjects and reference members are template-argument-equivalent. @@ -2421,7 +2422,7 @@ \begin{bnf} \nontermdef{deduction-guide}\br - \opt{explicit-specifier} template-name \terminal{(} parameter-declaration-clause \terminal{)} \terminal{->} simple-template-id \terminal{;} + \opt{explicit-specifier} template-name \terminal{(} parameter-declaration-clause \terminal{)} \opt{requires-clause} \terminal{->} simple-template-id \terminal{;} \end{bnf} \pnum @@ -2739,6 +2740,9 @@ \item In a \grammarterm{using-declaration}\iref{namespace.udecl}; the pattern is a \grammarterm{using-declarator}. +\item In a \grammarterm{friend-type-declaration}\iref{class.mem.general}; +the pattern is a \grammarterm{friend-type-specifier}. + \item In a template parameter pack that is a pack expansion\iref{temp.param}: \begin{itemize} \item @@ -4408,6 +4412,8 @@ \grammarterm{elaborated-type-specifier}, \grammarterm{class-or-decltype}, or \item +a \grammarterm{simple-type-specifier} of a \grammarterm{friend-type-specifier}, or +\item a \grammarterm{type-specifier} of a \begin{itemize} \item \grammarterm{new-type-id}, @@ -4423,7 +4429,7 @@ \end{itemize} \item a \grammarterm{decl-specifier} of the \grammarterm{decl-specifier-seq} of a \begin{itemize} -\item \grammarterm{simple-declaration} or a \grammarterm{function-definition} in namespace scope, +\item \grammarterm{simple-declaration} or \grammarterm{function-definition} in namespace scope, \item \grammarterm{member-declaration}, \item \grammarterm{parameter-declaration} in a \grammarterm{member-declaration}, \begin{footnote} @@ -4508,6 +4514,11 @@ within a templated entity and the innermost enclosing template is not instantiated, or \item +no valid specialization, +ignoring \grammarterm{static_assert-declaration}{s} that fail, +can be generated for a default \grammarterm{template-argument} and +the default \grammarterm{template-argument} is not used in any instantiation, or +\item no specialization of an alias template\iref{temp.alias} is valid and no specialization of the alias template is named in the program, or \item @@ -4565,8 +4576,6 @@ \end{itemize} \end{note} -Otherwise, no diagnostic shall be issued for a template -for which a valid specialization can be generated. \begin{note} If a template is instantiated, errors will be diagnosed according to the other rules in this document. @@ -5062,7 +5071,7 @@ template int C::f(); // error: finds both \tcode{A::m} and \tcode{B::m} template int C::g(); // OK, transformation to class member access syntax - // does not occur in the template definition context; see~\ref{class.mfct.non.static} + // does not occur in the template definition context; see~\ref{expr.prim.id.general} \end{codeblock} \end{example} @@ -6286,7 +6295,7 @@ template void Array::mf(); template void sort(Array& v) { @\commentellip@ } -template void sort(Array&); // argument is deduced here +template void sort(Array&); // argument is deduced here\iref{temp.arg.explicit} namespace N { template void f(T&) { } @@ -6317,7 +6326,7 @@ into the templated function, variable, or class are two declarations of the same entity. \begin{note} -These declarations are required to have matching types as specified in~\ref{basic.link}, except as specified in~\ref{except.spec}. +These declarations need to have matching types as specified in~\ref{basic.link}, except as specified in~\ref{except.spec}. \begin{example} \begin{codeblock} template T var = {}; @@ -6347,27 +6356,9 @@ data member of a class template shall be present in every translation unit in which it is explicitly instantiated. -\pnum -A trailing -\grammarterm{template-argument} -can be left unspecified in an explicit instantiation of a function template -specialization or of a member function template specialization provided -it can be deduced\iref{temp.deduct.decl}. -If all template arguments can be deduced, -the empty template argument list \tcode{<>} may be omitted. -\begin{example} -\begin{codeblock} -template class Array { @\commentellip@ }; -template void sort(Array& v) { @\commentellip@ } - -// instantiate \tcode{sort(Array\&)} -- template-argument deduced -template void sort<>(Array&); -\end{codeblock} -\end{example} - \pnum \begin{note} -An explicit instantiation of a constrained template is required +An explicit instantiation of a constrained template needs to satisfy that template's associated constraints\iref{temp.constr.decl}. The satisfaction of constraints is determined % FIXME: What is a "template name"? Does this mean "simple-template-id"? @@ -6474,28 +6465,29 @@ \begin{codeblock} template class stream; -template<> class stream { @\commentellip@ }; +template<> class stream { @\commentellip@ }; // \#1 template class Array { @\commentellip@ }; template void sort(Array& v) { @\commentellip@ } -template<> void sort(Array&); +template<> void sort(Array&); // \#2 +template<> void sort(Array&); // \#3 template argument is deduced\iref{temp.arg.explicit} \end{codeblock} Given these declarations, -\tcode{stream} -will be used as the definition of streams of +\#1 will be used as the definition of streams of \tcode{char}s; other streams will be handled by class template specializations instantiated from the class template. Similarly, -\tcode{sort} -will be used as the sort function for arguments +\#2 will be used as the sort function for arguments of +type \tcode{Array} and +\#3 will be used for arguments of type \tcode{Array}; other \tcode{Array} -types will be sorted by functions generated from the template. +types will be sorted by functions generated from the function template. \end{example} \pnum @@ -6514,10 +6506,9 @@ An explicit specialization does not introduce a name\iref{basic.scope.scope}. A declaration of a function template, class template, or variable template being explicitly specialized shall be reachable from the declaration of -the explicit -specialization. +the explicit specialization. \begin{note} -A declaration, but not a definition of the template is required. +A declaration, but not a definition of the template is needed. \end{note} The definition of a class or class template shall be reachable from the declaration of an explicit specialization for a member template of the class @@ -6688,27 +6679,9 @@ \end{codeblock} \end{example} -\pnum -A trailing -\grammarterm{template-argument} -can be left unspecified in the -\grammarterm{template-id} -naming an explicit function template specialization -provided it can be deduced\iref{temp.deduct.decl}. -\begin{example} -\begin{codeblock} -template class Array { @\commentellip@ }; -template void sort(Array& v); - -// explicit specialization for \tcode{sort(Array\&)} -// with deduced template-argument of type \tcode{int} -template<> void sort(Array&); -\end{codeblock} -\end{example} - \pnum \begin{note} -An explicit specialization of a constrained template is required +An explicit specialization of a constrained template needs to satisfy that template's associated constraints\iref{temp.constr.decl}. The satisfaction of constraints is determined when forming the template name of an explicit specialization @@ -7305,10 +7278,8 @@ invalid type or expression is one that would be ill-formed, with a diagnostic required, if written in the same context using the substituted arguments. \begin{note} -If no -diagnostic is required, the program is still ill-formed. Access checking is done -as part of the substitution -process. +If no diagnostic is required, the program is still ill-formed. +Access checking is done as part of the substitution process. \end{note} Invalid types and expressions can result in a deduction failure only in the immediate context of the deduction substitution loci. diff --git a/source/threads.tex b/source/threads.tex index c906079668..9ba0aabcec 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -2265,7 +2265,34 @@ template T atomic_fetch_xor_explicit(atomic*, typename atomic::value_type, // freestanding memory_order) noexcept; - + template + T atomic_fetch_max(volatile atomic*, // freestanding + typename atomic::value_type) noexcept; + template + 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 + 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 + 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 + typename atomic::value_type, + memory_order) noexcept; template void atomic_wait(const volatile atomic*, // freestanding typename atomic::value_type) noexcept; @@ -3289,6 +3316,10 @@ 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; @@ -3318,6 +3349,8 @@ \indexlibrarymember{fetch_add}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{fetch_and}{atomic_ref<\placeholder{integral-type}>}% +\indexlibrarymember{fetch_max}{atomic_ref<\placeholder{integral-type}>}% +\indexlibrarymember{fetch_min}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{fetch_or}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{fetch_xor}{atomic_ref<\placeholder{integral-type}>}% @@ -3343,7 +3376,7 @@ \pnum \indextext{signed integer representation!two's complement}% \remarks -For signed integer types, +Except for \tcode{fetch_max} and \tcode{fetch_min}, for signed integer types the result is as if the object value and parameters were converted to their corresponding unsigned types, the computation performed on those types, and @@ -3351,6 +3384,12 @@ \begin{note} There are no undefined results arising from the computation. \end{note} + +\pnum +For \tcode{fetch_max} and \tcode{fetch_min}, the maximum and minimum +computation is performed as if by \tcode{max} and \tcode{min} algorithms +\iref{alg.min.max}, respectively, with the object value and the first +parameter as the arguments. \end{itemdescr} \indexlibrarymember{operator+=}{atomic_ref<\placeholder{integral-type}>}% @@ -3522,6 +3561,8 @@ 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; @@ -3548,6 +3589,8 @@ \indexlibrarymember{fetch_add}{atomic_ref}% \indexlibrarymember{fetch_sub}{atomic_ref}% +\indexlibrarymember{fetch_max}{atomic_ref}% +\indexlibrarymember{fetch_min}{atomic_ref}% \begin{itemdecl} T* fetch_@\placeholdernc{key}@(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} @@ -3574,8 +3617,22 @@ \remarks The result may be an undefined address, but the operations otherwise have no undefined behavior. + +\pnum +For \tcode{fetch_max} and \tcode{fetch_min}, the maximum and minimum +computation is performed as if by \tcode{max} and \tcode{min} +algorithms\iref{alg.min.max}, respectively, with the object value and the first +parameter as the arguments. + +\begin{note} +If the pointers point to different complete objects (or subobjects thereof), +the \tcode{<} operator does not establish a strict weak ordering +(\tref{cpp17.lessthancomparable}, \ref{expr.rel}). +\end{note} \end{itemdescr} + + \indexlibrarymember{operator+=}{atomic_ref}% \indexlibrarymember{operator-=}{atomic_ref}% \begin{itemdecl} @@ -4301,6 +4358,14 @@ memory_order = memory_order::seq_cst) volatile noexcept; @\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}@, + 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}@, + memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ operator++(int) volatile noexcept; @\placeholdernc{integral-type}@ operator++(int) noexcept; @@ -4357,32 +4422,44 @@ \tcode{add} & \tcode{+} & addition & +\tcode{and} & + \tcode{\&} & + bitwise and \\ \tcode{sub} & \tcode{-} & - subtraction \\ + subtraction & \tcode{or} & \tcode{|} & - bitwise inclusive or & + bitwise inclusive or \\ +\tcode{max} & + & + maximum & \tcode{xor} & \tcode{\caret} & bitwise exclusive or \\ -\tcode{and} & - \tcode{\&} & - bitwise and &&&\\ +\tcode{min} & + & + minimum &&&\\ \end{floattable} \indexlibraryglobal{atomic_fetch_add}% \indexlibraryglobal{atomic_fetch_and}% +\indexlibraryglobal{atomic_fetch_max}% +\indexlibraryglobal{atomic_fetch_min}% \indexlibraryglobal{atomic_fetch_or}% \indexlibraryglobal{atomic_fetch_sub}% \indexlibraryglobal{atomic_fetch_xor}% \indexlibraryglobal{atomic_fetch_add_explicit}% \indexlibraryglobal{atomic_fetch_and_explicit}% +\indexlibraryglobal{atomic_fetch_max_explicit}% +\indexlibraryglobal{atomic_fetch_min_explicit}% \indexlibraryglobal{atomic_fetch_or_explicit}% \indexlibraryglobal{atomic_fetch_sub_explicit}% \indexlibraryglobal{atomic_fetch_xor_explicit}% \indexlibrarymember{fetch_add}{atomic<\placeholder{integral-type}>}% \indexlibrarymember{fetch_and}{atomic<\placeholder{integral-type}>}% +\indexlibrarymember{fetch_max}{atomic<\placeholder{integral-type}>}% +\indexlibrarymember{fetch_min}{atomic<\placeholder{integral-type}>}% \indexlibrarymember{fetch_or}{atomic<\placeholder{integral-type}>}% \indexlibrarymember{fetch_sub}{atomic<\placeholder{integral-type}>}% \indexlibrarymember{fetch_xor}{atomic<\placeholder{integral-type}>}% @@ -4412,7 +4489,7 @@ \pnum \indextext{signed integer representation!two's complement}% \remarks -For signed integer types, +Except for \tcode{fetch_max} and \tcode{fetch_min}, for signed integer types the result is as if the object value and parameters were converted to their corresponding unsigned types, the computation performed on those types, and @@ -4421,6 +4498,11 @@ There are no undefined results arising from the computation. \end{note} +\pnum +For \tcode{fetch_max} and \tcode{fetch_min}, the maximum and minimum +computation is performed as if by \tcode{max} and \tcode{min} algorithms +\iref{alg.min.max}, respectively, with the object value and the first parameter +as the arguments. \end{itemdescr} \indexlibrarymember{operator+=}{atomic}% @@ -4659,6 +4741,10 @@ T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; + T* fetch_max(T*, memory_order = memory_order::seq_cst) volatile noexcept; + 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; T* operator++(int) volatile noexcept; T* operator++(int) noexcept; @@ -4712,13 +4798,25 @@ \tcode{sub} & \tcode{-} & subtraction \\ +\tcode{max} & + & + maximum & +\tcode{min} & + & + minimum \\ \end{floattable} \indexlibraryglobal{atomic_fetch_add}% +\indexlibraryglobal{atomic_fetch_max}% +\indexlibraryglobal{atomic_fetch_min}% \indexlibraryglobal{atomic_fetch_sub}% \indexlibraryglobal{atomic_fetch_add_explicit}% +\indexlibraryglobal{atomic_fetch_max_explicit}% +\indexlibraryglobal{atomic_fetch_min_explicit}% \indexlibraryglobal{atomic_fetch_sub_explicit}% \indexlibrarymember{fetch_add}{atomic}% +\indexlibrarymember{fetch_max}{atomic}% +\indexlibrarymember{fetch_min}{atomic}% \indexlibrarymember{fetch_sub}{atomic}% \begin{itemdecl} T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept; @@ -4754,6 +4852,18 @@ \remarks The result may be an undefined address, but the operations otherwise have no undefined behavior. + +\pnum +For \tcode{fetch_max} and \tcode{fetch_min}, the maximum and minimum +computation is performed as if by \tcode{max} and \tcode{min} +algorithms\iref{alg.min.max}, respectively, with the object value and the first +parameter as the arguments. + +\begin{note} +If the pointers point to different complete objects (or subobjects thereof), +the \tcode{<} operator does not establish a strict weak ordering +(\tref{cpp17.lessthancomparable}, \ref{expr.rel}). +\end{note} \end{itemdescr} \indexlibrarymember{operator+=}{atomic}% @@ -6305,8 +6415,8 @@ \begin{note} After a thread \tcode{A} has called \tcode{unlock()}, releasing a mutex, it is possible for another thread \tcode{B} to lock the same mutex, observe that it is no longer in use, unlock it, and -destroy it, before thread \tcode{A} appears to have returned from its unlock call. Implementations -are required to handle such scenarios correctly, as long as thread \tcode{A} doesn't access the +destroy it, before thread \tcode{A} appears to have returned from its unlock call. Conforming implementations +handle such scenarios correctly, as long as thread \tcode{A} does not access the mutex after the unlock call returns. These cases typically occur when a reference-counted object contains a mutex that is used to protect the reference count. \end{note} @@ -8220,7 +8330,7 @@ \effects An execution of \tcode{call_once} that does not call its \tcode{func} is a \term{passive} execution. An execution of \tcode{call_once} that calls its \tcode{func} -is an \term{active} execution. An active execution calls +is an \term{active} execution. An active execution evaluates \tcode{\placeholdernc{INVOKE}(\brk{}% std::forward(func), std::forward(args)...)}\iref{func.require}. If such a call to \tcode{func} @@ -8376,7 +8486,7 @@ \pnum \begin{note} It is the user's responsibility to ensure that waiting threads -do not erroneously assume that the thread has finished if they experience +do not incorrectly assume that the thread has finished if they experience spurious wakeups. This typically requires that the condition being waited for is satisfied while holding the lock on \tcode{lk}, and that this lock is not released and reacquired prior to calling \tcode{notify_all_at_thread_exit}. @@ -9262,7 +9372,7 @@ template class counting_semaphore; - using binary_semaphore = counting_semaphore<1>; + using @\libglobal{binary_semaphore}@ = counting_semaphore<1>; } \end{codeblock} diff --git a/source/time.tex b/source/time.tex index 7fa74b7d30..d66ef5652c 100644 --- a/source/time.tex +++ b/source/time.tex @@ -7923,7 +7923,7 @@ @\tcode{\placeholder{day}}@/@\tcode{\placeholder{month}}@/@\tcode{\placeholder{year}}@ \end{codeblock} -Anywhere a \tcode{\placeholder{day}} is required, any of the following can also be specified: +Anywhere a \tcode{\placeholder{day}} is needed, any of the following can also be specified: \begin{codeblock} last @@ -11021,7 +11021,7 @@ \pnum Each \tcode{parse} overload specified in this subclause calls \tcode{from_stream} unqualified, -so as to enable argument dependent lookup\iref{basic.lookup.argdep}. +so as to enable argument-dependent lookup\iref{basic.lookup.argdep}. In the following paragraphs, let \tcode{is} denote an object of type \tcode{basic_istream} and let \tcode{I} be \tcode{basic_istream\&}, @@ -11540,7 +11540,7 @@ The specializations are enabled\iref{unord.hash}. \begin{note} All the \tcode{hash} specializations listed above meet the -\oldconcept{Cpp17Hash} requirements, even when called on objects \tcode{k} +\oldconcept{Hash} requirements, even when called on objects \tcode{k} of type \tcode{Key} such that \tcode{k.ok()} is \tcode{false}. \end{note} \end{itemdescr} diff --git a/source/utilities.tex b/source/utilities.tex index 4546698fb5..a354b49ff0 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -1282,9 +1282,11 @@ \begin{itemdescr} \pnum -\expects -Each of \tcode{decltype(x.first == y.first)} and -\tcode{decltype(x.second == y.second)} models \exposconcept{boolean-testable}. +\constraints +\tcode{x.first == y.first} and \tcode{x.second == y.second} are +valid expressions and +each of \tcode{decltype(x.first == y.first)} and +\tcode{decltype(x.second == y.second)} models \exposconceptx{boolean-\newline testable}{boolean-testable}. \pnum \returns @@ -2032,7 +2034,7 @@ \tcode{true}, and \item -either \tcode{sizeof...(Types)} is not \tcode{1}, or +either \tcode{sizeof...(Types)} is not 1, or (when \tcode{Types...} expands to \tcode{T}) \tcode{is_convertible_v} and \tcode{is_constructible_v} are both \tcode{false}. @@ -2049,6 +2051,12 @@ \begin{codeblock} !(is_convertible_v(std::forward(u))), Types> && ...) \end{codeblock} +The constructor is defined as deleted if +\begin{codeblock} +(reference_constructs_from_temporary_v(std::forward(u)))> + || ...) +\end{codeblock} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{tuple}% @@ -2730,7 +2738,8 @@ \begin{itemdescr} \pnum -All specializations of \tcode{tuple_size} meet the +Except where specified otherwise, +all specializations of \tcode{tuple_size} meet the \oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts} with a base characteristic of \tcode{integral_constant} for some \tcode{N}. @@ -2928,18 +2937,14 @@ For the first overload let \tcode{UTuple} be \tcode{tuple}. \pnum -\mandates +\constraints For all \tcode{i}, where $0 \leq \tcode{i} < \tcode{sizeof...(TTypes)}$, -\tcode{get(t) == get(u)} is a valid expression. +\tcode{get(t) == get(u)} is a valid expression and +\tcode{decltype(get(t) == get(u))} models \exposconcept{boolean-testable}. \tcode{sizeof...(TTypes)} equals \tcode{tuple_size_v}. -\pnum -\expects -For all \tcode{i}, \tcode{decltype(get(t) == get(u))} models -\exposconcept{boolean-testable}. - \pnum \returns \tcode{true} if \tcode{get(t) == get(u)} for all @@ -3002,7 +3007,7 @@ (or \tcode{u$_{\mathrm{tail}}$}) to be constructed. It might not even be possible, as \tcode{t} and \tcode{u} are not required to be copy constructible. Also, all comparison operator functions are short circuited; -they do not perform element accesses beyond what is required to determine the +they do not perform element accesses beyond what is needed to determine the result of the comparison. \end{note} @@ -4392,7 +4397,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{*x == *y} is well-formed and its result is convertible to \tcode{bool}. \begin{note} @@ -4417,7 +4422,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{*x != *y} is well-formed and its result is convertible to \tcode{bool}. @@ -4441,7 +4446,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints \tcode{*x < *y} is well-formed and its result is convertible to \tcode{bool}. @@ -4465,7 +4470,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{*x > *y} is well-formed and its result is convertible to \tcode{bool}. @@ -4489,7 +4494,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{*x <= *y} is well-formed and its result is convertible to \tcode{bool}. @@ -4513,7 +4518,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{*x >= *y} is well-formed and its result is convertible to \tcode{bool}. @@ -4582,7 +4587,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{*x == v} is well-formed and its result is convertible to \tcode{bool}. \begin{note} @@ -4601,7 +4606,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{v == *x} is well-formed and its result is convertible to \tcode{bool}. @@ -4617,7 +4622,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{*x != v} is well-formed and its result is convertible to \tcode{bool}. @@ -4633,7 +4638,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{v != *x} is well-formed and its result is convertible to \tcode{bool}. @@ -4649,7 +4654,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{*x < v} is well-formed and its result is convertible to \tcode{bool}. @@ -4665,7 +4670,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{v < *x} is well-formed and its result is convertible to \tcode{bool}. @@ -4681,7 +4686,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{*x > v} is well-formed and its result is convertible to \tcode{bool}. @@ -4697,7 +4702,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{v > *x} is well-formed and its result is convertible to \tcode{bool}. @@ -4713,7 +4718,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{*x <= v} is well-formed and its result is convertible to \tcode{bool}. @@ -4729,7 +4734,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{v <= *x} is well-formed and its result is convertible to \tcode{bool}. @@ -4745,7 +4750,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{*x >= v} is well-formed and its result is convertible to \tcode{bool}. @@ -4761,7 +4766,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints The expression \tcode{v >= *x} is well-formed and its result is convertible to \tcode{bool}. @@ -5984,7 +5989,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints \tcode{\exposid{GET}<$i$>(v) == \exposid{GET}<$i$>(w)} is a valid expression that is convertible to \tcode{bool}, for all $i$. @@ -6003,7 +6008,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints \tcode{\exposid{GET}<$i$>(v) != \exposid{GET}<$i$>(w)} is a valid expression that is convertible to \tcode{bool}, for all $i$. @@ -6022,7 +6027,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints \tcode{\exposid{GET}<$i$>(v) < \exposid{GET}<$i$>(w)} is a valid expression that is convertible to \tcode{bool}, for all $i$. @@ -6043,7 +6048,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints \tcode{\exposid{GET}<$i$>(v) > \exposid{GET}<$i$>(w)} is a valid expression that is convertible to \tcode{bool}, for all $i$. @@ -6064,7 +6069,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints \tcode{\exposid{GET}<$i$>(v) <= \exposid{GET}<$i$>(w)} is a valid expression that is convertible to \tcode{bool}, for all $i$. @@ -6085,7 +6090,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints \tcode{\exposid{GET}<$i$>(v) >= \exposid{GET}<$i$>(w)} is a valid expression that is convertible to \tcode{bool}, for all $i$. @@ -6115,7 +6120,7 @@ if (v.valueless_by_exception()) return strong_ordering::less; if (w.valueless_by_exception()) return strong_ordering::greater; if (auto c = v.index() <=> w.index(); c != 0) return c; -return \exposid{GET}<@$i$@>(v) <=> \exposid{GET}<@$i$@>(w); +return @\exposid{GET}@<@$i$@>(v) <=> @\exposid{GET}@<@$i$@>(w); \end{codeblock} with $i$ being \tcode{v.index()}. \end{itemdescr} @@ -7304,10 +7309,10 @@ class bad_expected_access : public exception { protected: bad_expected_access() noexcept; - bad_expected_access(const bad_expected_access&); - bad_expected_access(bad_expected_access&&); - bad_expected_access& operator=(const bad_expected_access&); - bad_expected_access& operator=(bad_expected_access&&); + bad_expected_access(const bad_expected_access&) noexcept; + bad_expected_access(bad_expected_access&&) noexcept; + bad_expected_access& operator=(const bad_expected_access& noexcept); + bad_expected_access& operator=(bad_expected_access&&) noexcept; ~bad_expected_access(); public: @@ -9125,6 +9130,11 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_move_constructible_v} is \tcode{true} and +\tcode{is_move_assignable_v} is \tcode{true}. + \pnum \effects \begin{itemize} @@ -9151,11 +9161,6 @@ \remarks The exception specification is equivalent to \tcode{is_nothrow_move_constructible_v \&\& is_nothrow_move_assignable_v}. - -\pnum -This operator is defined as deleted unless -\tcode{is_move_constructible_v} is \tcode{true} and -\tcode{is_move_assignable_v} is \tcode{true}. \end{itemdescr} \indexlibrarymember{operator=}{expected}% @@ -10992,6 +10997,16 @@ template constexpr invoke_result_t operator()(ArgTypes&&...) const noexcept(is_nothrow_invocable_v); + + // \ref{refwrap.comparisons}, comparisons + friend constexpr bool operator==(reference_wrapper, reference_wrapper); + friend constexpr bool operator==(reference_wrapper, const T&); + friend constexpr bool operator==(reference_wrapper, reference_wrapper); + + friend constexpr @\exposidnc{synth-three-way-result}@ operator<=>(reference_wrapper, reference_wrapper); + friend constexpr @\exposidnc{synth-three-way-result}@ operator<=>(reference_wrapper, const T&); + friend constexpr @\exposidnc{synth-three-way-result}@ operator<=>(reference_wrapper, + reference_wrapper); }; template @@ -11010,6 +11025,12 @@ \pnum The template parameter \tcode{T} of \tcode{reference_wrapper} may be an incomplete type. +\begin{note} +Using the comparison operators described in subclause \ref{refwrap.comparisons} +with \tcode{T} being an incomplete type +can lead to an ill-formed program +with no diagnostic required\iref{temp.point,temp.constr.atomic}. +\end{note} \rSec3[refwrap.const]{Constructors} @@ -11113,6 +11134,88 @@ \tcode{\placeholdernc{INVOKE}(get(), std::forward(args)...)}.\iref{func.require} \end{itemdescr} +\rSec3[refwrap.comparisons]{Comparisons} + +\begin{itemdecl} +friend constexpr bool operator==(reference_wrapper x, reference_wrapper y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The expression \tcode{x.get() == y.get()} is well-formed and +its result is convertible to \tcode{bool}. + +\pnum +\returns +\tcode{x.get() == y.get()}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(reference_wrapper x, const T& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The expression \tcode{x.get() == y} is well-formed and +its result is convertible to \tcode{bool}. + +\pnum +\returns +\tcode{x.get() == y}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(reference_wrapper x, reference_wrapper y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false} and +the expression \tcode{x.get() == y.get()} is well-formed and +its result is convertible to \tcode{bool}. + +\pnum +\returns +\tcode{x.get() == y.get()}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposidnc{synth-three-way-result}@ operator<=>(reference_wrapper x, reference_wrapper y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{synth-three-way}(x.get(), y.get())}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposidnc{synth-three-way-result}@ operator<=>(reference_wrapper x, const T& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{synth-three-way}(x.get(), y)}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposidnc{synth-three-way-result}@ operator<=>(reference_wrapper x, + reference_wrapper y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + +\pnum +\returns +\tcode{\exposid{synth-three-way}(x.get(), y.get())}. +\end{itemdescr} \rSec3[refwrap.helpers]{Helper functions} @@ -15564,7 +15667,6 @@ \indexlibraryglobal{wformat_context}% \indexlibraryglobal{format_args}% \indexlibraryglobal{wformat_args}% -\indexlibraryglobal{format_args_t}% \indexlibraryglobal{format_to_n_result}% \indexlibrarymember{out}{format_to_n_result}% \indexlibrarymember{size}{format_to_n_result}% @@ -15664,6 +15766,10 @@ // \ref{format.formatter}, formatter template struct formatter; + // \ref{format.formatter.locking}, formatter locking + template + constexpr bool enable_nonlocking_formatter_optimization = false; + // \ref{format.formattable}, concept \libconcept{formattable} template concept formattable = @\seebelow@; @@ -16907,6 +17013,24 @@ \\ \end{concepttable} +\rSec3[format.formatter.locking]{Formatter locking} + +\indexlibraryglobal{enable_nonlocking_formatter_optimization}% +\begin{itemdecl} +template + constexpr bool enable_nonlocking_formatter_optimization = false; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\remarks +Pursuant to \ref{namespace.std}, +users may specialize \tcode{enable_nonlocking_formatter_optimization} for +cv-unqualified program-defined types. +Such specializations shall be usable in constant expressions\iref{expr.const} +and have type \tcode{const bool}. +\end{itemdescr} + \rSec3[format.formattable]{Concept \cname{formattable}} \pnum @@ -17015,6 +17139,13 @@ interpret the format specification as a \fmtgrammarterm{std-format-spec} as described in \ref{format.string.std}. +In addition, +for each type \tcode{T} for which +a \tcode{formatter} specialization is provided above, +each of the headers provides the following specialization: +\begin{codeblock} +template<> inline constexpr bool enable_nonlocking_formatter_optimization = true; +\end{codeblock} \begin{note} Specializations such as \tcode{formatter} and \tcode{formatter} @@ -17272,10 +17403,15 @@ \pnum An instance of \tcode{basic_format_parse_context} holds -the format string parsing state consisting of +the format string parsing state, consisting of the format string range being parsed and the argument counter for automatic indexing. +\pnum +If a program declares an explicit or partial specialization of +\tcode{basic_format_parse_context}, +the program is ill-formed, no diagnostic required. + \indexlibraryctor{basic_format_parse_context}% \begin{itemdecl} constexpr explicit basic_format_parse_context(basic_string_view fmt) noexcept; @@ -17352,8 +17488,10 @@ \pnum \throws -\tcode{format_error} if \tcode{indexing_ == manual} is \tcode{true} -which indicates mixing of automatic and manual argument indexing. +\tcode{format_error} if \tcode{indexing_ == manual} is \tcode{true}. +\begin{note} +This indicates mixing of automatic and manual argument indexing. +\end{note} \pnum \remarks @@ -17379,13 +17517,15 @@ \pnum \throws \tcode{format_error} if -\tcode{indexing_ == automatic} is \tcode{true} -which indicates mixing of automatic and manual argument indexing. +\tcode{indexing_ == automatic} is \tcode{true}. +\begin{note} +This indicates mixing of automatic and manual argument indexing. +\end{note} \pnum \remarks -Call expressions where \tcode{id >= num_args_} is \tcode{true} are not -core constant expressions\iref{expr.const}. +A call to this function is a core constant expression\iref{expr.const} only if +\tcode{id < num_args_} is \tcode{true}. \end{itemdescr} \indexlibrarymember{check_dynamic_spec}{basic_format_parse_context}% @@ -17414,12 +17554,14 @@ \pnum \remarks -Call expressions where -\tcode{id >= num_args_} or +A call to this function is a core constant expression only if +\begin{itemize} +\item +\tcode{id < num_args_} is \tcode{true} and +\item the type of the corresponding format argument -(after conversion to \tcode{basic_format_arg}) -is not one of the types in \tcode{Ts...} -are not core constant expressions\iref{expr.const}. +(after conversion to \tcode{basic_format_arg}) is one of the types in \tcode{Ts...}. +\end{itemize} \end{itemdescr} \indexlibrarymember{check_dynamic_spec_integral}{basic_format_parse_context}% @@ -17481,6 +17623,11 @@ An instance of \tcode{basic_format_context} holds formatting state consisting of the formatting arguments and the output iterator. +\pnum +If a program declares an explicit or partial specialization of +\tcode{basic_format_context}, +the program is ill-formed, no diagnostic required. + \pnum \tcode{Out} shall model \tcode{\libconcept{output_iterator}}. @@ -18859,13 +19006,27 @@ If there are multiple such values, which value is produced is unspecified. A bit in the value representation of the result is indeterminate if it does not correspond to a bit in the value representation of \tcode{from} or -corresponds to a bit of an object that is not within its lifetime or +corresponds to a bit +for which the smallest enclosing object is not within its lifetime or has an indeterminate value\iref{basic.indet}. -For each bit in the value representation of the result that is indeterminate, -the smallest object containing that bit has an indeterminate value; -the behavior is undefined unless that object is -of unsigned ordinary character type or \tcode{std::byte} type. -The result does not otherwise contain any indeterminate values. +A bit in the value representation of the result is erroneous +if it corresponds to a bit +for which the smallest enclosing object has an erroneous value. +For each bit $b$ in the value representation of the result +that is indeterminate or erroneous, +let $u$ be the smallest object containing that bit enclosing $b$: +\begin{itemize} +\item +If $u$ is of unsigned ordinary character type or \tcode{std::byte} type, +$u$ has an indeterminate value +if any of the bits in its value representation are indeterminate, or +otherwise has an erroneous value. +\item +Otherwise, if $b$ is indeterminate, the behavior is undefined. +\item +Otherwise, the behaviour is erroneous, and the result is as specified above. +\end{itemize} +The result does not otherwise contain any indeterminate or erroneous values. \pnum \remarks @@ -19255,9 +19416,18 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\replaceable +A \Cpp{} program may define a function with this function signature, and +thereby displace the default version defined by the \Cpp{} standard library. + +\pnum +\required +This function has no preconditions. \pnum -The semantics of this function are \impldef{semantics of \tcode{is_debugger_present}}. +\default +\impldef{default semantics of \tcode{is_debugger_present}}. \begin{note} When tracing the execution of a program with a debugger, an implementation diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index 56d006ae82..cd814e0a13 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -37,6 +37,37 @@ % P2870R3 Remove `basic_string::reserve()` with no parameters \removedxref{depr.string.capacity} +% P2867R2 Remove deprecated strstreams +\removedxref{depr.istrstream} +\removedxref{depr.istrstream.cons} +\removedxref{depr.istrstream.general} +\removedxref{depr.istrstream.members} +\removedxref{depr.ostrstream} +\removedxref{depr.ostrstream.cons} +\removedxref{depr.ostrstream.general} +\removedxref{depr.ostrstream.members} +\removedxref{depr.str.strstreams} +\removedxref{depr.strstream} +\removedxref{depr.strstream.cons} +\removedxref{depr.strstream.dest} +\removedxref{depr.strstream.general} +\removedxref{depr.strstream.oper} +\removedxref{depr.strstream.syn} +\removedxref{depr.strstreambuf} +\removedxref{depr.strstreambuf.cons} +\removedxref{depr.strstreambuf.general} +\removedxref{depr.strstreambuf.members} +\removedxref{depr.strstreambuf.virtuals} + +% P2869R4 Remove deprecated shared_ptr atomic access +\removedxref{depr.util.smartptr.shared.atomic} + +% P2872R3 Remove wstring_convert +\removedxref{depr.conversions} +\removedxref{depr.conversions.buffer} +\removedxref{depr.conversions.general} +\removedxref{depr.conversions.string} + %%% Renamed sections. %%% Examples: % @@ -48,6 +79,9 @@ % https://github.com/cplusplus/draft/pull/6255 \movedxref{container.gen.reqmts}{container.requirements.general} +% P2875 Undeprecate polymorphic_allocator::destroy +\movedxref{depr.mem.poly.allocator.mem}{mem.poly.allocator.mem} + % https://github.com/cplusplus/draft/pull/6653 \movedxref{mismatch}{alg.mismatch} diff --git a/tools/check-source.sh b/tools/check-source.sh index f5262fee1e..5ddbdf9dfc 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -125,7 +125,7 @@ grep -ne '\bexplicit\b.*\bconstexpr\b' $texlib | fail 'explicit constexpr' || failed=1 # In library declarations, static should not follow constexpr -grep -ne '\bconstexpr\b.*\bstatic\b' $texlib | grep -ve '\bconstexpr\b.*\bnon-static\b' | +grep -ne '\bconstexpr\b.*\sstatic\s' $texlib | fail 'constexpr static' || failed=1 # "Class" heading without namespace