diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 45b4a1b4fc..2c1415675c 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -2,12 +2,11 @@ name: check -on: - pull_request: - push: +on: [pull_request, push] defaults: run: + shell: bash working-directory: source jobs: @@ -16,18 +15,25 @@ jobs: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 - - name: check-source + - name: checkout + uses: actions/checkout@v2 + + - name: check-source.sh run: ../tools/check-source.sh + - name: update-apt-cache run: sudo apt-get update + - name: install run: sudo apt-get install latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended lmodern + - name: make run: make quiet - - name: check-output + + - name: check-output.sh run: ../tools/check-output.sh - - name: upload pdf + + - name: upload PDF uses: actions/upload-artifact@v2 with: name: draft-snapshot diff --git a/papers/n4911.html b/papers/n4911.html new file mode 100644 index 0000000000..11b62cf3a1 --- /dev/null +++ b/papers/n4911.html @@ -0,0 +1,1027 @@ + + + + + +N4911 + + +

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

+ +

Date: 2022-03-17

+ +

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

+ +

Email: cxxeditor@gmail.com

+ +

Acknowledgements

+ +

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

+ +

New papers

+ + + +

Motions incorporated into working draft

+ +

Core working group polls

+ +

CWG poll 1: Accept as Defect Reports all issues except issue 2502 in +P2533R0 +(Core Language Working Group "ready" Issues for the February, 2022 meeting) and +apply the proposed resolutions for all of the issues to the C++ working paper.

+ +

CWG poll 2: Apply the changes in +P2173R1 +(Attributes on Lambda-Expressions) to the C++ Working Paper.

+ +

CWG poll 3: Apply the changes in +P2493R0 +(Missing feature test macros for C++20 core papers) to the C++ Working Paper.

+ +

Library working group polls

+ +

LWG poll 1: Apply the changes for all Tentatively Ready issues in +P2531R0 (C++ +Standard Library Issues to be moved in Virtual Plenary, Feb. 2022) to the C++ +working paper.

+ +

LWG poll 2: Apply the changes in +P0323R12 +(std::expected) to the C++ working paper.

+ +

LWG poll 3: Apply the changes in +P0533R9 +(constexpr for <cmath> and <cstdlib>) to the C++ working paper.

+ +

LWG poll 4: Apply the changes in +P0627R6 +(Function to mark unreachable code) to the C++ working paper.

+ +

LWG poll 5: Apply the changes in +P1206R7 +(ranges::to: A function to convert any range to a container) to the C++ working +paper.

+ +

LWG poll 6: Apply the changes in +P1413R3 +(Deprecate std::aligned_storage and std::aligned_union) to the C++ working +paper.

+ +

LWG poll 7: Apply the changes in +P2255R2 (A +type trait to detect reference binding to temporary) to the C++ working paper.

+ +

LWG poll 8: Apply the changes in +P2273R3 +(Making std::unique_ptr constexpr) to the C++ working paper.

+ +

LWG poll 9: Apply the changes in +P2387R3 +(Pipe support for user-defined range adaptors) to the C++ working paper.

+ +

LWG poll 10: Apply the changes in +P2440R1 +(ranges::iota, ranges::shift_left and ranges::shift_right) to the C++ +working paper.

+ +

LWG poll 11: Apply the changes in +P2441R2 +(views::join_with) to the C++ working paper.

+ +

LWG poll 12: Apply the changes in +P2442R1 +(Windowing range adaptors: views::chunk and views::slide) to the C++ working +paper.

+ +

LWG poll 13: Apply the changes in +P2443R1 +(views::chunk_by) to the C++ working paper.

+ +

Editorial changes

+ +

Notes on motions

+ + + +

Clause reorganization

+ +

We rearranged several clauses and subclauses. Over the years, the original +clause structure had been becoming less appropriate for the growing amount of +content, and we hope that the new structure is more suitable to the current (and +anticipated future) content.

+ + + +

We are aiming to not change the top-level clause structure more than once per +standard publication cycle. We have had suggestions to create a new top-level +clause "Text" for text-related content (such as locales and regular expressions, +but also anticipating new material). We have not yet reached consensus, and we +will probably perform that reorganization during the C++26 cycle.

+ +

Requirements tables

+ +

We have begun replacing the large requirements tables in the library with more +conventional paragraphs, as described in editorial paper +P2416R2. +Each requirement is now presented in a style similar to that of function +declarations, followed by as many specification elements as appropriate. A new +"Result:" element has been added to capture the type of a type requirement, +and the type and value category of an expression requirement.

+ +

We have applied these changes to the container, allocator, and regular +expression trait requirements.

+ +

Term labels

+ +

We have started introducing explicit LaTeX labels for defined terms, and we have +updated cross references to refer to those term labels instead of the label of +the subclause that contains the term. This does not change the presentation of +the reference, but makes it less likely that cross references are invalidated by +moving text around.

+ +

In the future, we might extend this to turn the use of a term into a hyperlink +to the page on which the term's definition appears.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4901 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 04e0ea7074c9b0d0ca939821ce0f575c589df6b7
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Oct 21 23:52:55 2021 +0200
+
+    [pairs.pair] Use T1/T2, not first_type/second_type
+
+commit ed6e1b5da5d13449cf27c878c60e90892289f98a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 23 01:20:31 2021 +0200
+
+    [index] Fix dangling 'see' references
+
+    Also update the automatic check script to prevent
+    further occurrences.
+
+commit 3d1424716844aef59891d770709e19d83b5bea35
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 24 22:05:40 2021 +0200
+
+    [ranges] Remove \expos markers for nested types (#4829)
+
+    An \expos marker should appear only on the first
+    declaration of a name.
+
+commit 741c20794fdc7aec28afcd9e6c52d6d184d2845c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Oct 26 16:36:39 2021 +0200
+
+    [class.copy.assign] Fix phrasing in note to avoid 'could'. (#4418)
+
+commit f3ab334c789ac89d2f6baf501d60716278cb8fa3
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Jul 4 23:30:42 2021 +0200
+
+    [contents] Add special lookup treatment for swap
+
+commit 280684c7824b6b7f62c003b909ccf3703d82681b
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Mon Nov 8 07:19:14 2021 -0400
+
+    [defs] Update introduction to match ISO Directives (#5096)
+
+    Reference: https://www.iso.org/sites/directives/current/part2/index.xhtml#_idTextAnchor218
+
+commit 1567c481e3ca3c52f80e4a33db0f913ce1392c4d
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Nov 9 09:31:08 2021 +0000
+
+    [intro.refs] Update dated reference to previous POSIX standard
+
+    Fixes #5098
+
+commit c8ec4ab45f58e3a16d8dcb12bd660dd2cf6e936a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Nov 23 17:22:38 2021 +0100
+
+    [refwrap.general] Add cross-references to the class synopsis (#5122)
+
+    Also rename [refwrap.const], because it does not specify
+    any destructors.
+
+commit b4bf594c81865f892bae81342ffb67c8ca8adb74
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Nov 23 17:24:35 2021 +0100
+
+    [smartptr] Rework subclause nesting (#5119)
+
+commit d0cb462d511e5c9bf1ae7403c275f7c1ccf2543d
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Sat Nov 20 02:16:40 2021 +0800
+
+    [range.adjacent.overview] Fix multi-character in example
+
+commit 26f6a1f7573ea54ed93b4e90d0e487fe39d44b87
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Nov 13 10:01:36 2021 +0100
+
+    [dcl.typedef] Add explanation for lookup failure in example
+
+commit c63e5e836e8dbe0ae6c7ebc1b2a1b1534d37a220
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Nov 10 23:40:48 2021 +0100
+
+    [input.output] Fix headings of 'assign and swap' subclauses
+
+commit d2699e5de0c10085df309074d2dfbc57d5bc86bb
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Oct 27 21:20:02 2021 +0200
+
+    [std] Replace 'OK:' in code comments with 'OK,'
+
+    In contrast to errors, which use a colon, an OK comment
+    is not followed by any unique reason why the code is
+    well-formed, but by a subjective highlighting of a fact.
+
+commit 5e3f1ad0ceb89feb2977a0531422bcbe9ab8fba7
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Oct 26 21:49:15 2021 +0200
+
+    [stdatomic.h.syn] Fix missing \expos
+
+    and augment the autmatic checks accordingly.
+
+commit 16e60c63ad14f3f3fc9132a8443421a15ebec8fc
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Nov 9 13:09:27 2021 +0100
+
+    [locale.time.get] Replace 'ISO/IEC 9945' with 'POSIX'
+
+    We introduce POSIX as an alias for ISO/IEC 9945, and we use 'POSIX'
+    everywhere else.
+
+commit 31c32e035770797eedc69f150c3a3484bbe828a5
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Nov 9 17:54:18 2021 +0100
+
+    [locale.time.get.virtuals] Use 'conversion specification'
+
+    POSIX does not define the term 'conversion directive'.
+
+commit fbab3f13719c34affdb7b712aed7f6d2313570d7
+Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com>
+Date:   Tue Nov 23 20:03:13 2021 +0300
+
+    [defns.access, basic.lval] Clarify what can be accessed and how (#4777)
+
+commit 5475bdab828b3585a21172945303ccebbcefb516
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Oct 21 22:11:07 2021 +0200
+
+    [c.mb.wcs] mbrtoc8 stores code units, not characters
+
+commit ba4bb3ee56b94b63d0d1e5914a136a04b1620052
+Author: mordante <koraq@xs4all.nl>
+Date:   Tue Nov 23 18:13:22 2021 +0100
+
+    [format.functions] Add "std::move" around "out" (#5069)
+
+    This fixes a misapplication of the resolution of LWG 3539.
+
+commit 0d0ec1a1393b3baae564234007c94b80da9bab48
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Nov 23 18:15:55 2021 +0100
+
+    [func.wrap.{func.general, move.class}] Remove 'first-class object' (#5067)
+
+    The term is undefined and does not improve the specification.
+
+commit d27c3b388befadc4c35aac1d12f0ba8581f14a5f
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Nov 12 14:29:00 2021 +0000
+
+    [spanstream.ctor] Fix base class name in effects
+
+commit c1935504da840995b1bb60eba536cb12bca5ae71
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Tue Nov 23 11:51:37 2021 -0600
+
+    [basic.start.main] Remove redundant phrase (#5083)
+
+commit 70eb0406596b4f4e3d97ed50b3fd6d93b3032d18
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 25 23:57:58 2021 +0200
+
+    [basic.start.main] Avoid implementation guidance in a note
+
+commit ac8d6611a739c64eda4a7062f2cb83f770cd8a53
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 25 23:58:08 2021 +0200
+
+    [dcl.link] Avoid implementation guidance in a note
+
+commit 2ad67aefe350017c4e9403ba2015af683813787f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Nov 6 22:08:47 2021 +0100
+
+    [lex] Remove Unicode character name abbreviations
+
+    They are not part of the character name or alias.
+    The presentation in ISO 10646 is misleading, though.
+
+commit 29c89b16e92cd03a76eb2a19866e683a7bb7ac80
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Nov 6 22:15:05 2021 +0100
+
+    [lex] Rename U+0007 BELL to ALERT
+
+    The former is ambiguous with U+1F514 BELL.
+    The ALERT alias is defined in UCD NameAliases.txt.
+
+commit 408623b7d8f0efd77403d1d0142d9bd59d1cfe55
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Dec 4 11:19:54 2021 +0100
+
+    [associative.reqmts.general] Fix typo: 'kx', not 'rx' (#5136)
+
+commit f03473cd1e32691c105260e65dd534960cf9db21
+Author: Neven Sajko <nsajko@gmail.com>
+Date:   Sun Dec 5 21:19:00 2021 +0100
+
+    [over.sub] Fix typo: change oeprator to operator (#5140)
+
+commit c69a35501174f5ab5d3f13f12186cc9b1fcd40dd
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Dec 14 11:24:04 2021 +0100
+
+    [range.access] Fix cross-references for 'array' (#5147)
+
+    Also introduce a label 'term.array.type' in [dcl.array].
+
+commit 7a09dddd036359a10cf10b8e7d80c8edd8c76817
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 16 19:39:18 2021 +0100
+
+    [basic.fundamental] Excise normative requirements on std::numeric_limits (#5105)
+
+commit c2617432eac3313abd2134a26e2d8a1d925dfd15
+Author: Casey Carter <Casey@Carter.net>
+Date:   Thu Dec 16 23:53:17 2021 -0800
+
+    [depr.default.allocator] Index allocator::is_always_equal here (#5152)
+
+    LWG3170 deprecated `allocator::is_always_equal`. We moved it to Annex D, but left the index entry behind.
+
+commit 28effaea15ef697f5a64fba47b9c095c9fbfe82a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Dec 19 22:16:18 2021 +0100
+
+    [ptr.align,re.regiter.incr] Replace 'compiler' with 'implementation'
+
+commit 575b9a99062de34cc44bc45aeb459f32aa12b98f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Dec 19 22:19:19 2021 +0100
+
+    [smartptr.adapt] Emphasize that casting might not always be viable
+
+commit 9ba8e0329a0f5db15544c31c514ff44e0003f08f
+Author: frederick-vs-ja <de34@live.cn>
+Date:   Tue Jan 11 23:29:26 2022 +0800
+
+    [pairs.pair] Add missing _v for type traits (#5196)
+
+commit dae6769d9767e2e47f2fe451d9c796dd07d0ae29
+Author: zhihaoy <43971430+zhihaoy@users.noreply.github.com>
+Date:   Thu Jan 13 14:03:25 2022 -0800
+
+    [func.memfn] Correct target object by fixing typo (#5202)
+
+commit 5f830f97829965cf791dfe6eef6b84d6283712be
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Nov 24 22:04:55 2021 +0100
+
+    [lib] Add 'namespace std' wrappings around class definitions
+
+    Those were missing in a few places, notably [rand].
+
+    Also add an automated check.
+
+commit 1031a409dfacb84b9871b16502c73e15249160eb
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Nov 19 23:02:19 2021 +0100
+
+    [chrono.syn] Use nested namespace definitions for clarity
+
+commit dad631ac4bd30e7ab6de5a888f77ed2b5b44c17d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Nov 6 09:39:55 2021 +0100
+
+    [except.throw,except.handle] Move lvalue specification for copies
+
+commit c6e5eea4f11efec62a4718acd4eb17fb99fd4899
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 25 23:41:31 2021 +0200
+
+    [expr.prim.req.general] Change requirement-seq to right-recursive
+
+    consistent with the specification of other -seq non-terminals.
+
+commit 872fce6effc603735c9717981807eb6bb8b4f838
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Dec 4 11:33:32 2021 +0100
+
+    [associative.reqmts.general] Fix confusing local use of 'r'
+
+commit 3d1bf58b74860fc1e86cd1cf536b7022b90d688d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Jan 7 20:26:15 2022 +0100
+
+    [temp.res.general] Clarify binding of names
+
+commit 4123264d22c7617d828083c9ad954b5541934621
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 25 18:15:14 2021 +0200
+
+    [temp.constr.atomic] Fix phrasing in note
+
+commit 26ce304780d79bba03a791b2f4299f083f021238
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Dec 14 09:25:41 2021 +0100
+
+    [dcl.meaning.general] Clarify correspondence for block-scope friends
+
+commit 3c19e315dbb05a2c22b8f5b075af39a7572cdaa1
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 23 11:18:17 2021 +0100
+
+    [meta.rel] Avoid undefined term 'void types'
+
+commit 90d178d022c7d597629853ebc70262489e49d5e9
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Jan 14 19:46:15 2022 +0100
+
+    [class.default.ctor] Fix implicit invocation of default constructor  (#4026)
+
+    Initialization is fully specified in [dcl.init],
+    so turn the list of default-initialization cases
+    into a note and shorten it appropriately.
+
+commit e1bfc25c56c7ab303241f980fa00d7ae402e1f5c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Jul 5 23:51:41 2021 +0200
+
+    [stmt.return,class.{ctor,dtor}] Clarify no return operand
+
+    Highlight that constructors and destructors do not have a
+    return type and thus a return statement within a constructor
+    or destructor cannot have an operand.
+
+commit b345505b88b376d547220254fd858840efbfb937
+Author: Chuanqi Xu <yedeng.yd@linux.alibaba.com>
+Date:   Fri Jan 14 10:10:11 2022 +0800
+
+    [temp.param] Delete outdated wording at p15
+
+    The wording at [temp.param]/15 says:
+    > A template-parameter shall not be given default arguments by two
+    > different declarations if one is reachable from the other.
+
+    But it is conflicted with [basic.def.odr]/13:
+    > There can be more than one definition of a
+    > ...
+    >       default template argument
+    > ...
+    > in a program provided that each definition appears in a different
+    > translation unit and the definitions satisfy the [same-meaning
+    > criteria of the ODR].
+
+    [temp.param] should be deleted otherwise we couldn't modularize a real
+    project.
+
+commit fc9818bcdaa08f65c8d99f7df70b418810c36893
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 15 09:43:55 2022 +0100
+
+    [util.smartptr.atomic] Add cross-reference to <memory> header (#5207)
+
+commit 5c59ede65b362afb418bda3cf82123ae2ca2553c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 23 11:36:39 2021 +0100
+
+    [locale.ctype.virtuals] Clarify do_widen parameter
+
+commit cec2d218209abf2979a3c7fabc9970d8677b9e63
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 23 12:53:01 2021 +0100
+
+    [diff.stmt] Properly refer to function return types
+
+    Also annotate the 'void' and 'int' keywords.
+
+commit ba9124e62ea85c922d501dfc52bc4d44c85933bd
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Jan 21 15:57:58 2022 +0000
+
+    [util.smartptr.atomic.general] Fix cross-reference to shared_ptr (#5222)
+
+commit 3cb2ee9d67360612e6361aa26d1805c8ed30c6e6
+Author: Chuanqi Xu <68680648+ChuanqiXu9@users.noreply.github.com>
+Date:   Sat Jan 22 17:43:22 2022 +0800
+
+    [temp.dep.general] add trailing 'or' (#5186)
+
+commit 4e2dbd25fa137f12c8fa6b960bc2db45be994414
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 22 13:38:10 2022 +0100
+
+    [class.free] Move into [class.mem]
+
+    The class-specific allocation and deallocation functions,
+    whose declaration properties are specified in this section,
+    are class member functions.
+
+commit 7987ef93488842bbdbbd6e4de996f463939fe0e8
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 22 13:45:23 2022 +0100
+
+    [class.free] Change subclause heading and add indexing
+
+    Rename the heading to "Allocation and deallocation functions",
+    which is more appropriate for the contents of the subclause.
+
+commit 07db0b3182495339b00221bba41549913e0a6a0e
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 22 14:35:11 2022 +0100
+
+    [stacktrace] Move into [diagnostics]
+
+commit 0df02c99d04dd0e0d29ea520904ea64f69ea6c36
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Jan 20 19:42:09 2022 +0100
+
+    [class.mem.general] Add cross-reference for 'layout-compatible type'
+
+commit 2e5976f894d821e442a6f98c3e235381f8067570
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Jan 20 19:36:15 2022 +0100
+
+    [stmt.return] Clarify flowing off the end of a function
+
+commit 88541f7ad5de85389adb0e88f295091d29f00030
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Jan 25 23:12:55 2022 +0100
+
+    [range.req.general] Remove incorrect normative duplication for 'view' (#5235)
+
+commit 0539c5e2cdf7605c5704eb2b63916b6c5c3b9539
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Feb 18 13:42:57 2021 +0100
+
+    [macros,structure.specifications] Add 'Result' element
+
+commit 408a22b1b58207de4af28d59afd20156e715e35f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Jan 7 23:48:43 2021 +0100
+
+    [re.req] Replace requirements table with \itemdescr
+
+commit 93ff092d1cd2b335f372b9546365b3d495caf2d8
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Nov 14 20:05:03 2021 +0100
+
+    [container.requirements] Replace requirements tables with \itemdescr
+
+    and adjust cross-references to container requirements tables
+    throughout the standard library.
+
+commit 4b1a735f393aa5c864d0a5aba45514aec63f5a90
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Jun 27 11:26:39 2021 +0200
+
+    [container.requirements] Omit redundant specification
+
+    where "Effects: Equivalent to" wording is used.
+
+commit d37470de0392f032d96c85610c947918269532a9
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Feb 20 00:09:56 2022 +0100
+
+    [lex.name] Rephrase note to avoid upper/lower-case
+
+commit efd0cab6f2d11f29f205c15672108f6e20de6010
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Feb 20 14:28:36 2022 +0100
+
+    [lib] Add missing \pnum before descriptive elements
+
+    Also fix the ineffective check script by rewriting the
+    check in straightforward awk.
+
+commit ff92c80b70b9cd887512f96e5d5525c20550d12f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Feb 6 09:52:01 2022 +0100
+
+    [iterator.concept.winc] Remove duplicate paragraph
+
+    This fixes a bad merge between P2393R1 Cleaning up integer-class types
+    and P2321R2 zip.
+
+commit a4dfa1f0c46152d3a3399bc32a60fcf11edd4a5d
+Author: Chuanqi Xu <68680648+ChuanqiXu9@users.noreply.github.com>
+Date:   Mon Feb 21 07:18:41 2022 +0800
+
+    [module.interface] Add adjective 'exported' (#5290)
+
+    It was clear in context that "the declaration" is exported, but
+    it is easier to understand if we restate "an exported declaration".
+
+commit 90ef396f088a4e1730a3f73f3db44d9ad8b872b7
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Feb 1 13:58:38 2022 +0000
+
+    [fs.class.directory.iterator.general] Fix grammar
+
+commit 1155c4a361c446eee4602b7fd2e82eba7a4f8c4f
+Author: languagelawyer <language.lawyer@gmail.com>
+Date:   Sat Jan 22 23:27:49 2022 +0300
+
+    [temp.res] Move a note outside itemize environment
+
+commit 44c79f59de6c4ea179bacc698272d713e696b117
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 29 09:37:59 2022 +0100
+
+    [derivation] Remove 'basic integral type' from footnote
+
+    Also switch footnote to note.
+
+commit 785b0a84e7b0f8108b5140f33494ceff3d0bd282
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 23 11:40:48 2021 +0100
+
+    [diff.expr] Replace 'will' with present tense
+
+    Also annotate the 'void' keyword.
+
+commit 97a72e1c4f1616f2163d34deafea010d68099a7c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Dec 5 21:22:48 2021 +0100
+
+    [temp.local] Fix type-name interpretation of injected-class-name
+
+commit a8e63922a5f049ab2c58a33117913688b8dc096a
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Feb 21 20:27:01 2022 +0800
+
+    [container.gen.reqmts] Replace "Value:" with "Returns:" (#5256)
+
+commit d267cde4fcc2c13ef87170d68f94f1ae6e499c23
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Feb 21 13:51:45 2022 +0100
+
+    [over.best.ics] Clarify phrasing around user-defined conversion sequence (#5086)
+
+    This replaces the use of "with" that is popular in mathematical writing
+    with a more common construction.
+
+commit 7424b45d8470b8765cdf3b25bcfd9a9a89c0c936
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Jan 3 22:24:23 2022 +0100
+
+    [expr] Cleanup for 'discarded-value expression'
+
+commit b5ce71b34217f9d974e96cc366984cbd5f4b71e6
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Dec 17 20:31:57 2021 +0100
+
+    [atomics] Harmonize references to atomics operations tables
+
+commit ef78018c8d61d79dc9cddc5f4b2d00a7929964fa
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Jan 21 23:01:25 2022 +0100
+
+    [std] Replace hyphen with period in labels
+
+    and add a check.
+
+commit 58ea575dd9b4a410dcf457b3357bef4a720e1608
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Jan 13 23:21:05 2022 +0100
+
+    [function.objects,ranges] Introduce labels for call wrappers
+
+    In particular, 'term.perfect.forwarding.call.wrapper'
+    and 'term.simple.call.wrapper', and refer to them.
+
+commit 0c53beacef2289e4cc4fabbdff99eb3b6c7ae4ad
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Jul 5 23:16:20 2021 +0200
+
+    [unique.ptr.single] Rephrase destruction
+
+commit 03b9040814ecd548f2de18668df0655ef7b37efb
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Tue Feb 22 09:39:37 2022 +0800
+
+    [version.syn] Remove mention of nonexistent header `<priority_queue>`
+
+commit 97430e8f867f5b97f79c8064c32dd1bde117198a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Nov 22 22:20:16 2021 +0100
+
+    [allocator.adaptor.members] Fix select_on_container_copy_construction
+
+    The description was confusing objects and types.
+
+commit 2cd31adb2033b4ae82339ef270bc058128cbd199
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 22:38:13 2022 +0100
+
+    [bit] Move into [utilities]
+
+commit e3532fd233355f93558f6a53d14b72e16a1f1ed2
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 22:44:52 2022 +0100
+
+    [memory] Create new clause
+
+    and move [memory], [smartptr], [mem.res], and [allocator.adaptor]
+    from [utilities] into the new clause.
+
+commit cb7b98d46c4603ccc485fe826fb4363cb2c039bf
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 22:48:10 2022 +0100
+
+    [comparisons.three.way,func.search] Add namespace around class definition
+
+commit 1daeb8e44b659c5cdf7133df68def1264c8b5774
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 22:54:01 2022 +0100
+
+    Move [string.view] to before [string.classes]
+
+commit 724e83e4d0cd82737952711d31505872188269ab
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 23:01:35 2022 +0100
+
+    [meta] Create new clause
+
+    and move [intseq], [meta], and [ratio] from [utilities] into the
+    new clause.
+
+commit af8334b94be2df5bf009ef7381460f56e6224c44
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 23:06:45 2022 +0100
+
+    [meta] Adjust cross-references
+
+commit d74c2170a9f4c928519461d7742293af2d141852
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 23:19:51 2022 +0100
+
+    Move [atomics] into [thread]
+
+    Rename [thread] to 'Concurrency support library'.
+
+commit 888602381e6c4e5fc886a7e575a95c905998b487
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Feb 24 11:35:19 2022 +0800
+
+    [headers] List <expected>
+
+commit aa2c64589cf2a784e9c551a2a54df59b880613d3
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Feb 24 15:09:08 2022 +0100
+
+    [thread] Rename to 'Concurrency support library'
+
+    Missed update with commit d74c2170a9f4c928519461d7742293af2d141852.
+
+commit 000d4c091a244b3bf81470c6c6a4f2f35c3ec602
+Author: hewillk <67143766+hewillk@users.noreply.github.com>
+Date:   Fri Feb 25 01:14:48 2022 +0800
+
+    [range.chunk.outer.value] Add missing private specifier
+
+commit 2901f3f6c00060e6c0a368efd28fd50ba07350f1
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Feb 25 23:38:49 2022 +0100
+
+    [diff.cpp20.library] Add subclause, highlighting new headers
+
+commit 1c88b6bdafb2eb128e7da05815f3b30fa52d3710
+Author: hewillk <67143766+hewillk@users.noreply.github.com>
+Date:   Sun Feb 27 21:23:40 2022 +0800
+
+    [range.slide.overview] Fix bad quotation marks for string-literal (#5326)
+
+commit dd346dcbd723ae27d6a2c2a74aad8a17a62ea687
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Mar 6 00:18:57 2022 +0100
+
+    [expr.const] Add cross-reference for construct_at
+
+commit 8679960561e6f18ca533915626cdd5ecd349bcf4
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Feb 27 22:22:30 2022 +0100
+
+    [allocator.requirements.general] Replace table for descriptive variables
+
+commit 0befc0e9f7e1df2451fa115b9ff12dbd8d384c5d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Feb 27 23:59:42 2022 +0100
+
+    [allocator.requirements.general] Dismantle requirements table
+
+commit 4e4aa46276d1542b2f0ff66ebd0f66df8ba0d785
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Feb 28 00:17:47 2022 +0100
+
+    [lib] Fix cross-references to replaced table cpp17.allocator
+
+commit 2d8e11333fe4e188a940bc5c4e1a2f33b139ee3b
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Mon Feb 21 14:49:31 2022 -0400
+
+    [array.overview] Don't mention swap as an exception
+
+    The container requirements already describe this behavior,
+    so from the POV of this subclause, there's no exception.
+
+commit 65e74383deb8bcc0cab8e813b6360e9b1e8f6b10
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Mon Feb 21 14:52:15 2022 -0400
+
+    [array.overview] Mention condition of exception
+
diff --git a/papers/n4911.md b/papers/n4911.md new file mode 100644 index 0000000000..35188804ab --- /dev/null +++ b/papers/n4911.md @@ -0,0 +1,892 @@ +# N4911 Editors' Report -- Programming Languages -- C++ + +Date: 2022-03-17 + +Thomas Köppe (editor, Google DeepMind) +Jens Maurer (co-editor) +Dawn Perchik (co-editor, Bright Side Computing, LLC) +Richard Smith (co-editor, Google Inc) + +Email: `cxxeditor@gmail.com` + +## Acknowledgements + +Thanks to all those who have [submitted editorial +issues](https://github.com/cplusplus/draft/wiki/How-to-submit-an-editorial-issue) +and to those who have provided pull requests with fixes, and special thanks to +Johel Ernesto Guerrero Peña for providing in-depth review of most of the draft +motion applications. + +## New papers + + * [N4910](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4910.pdf) is the + current working draft for C++23. It replaces + [N4901](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4901.pdf). + * N4911 is this Editors' Report. + +## Motions incorporated into working draft + +### Core working group polls + +CWG poll 1: Accept as Defect Reports all issues _except issue 2502_ in +[P2533R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2533r0.html) +(Core Language Working Group "ready" Issues for the February, 2022 meeting) and +apply the proposed resolutions for all of the issues to the C++ working paper. + +CWG poll 2: Apply the changes in +[P2173R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2173r1.pdf) +(Attributes on Lambda-Expressions) to the C++ Working Paper. + +CWG poll 3: Apply the changes in +[P2493R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2493r0.html) +(Missing feature test macros for C++20 core papers) to the C++ Working Paper. + +### Library working group polls + +LWG poll 1: Apply the changes for all Tentatively Ready issues in +[P2531R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2531r0.html) (C++ +Standard Library Issues to be moved in Virtual Plenary, Feb. 2022) to the C++ +working paper. + +LWG poll 2: Apply the changes in +[P0323R12](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p0323r12.html) +(`std::expected`) to the C++ working paper. + +LWG poll 3: Apply the changes in +[P0533R9](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0533r9.pdf) +(constexpr for `` and ``) to the C++ working paper. + +LWG poll 4: Apply the changes in +[P0627R6](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0627r6.pdf) +(Function to mark unreachable code) to the C++ working paper. + +LWG poll 5: Apply the changes in +[P1206R7](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1206r7.pdf) +(ranges::to: A function to convert any range to a container) to the C++ working +paper. + +LWG poll 6: Apply the changes in +[P1413R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1413r3.pdf) +(Deprecate `std::aligned_storage` and `std::aligned_union`) to the C++ working +paper. + +LWG poll 7: Apply the changes in +[P2255R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2255r2.html) (A +type trait to detect reference binding to temporary) to the C++ working paper. + +LWG poll 8: Apply the changes in +[P2273R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2273r3.pdf) +(Making `std::unique_ptr` constexpr) to the C++ working paper. + +LWG poll 9: Apply the changes in +[P2387R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2387r3.html) +(Pipe support for user-defined range adaptors) to the C++ working paper. + +LWG poll 10: Apply the changes in +[P2440R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2440r1.html) +(`ranges::iota`, `ranges::shift_left` and `ranges::shift_right`) to the C++ +working paper. + +LWG poll 11: Apply the changes in +[P2441R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2441r2.html) +(`views::join_with`) to the C++ working paper. + +LWG poll 12: Apply the changes in +[P2442R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2442r1.html) +(Windowing range adaptors: `views::chunk` and `views::slide`) to the C++ working +paper. + +LWG poll 13: Apply the changes in +[P2443R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2443r1.html) +(`views::chunk_by`) to the C++ working paper. + +## Editorial changes + +### Notes on motions + +* **Poll CWG-2:** The wording was adjusted to integrate with the new wording + from issue + [CWG-2509](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2533r0.html#2509) + to use the new term _lambda-specifier-seq_ instead of the original + _decl-specifier-seq_. + +* **Poll LWG-1:** Issue + [LWG-3616](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2531r0.html#3616) + was skipped, since it had already been [applied + editorially](https://github.com/cplusplus/draft/commit/8753efabbbfec8371a82de1af60337fa6a6b6dc2). + +* **Poll LWG-8:** The wording was integrated with the resolution of + [LWG-3632](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2531r0.html#3632). + +### Clause reorganization + +We rearranged several clauses and subclauses. Over the years, the original +clause structure had been becoming less appropriate for the growing amount of +content, and we hope that the new structure is more suitable to the current (and +anticipated future) content. + +* New top-level clause "Memory management library [mem]", after [diagnostics]. + This clause contains ``, memory parts of ``, smart pointers, + memory resources, and scoped allocators, previously part of [utilities]. + +* The "Metaprogramming library [meta]" subclause from [utilities] is now a + new top-level clause, in between [mem] and [utilities]. We expect future + reflection material to be added to this clause. + +* The "Atomic operations [atomics]" clause has been integrated into the + top-level [thread] clause, which has been renamed to "Concurrency support + library [thread]". + +* "Bit manipulation [bit]" has been moved to the end of the [utilities] clause. + +* "Stacktrace [stacktrace]" has been moved to the end of the [diagnostics] clause. + +* "String view classes [string.view]" has been moved to immediately before + [string.classes]. + +* "Allocation and deallocation functions [class.free]" has been moved to + immediately before [class.nest]. + +We are aiming to not change the top-level clause structure more than once per +standard publication cycle. We have had suggestions to create a new top-level +clause "Text" for text-related content (such as locales and regular expressions, +but also anticipating new material). We have not yet reached consensus, and we +will probably perform that reorganization during the C++26 cycle. + +### Requirements tables + +We have begun replacing the large requirements tables in the library with more +conventional paragraphs, as described in editorial paper +[P2416R2](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2416r2.pdf). +Each requirement is now presented in a style similar to that of function +declarations, followed by as many specification elements as appropriate. A new +"_Result_:" element has been added to capture the type of a type requirement, +and the type and value category of an expression requirement. + +We have applied these changes to the container, allocator, and regular +expression trait requirements. + +### Term labels + +We have started introducing explicit LaTeX labels for defined terms, and we have +updated cross references to refer to those term labels instead of the label of +the subclause that contains the term. This does not change the presentation of +the reference, but makes it less likely that cross references are invalidated by +moving text around. + +In the future, we might extend this to turn the use of a term into a hyperlink +to the page on which the term's definition appears. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4901 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/n4901...n4910). + + commit 04e0ea7074c9b0d0ca939821ce0f575c589df6b7 + Author: Jens Maurer + Date: Thu Oct 21 23:52:55 2021 +0200 + + [pairs.pair] Use T1/T2, not first_type/second_type + + commit ed6e1b5da5d13449cf27c878c60e90892289f98a + Author: Jens Maurer + Date: Sat Oct 23 01:20:31 2021 +0200 + + [index] Fix dangling 'see' references + + Also update the automatic check script to prevent + further occurrences. + + commit 3d1424716844aef59891d770709e19d83b5bea35 + Author: Jens Maurer + Date: Sun Oct 24 22:05:40 2021 +0200 + + [ranges] Remove \expos markers for nested types (#4829) + + An \expos marker should appear only on the first + declaration of a name. + + commit 741c20794fdc7aec28afcd9e6c52d6d184d2845c + Author: Jens Maurer + Date: Tue Oct 26 16:36:39 2021 +0200 + + [class.copy.assign] Fix phrasing in note to avoid 'could'. (#4418) + + commit f3ab334c789ac89d2f6baf501d60716278cb8fa3 + Author: Jens Maurer + Date: Sun Jul 4 23:30:42 2021 +0200 + + [contents] Add special lookup treatment for swap + + commit 280684c7824b6b7f62c003b909ccf3703d82681b + Author: Johel Ernesto Guerrero Peña + Date: Mon Nov 8 07:19:14 2021 -0400 + + [defs] Update introduction to match ISO Directives (#5096) + + Reference: https://www.iso.org/sites/directives/current/part2/index.xhtml#_idTextAnchor218 + + commit 1567c481e3ca3c52f80e4a33db0f913ce1392c4d + Author: Jonathan Wakely + Date: Tue Nov 9 09:31:08 2021 +0000 + + [intro.refs] Update dated reference to previous POSIX standard + + Fixes #5098 + + commit c8ec4ab45f58e3a16d8dcb12bd660dd2cf6e936a + Author: Jens Maurer + Date: Tue Nov 23 17:22:38 2021 +0100 + + [refwrap.general] Add cross-references to the class synopsis (#5122) + + Also rename [refwrap.const], because it does not specify + any destructors. + + commit b4bf594c81865f892bae81342ffb67c8ca8adb74 + Author: Jens Maurer + Date: Tue Nov 23 17:24:35 2021 +0100 + + [smartptr] Rework subclause nesting (#5119) + + commit d0cb462d511e5c9bf1ae7403c275f7c1ccf2543d + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Sat Nov 20 02:16:40 2021 +0800 + + [range.adjacent.overview] Fix multi-character in example + + commit 26f6a1f7573ea54ed93b4e90d0e487fe39d44b87 + Author: Jens Maurer + Date: Sat Nov 13 10:01:36 2021 +0100 + + [dcl.typedef] Add explanation for lookup failure in example + + commit c63e5e836e8dbe0ae6c7ebc1b2a1b1534d37a220 + Author: Jens Maurer + Date: Wed Nov 10 23:40:48 2021 +0100 + + [input.output] Fix headings of 'assign and swap' subclauses + + commit d2699e5de0c10085df309074d2dfbc57d5bc86bb + Author: Jens Maurer + Date: Wed Oct 27 21:20:02 2021 +0200 + + [std] Replace 'OK:' in code comments with 'OK,' + + In contrast to errors, which use a colon, an OK comment + is not followed by any unique reason why the code is + well-formed, but by a subjective highlighting of a fact. + + commit 5e3f1ad0ceb89feb2977a0531422bcbe9ab8fba7 + Author: Jens Maurer + Date: Tue Oct 26 21:49:15 2021 +0200 + + [stdatomic.h.syn] Fix missing \expos + + and augment the autmatic checks accordingly. + + commit 16e60c63ad14f3f3fc9132a8443421a15ebec8fc + Author: Jens Maurer + Date: Tue Nov 9 13:09:27 2021 +0100 + + [locale.time.get] Replace 'ISO/IEC 9945' with 'POSIX' + + We introduce POSIX as an alias for ISO/IEC 9945, and we use 'POSIX' + everywhere else. + + commit 31c32e035770797eedc69f150c3a3484bbe828a5 + Author: Jens Maurer + Date: Tue Nov 9 17:54:18 2021 +0100 + + [locale.time.get.virtuals] Use 'conversion specification' + + POSIX does not define the term 'conversion directive'. + + commit fbab3f13719c34affdb7b712aed7f6d2313570d7 + Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com> + Date: Tue Nov 23 20:03:13 2021 +0300 + + [defns.access, basic.lval] Clarify what can be accessed and how (#4777) + + commit 5475bdab828b3585a21172945303ccebbcefb516 + Author: Jens Maurer + Date: Thu Oct 21 22:11:07 2021 +0200 + + [c.mb.wcs] mbrtoc8 stores code units, not characters + + commit ba4bb3ee56b94b63d0d1e5914a136a04b1620052 + Author: mordante + Date: Tue Nov 23 18:13:22 2021 +0100 + + [format.functions] Add "std::move" around "out" (#5069) + + This fixes a misapplication of the resolution of LWG 3539. + + commit 0d0ec1a1393b3baae564234007c94b80da9bab48 + Author: Jens Maurer + Date: Tue Nov 23 18:15:55 2021 +0100 + + [func.wrap.{func.general, move.class}] Remove 'first-class object' (#5067) + + The term is undefined and does not improve the specification. + + commit d27c3b388befadc4c35aac1d12f0ba8581f14a5f + Author: Jonathan Wakely + Date: Fri Nov 12 14:29:00 2021 +0000 + + [spanstream.ctor] Fix base class name in effects + + commit c1935504da840995b1bb60eba536cb12bca5ae71 + Author: timsong-cpp + Date: Tue Nov 23 11:51:37 2021 -0600 + + [basic.start.main] Remove redundant phrase (#5083) + + commit 70eb0406596b4f4e3d97ed50b3fd6d93b3032d18 + Author: Jens Maurer + Date: Mon Oct 25 23:57:58 2021 +0200 + + [basic.start.main] Avoid implementation guidance in a note + + commit ac8d6611a739c64eda4a7062f2cb83f770cd8a53 + Author: Jens Maurer + Date: Mon Oct 25 23:58:08 2021 +0200 + + [dcl.link] Avoid implementation guidance in a note + + commit 2ad67aefe350017c4e9403ba2015af683813787f + Author: Jens Maurer + Date: Sat Nov 6 22:08:47 2021 +0100 + + [lex] Remove Unicode character name abbreviations + + They are not part of the character name or alias. + The presentation in ISO 10646 is misleading, though. + + commit 29c89b16e92cd03a76eb2a19866e683a7bb7ac80 + Author: Jens Maurer + Date: Sat Nov 6 22:15:05 2021 +0100 + + [lex] Rename U+0007 BELL to ALERT + + The former is ambiguous with U+1F514 BELL. + The ALERT alias is defined in UCD NameAliases.txt. + + commit 408623b7d8f0efd77403d1d0142d9bd59d1cfe55 + Author: Jens Maurer + Date: Sat Dec 4 11:19:54 2021 +0100 + + [associative.reqmts.general] Fix typo: 'kx', not 'rx' (#5136) + + commit f03473cd1e32691c105260e65dd534960cf9db21 + Author: Neven Sajko + Date: Sun Dec 5 21:19:00 2021 +0100 + + [over.sub] Fix typo: change oeprator to operator (#5140) + + commit c69a35501174f5ab5d3f13f12186cc9b1fcd40dd + Author: Jens Maurer + Date: Tue Dec 14 11:24:04 2021 +0100 + + [range.access] Fix cross-references for 'array' (#5147) + + Also introduce a label 'term.array.type' in [dcl.array]. + + commit 7a09dddd036359a10cf10b8e7d80c8edd8c76817 + Author: Jens Maurer + Date: Thu Dec 16 19:39:18 2021 +0100 + + [basic.fundamental] Excise normative requirements on std::numeric_limits (#5105) + + commit c2617432eac3313abd2134a26e2d8a1d925dfd15 + Author: Casey Carter + Date: Thu Dec 16 23:53:17 2021 -0800 + + [depr.default.allocator] Index allocator::is_always_equal here (#5152) + + LWG3170 deprecated `allocator::is_always_equal`. We moved it to Annex D, but left the index entry behind. + + commit 28effaea15ef697f5a64fba47b9c095c9fbfe82a + Author: Jens Maurer + Date: Sun Dec 19 22:16:18 2021 +0100 + + [ptr.align,re.regiter.incr] Replace 'compiler' with 'implementation' + + commit 575b9a99062de34cc44bc45aeb459f32aa12b98f + Author: Jens Maurer + Date: Sun Dec 19 22:19:19 2021 +0100 + + [smartptr.adapt] Emphasize that casting might not always be viable + + commit 9ba8e0329a0f5db15544c31c514ff44e0003f08f + Author: frederick-vs-ja + Date: Tue Jan 11 23:29:26 2022 +0800 + + [pairs.pair] Add missing _v for type traits (#5196) + + commit dae6769d9767e2e47f2fe451d9c796dd07d0ae29 + Author: zhihaoy <43971430+zhihaoy@users.noreply.github.com> + Date: Thu Jan 13 14:03:25 2022 -0800 + + [func.memfn] Correct target object by fixing typo (#5202) + + commit 5f830f97829965cf791dfe6eef6b84d6283712be + Author: Jens Maurer + Date: Wed Nov 24 22:04:55 2021 +0100 + + [lib] Add 'namespace std' wrappings around class definitions + + Those were missing in a few places, notably [rand]. + + Also add an automated check. + + commit 1031a409dfacb84b9871b16502c73e15249160eb + Author: Jens Maurer + Date: Fri Nov 19 23:02:19 2021 +0100 + + [chrono.syn] Use nested namespace definitions for clarity + + commit dad631ac4bd30e7ab6de5a888f77ed2b5b44c17d + Author: Jens Maurer + Date: Sat Nov 6 09:39:55 2021 +0100 + + [except.throw,except.handle] Move lvalue specification for copies + + commit c6e5eea4f11efec62a4718acd4eb17fb99fd4899 + Author: Jens Maurer + Date: Mon Oct 25 23:41:31 2021 +0200 + + [expr.prim.req.general] Change requirement-seq to right-recursive + + consistent with the specification of other -seq non-terminals. + + commit 872fce6effc603735c9717981807eb6bb8b4f838 + Author: Jens Maurer + Date: Sat Dec 4 11:33:32 2021 +0100 + + [associative.reqmts.general] Fix confusing local use of 'r' + + commit 3d1bf58b74860fc1e86cd1cf536b7022b90d688d + Author: Jens Maurer + Date: Fri Jan 7 20:26:15 2022 +0100 + + [temp.res.general] Clarify binding of names + + commit 4123264d22c7617d828083c9ad954b5541934621 + Author: Jens Maurer + Date: Mon Oct 25 18:15:14 2021 +0200 + + [temp.constr.atomic] Fix phrasing in note + + commit 26ce304780d79bba03a791b2f4299f083f021238 + Author: Jens Maurer + Date: Tue Dec 14 09:25:41 2021 +0100 + + [dcl.meaning.general] Clarify correspondence for block-scope friends + + commit 3c19e315dbb05a2c22b8f5b075af39a7572cdaa1 + Author: Jens Maurer + Date: Thu Dec 23 11:18:17 2021 +0100 + + [meta.rel] Avoid undefined term 'void types' + + commit 90d178d022c7d597629853ebc70262489e49d5e9 + Author: Jens Maurer + Date: Fri Jan 14 19:46:15 2022 +0100 + + [class.default.ctor] Fix implicit invocation of default constructor (#4026) + + Initialization is fully specified in [dcl.init], + so turn the list of default-initialization cases + into a note and shorten it appropriately. + + commit e1bfc25c56c7ab303241f980fa00d7ae402e1f5c + Author: Jens Maurer + Date: Mon Jul 5 23:51:41 2021 +0200 + + [stmt.return,class.{ctor,dtor}] Clarify no return operand + + Highlight that constructors and destructors do not have a + return type and thus a return statement within a constructor + or destructor cannot have an operand. + + commit b345505b88b376d547220254fd858840efbfb937 + Author: Chuanqi Xu + Date: Fri Jan 14 10:10:11 2022 +0800 + + [temp.param] Delete outdated wording at p15 + + The wording at [temp.param]/15 says: + > A template-parameter shall not be given default arguments by two + > different declarations if one is reachable from the other. + + But it is conflicted with [basic.def.odr]/13: + > There can be more than one definition of a + > ... + > default template argument + > ... + > in a program provided that each definition appears in a different + > translation unit and the definitions satisfy the [same-meaning + > criteria of the ODR]. + + [temp.param] should be deleted otherwise we couldn't modularize a real + project. + + commit fc9818bcdaa08f65c8d99f7df70b418810c36893 + Author: Jens Maurer + Date: Sat Jan 15 09:43:55 2022 +0100 + + [util.smartptr.atomic] Add cross-reference to header (#5207) + + commit 5c59ede65b362afb418bda3cf82123ae2ca2553c + Author: Jens Maurer + Date: Thu Dec 23 11:36:39 2021 +0100 + + [locale.ctype.virtuals] Clarify do_widen parameter + + commit cec2d218209abf2979a3c7fabc9970d8677b9e63 + Author: Jens Maurer + Date: Thu Dec 23 12:53:01 2021 +0100 + + [diff.stmt] Properly refer to function return types + + Also annotate the 'void' and 'int' keywords. + + commit ba9124e62ea85c922d501dfc52bc4d44c85933bd + Author: Jonathan Wakely + Date: Fri Jan 21 15:57:58 2022 +0000 + + [util.smartptr.atomic.general] Fix cross-reference to shared_ptr (#5222) + + commit 3cb2ee9d67360612e6361aa26d1805c8ed30c6e6 + Author: Chuanqi Xu <68680648+ChuanqiXu9@users.noreply.github.com> + Date: Sat Jan 22 17:43:22 2022 +0800 + + [temp.dep.general] add trailing 'or' (#5186) + + commit 4e2dbd25fa137f12c8fa6b960bc2db45be994414 + Author: Jens Maurer + Date: Sat Jan 22 13:38:10 2022 +0100 + + [class.free] Move into [class.mem] + + The class-specific allocation and deallocation functions, + whose declaration properties are specified in this section, + are class member functions. + + commit 7987ef93488842bbdbbd6e4de996f463939fe0e8 + Author: Jens Maurer + Date: Sat Jan 22 13:45:23 2022 +0100 + + [class.free] Change subclause heading and add indexing + + Rename the heading to "Allocation and deallocation functions", + which is more appropriate for the contents of the subclause. + + commit 07db0b3182495339b00221bba41549913e0a6a0e + Author: Jens Maurer + Date: Sat Jan 22 14:35:11 2022 +0100 + + [stacktrace] Move into [diagnostics] + + commit 0df02c99d04dd0e0d29ea520904ea64f69ea6c36 + Author: Jens Maurer + Date: Thu Jan 20 19:42:09 2022 +0100 + + [class.mem.general] Add cross-reference for 'layout-compatible type' + + commit 2e5976f894d821e442a6f98c3e235381f8067570 + Author: Jens Maurer + Date: Thu Jan 20 19:36:15 2022 +0100 + + [stmt.return] Clarify flowing off the end of a function + + commit 88541f7ad5de85389adb0e88f295091d29f00030 + Author: Jens Maurer + Date: Tue Jan 25 23:12:55 2022 +0100 + + [range.req.general] Remove incorrect normative duplication for 'view' (#5235) + + commit 0539c5e2cdf7605c5704eb2b63916b6c5c3b9539 + Author: Jens Maurer + Date: Thu Feb 18 13:42:57 2021 +0100 + + [macros,structure.specifications] Add 'Result' element + + commit 408a22b1b58207de4af28d59afd20156e715e35f + Author: Jens Maurer + Date: Thu Jan 7 23:48:43 2021 +0100 + + [re.req] Replace requirements table with \itemdescr + + commit 93ff092d1cd2b335f372b9546365b3d495caf2d8 + Author: Jens Maurer + Date: Sun Nov 14 20:05:03 2021 +0100 + + [container.requirements] Replace requirements tables with \itemdescr + + and adjust cross-references to container requirements tables + throughout the standard library. + + commit 4b1a735f393aa5c864d0a5aba45514aec63f5a90 + Author: Jens Maurer + Date: Sun Jun 27 11:26:39 2021 +0200 + + [container.requirements] Omit redundant specification + + where "Effects: Equivalent to" wording is used. + + commit d37470de0392f032d96c85610c947918269532a9 + Author: Jens Maurer + Date: Sun Feb 20 00:09:56 2022 +0100 + + [lex.name] Rephrase note to avoid upper/lower-case + + commit efd0cab6f2d11f29f205c15672108f6e20de6010 + Author: Jens Maurer + Date: Sun Feb 20 14:28:36 2022 +0100 + + [lib] Add missing \pnum before descriptive elements + + Also fix the ineffective check script by rewriting the + check in straightforward awk. + + commit ff92c80b70b9cd887512f96e5d5525c20550d12f + Author: Jens Maurer + Date: Sun Feb 6 09:52:01 2022 +0100 + + [iterator.concept.winc] Remove duplicate paragraph + + This fixes a bad merge between P2393R1 Cleaning up integer-class types + and P2321R2 zip. + + commit a4dfa1f0c46152d3a3399bc32a60fcf11edd4a5d + Author: Chuanqi Xu <68680648+ChuanqiXu9@users.noreply.github.com> + Date: Mon Feb 21 07:18:41 2022 +0800 + + [module.interface] Add adjective 'exported' (#5290) + + It was clear in context that "the declaration" is exported, but + it is easier to understand if we restate "an exported declaration". + + commit 90ef396f088a4e1730a3f73f3db44d9ad8b872b7 + Author: Jonathan Wakely + Date: Tue Feb 1 13:58:38 2022 +0000 + + [fs.class.directory.iterator.general] Fix grammar + + commit 1155c4a361c446eee4602b7fd2e82eba7a4f8c4f + Author: languagelawyer + Date: Sat Jan 22 23:27:49 2022 +0300 + + [temp.res] Move a note outside itemize environment + + commit 44c79f59de6c4ea179bacc698272d713e696b117 + Author: Jens Maurer + Date: Sat Jan 29 09:37:59 2022 +0100 + + [derivation] Remove 'basic integral type' from footnote + + Also switch footnote to note. + + commit 785b0a84e7b0f8108b5140f33494ceff3d0bd282 + Author: Jens Maurer + Date: Thu Dec 23 11:40:48 2021 +0100 + + [diff.expr] Replace 'will' with present tense + + Also annotate the 'void' keyword. + + commit 97a72e1c4f1616f2163d34deafea010d68099a7c + Author: Jens Maurer + Date: Sun Dec 5 21:22:48 2021 +0100 + + [temp.local] Fix type-name interpretation of injected-class-name + + commit a8e63922a5f049ab2c58a33117913688b8dc096a + Author: A. Jiang + Date: Mon Feb 21 20:27:01 2022 +0800 + + [container.gen.reqmts] Replace "Value:" with "Returns:" (#5256) + + commit d267cde4fcc2c13ef87170d68f94f1ae6e499c23 + Author: Jens Maurer + Date: Mon Feb 21 13:51:45 2022 +0100 + + [over.best.ics] Clarify phrasing around user-defined conversion sequence (#5086) + + This replaces the use of "with" that is popular in mathematical writing + with a more common construction. + + commit 7424b45d8470b8765cdf3b25bcfd9a9a89c0c936 + Author: Jens Maurer + Date: Mon Jan 3 22:24:23 2022 +0100 + + [expr] Cleanup for 'discarded-value expression' + + commit b5ce71b34217f9d974e96cc366984cbd5f4b71e6 + Author: Jens Maurer + Date: Fri Dec 17 20:31:57 2021 +0100 + + [atomics] Harmonize references to atomics operations tables + + commit ef78018c8d61d79dc9cddc5f4b2d00a7929964fa + Author: Jens Maurer + Date: Fri Jan 21 23:01:25 2022 +0100 + + [std] Replace hyphen with period in labels + + and add a check. + + commit 58ea575dd9b4a410dcf457b3357bef4a720e1608 + Author: Jens Maurer + Date: Thu Jan 13 23:21:05 2022 +0100 + + [function.objects,ranges] Introduce labels for call wrappers + + In particular, 'term.perfect.forwarding.call.wrapper' + and 'term.simple.call.wrapper', and refer to them. + + commit 0c53beacef2289e4cc4fabbdff99eb3b6c7ae4ad + Author: Jens Maurer + Date: Mon Jul 5 23:16:20 2021 +0200 + + [unique.ptr.single] Rephrase destruction + + commit 03b9040814ecd548f2de18668df0655ef7b37efb + Author: S. B. Tam + Date: Tue Feb 22 09:39:37 2022 +0800 + + [version.syn] Remove mention of nonexistent header `` + + commit 97430e8f867f5b97f79c8064c32dd1bde117198a + Author: Jens Maurer + Date: Mon Nov 22 22:20:16 2021 +0100 + + [allocator.adaptor.members] Fix select_on_container_copy_construction + + The description was confusing objects and types. + + commit 2cd31adb2033b4ae82339ef270bc058128cbd199 + Author: Jens Maurer + Date: Wed Feb 23 22:38:13 2022 +0100 + + [bit] Move into [utilities] + + commit e3532fd233355f93558f6a53d14b72e16a1f1ed2 + Author: Jens Maurer + Date: Wed Feb 23 22:44:52 2022 +0100 + + [memory] Create new clause + + and move [memory], [smartptr], [mem.res], and [allocator.adaptor] + from [utilities] into the new clause. + + commit cb7b98d46c4603ccc485fe826fb4363cb2c039bf + Author: Jens Maurer + Date: Wed Feb 23 22:48:10 2022 +0100 + + [comparisons.three.way,func.search] Add namespace around class definition + + commit 1daeb8e44b659c5cdf7133df68def1264c8b5774 + Author: Jens Maurer + Date: Wed Feb 23 22:54:01 2022 +0100 + + Move [string.view] to before [string.classes] + + commit 724e83e4d0cd82737952711d31505872188269ab + Author: Jens Maurer + Date: Wed Feb 23 23:01:35 2022 +0100 + + [meta] Create new clause + + and move [intseq], [meta], and [ratio] from [utilities] into the + new clause. + + commit af8334b94be2df5bf009ef7381460f56e6224c44 + Author: Jens Maurer + Date: Wed Feb 23 23:06:45 2022 +0100 + + [meta] Adjust cross-references + + commit d74c2170a9f4c928519461d7742293af2d141852 + Author: Jens Maurer + Date: Wed Feb 23 23:19:51 2022 +0100 + + Move [atomics] into [thread] + + Rename [thread] to 'Concurrency support library'. + + commit 888602381e6c4e5fc886a7e575a95c905998b487 + Author: A. Jiang + Date: Thu Feb 24 11:35:19 2022 +0800 + + [headers] List + + commit aa2c64589cf2a784e9c551a2a54df59b880613d3 + Author: Jens Maurer + Date: Thu Feb 24 15:09:08 2022 +0100 + + [thread] Rename to 'Concurrency support library' + + Missed update with commit d74c2170a9f4c928519461d7742293af2d141852. + + commit 000d4c091a244b3bf81470c6c6a4f2f35c3ec602 + Author: hewillk <67143766+hewillk@users.noreply.github.com> + Date: Fri Feb 25 01:14:48 2022 +0800 + + [range.chunk.outer.value] Add missing private specifier + + commit 2901f3f6c00060e6c0a368efd28fd50ba07350f1 + Author: Jens Maurer + Date: Fri Feb 25 23:38:49 2022 +0100 + + [diff.cpp20.library] Add subclause, highlighting new headers + + commit 1c88b6bdafb2eb128e7da05815f3b30fa52d3710 + Author: hewillk <67143766+hewillk@users.noreply.github.com> + Date: Sun Feb 27 21:23:40 2022 +0800 + + [range.slide.overview] Fix bad quotation marks for string-literal (#5326) + + commit dd346dcbd723ae27d6a2c2a74aad8a17a62ea687 + Author: Jens Maurer + Date: Sun Mar 6 00:18:57 2022 +0100 + + [expr.const] Add cross-reference for construct_at + + commit 8679960561e6f18ca533915626cdd5ecd349bcf4 + Author: Jens Maurer + Date: Sun Feb 27 22:22:30 2022 +0100 + + [allocator.requirements.general] Replace table for descriptive variables + + commit 0befc0e9f7e1df2451fa115b9ff12dbd8d384c5d + Author: Jens Maurer + Date: Sun Feb 27 23:59:42 2022 +0100 + + [allocator.requirements.general] Dismantle requirements table + + commit 4e4aa46276d1542b2f0ff66ebd0f66df8ba0d785 + Author: Jens Maurer + Date: Mon Feb 28 00:17:47 2022 +0100 + + [lib] Fix cross-references to replaced table cpp17.allocator + + commit 2d8e11333fe4e188a940bc5c4e1a2f33b139ee3b + Author: Johel Ernesto Guerrero Peña + Date: Mon Feb 21 14:49:31 2022 -0400 + + [array.overview] Don't mention swap as an exception + + The container requirements already describe this behavior, + so from the POV of this subclause, there's no exception. + + commit 65e74383deb8bcc0cab8e813b6360e9b1e8f6b10 + Author: Johel Ernesto Guerrero Peña + Date: Mon Feb 21 14:52:15 2022 -0400 + + [array.overview] Mention condition of exception diff --git a/papers/wd-index.md b/papers/wd-index.md index 675cf0c61b..5b3d4dee1e 100644 --- a/papers/wd-index.md +++ b/papers/wd-index.md @@ -38,5 +38,6 @@ * [N4868](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4868.pdf) 2020-10 C++ Working Draft * [N4878](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4878.pdf) 2020-12 C++ Working Draft * [N4885](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4885.pdf) 2021-03 C++ Working Draft - * [N4892](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4892.pdf) 2021-03 C++ Working Draft - * [N4901](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4901.pdf) 2021-03 C++ Working Draft + * [N4892](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4892.pdf) 2021-06 C++ Working Draft + * [N4901](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4901.pdf) 2021-10 C++ Working Draft + * [N4910](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4910.pdf) 2022-03 C++ Working Draft diff --git a/source/algorithms.tex b/source/algorithms.tex index c35079a748..4c0f369fac 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -641,6 +641,9 @@ template struct in_found_result; + + template + struct out_value_result; } // \ref{alg.nonmodifying}, non-modifying sequence operations @@ -1815,6 +1818,15 @@ shift_left(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, typename iterator_traits::difference_type n); + + namespace ranges { + template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S> + constexpr subrange shift_left(I first, S last, iter_difference_t n); + template<@\libconcept{forward_range}@ R> + requires @\libconcept{permutable}@> + constexpr borrowed_subrange_t shift_left(R&& r, range_difference_t n); + } + template constexpr ForwardIterator shift_right(ForwardIterator first, ForwardIterator last, @@ -1825,6 +1837,14 @@ ForwardIterator first, ForwardIterator last, typename iterator_traits::difference_type n); + namespace ranges { + template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S> + constexpr subrange shift_right(I first, S last, iter_difference_t n); + template<@\libconcept{forward_range}@ R> + requires @\libconcept{permutable}@> + constexpr borrowed_subrange_t shift_right(R&& r, range_difference_t n); + } + // \ref{alg.sorting}, sorting and related operations // \ref{alg.sort}, sorting template @@ -2651,7 +2671,7 @@ constexpr T min(initializer_list r, Comp comp = {}, Proj proj = {}); template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> - requires @\libconcept{indirectly_copyable}@_storable, range_value_t*> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr range_value_t min(R&& r, Comp comp = {}, Proj proj = {}); } @@ -2673,7 +2693,7 @@ constexpr T max(initializer_list r, Comp comp = {}, Proj proj = {}); template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> - requires @\libconcept{indirectly_copyable}@_storable, range_value_t*> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr range_value_t max(R&& r, Comp comp = {}, Proj proj = {}); } @@ -2700,7 +2720,7 @@ minmax(initializer_list r, Comp comp = {}, Proj proj = {}); template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> - requires @\libconcept{indirectly_copyable}@_storable, range_value_t*> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr minmax_result> minmax(R&& r, Comp comp = {}, Proj proj = {}); } @@ -2741,7 +2761,7 @@ ForwardIterator first, ForwardIterator last, Compare comp); - namespace ranges { + namespace ranges { template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr I max_element(I first, S last, Comp comp = {}, Proj proj = {}); @@ -3037,6 +3057,24 @@ return {std::move(in), found}; } }; + + template + struct out_value_result { + [[no_unique_address]] O out; + [[no_unique_address]] T value; + + template + requires @\libconcept{convertible_to}@ && @\libconcept{convertible_to}@ + constexpr operator out_value_result() const & { + return {out, value}; + } + + template + requires @\libconcept{convertible_to}@ && @\libconcept{convertible_to}@ + constexpr operator out_value_result() && { + return {std::move(out), std::move(value)}; + } + }; } \end{codeblock} @@ -3295,7 +3333,7 @@ \pnum \mandates The type \tcode{Size} is convertible -to an integral type~(\ref{conv.integral}, \ref{class.conv}). +to an integral type\iref{conv.integral,class.conv}. \pnum \expects @@ -3335,7 +3373,7 @@ \pnum \mandates The type \tcode{Size} is convertible -to an integral type~(\ref{conv.integral}, \ref{class.conv}). +to an integral type\iref{conv.integral,class.conv}. \pnum \expects @@ -4207,7 +4245,7 @@ \pnum \mandates The type \tcode{Size} -is convertible to an integral type~(\ref{conv.integral}, \ref{class.conv}). +is convertible to an integral type\iref{conv.integral,class.conv}. \pnum \returns @@ -4447,7 +4485,7 @@ \pnum \mandates The type \tcode{Size} is convertible -to an integral type~(\ref{conv.integral}, \ref{class.conv}). +to an integral type\iref{conv.integral,class.conv}. \pnum \effects @@ -5188,7 +5226,7 @@ The expression \tcode{value} is writable\iref{iterator.requirements.general} to the output iterator. The type \tcode{Size} is convertible -to an integral type~(\ref{conv.integral}, \ref{class.conv}). +to an integral type\iref{conv.integral,class.conv}. \pnum \effects @@ -5242,7 +5280,7 @@ \pnum \mandates \tcode{Size} is convertible -to an integral type~(\ref{conv.integral}, \ref{class.conv}). +to an integral type\iref{conv.integral,class.conv}. \pnum \effects @@ -6003,14 +6041,20 @@ ForwardIterator shift_left(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, typename iterator_traits::difference_type n); + +template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S> + constexpr subrange ranges::shift_left(I first, S last, iter_difference_t n); +template<@\libconcept{forward_range}@ R> + requires @\libconcept{permutable}@> + constexpr borrowed_subrange_t ranges::shift_left(R&& r, range_difference_t n) \end{itemdecl} \begin{itemdescr} \pnum \expects \tcode{n >= 0} is \tcode{true}. -The type of \tcode{*first} meets -the \oldconcept{MoveAssignable} requirements. +For the overloads in namespace \tcode{std}, +the type of \tcode{*first} meets the \oldconcept{MoveAssignable} requirements. \pnum \effects @@ -6019,14 +6063,22 @@ from position \tcode{first + n + i} into position \tcode{first + i} for each non-negative integer \tcode{i < (last - first) - n}. -In the first overload case, does so in order starting +For the overloads without an \tcode{ExecutionPolicy} template parameter, +does so in order starting from \tcode{i = 0} and proceeding to \tcode{i = (last - first) - n - 1}. \pnum \returns -\tcode{first + (last - first - n)} +Let \exposid{NEW_LAST} be \tcode{first + (last - first - n)} if \tcode{n < last - first}, otherwise \tcode{first}. +\begin{itemize} +\item +\exposid{NEW_LAST} for the overloads in namespace \tcode{std}. +\item +\tcode{\{first, \exposid{NEW_LAST}\}} +for the overloads in namespace \tcode{ranges}. +\end{itemize} \pnum \complexity @@ -6043,15 +6095,21 @@ ForwardIterator shift_right(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, typename iterator_traits::difference_type n); + +template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S> + constexpr subrange ranges::shift_right(I first, S last, iter_difference_t n); +template<@\libconcept{forward_range}@ R> + requires @\libconcept{permutable}@> + constexpr borrowed_subrange_t ranges::shift_right(R&& r, range_difference_t n); \end{itemdecl} \begin{itemdescr} \pnum \expects \tcode{n >= 0} is \tcode{true}. -The type of \tcode{*first} meets -the \oldconcept{MoveAssignable} requirements. -\tcode{ForwardIterator} meets +For the overloads in namespace \tcode{std}, +the type of \tcode{*first} meets the \oldconcept{MoveAssignable} requirements, +and \tcode{ForwardIterator} meets the \oldconcept{BidirectionalIterator} requirements\iref{bidirectional.iterators} or the \oldconcept{ValueSwap\-pable} requirements. @@ -6061,16 +6119,29 @@ Otherwise, moves the element from position \tcode{first + i} into position \tcode{first + n + i} for each non-negative integer \tcode{i < (last - first) - n}. -In the first overload case, if \tcode{ForwardIterator} meets -the \oldconcept{BidirectionalIterator} requirements, -does so in order starting -from \tcode{i = (last - first) - n - 1} and proceeding to \tcode{i = 0}. +Does so in order starting +from \tcode{i = (last - first) - n - 1} and proceeding to \tcode{i = 0} if: +\begin{itemize} +\item +for the overload in namespace \tcode{std} +without an \tcode{ExecutionPolicy} template parameter, +\tcode{Forward\-Iterator} meets the \oldconcept{BidirectionalIterator} requirements, +\item +for the overloads in namespace \tcode{ranges}, +\tcode{I} models \libconcept{bidirectional_iterator}. +\end{itemize} \pnum \returns -\tcode{first + n} -if \tcode{n < last - first}, +Let \exposid{NEW_FIRST} be \tcode{first + n} if \tcode{n < last - first}, otherwise \tcode{last}. +\begin{itemize} +\item +\exposid{NEW_FIRST} for the overloads in namespace \tcode{std}. +\item +\tcode{\{\exposid{NEW_FIRST}, last\}} +for the overloads in namespace \tcode{ranges}. +\end{itemize} \pnum \complexity @@ -6737,7 +6808,7 @@ \pnum \expects The elements \tcode{e} of \range{first}{last} -are partitioned with respect to the expression +are partitioned with respect to the expression\\ \tcode{bool(invoke(comp, invoke(proj, e), value))}. \pnum @@ -6784,7 +6855,7 @@ \pnum \expects The elements \tcode{e} of \range{first}{last} -are partitioned with respect to the expression +are partitioned with respect to the expression\\ \tcode{!bool(invoke(comp, value, invoke(proj, e)))}. \pnum @@ -8264,7 +8335,7 @@ constexpr T ranges::min(initializer_list r, Comp comp = {}, Proj proj = {}); template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> - requires @\libconcept{indirectly_copyable}@_storable, range_value_t*> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr range_value_t ranges::min(R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} @@ -9104,6 +9175,18 @@ template constexpr void iota(ForwardIterator first, ForwardIterator last, T value); + namespace ranges { + template + using iota_result = out_value_result; + + template<@\libconcept{input_or_output_iterator}@ O, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ T> + requires @\libconcept{indirectly_writable}@ + constexpr iota_result iota(O first, S last, T value); + + template<@\libconcept{weakly_incrementable}@ T, @\libconcept{output_range}@ R> + constexpr iota_result, T> iota(R&& r, T value); + } + // \ref{numeric.ops.gcd}, greatest common divisor template constexpr common_type_t gcd(M m, N n); @@ -10105,6 +10188,29 @@ Exactly \tcode{last - first} increments and assignments. \end{itemdescr} +\indexlibraryglobal{iota}% +\begin{itemdecl} +template<@\libconcept{input_or_output_iterator}@ O, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ T> + requires @\libconcept{indirectly_writable}@ + constexpr ranges::iota_result ranges::iota(O first, S last, T value); +template<@\libconcept{weakly_incrementable}@ T, @\libconcept{output_range}@ R> + constexpr ranges::iota_result, T> ranges::iota(R&& r, T value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +while (first != last) { + *first = as_const(value); + ++first; + ++value; +} +return {std::move(first), std::move(value)}; +\end{codeblock} +\end{itemdescr} + \rSec2[numeric.ops.gcd]{Greatest common divisor} \indexlibraryglobal{gcd}% @@ -10968,5 +11074,4 @@ Any exception thrown by \tcode{compar}\iref{res.on.exception.handling}. \end{itemdescr} -\xref -ISO C 7.22.5. +\xrefc{7.22.5} diff --git a/source/atomics.tex b/source/atomics.tex deleted file mode 100644 index 77967cd1ba..0000000000 --- a/source/atomics.tex +++ /dev/null @@ -1,3844 +0,0 @@ -%!TEX root = std.tex -\rSec0[atomics]{Atomic operations library} - -\rSec1[atomics.general]{General} - -\pnum -This Clause describes components for fine-grained atomic access. This access is -provided via operations on atomic objects. - -\pnum -The following subclauses describe atomics requirements and components for types -and operations, as summarized in \tref{atomics.summary}. - -\begin{libsumtab}{Atomics library summary}{atomics.summary} -\ref{atomics.alias} & Type aliases & \tcode{} \\ -\ref{atomics.order} & Order and consistency & \\ -\ref{atomics.lockfree} & Lock-free property & \\ -\ref{atomics.wait} & Waiting and notifying & \\ -\ref{atomics.ref.generic} & Class template \tcode{atomic_ref} & \\ -\ref{atomics.types.generic} & Class template \tcode{atomic} & \\ -\ref{atomics.nonmembers} & Non-member functions & \\ -\ref{atomics.flag} & Flag type and operations & \\ -\ref{atomics.fences} & Fences & \\ \rowsep -\ref{stdatomic.h.syn} & C compatibility & \tcode{} \\ -\end{libsumtab} - -\rSec1[atomics.syn]{Header \tcode{} synopsis} - -\indexheader{atomic}% -\begin{codeblock} -namespace std { - // \ref{atomics.order}, order and consistency - enum class memory_order : @\unspec@; - template - T kill_dependency(T y) noexcept; -} - -// \ref{atomics.lockfree}, lock-free property -#define ATOMIC_BOOL_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR8_T_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR16_T_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR32_T_LOCK_FREE @\unspec@ -#define ATOMIC_WCHAR_T_LOCK_FREE @\unspec@ -#define ATOMIC_SHORT_LOCK_FREE @\unspec@ -#define ATOMIC_INT_LOCK_FREE @\unspec@ -#define ATOMIC_LONG_LOCK_FREE @\unspec@ -#define ATOMIC_LLONG_LOCK_FREE @\unspec@ -#define ATOMIC_POINTER_LOCK_FREE @\unspec@ - -namespace std { - // \ref{atomics.ref.generic}, class template \tcode{atomic_ref} - template struct atomic_ref; - // \ref{atomics.ref.pointer}, partial specialization for pointers - template struct atomic_ref; - - // \ref{atomics.types.generic}, class template \tcode{atomic} - template struct atomic; - // \ref{atomics.types.pointer}, partial specialization for pointers - template struct atomic; - - // \ref{atomics.nonmembers}, non-member functions - template - bool atomic_is_lock_free(const volatile atomic*) noexcept; - template - bool atomic_is_lock_free(const atomic*) noexcept; - template - void atomic_store(volatile atomic*, typename atomic::value_type) noexcept; - template - void atomic_store(atomic*, typename atomic::value_type) noexcept; - template - void atomic_store_explicit(volatile atomic*, typename atomic::value_type, - memory_order) noexcept; - template - void atomic_store_explicit(atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_load(const volatile atomic*) noexcept; - template - T atomic_load(const atomic*) noexcept; - template - T atomic_load_explicit(const volatile atomic*, memory_order) noexcept; - template - T atomic_load_explicit(const atomic*, memory_order) noexcept; - template - T atomic_exchange(volatile atomic*, typename atomic::value_type) noexcept; - template - T atomic_exchange(atomic*, typename atomic::value_type) noexcept; - template - T atomic_exchange_explicit(volatile atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_exchange_explicit(atomic*, typename atomic::value_type, - memory_order) noexcept; - template - bool atomic_compare_exchange_weak(volatile atomic*, - typename atomic::value_type*, - typename atomic::value_type) noexcept; - template - bool atomic_compare_exchange_weak(atomic*, - typename atomic::value_type*, - typename atomic::value_type) noexcept; - template - bool atomic_compare_exchange_strong(volatile atomic*, - typename atomic::value_type*, - typename atomic::value_type) noexcept; - template - bool atomic_compare_exchange_strong(atomic*, - typename atomic::value_type*, - typename atomic::value_type) noexcept; - template - bool atomic_compare_exchange_weak_explicit(volatile atomic*, - typename atomic::value_type*, - typename atomic::value_type, - memory_order, memory_order) noexcept; - template - bool atomic_compare_exchange_weak_explicit(atomic*, - typename atomic::value_type*, - typename atomic::value_type, - memory_order, memory_order) noexcept; - template - bool atomic_compare_exchange_strong_explicit(volatile atomic*, - typename atomic::value_type*, - typename atomic::value_type, - memory_order, memory_order) noexcept; - template - bool atomic_compare_exchange_strong_explicit(atomic*, - typename atomic::value_type*, - typename atomic::value_type, - memory_order, memory_order) noexcept; - - template - T atomic_fetch_add(volatile atomic*, typename atomic::difference_type) noexcept; - template - T atomic_fetch_add(atomic*, typename atomic::difference_type) noexcept; - template - T atomic_fetch_add_explicit(volatile atomic*, typename atomic::difference_type, - memory_order) noexcept; - template - T atomic_fetch_add_explicit(atomic*, typename atomic::difference_type, - memory_order) noexcept; - template - T atomic_fetch_sub(volatile atomic*, typename atomic::difference_type) noexcept; - template - T atomic_fetch_sub(atomic*, typename atomic::difference_type) noexcept; - template - T atomic_fetch_sub_explicit(volatile atomic*, typename atomic::difference_type, - memory_order) noexcept; - template - T atomic_fetch_sub_explicit(atomic*, typename atomic::difference_type, - memory_order) noexcept; - template - T atomic_fetch_and(volatile atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_and(atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_and_explicit(volatile atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_fetch_and_explicit(atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_fetch_or(volatile atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_or(atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_or_explicit(volatile atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_fetch_or_explicit(atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_fetch_xor(volatile atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_xor(atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_xor_explicit(volatile atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_fetch_xor_explicit(atomic*, typename atomic::value_type, - memory_order) noexcept; - - template - void atomic_wait(const volatile atomic*, typename atomic::value_type); - template - void atomic_wait(const atomic*, typename atomic::value_type); - template - void atomic_wait_explicit(const volatile atomic*, typename atomic::value_type, - memory_order); - template - void atomic_wait_explicit(const atomic*, typename atomic::value_type, - memory_order); - template - void atomic_notify_one(volatile atomic*); - template - void atomic_notify_one(atomic*); - template - void atomic_notify_all(volatile atomic*); - template - void atomic_notify_all(atomic*); - - // \ref{atomics.alias}, type aliases - using atomic_bool = atomic; - using atomic_char = atomic; - using atomic_schar = atomic; - using atomic_uchar = atomic; - using atomic_short = atomic; - using atomic_ushort = atomic; - using atomic_int = atomic; - using atomic_uint = atomic; - using atomic_long = atomic; - using atomic_ulong = atomic; - using atomic_llong = atomic; - using atomic_ullong = atomic; - using atomic_char8_t = atomic; - using atomic_char16_t = atomic; - using atomic_char32_t = atomic; - using atomic_wchar_t = atomic; - - using atomic_int8_t = atomic; - using atomic_uint8_t = atomic; - using atomic_int16_t = atomic; - using atomic_uint16_t = atomic; - using atomic_int32_t = atomic; - using atomic_uint32_t = atomic; - using atomic_int64_t = atomic; - using atomic_uint64_t = atomic; - - using atomic_int_least8_t = atomic; - using atomic_uint_least8_t = atomic; - using atomic_int_least16_t = atomic; - using atomic_uint_least16_t = atomic; - using atomic_int_least32_t = atomic; - using atomic_uint_least32_t = atomic; - using atomic_int_least64_t = atomic; - using atomic_uint_least64_t = atomic; - - using atomic_int_fast8_t = atomic; - using atomic_uint_fast8_t = atomic; - using atomic_int_fast16_t = atomic; - using atomic_uint_fast16_t = atomic; - using atomic_int_fast32_t = atomic; - using atomic_uint_fast32_t = atomic; - using atomic_int_fast64_t = atomic; - using atomic_uint_fast64_t = atomic; - - using atomic_intptr_t = atomic; - using atomic_uintptr_t = atomic; - using atomic_size_t = atomic; - using atomic_ptrdiff_t = atomic; - using atomic_intmax_t = atomic; - using atomic_uintmax_t = atomic; - - using atomic_signed_lock_free = @\seebelow@; - using atomic_unsigned_lock_free = @\seebelow@; - - // \ref{atomics.flag}, flag type and operations - struct atomic_flag; - - bool atomic_flag_test(const volatile atomic_flag*) noexcept; - bool atomic_flag_test(const atomic_flag*) noexcept; - bool atomic_flag_test_explicit(const volatile atomic_flag*, memory_order) noexcept; - bool atomic_flag_test_explicit(const atomic_flag*, memory_order) noexcept; - bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept; - bool atomic_flag_test_and_set(atomic_flag*) noexcept; - bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order) noexcept; - bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept; - void atomic_flag_clear(volatile atomic_flag*) noexcept; - void atomic_flag_clear(atomic_flag*) noexcept; - void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept; - void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; - - void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept; - void atomic_flag_wait(const atomic_flag*, bool) noexcept; - void atomic_flag_wait_explicit(const volatile atomic_flag*, - bool, memory_order) noexcept; - void atomic_flag_wait_explicit(const atomic_flag*, - bool, memory_order) noexcept; - void atomic_flag_notify_one(volatile atomic_flag*) noexcept; - void atomic_flag_notify_one(atomic_flag*) noexcept; - void atomic_flag_notify_all(volatile atomic_flag*) noexcept; - void atomic_flag_notify_all(atomic_flag*) noexcept; - - // \ref{atomics.fences}, fences - extern "C" void atomic_thread_fence(memory_order) noexcept; - extern "C" void atomic_signal_fence(memory_order) noexcept; -} -\end{codeblock} - -\rSec1[atomics.alias]{Type aliases} -\indexlibraryglobal{atomic_bool}% -\indexlibraryglobal{atomic_char}% -\indexlibraryglobal{atomic_schar}% -\indexlibraryglobal{atomic_uchar}% -\indexlibraryglobal{atomic_short}% -\indexlibraryglobal{atomic_ushort}% -\indexlibraryglobal{atomic_int}% -\indexlibraryglobal{atomic_uint}% -\indexlibraryglobal{atomic_long}% -\indexlibraryglobal{atomic_ulong}% -\indexlibraryglobal{atomic_llong}% -\indexlibraryglobal{atomic_ullong}% -\indexlibraryglobal{atomic_char8_t}% -\indexlibraryglobal{atomic_char16_t}% -\indexlibraryglobal{atomic_char32_t}% -\indexlibraryglobal{atomic_wchar_t}% -\indexlibraryglobal{atomic_int8_t}% -\indexlibraryglobal{atomic_uint8_t}% -\indexlibraryglobal{atomic_int16_t}% -\indexlibraryglobal{atomic_uint16_t}% -\indexlibraryglobal{atomic_int32_t}% -\indexlibraryglobal{atomic_uint32_t}% -\indexlibraryglobal{atomic_int64_t}% -\indexlibraryglobal{atomic_uint64_t}% -\indexlibraryglobal{atomic_int_least8_t}% -\indexlibraryglobal{atomic_uint_least8_t}% -\indexlibraryglobal{atomic_int_least16_t}% -\indexlibraryglobal{atomic_uint_least16_t}% -\indexlibraryglobal{atomic_int_least32_t}% -\indexlibraryglobal{atomic_uint_least32_t}% -\indexlibraryglobal{atomic_int_least64_t}% -\indexlibraryglobal{atomic_uint_least64_t}% -\indexlibraryglobal{atomic_int_fast8_t}% -\indexlibraryglobal{atomic_uint_fast8_t}% -\indexlibraryglobal{atomic_int_fast16_t}% -\indexlibraryglobal{atomic_uint_fast16_t}% -\indexlibraryglobal{atomic_int_fast32_t}% -\indexlibraryglobal{atomic_uint_fast32_t}% -\indexlibraryglobal{atomic_int_fast64_t}% -\indexlibraryglobal{atomic_uint_fast64_t}% -\indexlibraryglobal{atomic_intptr_t}% -\indexlibraryglobal{atomic_uintptr_t}% -\indexlibraryglobal{atomic_size_t}% -\indexlibraryglobal{atomic_ptrdiff_t}% -\indexlibraryglobal{atomic_intmax_t}% -\indexlibraryglobal{atomic_uintmax_t}% -\pnum -The type aliases \tcode{atomic_int$N$_t}, \tcode{atomic_uint$N$_t}, -\tcode{atomic_intptr_t}, and \tcode{atomic_uintptr_t} -are defined if and only if -\tcode{int$N$_t}, \tcode{uint$N$_t}, -\tcode{intptr_t}, and \tcode{uintptr_t} -are defined, respectively. - -\pnum -\indexlibraryglobal{atomic_signed_lock_free}% -\indexlibraryglobal{atomic_unsigned_lock_free}% -The type aliases -\tcode{atomic_signed_lock_free} and \tcode{atomic_unsigned_lock_free} -name specializations of \tcode{atomic} -whose template arguments are integral types, respectively signed and unsigned, -and whose \tcode{is_always_lock_free} property is \tcode{true}. -\begin{note} -\indextext{implementation!freestanding}% -These aliases are optional in freestanding implementations\iref{compliance}. -\end{note} -Implementations should choose for these aliases -the integral specializations of \tcode{atomic} -for which the atomic waiting and notifying operations\iref{atomics.wait} -are most efficient. - -\rSec1[atomics.order]{Order and consistency} -\indexlibraryglobal{memory_order}% -\indexlibrarymember{relaxed}{memory_order}% -\indexlibrarymember{consume}{memory_order}% -\indexlibrarymember{acquire}{memory_order}% -\indexlibrarymember{release}{memory_order}% -\indexlibrarymember{acq_rel}{memory_order}% -\indexlibrarymember{seq_cst}{memory_order}% -\indexlibraryglobal{memory_order_relaxed}% -\indexlibraryglobal{memory_order_consume}% -\indexlibraryglobal{memory_order_acquire}% -\indexlibraryglobal{memory_order_release}% -\indexlibraryglobal{memory_order_acq_rel}% -\indexlibraryglobal{memory_order_seq_cst}% - -\begin{codeblock} -namespace std { - enum class memory_order : @\unspec@ { - relaxed, consume, acquire, release, acq_rel, seq_cst - }; - inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; - inline constexpr memory_order memory_order_consume = memory_order::consume; - inline constexpr memory_order memory_order_acquire = memory_order::acquire; - inline constexpr memory_order memory_order_release = memory_order::release; - inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; - inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; -} -\end{codeblock} - -\pnum -The enumeration \tcode{memory_order} specifies the detailed regular -(non-atomic) memory synchronization order as defined in -\ref{intro.multithread} and may provide for operation ordering. Its -enumerated values and their meanings are as follows: - -\begin{itemize} -\item \tcode{memory_order::relaxed}: no operation orders memory. - -\item \tcode{memory_order::release}, \tcode{memory_order::acq_rel}, and -\tcode{memory_order::seq_cst}: a store operation performs a release operation on the -affected memory location. - -\item \tcode{memory_order::consume}: a load operation performs a consume operation on the -affected memory location. -\begin{note} -Prefer \tcode{memory_order::acquire}, which provides stronger guarantees -than \tcode{memory_order::consume}. Implementations have found it infeasible -to provide performance better than that of \tcode{memory_order::acquire}. -Specification revisions are under consideration. -\end{note} - -\item \tcode{memory_order::acquire}, \tcode{memory_order::acq_rel}, and -\tcode{memory_order::seq_cst}: a load operation performs an acquire operation on the -affected memory location. -\end{itemize} - -\begin{note} -Atomic operations specifying \tcode{memory_order::relaxed} are relaxed -with respect to memory ordering. Implementations must still guarantee that any -given atomic access to a particular atomic object be indivisible with respect -to all other atomic accesses to that object. -\end{note} - -\pnum -An atomic operation $A$ that performs a release operation on an atomic -object $M$ synchronizes with an atomic operation $B$ that performs -an acquire operation on $M$ and takes its value from any side effect in the -release sequence headed by $A$. - -\pnum -An atomic operation $A$ on some atomic object $M$ is -\defn{coherence-ordered before} -another atomic operation $B$ on $M$ if -\begin{itemize} -\item $A$ is a modification, and -$B$ reads the value stored by $A$, or -\item $A$ precedes $B$ -in the modification order of $M$, or -\item $A$ and $B$ are not -the same atomic read-modify-write operation, and -there exists an atomic modification $X$ of $M$ -such that $A$ reads the value stored by $X$ and -$X$ precedes $B$ -in the modification order of $M$, or -\item there exists an atomic modification $X$ of $M$ -such that $A$ is coherence-ordered before $X$ and -$X$ is coherence-ordered before $B$. -\end{itemize} - -\pnum -There is a single total order $S$ -on all \tcode{memory_order::seq_cst} operations, including fences, -that satisfies the following constraints. -First, if $A$ and $B$ are -\tcode{memory_order::seq_cst} operations and -$A$ strongly happens before $B$, -then $A$ precedes $B$ in $S$. -Second, for every pair of atomic operations $A$ and -$B$ on an object $M$, -where $A$ is coherence-ordered before $B$, -the following four conditions are required to be satisfied by $S$: -\begin{itemize} -\item if $A$ and $B$ are both -\tcode{memory_order::seq_cst} operations, -then $A$ precedes $B$ in $S$; and -\item if $A$ is a \tcode{memory_order::seq_cst} operation and -$B$ happens before -a \tcode{memory_order::seq_cst} fence $Y$, -then $A$ precedes $Y$ in $S$; and -\item if a \tcode{memory_order::seq_cst} fence $X$ -happens before $A$ and -$B$ is a \tcode{memory_order::seq_cst} operation, -then $X$ precedes $B$ in $S$; and -\item if a \tcode{memory_order::seq_cst} fence $X$ -happens before $A$ and -$B$ happens before -a \tcode{memory_order::seq_cst} fence $Y$, -then $X$ precedes $Y$ in $S$. -\end{itemize} - -\pnum -\begin{note} -This definition ensures that $S$ is consistent with -the modification order of any atomic object $M$. -It also ensures that -a \tcode{memory_order::seq_cst} load $A$ of $M$ -gets its value either from the last modification of $M$ -that precedes $A$ in $S$ or -from some non-\tcode{memory_order::seq_cst} modification of $M$ -that does not happen before any modification of $M$ -that precedes $A$ in $S$. -\end{note} - -\pnum -\begin{note} -We do not require that $S$ be consistent with -``happens before''\iref{intro.races}. -This allows more efficient implementation -of \tcode{memory_order::acquire} and \tcode{memory_order::release} -on some machine architectures. -It can produce surprising results -when these are mixed with \tcode{memory_order::seq_cst} accesses. -\end{note} - -\pnum -\begin{note} -\tcode{memory_order::seq_cst} ensures sequential consistency only -for a program that is free of data races and -uses exclusively \tcode{memory_order::seq_cst} atomic operations. -Any use of weaker ordering will invalidate this guarantee -unless extreme care is used. -In many cases, \tcode{memory_order::seq_cst} atomic operations are reorderable -with respect to other atomic operations performed by the same thread. -\end{note} - -\pnum -Implementations should ensure that no ``out-of-thin-air'' values are computed that -circularly depend on their own computation. - -\begin{note} -For example, with \tcode{x} and \tcode{y} initially zero, -\begin{codeblock} -// Thread 1: -r1 = y.load(memory_order::relaxed); -x.store(r1, memory_order::relaxed); -\end{codeblock} - -\begin{codeblock} -// Thread 2: -r2 = x.load(memory_order::relaxed); -y.store(r2, memory_order::relaxed); -\end{codeblock} -this recommendation discourages producing \tcode{r1 == r2 == 42}, since the store of 42 to \tcode{y} is only -possible if the store to \tcode{x} stores \tcode{42}, which circularly depends on the -store to \tcode{y} storing \tcode{42}. Note that without this restriction, such an -execution is possible. -\end{note} - -\pnum -\begin{note} -The recommendation similarly disallows \tcode{r1 == r2 == 42} in the -following example, with \tcode{x} and \tcode{y} again initially zero: - -\begin{codeblock} -// Thread 1: -r1 = x.load(memory_order::relaxed); -if (r1 == 42) y.store(42, memory_order::relaxed); -\end{codeblock} - -\begin{codeblock} -// Thread 2: -r2 = y.load(memory_order::relaxed); -if (r2 == 42) x.store(42, memory_order::relaxed); -\end{codeblock} -\end{note} - -\pnum -Atomic read-modify-write operations shall always read the last value -(in the modification order) written before the write associated with -the read-modify-write operation. - -\pnum -Implementations should make atomic stores visible to atomic loads within a reasonable -amount of time. - -\indexlibraryglobal{kill_dependency}% -\begin{itemdecl} -template - T kill_dependency(T y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The argument does not carry a dependency to the return -value\iref{intro.multithread}. - -\pnum -\returns -\tcode{y}. -\end{itemdescr} - - -\rSec1[atomics.lockfree]{Lock-free property} - -\indexlibraryglobal{ATOMIC_BOOL_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_CHAR_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_CHAR8_T_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_CHAR16_T_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_CHAR32_T_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_WCHAR_T_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_SHORT_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_INT_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_LONG_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_LLONG_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_POINTER_LOCK_FREE}% -\indeximpldef{values of various \tcode{ATOMIC_..._LOCK_FREE} macros} -\begin{codeblock} -#define ATOMIC_BOOL_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR8_T_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR16_T_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR32_T_LOCK_FREE @\unspec@ -#define ATOMIC_WCHAR_T_LOCK_FREE @\unspec@ -#define ATOMIC_SHORT_LOCK_FREE @\unspec@ -#define ATOMIC_INT_LOCK_FREE @\unspec@ -#define ATOMIC_LONG_LOCK_FREE @\unspec@ -#define ATOMIC_LLONG_LOCK_FREE @\unspec@ -#define ATOMIC_POINTER_LOCK_FREE @\unspec@ -\end{codeblock} - -\pnum -The \tcode{ATOMIC_..._LOCK_FREE} macros indicate the lock-free property of the -corresponding atomic types, with the signed and unsigned variants grouped -together. The properties also apply to the corresponding (partial) specializations of the -\tcode{atomic} template. A value of 0 indicates that the types are never -lock-free. A value of 1 indicates that the types are sometimes lock-free. A -value of 2 indicates that the types are always lock-free. - -\pnum -At least one signed integral specialization of the \tcode{atomic} template, -along with the specialization -for the corresponding unsigned type\iref{basic.fundamental}, -is always lock-free. -\begin{note} -\indextext{implementation!freestanding}% -This requirement is optional in freestanding implementations\iref{compliance}. -\end{note} - -\pnum -The functions \tcode{atomic::is_lock_free} and -\tcode{atomic_is_lock_free}\iref{atomics.types.operations} -indicate whether the object is lock-free. In any given program execution, the -result of the lock-free query -is the same for all atomic objects of the same type. - -\pnum -Atomic operations that are not lock-free are considered to potentially -block\iref{intro.progress}. - -\pnum -\recommended -Operations that are lock-free should also be address-free. -\begin{footnote} -That is, -atomic operations on the same memory location via two different addresses will -communicate atomically. -\end{footnote} -The implementation of these operations should not depend on any per-process state. -\begin{note} -This restriction enables communication by memory that is -mapped into a process more than once and by memory that is shared between two -processes. -\end{note} - -\rSec1[atomics.wait]{Waiting and notifying} - -\pnum -\defnx{Atomic waiting operations}{atomic!waiting operation} -and \defnx{atomic notifying operations}{atomic!notifying operation} -provide a mechanism to wait for the value of an atomic object to change -more efficiently than can be achieved with polling. -An atomic waiting operation may block until it is unblocked -by an atomic notifying operation, according to each function's effects. -\begin{note} -Programs are not guaranteed to observe transient atomic values, -an issue known as the A-B-A problem, -resulting in continued blocking if a condition is only temporarily met. -\end{note} - -\pnum -\begin{note} -The following functions are atomic waiting operations: -\begin{itemize} -\item \tcode{atomic::wait}, -\item \tcode{atomic_flag::wait}, -\item \tcode{atomic_wait} and \tcode{atomic_wait_explicit}, -\item \tcode{atomic_flag_wait} and \tcode{atomic_flag_wait_explicit}, and -\item \tcode{atomic_ref::wait}. -\end{itemize} -\end{note} - -\pnum -\begin{note} -The following functions are atomic notifying operations: -\begin{itemize} -\item \tcode{atomic::notify_one} and \tcode{atomic::notify_all}, -\item \tcode{atomic_flag::notify_one} and \tcode{atomic_flag::notify_all}, -\item \tcode{atomic_notify_one} and \tcode{atomic_notify_all}, -\item \tcode{atomic_flag_notify_one} and \tcode{atomic_flag_notify_all}, and -\item \tcode{atomic_ref::notify_one} and \tcode{atomic_ref::notify_all}. -\end{itemize} -\end{note} - -\indextext{atomic!waiting operation!eligible to be unblocked}% -\pnum -A call to an atomic waiting operation on an atomic object \tcode{M} -is \defn{eligible to be unblocked} -by a call to an atomic notifying operation on \tcode{M} -if there exist side effects \tcode{X} and \tcode{Y} on \tcode{M} such that: -\begin{itemize} -\item the atomic waiting operation has blocked after observing the result of \tcode{X}, -\item \tcode{X} precedes \tcode{Y} in the modification order of \tcode{M}, and -\item \tcode{Y} happens before the call to the atomic notifying operation. -\end{itemize} - -\rSec1[atomics.ref.generic]{Class template \tcode{atomic_ref}} - -\rSec2[atomics.ref.generic.general]{General} - -\indexlibraryglobal{atomic_ref}% -\indexlibrarymember{value_type}{atomic_ref}% -\begin{codeblock} -namespace std { - template struct atomic_ref { - private: - T* ptr; // \expos - public: - using value_type = T; - static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - explicit atomic_ref(T&); - atomic_ref(const atomic_ref&) noexcept; - atomic_ref& operator=(const atomic_ref&) = delete; - - void store(T, memory_order = memory_order::seq_cst) const noexcept; - T operator=(T) const noexcept; - T load(memory_order = memory_order::seq_cst) const noexcept; - operator T() const noexcept; - - T exchange(T, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(T&, T, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(T&, T, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(T&, T, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(T&, T, - memory_order = memory_order::seq_cst) const noexcept; - - void wait(T, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; - }; -} -\end{codeblock} - -\pnum -An \tcode{atomic_ref} object applies atomic operations\iref{atomics.general} to -the object referenced by \tcode{*ptr} such that, -for the lifetime\iref{basic.life} of the \tcode{atomic_ref} object, -the object referenced by \tcode{*ptr} is an atomic object\iref{intro.races}. - -\pnum -The program is ill-formed if \tcode{is_trivially_copyable_v} is \tcode{false}. - -\pnum -The lifetime\iref{basic.life} of an object referenced by \tcode{*ptr} -shall exceed the lifetime of all \tcode{atomic_ref}s that reference the object. -While any \tcode{atomic_ref} instances exist -that reference the \tcode{*ptr} object, -all accesses to that object shall exclusively occur -through those \tcode{atomic_ref} instances. -No subobject of the object referenced by \tcode{atomic_ref} -shall be concurrently referenced by any other \tcode{atomic_ref} object. - -\pnum -Atomic operations applied to an object -through a referencing \tcode{atomic_ref} are atomic with respect to -atomic operations applied through any other \tcode{atomic_ref} -referencing the same object. -\begin{note} -Atomic operations or the \tcode{atomic_ref} constructor can acquire -a shared resource, such as a lock associated with the referenced object, -to enable atomic operations to be applied to the referenced object. -\end{note} - -\rSec2[atomics.ref.ops]{Operations} - -\indexlibrarymember{required_alignment}{atomic_ref}% -\indexlibrarymember{required_alignment}{atomic_ref}% -\indexlibrarymember{required_alignment}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{required_alignment}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -static constexpr size_t required_alignment; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The alignment required for an object to be referenced by an atomic reference, -which is at least \tcode{alignof(T)}. - -\pnum -\begin{note} -Hardware could require an object -referenced by an \tcode{atomic_ref} -to have stricter alignment\iref{basic.align} -than other objects of type \tcode{T}. -Further, whether operations on an \tcode{atomic_ref} -are lock-free could depend on the alignment of the referenced object. -For example, lock-free operations on \tcode{std::complex} -could be supported only if aligned to \tcode{2*alignof(double)}. -\end{note} -\end{itemdescr} - -\indexlibrarymember{is_always_lock_free}{atomic_ref}% -\indexlibrarymember{is_always_lock_free}{atomic_ref}% -\indexlibrarymember{is_always_lock_free}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{is_always_lock_free}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -static constexpr bool is_always_lock_free; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The static data member \tcode{is_always_lock_free} is \tcode{true} -if the \tcode{atomic_ref} type's operations are always lock-free, -and \tcode{false} otherwise. -\end{itemdescr} - -\indexlibrarymember{is_lock_free}{atomic_ref}% -\indexlibrarymember{is_lock_free}{atomic_ref}% -\indexlibrarymember{is_lock_free}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{is_lock_free}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -bool is_lock_free() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if operations on all objects of the type \tcode{atomic_ref} -are lock-free, -\tcode{false} otherwise. -\end{itemdescr} - -\indexlibraryctor{atomic_ref}% -\indexlibraryctor{atomic_ref}% -\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}!constructor}% -\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}!constructor}% -\begin{itemdecl} -atomic_ref(T& obj); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The referenced object is aligned to \tcode{required_alignment}. - -\pnum -\ensures -\tcode{*this} references \tcode{obj}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibraryctor{atomic_ref}% -\indexlibraryctor{atomic_ref}% -\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}!constructor}% -\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}!constructor}% -\begin{itemdecl} -atomic_ref(const atomic_ref& ref) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{*this} references the object referenced by \tcode{ref}. -\end{itemdescr} - -\indexlibrarymember{store}{atomic_ref}% -\indexlibrarymember{store}{atomic_ref}% -\indexlibrarymember{store}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{store}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -void store(T desired, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The \tcode{order} argument is neither -\tcode{memory_order::consume}, -\tcode{memory_order::acquire}, nor -\tcode{memory_order::acq_rel}. - -\pnum -\effects -Atomically replaces the value referenced by \tcode{*ptr} -with the value of \tcode{desired}. -Memory is affected according to the value of \tcode{order}. -\end{itemdescr} - -\indexlibrarymember{operator=}{atomic_ref}% -\indexlibrarymember{operator=}{atomic_ref}% -\indexlibrarymember{operator=}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator=}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -T operator=(T desired) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -store(desired); -return desired; -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{load}{atomic_ref}% -\indexlibrarymember{load}{atomic_ref}% -\indexlibrarymember{load}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{load}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -T load(memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The \tcode{order} argument is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Memory is affected according to the value of \tcode{order}. - -\pnum -\returns -Atomically returns the value referenced by \tcode{*ptr}. -\end{itemdescr} - -\indexlibrarymember{operator \placeholder{type}}{atomic_ref}% -\indexlibrarymember{operator T*}{atomic_ref}% -\indexlibrarymember{operator \placeholder{integral}}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator \placeholder{floating-point}}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -operator T() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return load();} -\end{itemdescr} - -\indexlibrarymember{exchange}{atomic_ref}% -\indexlibrarymember{exchange}{atomic_ref}% -\indexlibrarymember{exchange}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{exchange}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -T exchange(T desired, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically replaces the value referenced by \tcode{*ptr} -with \tcode{desired}. -Memory is affected according to the value of \tcode{order}. -This operation is an atomic read-modify-write operation\iref{intro.multithread}. - -\pnum -\returns -Atomically returns the value referenced by \tcode{*ptr} -immediately before the effects. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_weak}{atomic_ref}% -\indexlibrarymember{compare_exchange_weak}{atomic_ref}% -\indexlibrarymember{compare_exchange_weak}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{compare_exchange_weak}{atomic_ref<\placeholder{floating-point}>}% -\indexlibrarymember{compare_exchange_strong}{atomic_ref}% -\indexlibrarymember{compare_exchange_strong}{atomic_ref}% -\indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -bool compare_exchange_weak(T& expected, T desired, - memory_order success, memory_order failure) const noexcept; - -bool compare_exchange_strong(T& expected, T desired, - memory_order success, memory_order failure) const noexcept; - -bool compare_exchange_weak(T& expected, T desired, - memory_order order = memory_order::seq_cst) const noexcept; - -bool compare_exchange_strong(T& expected, T desired, - memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The \tcode{failure} argument is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Retrieves the value in \tcode{expected}. -It then atomically compares the value representation of -the value referenced by \tcode{*ptr} for equality -with that previously retrieved from \tcode{expected}, -and if \tcode{true}, replaces the value referenced by \tcode{*ptr} -with that in \tcode{desired}. -If and only if the comparison is \tcode{true}, -memory is affected according to the value of \tcode{success}, and -if the comparison is \tcode{false}, -memory is affected according to the value of \tcode{failure}. -When only one \tcode{memory_order} argument is supplied, -the value of \tcode{success} is \tcode{order}, and -the value of \tcode{failure} is \tcode{order} -except that a value of \tcode{memory_order::acq_rel} shall be replaced by -the value \tcode{memory_order::acquire} and -a value of \tcode{memory_order::release} shall be replaced by -the value \tcode{memory_order::relaxed}. -If and only if the comparison is \tcode{false} then, -after the atomic operation, -the value in \tcode{expected} is replaced by -the value read from the value referenced by \tcode{*ptr} -during the atomic comparison. -If the operation returns \tcode{true}, -these operations are atomic read-modify-write operations\iref{intro.races} -on the value referenced by \tcode{*ptr}. -Otherwise, these operations are atomic load operations on that memory. - -\pnum -\returns -The result of the comparison. - -\pnum -\remarks -A weak compare-and-exchange operation may fail spuriously. -That is, even when the contents of memory referred to -by \tcode{expected} and \tcode{ptr} are equal, -it may return \tcode{false} and -store back to \tcode{expected} the same memory contents -that were originally there. -\begin{note} -This spurious failure enables implementation of compare-and-exchange -on a broader class of machines, e.g., load-locked store-conditional machines. -A consequence of spurious failure is -that nearly all uses of weak compare-and-exchange will be in a loop. -When a compare-and-exchange is in a loop, -the weak version will yield better performance on some platforms. -When a weak compare-and-exchange would require a loop and -a strong one would not, the strong one is preferable. -\end{note} -\end{itemdescr} - -\indexlibrarymember{wait}{atomic_ref}% -\begin{itemdecl} -void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is -neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Repeatedly performs the following steps, in order: -\begin{itemize} -\item - Evaluates \tcode{load(order)} and - compares its value representation for equality against that of \tcode{old}. -\item - If they compare unequal, returns. -\item - Blocks until it - is unblocked by an atomic notifying operation or is unblocked spuriously. -\end{itemize} - -\pnum -\remarks -This function is an atomic waiting operation\iref{atomics.wait} -on atomic object \tcode{*ptr}. -\end{itemdescr} - -\indexlibrarymember{notify_one}{atomic_ref}% -\begin{itemdecl} -void notify_one() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of at least one atomic waiting operation on \tcode{*ptr} -that is eligible to be unblocked\iref{atomics.wait} by this call, -if any such atomic waiting operations exist. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait} -on atomic object \tcode{*ptr}. -\end{itemdescr} - -\indexlibrarymember{notify_all}{atomic_ref}% -\begin{itemdecl} -void notify_all() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of all atomic waiting operations on \tcode{*ptr} -that are eligible to be unblocked\iref{atomics.wait} by this call. - -\pnum -\remarks - This function is an atomic notifying operation\iref{atomics.wait} - on atomic object \tcode{*ptr}. -\end{itemdescr} - -\rSec2[atomics.ref.int]{Specializations for integral types} - -\pnum -\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}}% -There are specializations of the \tcode{atomic_ref} class template -for the integral types -\tcode{char}, -\tcode{signed char}, -\tcode{unsigned char}, -\tcode{short}, -\tcode{unsigned short}, -\tcode{int}, -\tcode{unsigned int}, -\tcode{long}, -\tcode{unsigned long}, -\tcode{long long}, -\tcode{unsigned long long}, -\keyword{char8_t}, -\keyword{char16_t}, -\keyword{char32_t}, -\keyword{wchar_t}, -and any other types needed by the typedefs in the header \libheaderref{cstdint}. -For each such type \tcode{\placeholder{integral}}, -the specialization \tcode{atomic_ref<\placeholder{integral}>} provides -additional atomic operations appropriate to integral types. -\begin{note} -The specialization \tcode{atomic_ref} -uses the primary template\iref{atomics.ref.generic}. -\end{note} - -\begin{codeblock} -namespace std { - template<> struct atomic_ref<@\placeholder{integral}@> { - private: - @\placeholder{integral}@* ptr; // \expos - public: - using value_type = @\placeholder{integral}@; - using difference_type = value_type; - static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - explicit atomic_ref(@\placeholder{integral}@&); - atomic_ref(const atomic_ref&) noexcept; - atomic_ref& operator=(const atomic_ref&) = delete; - - void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral}@ operator=(@\placeholder{integral}@) const noexcept; - @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const noexcept; - operator @\placeholdernc{integral}@() const noexcept; - - @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholder{integral}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholder{integral}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholder{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholder{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - - @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - - @\placeholdernc{integral}@ operator++(int) const noexcept; - @\placeholdernc{integral}@ operator--(int) const noexcept; - @\placeholdernc{integral}@ operator++() const noexcept; - @\placeholdernc{integral}@ operator--() const noexcept; - @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) const noexcept; - @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) const noexcept; - @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) const noexcept; - @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) const noexcept; - @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) const noexcept; - - void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; - }; -} -\end{codeblock} - -\pnum -Descriptions are provided below only for members -that differ from the primary template. - -\pnum -The following operations perform arithmetic computations. -The key, operator, and computation correspondence is identified -in \tref{atomic.types.int.comp}. - -\indexlibrarymember{fetch_add}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{fetch_and}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{fetch_or}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{fetch_xor}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -@\placeholdernc{integral}@ fetch_@\placeholdernc{key}@(@\placeholdernc{integral}@ operand, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically replaces the value referenced by \tcode{*ptr} with -the result of the computation applied to the value referenced by \tcode{*ptr} -and the given operand. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.races}. - -\pnum -\returns -Atomically, the value referenced by \tcode{*ptr} -immediately before the effects. - -\pnum -\indextext{signed integer representation!two's complement}% -\remarks -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 -the result converted back to the signed type. -\begin{note} -There are no undefined results arising from the computation. -\end{note} -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator-=}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator\&=}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator"|=}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator\caret=}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -@\placeholdernc{integral}@ operator @\placeholder{op}@=(@\placeholdernc{integral}@ operand) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\tcode{return fetch_\placeholdernc{key}(operand) \placeholder{op} operand;} -\end{itemdescr} - -\rSec2[atomics.ref.float]{Specializations for floating-point types} - -\pnum -\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}}% -There are specializations of the \tcode{atomic_ref} class template -for the floating-point types -\tcode{float}, -\tcode{double}, and -\tcode{long double}. -For each such type \tcode{\placeholder{floating-point}}, -the specialization \tcode{atomic_ref<\placeholder{floating-\-point}>} provides -additional atomic operations appropriate to floating-point types. - -\begin{codeblock} -namespace std { - template<> struct atomic_ref<@\placeholder{floating-point}@> { - private: - @\placeholder{floating-point}@* ptr; // \expos - public: - using value_type = @\placeholder{floating-point}@; - using difference_type = value_type; - static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - explicit atomic_ref(@\placeholder{floating-point}@&); - atomic_ref(const atomic_ref&) noexcept; - atomic_ref& operator=(const atomic_ref&) = delete; - - void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point}@ operator=(@\placeholder{floating-point}@) const noexcept; - @\placeholder{floating-point}@ load(memory_order = memory_order::seq_cst) const noexcept; - operator @\placeholdernc{floating-point}@() const noexcept; - - @\placeholder{floating-point}@ exchange(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) const noexcept; - - @\placeholder{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) const noexcept; - - @\placeholder{floating-point}@ operator+=(@\placeholder{floating-point}@) const noexcept; - @\placeholder{floating-point}@ operator-=(@\placeholder{floating-point}@) const noexcept; - - void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; - }; -} -\end{codeblock} - -\pnum -Descriptions are provided below only for members -that differ from the primary template. - -\pnum -The following operations perform arithmetic computations. -The key, operator, and computation correspondence are identified -in \tref{atomic.types.int.comp}. - -\indexlibrarymember{fetch_add}{atomic_ref<\placeholder{floating-point}>}% -\indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -@\placeholder{floating-point}@ fetch_@\placeholdernc{key}@(@\placeholder{floating-point}@ operand, - memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically replaces the value referenced by \tcode{*ptr} with -the result of the computation applied to the value referenced by \tcode{*ptr} -and the given operand. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.races}. - -\pnum -\returns -Atomically, the value referenced by \tcode{*ptr} -immediately before the effects. - -\pnum -\remarks -If the result is not a representable value for its type\iref{expr.pre}, -the result is unspecified, -but the operations otherwise have no undefined behavior. -Atomic arithmetic operations on \tcode{\placeholder{floating-point}} should conform to -the \tcode{std::numeric_limits<\placeholder{floating-point}>} traits -associated with the floating-point type\iref{limits.syn}. -The floating-point environment\iref{cfenv} -for atomic arithmetic operations on \tcode{\placeholder{floating-point}} -may be different than the calling thread's floating-point environment. -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic_ref<\placeholder{floating-point}>}% -\indexlibrarymember{operator-=}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -@\placeholder{floating-point}@ operator @\placeholder{op}@=(@\placeholder{floating-point}@ operand) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\tcode{return fetch_\placeholder{key}(operand) \placeholdernc{op} operand;} -\end{itemdescr} - -\rSec2[atomics.ref.pointer]{Partial specialization for pointers} -\indexlibraryglobal{atomic_ref}% - -\begin{codeblock} -namespace std { - template struct atomic_ref { - private: - T** ptr; // \expos - public: - using value_type = T*; - using difference_type = ptrdiff_t; - static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - explicit atomic_ref(T*&); - atomic_ref(const atomic_ref&) noexcept; - atomic_ref& operator=(const atomic_ref&) = delete; - - void store(T*, memory_order = memory_order::seq_cst) const noexcept; - T* operator=(T*) const noexcept; - T* load(memory_order = memory_order::seq_cst) const noexcept; - operator T*() const noexcept; - - T* exchange(T*, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(T*&, T*, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(T*&, T*, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(T*&, T*, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(T*&, T*, - memory_order = memory_order::seq_cst) const noexcept; - - T* fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept; - T* fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept; - - T* operator++(int) const noexcept; - T* operator--(int) const noexcept; - T* operator++() const noexcept; - T* operator--() const noexcept; - T* operator+=(difference_type) const noexcept; - T* operator-=(difference_type) const noexcept; - - void wait(T*, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; - }; -} -\end{codeblock} - -\pnum -Descriptions are provided below only for members -that differ from the primary template. - -\pnum -The following operations perform arithmetic computations. -The key, operator, and computation correspondence is identified -in \tref{atomic.types.pointer.comp}. - -\indexlibrarymember{fetch_add}{atomic_ref}% -\indexlibrarymember{fetch_sub}{atomic_ref}% -\begin{itemdecl} -T* fetch_@\placeholdernc{key}@(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{T} is a complete object type. - -\pnum -\effects -Atomically replaces the value referenced by \tcode{*ptr} with -the result of the computation applied to the value referenced by \tcode{*ptr} -and the given operand. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.races}. - -\pnum -\returns -Atomically, the value referenced by \tcode{*ptr} -immediately before the effects. - -\pnum -\remarks -The result may be an undefined address, -but the operations otherwise have no undefined behavior. -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic_ref}% -\indexlibrarymember{operator-=}{atomic_ref}% -\begin{itemdecl} -T* operator @\placeholder{op}@=(difference_type operand) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\tcode{return fetch_\placeholder{key}(operand) \placeholdernc{op} operand;} -\end{itemdescr} - -\rSec2[atomics.ref.memop]{Member operators - common to integers and pointers to objects} - -\indexlibrarymember{operator++}{atomic_ref}% -\indexlibrarymember{operator++}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator++(int) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return fetch_add(1);} -\end{itemdescr} - -\indexlibrarymember{operator--}{atomic_ref}% -\indexlibrarymember{operator--}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator--(int) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return fetch_sub(1);} -\end{itemdescr} - -\indexlibrarymember{operator++}{atomic_ref}% -\indexlibrarymember{operator++}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator++() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return fetch_add(1) + 1;} -\end{itemdescr} - -\indexlibrarymember{operator--}{atomic_ref}% -\indexlibrarymember{operator--}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator--() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return fetch_sub(1) - 1;} -\end{itemdescr} - -\rSec1[atomics.types.generic]{Class template \tcode{atomic}} - -\rSec2[atomics.types.generic.general]{General} - -\indexlibraryglobal{atomic}% -\indexlibrarymember{value_type}{atomic}% -\begin{codeblock} -namespace std { - template struct atomic { - using value_type = T; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const volatile noexcept; - bool is_lock_free() const noexcept; - - // \ref{atomics.types.operations}, operations on atomic types - constexpr atomic() noexcept(is_nothrow_default_constructible_v); - constexpr atomic(T) noexcept; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - T load(memory_order = memory_order::seq_cst) const volatile noexcept; - T load(memory_order = memory_order::seq_cst) const noexcept; - operator T() const volatile noexcept; - operator T() const noexcept; - void store(T, memory_order = memory_order::seq_cst) volatile noexcept; - void store(T, memory_order = memory_order::seq_cst) noexcept; - T operator=(T) volatile noexcept; - T operator=(T) noexcept; - - T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept; - T exchange(T, memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept; - bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept; - bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept; - - void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(T, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() volatile noexcept; - void notify_one() noexcept; - void notify_all() volatile noexcept; - void notify_all() noexcept; - }; -} -\end{codeblock} - -\indexlibraryglobal{atomic}% -\pnum -The template argument for \tcode{T} shall meet the -\oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} requirements. -The program is ill-formed if any of -\begin{itemize} -\item \tcode{is_trivially_copyable_v}, -\item \tcode{is_copy_constructible_v}, -\item \tcode{is_move_constructible_v}, -\item \tcode{is_copy_assignable_v}, or -\item \tcode{is_move_assignable_v} -\end{itemize} -is \tcode{false}. -\begin{note} -Type arguments that are -not also statically initializable can be difficult to use. -\end{note} - -\pnum -The specialization \tcode{atomic} is a standard-layout struct. - -\pnum -\begin{note} -The representation of an atomic specialization -need not have the same size and alignment requirement as -its corresponding argument type. -\end{note} - -\rSec2[atomics.types.operations]{Operations on atomic types} - -\indexlibraryctor{atomic}% -\indexlibraryctor{atomic}% -\indexlibrary{\idxcode{atomic<\placeholder{integral}>}!constructor}% -\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}!constructor}% -\begin{itemdecl} -constexpr atomic() noexcept(is_nothrow_default_constructible_v); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{is_default_constructible_v} is \tcode{true}. - -\pnum -\effects -Initializes the atomic object with the value of \tcode{T()}. -Initialization is not an atomic operation\iref{intro.multithread}. -\end{itemdescr} - -\indexlibraryctor{atomic}% -\indexlibraryctor{atomic}% -\indexlibrary{\idxcode{atomic<\placeholder{integral}>}!constructor}% -\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}!constructor}% -\begin{itemdecl} -constexpr atomic(T desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the object with the value \tcode{desired}. -Initialization is not an atomic operation\iref{intro.multithread}. -\begin{note} -It is possible to have an access to an atomic object \tcode{A} -race with its construction, for example by communicating the address of the -just-constructed object \tcode{A} to another thread via -\tcode{memory_order::relaxed} operations on a suitable atomic pointer -variable, and then immediately accessing \tcode{A} in the receiving thread. -This results in undefined behavior. -\end{note} -\end{itemdescr} - -\indexlibrarymember{is_always_lock_free}{atomic}% -\indexlibrarymember{is_always_lock_free}{atomic}% -\indexlibrarymember{is_always_lock_free}{atomic<\placeholder{integral}>}% -\indexlibrarymember{is_always_lock_free}{atomic<\placeholder{floating-point}>}% -\indexlibrarymember{is_always_lock_free}{atomic>}% -\indexlibrarymember{is_always_lock_free}{atomic>}% -\begin{itemdecl} -static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The \keyword{static} data member \tcode{is_always_lock_free} is \tcode{true} -if the atomic type's operations are always lock-free, and \tcode{false} otherwise. -\begin{note} -The value of \tcode{is_always_lock_free} is consistent with the value of -the corresponding \tcode{ATOMIC_..._LOCK_FREE} macro, if defined. -\end{note} -\end{itemdescr} - -\indexlibraryglobal{atomic_is_lock_free}% -\indexlibrarymember{is_lock_free}{atomic}% -\indexlibrarymember{is_lock_free}{atomic}% -\indexlibrarymember{is_lock_free}{atomic<\placeholder{integral}>}% -\indexlibrarymember{is_lock_free}{atomic<\placeholder{floating-point}>}% -\indexlibrarymember{is_lock_free}{atomic>}% -\indexlibrarymember{is_lock_free}{atomic>}% -\begin{itemdecl} -bool is_lock_free() const volatile noexcept; -bool is_lock_free() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if the object's operations are lock-free, \tcode{false} otherwise. -\begin{note} -The return value of the \tcode{is_lock_free} member function -is consistent with the value of \tcode{is_always_lock_free} for the same type. -\end{note} -\end{itemdescr} - -\indexlibraryglobal{atomic_store}% -\indexlibraryglobal{atomic_store_explicit}% -\indexlibrarymember{store}{atomic}% -\indexlibrarymember{store}{atomic}% -\indexlibrarymember{store}{atomic<\placeholder{integral}>}% -\indexlibrarymember{store}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; -void store(T desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\expects -The \tcode{order} argument is neither \tcode{memory_order::consume}, -\tcode{memory_order::acquire}, nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Atomically replaces the value pointed to by \keyword{this} -with the value of \tcode{desired}. Memory is affected according to the value of -\tcode{order}. -\end{itemdescr} - -\indexlibrarymember{operator=}{atomic}% -\indexlibrarymember{operator=}{atomic}% -\indexlibrarymember{operator=}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator=}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -T operator=(T desired) volatile noexcept; -T operator=(T desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to \tcode{store(desired)}. - -\pnum -\returns -\tcode{desired}. -\end{itemdescr} - -\indexlibraryglobal{atomic_load}% -\indexlibraryglobal{atomic_load_explicit}% -\indexlibrarymember{load}{atomic}% -\indexlibrarymember{load}{atomic}% -\indexlibrarymember{load}{atomic<\placeholder{integral}>}% -\indexlibrarymember{load}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -T load(memory_order order = memory_order::seq_cst) const volatile noexcept; -T load(memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\expects -The \tcode{order} argument is neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Memory is affected according to the value of \tcode{order}. - -\pnum -\returns -Atomically returns the value pointed to by \keyword{this}. -\end{itemdescr} - -\indexlibrarymember{operator \placeholder{type}}{atomic}% -\indexlibrarymember{operator T*}{atomic}% -\indexlibrarymember{operator \placeholder{integral}}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator \placeholder{floating-point}}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -operator T() const volatile noexcept; -operator T() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return load();} -\end{itemdescr} - - -\indexlibraryglobal{atomic_exchange}% -\indexlibraryglobal{atomic_exchange_explicit}% -\indexlibrarymember{exchange}{atomic}% -\indexlibrarymember{exchange}{atomic}% -\indexlibrarymember{exchange}{atomic<\placeholder{integral}>}% -\indexlibrarymember{exchange}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; -T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Atomically replaces the value pointed to by \keyword{this} -with \tcode{desired}. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.multithread}. - -\pnum -\returns -Atomically returns the value pointed to by \keyword{this} immediately before the effects. -\end{itemdescr} - -\indexlibraryglobal{atomic_compare_exchange_weak}% -\indexlibraryglobal{atomic_compare_exchange_strong}% -\indexlibraryglobal{atomic_compare_exchange_weak_explicit}% -\indexlibraryglobal{atomic_compare_exchange_strong_explicit}% -\indexlibrarymember{compare_exchange_weak}{atomic}% -\indexlibrarymember{compare_exchange_weak}{atomic}% -\indexlibrarymember{compare_exchange_weak}{atomic<\placeholder{integral}>}% -\indexlibrarymember{compare_exchange_weak}{atomic<\placeholder{floating-point}>}% -\indexlibrarymember{compare_exchange_strong}{atomic}% -\indexlibrarymember{compare_exchange_strong}{atomic}% -\indexlibrarymember{compare_exchange_strong}{atomic<\placeholder{integral}>}% -\indexlibrarymember{compare_exchange_strong}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -bool compare_exchange_weak(T& expected, T desired, - memory_order success, memory_order failure) volatile noexcept; -bool compare_exchange_weak(T& expected, T desired, - memory_order success, memory_order failure) noexcept; -bool compare_exchange_strong(T& expected, T desired, - memory_order success, memory_order failure) volatile noexcept; -bool compare_exchange_strong(T& expected, T desired, - memory_order success, memory_order failure) noexcept; -bool compare_exchange_weak(T& expected, T desired, - memory_order order = memory_order::seq_cst) volatile noexcept; -bool compare_exchange_weak(T& expected, T desired, - memory_order order = memory_order::seq_cst) noexcept; -bool compare_exchange_strong(T& expected, T desired, - memory_order order = memory_order::seq_cst) volatile noexcept; -bool compare_exchange_strong(T& expected, T desired, - memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\expects -The \tcode{failure} argument is neither \tcode{memory_order::release} nor -\tcode{memory_order::acq_rel}. - -\pnum -\effects -Retrieves the value in \tcode{expected}. It then atomically -compares the value representation of the value pointed to by \keyword{this} -for equality with that previously retrieved from \tcode{expected}, -and if true, replaces the value pointed to -by \keyword{this} with that in \tcode{desired}. -If and only if the comparison is \tcode{true}, memory is affected according to the -value of \tcode{success}, and if the comparison is false, memory is affected according -to the value of \tcode{failure}. When only one \tcode{memory_order} argument is -supplied, the value of \tcode{success} is \tcode{order}, and the value of -\tcode{failure} is \tcode{order} except that a value of \tcode{memory_order::acq_rel} -shall be replaced by the value \tcode{memory_order::acquire} and a value of -\tcode{memory_order::release} shall be replaced by the value -\tcode{memory_order::relaxed}. -If and only if the comparison is false then, after the atomic operation, -the value in \tcode{expected} is replaced by the value -pointed to by \keyword{this} during the atomic comparison. -If the operation returns \tcode{true}, these -operations are atomic read-modify-write -operations\iref{intro.multithread} on the memory -pointed to by \keyword{this}. -Otherwise, these operations are atomic load operations on that memory. - -\pnum -\returns -The result of the comparison. - -\pnum -\begin{note} -For example, the effect of -\tcode{compare_exchange_strong} -on objects without padding bits\iref{basic.types} is -\begin{codeblock} -if (memcmp(this, &expected, sizeof(*this)) == 0) - memcpy(this, &desired, sizeof(*this)); -else - memcpy(&expected, this, sizeof(*this)); -\end{codeblock} -\end{note} -\begin{example} -The expected use of the compare-and-exchange operations is as follows. The -compare-and-exchange operations will update \tcode{expected} when another iteration of -the loop is needed. -\begin{codeblock} -expected = current.load(); -do { - desired = function(expected); -} while (!current.compare_exchange_weak(expected, desired)); -\end{codeblock} -\end{example} -\begin{example} -Because the expected value is updated only on failure, -code releasing the memory containing the \tcode{expected} value on success will work. -For example, list head insertion will act atomically and would not introduce a -data race in the following code: -\begin{codeblock} -do { - p->next = head; // make new list node point to the current head -} while (!head.compare_exchange_weak(p->next, p)); // try to insert -\end{codeblock} -\end{example} - -\pnum -Implementations should ensure that weak compare-and-exchange operations do not -consistently return \tcode{false} unless either the atomic object has value -different from \tcode{expected} or there are concurrent modifications to the -atomic object. - -\pnum -\remarks -A weak compare-and-exchange operation may fail spuriously. That is, even when -the contents of memory referred to by \tcode{expected} and \keyword{this} are -equal, it may return \tcode{false} and store back to \tcode{expected} the same memory -contents that were originally there. -\begin{note} -This -spurious failure enables implementation of compare-and-exchange on a broader class of -machines, e.g., load-locked store-conditional machines. A -consequence of spurious failure is that nearly all uses of weak compare-and-exchange -will be in a loop. -When a compare-and-exchange is in a loop, the weak version will yield better performance -on some platforms. When a weak compare-and-exchange would require a loop and a strong one -would not, the strong one is preferable. -\end{note} - -\pnum -\begin{note} -Under cases where the \tcode{memcpy} and \tcode{memcmp} semantics of the compare-and-exchange -operations apply, the comparisons can fail for values that compare equal with -\tcode{operator==} if the value representation has trap bits or alternate -representations of the same value. Notably, on implementations conforming to -ISO/IEC/IEEE 60559, floating-point \tcode{-0.0} and \tcode{+0.0} -will not compare equal with \tcode{memcmp} but will compare equal with \tcode{operator==}, -and NaNs with the same payload will compare equal with \tcode{memcmp} but will not -compare equal with \tcode{operator==}. -\end{note} -\begin{note} -Because compare-and-exchange acts on an object's value representation, -padding bits that never participate in the object's value representation -are ignored. As a consequence, the following code is guaranteed to avoid -spurious failure: -\begin{codeblock} -struct padded { - char clank = 0x42; - // Padding here. - unsigned biff = 0xC0DEFEFE; -}; -atomic pad = {}; - -bool zap() { - padded expected, desired{0, 0}; - return pad.compare_exchange_strong(expected, desired); -} -\end{codeblock} -\end{note} -\begin{note} -For a union with bits that participate in the value representation -of some members but not others, compare-and-exchange might always fail. -This is because such padding bits have an indeterminate value when they -do not participate in the value representation of the active member. -As a consequence, the following code is not guaranteed to ever succeed: -\begin{codeblock} -union pony { - double celestia = 0.; - short luna; // padded -}; -atomic princesses = {}; - -bool party(pony desired) { - pony expected; - return princesses.compare_exchange_strong(expected, desired); -} -\end{codeblock} -\end{note} -\end{itemdescr} - -\indexlibrarymember{wait}{atomic}% -\indexlibrarymember{wait}{atomic}% -\indexlibrarymember{wait}{atomic<\placeholder{integral}>}% -\indexlibrarymember{wait}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept; -void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Repeatedly performs the following steps, in order: -\begin{itemize} -\item - Evaluates \tcode{load(order)} and - compares its value representation for equality against that of \tcode{old}. -\item - If they compare unequal, returns. -\item - Blocks until it - is unblocked by an atomic notifying operation or is unblocked spuriously. -\end{itemize} - -\pnum -\remarks -This function is an atomic waiting operation\iref{atomics.wait}. -\end{itemdescr} - -\indexlibrarymember{notify_one}{atomic}% -\indexlibrarymember{notify_one}{atomic}% -\indexlibrarymember{notify_one}{atomic<\placeholder{integral}>}% -\indexlibrarymember{notify_one}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -void notify_one() volatile noexcept; -void notify_one() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of at least one atomic waiting operation -that is eligible to be unblocked\iref{atomics.wait} by this call, -if any such atomic waiting operations exist. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\indexlibrarymember{notify_all}{atomic}% -\indexlibrarymember{notify_all}{atomic}% -\indexlibrarymember{notify_all}{atomic<\placeholder{integral}>}% -\indexlibrarymember{notify_all}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -void notify_all() volatile noexcept; -void notify_all() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of all atomic waiting operations -that are eligible to be unblocked\iref{atomics.wait} by this call. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\rSec2[atomics.types.int]{Specializations for integers} - -\indexlibrary{\idxcode{atomic<\placeholder{integral}>}}% -\pnum -There are specializations of the \tcode{atomic} -class template for the integral types -\tcode{char}, -\tcode{signed char}, -\tcode{unsigned char}, -\tcode{short}, -\tcode{unsigned short}, -\tcode{int}, -\tcode{unsigned int}, -\tcode{long}, -\tcode{unsigned long}, -\tcode{long long}, -\tcode{unsigned long long}, -\keyword{char8_t}, -\keyword{char16_t}, -\keyword{char32_t}, -\keyword{wchar_t}, -and any other types needed by the typedefs in the header \libheaderref{cstdint}. -For each such type \tcode{\placeholder{integral}}, the specialization -\tcode{atomic<\placeholder{integral}>} provides additional atomic operations appropriate to integral types. -\begin{note} -The specialization \tcode{atomic} -uses the primary template\iref{atomics.types.generic}. -\end{note} - -\begin{codeblock} -namespace std { - template<> struct atomic<@\placeholder{integral}@> { - using value_type = @\placeholder{integral}@; - using difference_type = value_type; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const volatile noexcept; - bool is_lock_free() const noexcept; - - constexpr atomic() noexcept; - constexpr atomic(@\placeholdernc{integral}@) noexcept; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral}@ operator=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator=(@\placeholdernc{integral}@) noexcept; - @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const volatile noexcept; - @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const noexcept; - operator @\placeholdernc{integral}@() const volatile noexcept; - operator @\placeholdernc{integral}@() const noexcept; - - @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order, memory_order) noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order, memory_order) noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) noexcept; - - @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - - @\placeholdernc{integral}@ operator++(int) volatile noexcept; - @\placeholdernc{integral}@ operator++(int) noexcept; - @\placeholdernc{integral}@ operator--(int) volatile noexcept; - @\placeholdernc{integral}@ operator--(int) noexcept; - @\placeholdernc{integral}@ operator++() volatile noexcept; - @\placeholdernc{integral}@ operator++() noexcept; - @\placeholdernc{integral}@ operator--() volatile noexcept; - @\placeholdernc{integral}@ operator--() noexcept; - @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) noexcept; - @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) noexcept; - @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) noexcept; - @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) noexcept; - @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) noexcept; - - void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() volatile noexcept; - void notify_one() noexcept; - void notify_all() volatile noexcept; - void notify_all() noexcept; - }; -} -\end{codeblock} - -\pnum -The atomic integral specializations -are standard-layout structs. -They each have -a trivial destructor. - -\pnum -Descriptions are provided below only for members that differ from the primary template. - -\pnum -The following operations perform arithmetic computations. The key, operator, and computation correspondence is: - -\begin{floattable} -{Atomic arithmetic computations}{atomic.types.int.comp}{lll|lll} -\hline -\hdstyle{\tcode{\placeholder{key}}} & - \hdstyle{Op} & - \hdstyle{Computation} & -\hdstyle{\tcode{\placeholder{key}}} & - \hdstyle{Op} & - \hdstyle{Computation} \\ \hline -\tcode{add} & - \tcode{+} & - addition & -\tcode{sub} & - \tcode{-} & - subtraction \\ -\tcode{or} & - \tcode{|} & - bitwise inclusive or & -\tcode{xor} & - \tcode{\caret} & - bitwise exclusive or \\ -\tcode{and} & - \tcode{\&} & - bitwise and &&&\\ -\end{floattable} - -\indexlibraryglobal{atomic_fetch_add}% -\indexlibraryglobal{atomic_fetch_and}% -\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_or_explicit}% -\indexlibraryglobal{atomic_fetch_sub_explicit}% -\indexlibraryglobal{atomic_fetch_xor_explicit}% -\indexlibrarymember{fetch_add}{atomic<\placeholder{integral}>}% -\indexlibrarymember{fetch_and}{atomic<\placeholder{integral}>}% -\indexlibrarymember{fetch_or}{atomic<\placeholder{integral}>}% -\indexlibrarymember{fetch_sub}{atomic<\placeholder{integral}>}% -\indexlibrarymember{fetch_xor}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; -T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Atomically replaces the value pointed to by -\keyword{this} with the result of the computation applied to the -value pointed to by \keyword{this} and the given \tcode{operand}. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.multithread}. - -\pnum -\returns -Atomically, the value pointed to by \keyword{this} immediately before the effects. - -\pnum -\indextext{signed integer representation!two's complement}% -\remarks -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 -the result converted back to the signed type. -\begin{note} -There are no undefined results arising from the computation. -\end{note} - -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic}% -\indexlibrarymember{operator-=}{atomic}% -\indexlibrarymember{operator+=}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator-=}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator\&=}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator"|=}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator\caret=}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -T operator @\placeholder{op}@=(T operand) volatile noexcept; -T operator @\placeholder{op}@=(T operand) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} -\end{itemdescr} - -\rSec2[atomics.types.float]{Specializations for floating-point types} - -\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}}% -\pnum -There are specializations of the \tcode{atomic} -class template for the floating-point types -\tcode{float}, -\tcode{double}, and -\tcode{long double}. -For each such type \tcode{\placeholdernc{floating-point}}, -the specialization \tcode{atomic<\placeholder{floating-point}>} -provides additional atomic operations appropriate to floating-point types. - -\begin{codeblock} -namespace std { - template<> struct atomic<@\placeholder{floating-point}@> { - using value_type = @\placeholdernc{floating-point}@; - using difference_type = value_type; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const volatile noexcept; - bool is_lock_free() const noexcept; - - constexpr atomic() noexcept; - constexpr atomic(@\placeholder{floating-point}@) noexcept; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) volatile noexcept; - void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{floating-point}@ operator=(@\placeholder{floating-point}@) volatile noexcept; - @\placeholdernc{floating-point}@ operator=(@\placeholder{floating-point}@) noexcept; - @\placeholdernc{floating-point}@ load(memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point}@ load(memory_order = memory_order::seq_cst) noexcept; - operator @\placeholdernc{floating-point}@() volatile noexcept; - operator @\placeholdernc{floating-point}@() noexcept; - - @\placeholdernc{floating-point}@ exchange(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point}@ exchange(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) noexcept; - - @\placeholdernc{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) noexcept; - - @\placeholdernc{floating-point}@ operator+=(@\placeholder{floating-point}@) volatile noexcept; - @\placeholdernc{floating-point}@ operator+=(@\placeholder{floating-point}@) noexcept; - @\placeholdernc{floating-point}@ operator-=(@\placeholder{floating-point}@) volatile noexcept; - @\placeholdernc{floating-point}@ operator-=(@\placeholder{floating-point}@) noexcept; - - void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() volatile noexcept; - void notify_one() noexcept; - void notify_all() volatile noexcept; - void notify_all() noexcept; - }; -} -\end{codeblock} - -\pnum -The atomic floating-point specializations -are standard-layout structs. -They each have -a trivial destructor. - -\pnum -Descriptions are provided below only for members that differ from the primary template. - -\pnum -The following operations perform arithmetic addition and subtraction computations. -The key, operator, and computation correspondence are identified in -\tref{atomic.types.int.comp}. - -\indexlibraryglobal{atomic_fetch_add}% -\indexlibraryglobal{atomic_fetch_sub}% -\indexlibraryglobal{atomic_fetch_add_explicit}% -\indexlibraryglobal{atomic_fetch_sub_explicit}% -\indexlibrarymember{fetch_add}{atomic<\placeholder{floating-point}>}% -\indexlibrarymember{fetch_sub}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; -T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Atomically replaces the value pointed to by \keyword{this} -with the result of the computation applied to the value pointed -to by \keyword{this} and the given \tcode{operand}. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.multithread}. - -\pnum -\returns -Atomically, the value pointed to by \keyword{this} immediately before the effects. - -\pnum -\remarks -If the result is not a representable value for its type\iref{expr.pre} -the result is unspecified, but the operations otherwise have no undefined -behavior. Atomic arithmetic operations on \tcode{\placeholder{floating-point}} -should conform to the \tcode{std::numeric_limits<\placeholder{floating-point}>} -traits associated with the floating-point type\iref{limits.syn}. -The floating-point environment\iref{cfenv} for atomic arithmetic operations -on \tcode{\placeholder{floating-point}} may be different than the -calling thread's floating-point environment. -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic}% -\indexlibrarymember{operator-=}{atomic}% -\indexlibrarymember{operator+=}{atomic<\placeholder{floating-point}>}% -\indexlibrarymember{operator-=}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -T operator @\placeholder{op}@=(T operand) volatile noexcept; -T operator @\placeholder{op}@=(T operand) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} - -\pnum -\remarks -If the result is not a representable value for its type\iref{expr.pre} -the result is unspecified, but the operations otherwise have no undefined -behavior. Atomic arithmetic operations on \tcode{\placeholder{floating-point}} -should conform to the \tcode{std::numeric_limits<\placeholder{floating-point}>} -traits associated with the floating-point type\iref{limits.syn}. -The floating-point environment\iref{cfenv} for atomic arithmetic operations -on \tcode{\placeholder{floating-point}} may be different than the -calling thread's floating-point environment. -\end{itemdescr} - -\rSec2[atomics.types.pointer]{Partial specialization for pointers} -\indexlibraryglobal{atomic}% - -\begin{codeblock} -namespace std { - template struct atomic { - using value_type = T*; - using difference_type = ptrdiff_t; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const volatile noexcept; - bool is_lock_free() const noexcept; - - constexpr atomic() noexcept; - constexpr atomic(T*) noexcept; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - void store(T*, memory_order = memory_order::seq_cst) volatile noexcept; - void store(T*, memory_order = memory_order::seq_cst) noexcept; - T* operator=(T*) volatile noexcept; - T* operator=(T*) noexcept; - T* load(memory_order = memory_order::seq_cst) const volatile noexcept; - T* load(memory_order = memory_order::seq_cst) const noexcept; - operator T*() const volatile noexcept; - operator T*() const noexcept; - - T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept; - T* exchange(T*, memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept; - bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept; - bool compare_exchange_weak(T*&, T*, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(T*&, T*, - memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(T*&, T*, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(T*&, T*, - memory_order = memory_order::seq_cst) noexcept; - - T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; - T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; - 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* operator++(int) volatile noexcept; - T* operator++(int) noexcept; - T* operator--(int) volatile noexcept; - T* operator--(int) noexcept; - T* operator++() volatile noexcept; - T* operator++() noexcept; - T* operator--() volatile noexcept; - T* operator--() noexcept; - T* operator+=(ptrdiff_t) volatile noexcept; - T* operator+=(ptrdiff_t) noexcept; - T* operator-=(ptrdiff_t) volatile noexcept; - T* operator-=(ptrdiff_t) noexcept; - - void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(T*, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() volatile noexcept; - void notify_one() noexcept; - void notify_all() volatile noexcept; - void notify_all() noexcept; - }; -} -\end{codeblock} - -\indexlibraryglobal{atomic}% -\pnum -There is a partial specialization of the \tcode{atomic} class template for pointers. -Specializations of this partial specialization are standard-layout structs. -They each have a trivial destructor. - -\pnum -Descriptions are provided below only for members that differ from the primary template. - -\pnum -The following operations perform pointer arithmetic. The key, operator, -and computation correspondence is: - -\begin{floattable} -{Atomic pointer computations}{atomic.types.pointer.comp}{lll|lll} -\hline -\hdstyle{\tcode{\placeholder{key}}} & - \hdstyle{Op} & - \hdstyle{Computation} & -\hdstyle{\tcode{\placeholder{key}}} & - \hdstyle{Op} & - \hdstyle{Computation} \\ \hline -\tcode{add} & - \tcode{+} & - addition & -\tcode{sub} & - \tcode{-} & - subtraction \\ -\end{floattable} - -\indexlibraryglobal{atomic_fetch_add}% -\indexlibraryglobal{atomic_fetch_sub}% -\indexlibraryglobal{atomic_fetch_add_explicit}% -\indexlibraryglobal{atomic_fetch_sub_explicit}% -\indexlibrarymember{fetch_add}{atomic}% -\indexlibrarymember{fetch_sub}{atomic}% -\begin{itemdecl} -T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept; -T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\mandates -\tcode{T} is a complete object type. -\begin{note} -Pointer arithmetic on \tcode{void*} or function pointers is ill-formed. -\end{note} - -\pnum -\effects -Atomically replaces the value pointed to by -\keyword{this} with the result of the computation applied to the -value pointed to by \keyword{this} and the given \tcode{operand}. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.multithread}. - -\pnum -\returns -Atomically, the value pointed to by \keyword{this} immediately before the effects. - -\pnum -\remarks -The result may be an undefined address, -but the operations otherwise have no undefined behavior. -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic}% -\indexlibrarymember{operator-=}{atomic}% -\begin{itemdecl} -T* operator @\placeholder{op}@=(ptrdiff_t operand) volatile noexcept; -T* operator @\placeholder{op}@=(ptrdiff_t operand) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} -\end{itemdescr} - -\rSec2[atomics.types.memop]{Member operators common to integers and pointers to objects} - -\indexlibrarymember{operator++}{atomic}% -\indexlibrarymember{operator++}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator++(int) volatile noexcept; -value_type operator++(int) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_add(1);} -\end{itemdescr} - -\indexlibrarymember{operator--}{atomic}% -\indexlibrarymember{operator--}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator--(int) volatile noexcept; -value_type operator--(int) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_sub(1);} -\end{itemdescr} - -\indexlibrarymember{operator++}{atomic}% -\indexlibrarymember{operator++}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator++() volatile noexcept; -value_type operator++() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_add(1) + 1;} -\end{itemdescr} - -\indexlibrarymember{operator--}{atomic}% -\indexlibrarymember{operator--}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator--() volatile noexcept; -value_type operator--() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_sub(1) - 1;} -\end{itemdescr} - -\rSec2[util.smartptr.atomic]{Partial specializations for smart pointers}% -\indextext{atomic!smart pointers|(}% - -\rSec3[util.smartptr.atomic.general]{General} - -\pnum -The library provides partial specializations of the \tcode{atomic} template -for shared-ownership smart pointers\iref{smartptr}. -The behavior of all operations is as specified in \ref{atomics.types.generic}, -unless specified otherwise. -The template parameter \tcode{T} of these partial specializations -may be an incomplete type. - -\pnum -All changes to an atomic smart pointer in \ref{util.smartptr.atomic}, and -all associated \tcode{use_count} increments, -are guaranteed to be performed atomically. -Associated \tcode{use_count} decrements -are sequenced after the atomic operation, -but are not required to be part of it. -Any associated deletion and deallocation -are sequenced after the atomic update step and -are not part of the atomic operation. -\begin{note} -If the atomic operation uses locks, -locks acquired by the implementation -will be held when any \tcode{use_count} adjustments are performed, and -will not be held when any destruction or deallocation -resulting from this is performed. -\end{note} - -\pnum -\begin{example} -\begin{codeblock} -template class atomic_list { - struct node { - T t; - shared_ptr next; - }; - atomic> head; - -public: - auto find(T t) const { - auto p = head.load(); - while (p && p->t != t) - p = p->next; - - return shared_ptr(move(p)); - } - - void push_front(T t) { - auto p = make_shared(); - p->t = t; - p->next = head; - while (!head.compare_exchange_weak(p->next, p)) {} - } -}; -\end{codeblock} -\end{example} - -\rSec3[util.smartptr.atomic.shared]{Partial specialization for \tcode{shared_ptr}} -\indexlibraryglobal{atomic>}% -\begin{codeblock} -namespace std { - template struct atomic> { - using value_type = shared_ptr; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - constexpr atomic() noexcept; - atomic(shared_ptr desired) noexcept; - atomic(const atomic&) = delete; - void operator=(const atomic&) = delete; - - shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; - operator shared_ptr() const noexcept; - void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; - void operator=(shared_ptr desired) noexcept; - - shared_ptr exchange(shared_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, - memory_order success, memory_order failure) noexcept; - bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, - memory_order success, memory_order failure) noexcept; - bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - - void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; - void notify_one() noexcept; - void notify_all() noexcept; - - private: - shared_ptr p; // \expos - }; -} -\end{codeblock} - -\indexlibraryctor{atomic>}% -\begin{itemdecl} -constexpr atomic() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{p\{\}}. -\end{itemdescr} - -\indexlibraryctor{atomic>}% -\begin{itemdecl} -atomic(shared_ptr desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the object with the value \tcode{desired}. -Initialization is not an atomic operation\iref{intro.multithread}. -\begin{note} -It is possible to have an access to -an atomic object \tcode{A} race with its construction, -for example, -by communicating the address of the just-constructed object \tcode{A} -to another thread via \tcode{memory_order::relaxed} operations -on a suitable atomic pointer variable, and -then immediately accessing \tcode{A} in the receiving thread. -This results in undefined behavior. -\end{note} -\end{itemdescr} - -\indexlibrarymember{store}{atomic>}% -\begin{itemdecl} -void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is neither -\tcode{memory_order::consume}, -\tcode{memory_order::acquire}, nor -\tcode{memory_order::acq_rel}. - -\pnum -\effects -Atomically replaces the value pointed to by \keyword{this} with -the value of \tcode{desired} as if by \tcode{p.swap(desired)}. -Memory is affected according to the value of \tcode{order}. -\end{itemdescr} - -\indexlibrarymember{operator=}{atomic>}% -\begin{itemdecl} -void operator=(shared_ptr desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{store(desired)}. -\end{itemdescr} - -\indexlibrarymember{load}{atomic>}% -\begin{itemdecl} -shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Memory is affected according to the value of \tcode{order}. - -\pnum -\returns -Atomically returns \tcode{p}. -\end{itemdescr} - -\indexlibrarymember{operator shared_ptr}{atomic>}% -\begin{itemdecl} -operator shared_ptr() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return load();} -\end{itemdescr} - -\indexlibrarymember{exchange}{atomic>}% -\begin{itemdecl} -shared_ptr exchange(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically replaces \tcode{p} with \tcode{desired} -as if by \tcode{p.swap(desired)}. -Memory is affected according to the value of \tcode{order}. -This is an atomic read-modify-write operation\iref{intro.races}. - -\pnum -\returns -Atomically returns the value of \tcode{p} immediately before the effects. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_weak}{atomic>}% -\indexlibrarymember{compare_exchange_strong}{atomic>}% -\begin{itemdecl} -bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, - memory_order success, memory_order failure) noexcept; -bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, - memory_order success, memory_order failure) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{failure} is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -If \tcode{p} is equivalent to \tcode{expected}, -assigns \tcode{desired} to \tcode{p} and -has synchronization semantics corresponding to the value of \tcode{success}, -otherwise assigns \tcode{p} to \tcode{expected} and -has synchronization semantics corresponding to the value of \tcode{failure}. - -\pnum -\returns -\tcode{true} if \tcode{p} was equivalent to \tcode{expected}, -\tcode{false} otherwise. - -\pnum -\remarks -Two \tcode{shared_ptr} objects are equivalent if -they store the same pointer value and -either share ownership or are both empty. -The weak form may fail spuriously. See \ref{atomics.types.operations}. - -\pnum -If the operation returns \tcode{true}, -\tcode{expected} is not accessed after the atomic update and -the operation is an atomic read-modify-write operation\iref{intro.multithread} -on the memory pointed to by \keyword{this}. -Otherwise, the operation is an atomic load operation on that memory, and -\tcode{expected} is updated with the existing value -read from the atomic object in the attempted atomic update. -The \tcode{use_count} update corresponding to the write to \tcode{expected} -is part of the atomic operation. -The write to \tcode{expected} itself -is not required to be part of the atomic operation. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_weak}{atomic>}% -\begin{itemdecl} -bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return compare_exchange_weak(expected, desired, order, fail_order); -\end{codeblock} -where \tcode{fail_order} is the same as \tcode{order} -except that a value of \tcode{memory_order::acq_rel} -shall be replaced by the value \tcode{memory_order::acquire} and -a value of \tcode{memory_order::release} -shall be replaced by the value \tcode{memory_order::relaxed}. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_strong}{atomic>}% -\begin{itemdecl} -bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return compare_exchange_strong(expected, desired, order, fail_order); -\end{codeblock} -where \tcode{fail_order} is the same as \tcode{order} -except that a value of \tcode{memory_order::acq_rel} -shall be replaced by the value \tcode{memory_order::acquire} and -a value of \tcode{memory_order::release} -shall be replaced by the value \tcode{memory_order::relaxed}. -\end{itemdescr} - -\indexlibrarymember{wait}{atomic>}% -\begin{itemdecl} -void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is -neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Repeatedly performs the following steps, in order: -\begin{itemize} -\item - Evaluates \tcode{load(order)} and compares it to \tcode{old}. -\item - If the two are not equivalent, returns. -\item - Blocks until it - is unblocked by an atomic notifying operation or is unblocked spuriously. -\end{itemize} - -\pnum -\remarks -Two \tcode{shared_ptr} objects are equivalent -if they store the same pointer and either share ownership or are both empty. -This function is an atomic waiting operation\iref{atomics.wait}. -\end{itemdescr} - -\indexlibrarymember{notify_one}{atomic>}% -\begin{itemdecl} -void notify_one() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of at least one atomic waiting operation -that is eligible to be unblocked\iref{atomics.wait} by this call, -if any such atomic waiting operations exist. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\indexlibrarymember{notify_all}{atomic>}% -\begin{itemdecl} -void notify_all() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of all atomic waiting operations -that are eligible to be unblocked\iref{atomics.wait} by this call. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\rSec3[util.smartptr.atomic.weak]{Partial specialization for \tcode{weak_ptr}} -\indexlibraryglobal{atomic>}% -\begin{codeblock} -namespace std { - template struct atomic> { - using value_type = weak_ptr; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - constexpr atomic() noexcept; - atomic(weak_ptr desired) noexcept; - atomic(const atomic&) = delete; - void operator=(const atomic&) = delete; - - weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; - operator weak_ptr() const noexcept; - void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; - void operator=(weak_ptr desired) noexcept; - - weak_ptr exchange(weak_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, - memory_order success, memory_order failure) noexcept; - bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, - memory_order success, memory_order failure) noexcept; - bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - - void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; - void notify_one() noexcept; - void notify_all() noexcept; - - private: - weak_ptr p; // \expos - }; -} -\end{codeblock} - -\indexlibraryctor{atomic>}% -\begin{itemdecl} -constexpr atomic() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{p\{\}}. -\end{itemdescr} - -\indexlibraryctor{atomic>}% -\begin{itemdecl} -atomic(weak_ptr desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the object with the value \tcode{desired}. -Initialization is not an atomic operation\iref{intro.multithread}. -\begin{note} -It is possible to have an access to -an atomic object \tcode{A} race with its construction, -for example, -by communicating the address of the just-constructed object \tcode{A} -to another thread via \tcode{memory_order::relaxed} operations -on a suitable atomic pointer variable, and -then immediately accessing \tcode{A} in the receiving thread. -This results in undefined behavior. -\end{note} -\end{itemdescr} - -\indexlibrarymember{store}{atomic>}% -\begin{itemdecl} -void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is neither -\tcode{memory_order::consume}, -\tcode{memory_order::acquire}, nor -\tcode{memory_order::acq_rel}. - -\pnum -\effects -Atomically replaces the value pointed to by \keyword{this} with -the value of \tcode{desired} as if by \tcode{p.swap(desired)}. -Memory is affected according to the value of \tcode{order}. -\end{itemdescr} - -\indexlibrarymember{operator=}{atomic>}% -\begin{itemdecl} -void operator=(weak_ptr desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{store(desired)}. -\end{itemdescr} - -\indexlibrarymember{load}{atomic>}% -\begin{itemdecl} -weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Memory is affected according to the value of \tcode{order}. - -\pnum -\returns -Atomically returns \tcode{p}. -\end{itemdescr} - -\indexlibrarymember{operator weak_ptr}{atomic>}% -\begin{itemdecl} -operator weak_ptr() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return load();} -\end{itemdescr} - -\indexlibrarymember{exchange}{atomic>}% -\begin{itemdecl} -weak_ptr exchange(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically replaces \tcode{p} with \tcode{desired} -as if by \tcode{p.swap(desired)}. -Memory is affected according to the value of \tcode{order}. -This is an atomic read-modify-write operation\iref{intro.races}. - -\pnum -\returns -Atomically returns the value of \tcode{p} immediately before the effects. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_weak}{atomic>}% -\begin{itemdecl} -bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, - memory_order success, memory_order failure) noexcept; -bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, - memory_order success, memory_order failure) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{failure} is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -If \tcode{p} is equivalent to \tcode{expected}, -assigns \tcode{desired} to \tcode{p} and -has synchronization semantics corresponding to the value of \tcode{success}, -otherwise assigns \tcode{p} to \tcode{expected} and -has synchronization semantics corresponding to the value of \tcode{failure}. - -\pnum -\returns -\tcode{true} if \tcode{p} was equivalent to \tcode{expected}, -\tcode{false} otherwise. - -\pnum -\remarks -Two \tcode{weak_ptr} objects are equivalent if -they store the same pointer value and -either share ownership or are both empty. -The weak form may fail spuriously. See \ref{atomics.types.operations}. - -\pnum -If the operation returns \tcode{true}, -\tcode{expected} is not accessed after the atomic update and -the operation is an atomic read-modify-write operation\iref{intro.multithread} -on the memory pointed to by \keyword{this}. -Otherwise, the operation is an atomic load operation on that memory, and -\tcode{expected} is updated with the existing value -read from the atomic object in the attempted atomic update. -The \tcode{use_count} update corresponding to the write to \tcode{expected} -is part of the atomic operation. -The write to \tcode{expected} itself -is not required to be part of the atomic operation. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_weak}{atomic>}% -\begin{itemdecl} -bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return compare_exchange_weak(expected, desired, order, fail_order); -\end{codeblock} -where \tcode{fail_order} is the same as \tcode{order} -except that a value of \tcode{memory_order::acq_rel} -shall be replaced by the value \tcode{memory_order::acquire} and -a value of \tcode{memory_order::release} -shall be replaced by the value \tcode{memory_order::relaxed}. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_strong}{atomic>}% -\begin{itemdecl} -bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return compare_exchange_strong(expected, desired, order, fail_order); -\end{codeblock} -where \tcode{fail_order} is the same as \tcode{order} -except that a value of \tcode{memory_order::acq_rel} -shall be replaced by the value \tcode{memory_order::acquire} and -a value of \tcode{memory_order::release} -shall be replaced by the value \tcode{memory_order::relaxed}. -\end{itemdescr} - -\indexlibrarymember{wait}{atomic>}% -\begin{itemdecl} -void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is -neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Repeatedly performs the following steps, in order: -\begin{itemize} -\item - Evaluates \tcode{load(order)} and compares it to \tcode{old}. -\item - If the two are not equivalent, returns. -\item - Blocks until it - is unblocked by an atomic notifying operation or is unblocked spuriously. -\end{itemize} - -\pnum -\remarks -Two \tcode{weak_ptr} objects are equivalent -if they store the same pointer and either share ownership or are both empty. -This function is an atomic waiting operation\iref{atomics.wait}. -\end{itemdescr} - - -\indexlibrarymember{notify_one}{atomic>}% -\begin{itemdecl} -void notify_one() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of at least one atomic waiting operation -that is eligible to be unblocked\iref{atomics.wait} by this call, -if any such atomic waiting operations exist. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\indexlibrarymember{notify_all}{atomic>}% -\begin{itemdecl} -void notify_all() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of all atomic waiting operations -that are eligible to be unblocked\iref{atomics.wait} by this call. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} -\indextext{atomic!smart pointers|)} - -\rSec1[atomics.nonmembers]{Non-member functions} - -\pnum -A non-member function template whose name matches the pattern -\tcode{atomic_\placeholder{f}} or the pattern \tcode{atomic_\placeholder{f}_explicit} -invokes the member function \tcode{\placeholder{f}}, with the value of the -first parameter as the object expression and the values of the remaining parameters -(if any) as the arguments of the member function call, in order. An argument -for a parameter of type \tcode{atomic::value_type*} is dereferenced when -passed to the member function call. -If no such member function exists, the program is ill-formed. - -\pnum -\begin{note} -The non-member functions enable programmers to write code that can be -compiled as either C or \Cpp{}, for example in a shared header file. -\end{note} - -\rSec1[atomics.flag]{Flag type and operations} - -\begin{codeblock} -namespace std { - struct atomic_flag { - constexpr atomic_flag() noexcept; - atomic_flag(const atomic_flag&) = delete; - atomic_flag& operator=(const atomic_flag&) = delete; - atomic_flag& operator=(const atomic_flag&) volatile = delete; - - bool test(memory_order = memory_order::seq_cst) const volatile noexcept; - bool test(memory_order = memory_order::seq_cst) const noexcept; - bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept; - bool test_and_set(memory_order = memory_order::seq_cst) noexcept; - void clear(memory_order = memory_order::seq_cst) volatile noexcept; - void clear(memory_order = memory_order::seq_cst) noexcept; - - void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(bool, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() volatile noexcept; - void notify_one() noexcept; - void notify_all() volatile noexcept; - void notify_all() noexcept; - }; -} -\end{codeblock} - -\pnum -The \tcode{atomic_flag} type provides the classic test-and-set functionality. It has two states, set and clear. - -\pnum -Operations on an object of type \tcode{atomic_flag} shall be lock-free. -The operations should also be address-free. - -\pnum -The \tcode{atomic_flag} type is a standard-layout struct. -It has a trivial destructor. - -\indexlibraryctor{atomic_flag}% -\begin{itemdecl} -constexpr atomic_flag::atomic_flag() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{*this} to the clear state. -\end{itemdescr} - -\indexlibraryglobal{atomic_flag_test}% -\indexlibraryglobal{atomic_flag_test_explicit}% -\indexlibrarymember{test}{atomic_flag}% -\begin{itemdecl} -bool atomic_flag_test(const volatile atomic_flag* object) noexcept; -bool atomic_flag_test(const atomic_flag* object) noexcept; -bool atomic_flag_test_explicit(const volatile atomic_flag* object, - memory_order order) noexcept; -bool atomic_flag_test_explicit(const atomic_flag* object, - memory_order order) noexcept; -bool atomic_flag::test(memory_order order = memory_order::seq_cst) const volatile noexcept; -bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -For \tcode{atomic_flag_test}, let \tcode{order} be \tcode{memory_order::seq_cst}. - -\pnum -\expects -\tcode{order} is -neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Memory is affected according to the value of \tcode{order}. - -\pnum -\returns -Atomically returns the value pointed to by \tcode{object} or \keyword{this}. -\end{itemdescr} - -\indexlibraryglobal{atomic_flag_test_and_set}% -\indexlibraryglobal{atomic_flag_test_and_set_explicit}% -\indexlibrarymember{test_and_set}{atomic_flag}% -\begin{itemdecl} -bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept; -bool atomic_flag_test_and_set(atomic_flag* object) noexcept; -bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept; -bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept; -bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept; -bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically sets the value pointed to by \tcode{object} or by \keyword{this} to \tcode{true}. Memory is affected according to the value of -\tcode{order}. These operations are atomic read-modify-write operations\iref{intro.multithread}. - -\pnum -\returns -Atomically, the value of the object immediately before the effects. -\end{itemdescr} - -\indexlibraryglobal{atomic_flag_clear}% -\indexlibraryglobal{atomic_flag_clear_explicit}% -\indexlibrarymember{clear}{atomic_flag}% -\begin{itemdecl} -void atomic_flag_clear(volatile atomic_flag* object) noexcept; -void atomic_flag_clear(atomic_flag* object) noexcept; -void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept; -void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept; -void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept; -void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The \tcode{order} argument is neither \tcode{memory_order::consume}, -\tcode{memory_order::acquire}, nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Atomically sets the value pointed to by \tcode{object} or by \keyword{this} to -\tcode{false}. Memory is affected according to the value of \tcode{order}. -\end{itemdescr} - -\indexlibraryglobal{atomic_flag_wait}% -\indexlibraryglobal{atomic_flag_wait_explicit}% -\indexlibrarymember{wait}{atomic_flag}% -\begin{itemdecl} -void atomic_flag_wait(const volatile atomic_flag* object, bool old) noexcept; -void atomic_flag_wait(const atomic_flag* object, bool old) noexcept; -void atomic_flag_wait_explicit(const volatile atomic_flag* object, - bool old, memory_order order) noexcept; -void atomic_flag_wait_explicit(const atomic_flag* object, - bool old, memory_order order) noexcept; -void atomic_flag::wait(bool old, memory_order order = - memory_order::seq_cst) const volatile noexcept; -void atomic_flag::wait(bool old, memory_order order = - memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -For \tcode{atomic_flag_wait}, -let \tcode{order} be \tcode{memory_order::seq_cst}. -Let \tcode{flag} be \tcode{object} for the non-member functions and -\keyword{this} for the member functions. - -\pnum -\expects -\tcode{order} is -neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Repeatedly performs the following steps, in order: -\begin{itemize} -\item - Evaluates \tcode{flag->test(order) != old}. -\item - If the result of that evaluation is \tcode{true}, returns. -\item - Blocks until it - is unblocked by an atomic notifying operation or is unblocked spuriously. -\end{itemize} - -\pnum -\remarks -This function is an atomic waiting operation\iref{atomics.wait}. -\end{itemdescr} - -\begin{itemdecl} -void atomic_flag_notify_one(volatile atomic_flag* object) noexcept; -void atomic_flag_notify_one(atomic_flag* object) noexcept; -void atomic_flag::notify_one() volatile noexcept; -void atomic_flag::notify_one() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of at least one atomic waiting operation -that is eligible to be unblocked\iref{atomics.wait} by this call, -if any such atomic waiting operations exist. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\begin{itemdecl} -void atomic_flag_notify_all(volatile atomic_flag* object) noexcept; -void atomic_flag_notify_all(atomic_flag* object) noexcept; -void atomic_flag::notify_all() volatile noexcept; -void atomic_flag::notify_all() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of all atomic waiting operations -that are eligible to be unblocked\iref{atomics.wait} by this call. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\rSec1[atomics.fences]{Fences} - -\pnum -This subclause introduces synchronization primitives called \term{fences}. Fences can have -acquire semantics, release semantics, or both. A fence with acquire semantics is called -an \term{acquire fence}. A fence with release semantics is called a \term{release -fence}. - -\pnum -A release fence $A$ synchronizes with an acquire fence $B$ if there exist -atomic operations $X$ and $Y$, both operating on some atomic object -$M$, such that $A$ is sequenced before $X$, $X$ modifies -$M$, $Y$ is sequenced before $B$, and $Y$ reads the value -written by $X$ or a value written by any side effect in the hypothetical release -sequence $X$ would head if it were a release operation. - -\pnum -A release fence $A$ synchronizes with an atomic operation $B$ that -performs an acquire operation on an atomic object $M$ if there exists an atomic -operation $X$ such that $A$ is sequenced before $X$, $X$ -modifies $M$, and $B$ reads the value written by $X$ or a value -written by any side effect in the hypothetical release sequence $X$ would head if -it were a release operation. - -\pnum -An atomic operation $A$ that is a release operation on an atomic object -$M$ synchronizes with an acquire fence $B$ if there exists some atomic -operation $X$ on $M$ such that $X$ is sequenced before $B$ -and reads the value written by $A$ or a value written by any side effect in the -release sequence headed by $A$. - -\indexlibraryglobal{atomic_thread_fence}% -\begin{itemdecl} -extern "C" void atomic_thread_fence(memory_order order) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Depending on the value of \tcode{order}, this operation: -\begin{itemize} -\item has no effects, if \tcode{order == memory_order::relaxed}; - -\item is an acquire fence, if \tcode{order == memory_order::acquire} or \tcode{order == memory_order::consume}; - -\item is a release fence, if \tcode{order == memory_order::release}; - -\item is both an acquire fence and a release fence, if \tcode{order == memory_order::acq_rel}; - -\item is a sequentially consistent acquire and release fence, if \tcode{order == memory_order::seq_cst}. -\end{itemize} -\end{itemdescr} - -\indexlibraryglobal{atomic_signal_fence}% -\begin{itemdecl} -extern "C" void atomic_signal_fence(memory_order order) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{atomic_thread_fence(order)}, except that -the resulting ordering constraints are established only between a thread and a -signal handler executed in the same thread. - -\pnum -\begin{note} -\tcode{atomic_signal_fence} can be used to specify the order in which actions -performed by the thread become visible to the signal handler. -Compiler optimizations and reorderings of loads and stores are inhibited in -the same way as with \tcode{atomic_thread_fence}, but the hardware fence instructions -that \tcode{atomic_thread_fence} would have inserted are not emitted. -\end{note} -\end{itemdescr} - -\rSec1[stdatomic.h.syn]{C compatibility} - -The header \libheaderdef{stdatomic.h} provides the following definitions: - -\begin{codeblock} -template - using @\exposid{std-atomic}@ = std::atomic; // exposition only - -#define _Atomic(T) @\exposid{std-atomic}@ - -#define ATOMIC_BOOL_LOCK_FREE @\seebelow@ -#define ATOMIC_CHAR_LOCK_FREE @\seebelow@ -#define ATOMIC_CHAR16_T_LOCK_FREE @\seebelow@ -#define ATOMIC_CHAR32_T_LOCK_FREE @\seebelow@ -#define ATOMIC_WCHAR_T_LOCK_FREE @\seebelow@ -#define ATOMIC_SHORT_LOCK_FREE @\seebelow@ -#define ATOMIC_INT_LOCK_FREE @\seebelow@ -#define ATOMIC_LONG_LOCK_FREE @\seebelow@ -#define ATOMIC_LLONG_LOCK_FREE @\seebelow@ -#define ATOMIC_POINTER_LOCK_FREE @\seebelow@ - -using std::@\libglobal{memory_order}@; // \seebelow -using std::@\libglobal{memory_order_relaxed}@; // \seebelow -using std::@\libglobal{memory_order_consume}@; // \seebelow -using std::@\libglobal{memory_order_acquire}@; // \seebelow -using std::@\libglobal{memory_order_release}@; // \seebelow -using std::@\libglobal{memory_order_acq_rel}@; // \seebelow -using std::@\libglobal{memory_order_seq_cst}@; // \seebelow - -using std::@\libglobal{atomic_flag}@; // \seebelow - -using std::@\libglobal{atomic_bool}@; // \seebelow -using std::@\libglobal{atomic_char}@; // \seebelow -using std::@\libglobal{atomic_schar}@; // \seebelow -using std::@\libglobal{atomic_uchar}@; // \seebelow -using std::@\libglobal{atomic_short}@; // \seebelow -using std::@\libglobal{atomic_ushort}@; // \seebelow -using std::@\libglobal{atomic_int}@; // \seebelow -using std::@\libglobal{atomic_uint}@; // \seebelow -using std::@\libglobal{atomic_long}@; // \seebelow -using std::@\libglobal{atomic_ulong}@; // \seebelow -using std::@\libglobal{atomic_llong}@; // \seebelow -using std::@\libglobal{atomic_ullong}@; // \seebelow -using std::@\libglobal{atomic_char8_t}@; // \seebelow -using std::@\libglobal{atomic_char16_t}@; // \seebelow -using std::@\libglobal{atomic_char32_t}@; // \seebelow -using std::@\libglobal{atomic_wchar_t}@; // \seebelow -using std::@\libglobal{atomic_int8_t}@; // \seebelow -using std::@\libglobal{atomic_uint8_t}@; // \seebelow -using std::@\libglobal{atomic_int16_t}@; // \seebelow -using std::@\libglobal{atomic_uint16_t}@; // \seebelow -using std::@\libglobal{atomic_int32_t}@; // \seebelow -using std::@\libglobal{atomic_uint32_t}@; // \seebelow -using std::@\libglobal{atomic_int64_t}@; // \seebelow -using std::@\libglobal{atomic_uint64_t}@; // \seebelow -using std::@\libglobal{atomic_int_least8_t}@; // \seebelow -using std::@\libglobal{atomic_uint_least8_t}@; // \seebelow -using std::@\libglobal{atomic_int_least16_t}@; // \seebelow -using std::@\libglobal{atomic_uint_least16_t}@; // \seebelow -using std::@\libglobal{atomic_int_least32_t}@; // \seebelow -using std::@\libglobal{atomic_uint_least32_t}@; // \seebelow -using std::@\libglobal{atomic_int_least64_t}@; // \seebelow -using std::@\libglobal{atomic_uint_least64_t}@; // \seebelow -using std::@\libglobal{atomic_int_fast8_t}@; // \seebelow -using std::@\libglobal{atomic_uint_fast8_t}@; // \seebelow -using std::@\libglobal{atomic_int_fast16_t}@; // \seebelow -using std::@\libglobal{atomic_uint_fast16_t}@; // \seebelow -using std::@\libglobal{atomic_int_fast32_t}@; // \seebelow -using std::@\libglobal{atomic_uint_fast32_t}@; // \seebelow -using std::@\libglobal{atomic_int_fast64_t}@; // \seebelow -using std::@\libglobal{atomic_uint_fast64_t}@; // \seebelow -using std::@\libglobal{atomic_intptr_t}@; // \seebelow -using std::@\libglobal{atomic_uintptr_t}@; // \seebelow -using std::@\libglobal{atomic_size_t}@; // \seebelow -using std::@\libglobal{atomic_ptrdiff_t}@; // \seebelow -using std::@\libglobal{atomic_intmax_t}@; // \seebelow -using std::@\libglobal{atomic_uintmax_t}@; // \seebelow - -using std::@\libglobal{atomic_is_lock_free}@; // \seebelow -using std::@\libglobal{atomic_load}@; // \seebelow -using std::@\libglobal{atomic_load_explicit}@; // \seebelow -using std::@\libglobal{atomic_store}@; // \seebelow -using std::@\libglobal{atomic_store_explicit}@; // \seebelow -using std::@\libglobal{atomic_exchange}@; // \seebelow -using std::@\libglobal{atomic_exchange_explicit}@; // \seebelow -using std::@\libglobal{atomic_compare_exchange_strong}@; // \seebelow -using std::@\libglobal{atomic_compare_exchange_strong_explicit}@; // \seebelow -using std::@\libglobal{atomic_compare_exchange_weak}@; // \seebelow -using std::@\libglobal{atomic_compare_exchange_weak_explicit}@; // \seebelow -using std::@\libglobal{atomic_fetch_add}@; // \seebelow -using std::@\libglobal{atomic_fetch_add_explicit}@; // \seebelow -using std::@\libglobal{atomic_fetch_sub}@; // \seebelow -using std::@\libglobal{atomic_fetch_sub_explicit}@; // \seebelow -using std::@\libglobal{atomic_fetch_or}@; // \seebelow -using std::@\libglobal{atomic_fetch_or_explicit}@; // \seebelow -using std::@\libglobal{atomic_fetch_and}@; // \seebelow -using std::@\libglobal{atomic_fetch_and_explicit}@; // \seebelow -using std::@\libglobal{atomic_flag_test_and_set}@; // \seebelow -using std::@\libglobal{atomic_flag_test_and_set_explicit}@; // \seebelow -using std::@\libglobal{atomic_flag_clear}@; // \seebelow -using std::@\libglobal{atomic_flag_clear_explicit}@; // \seebelow - -using std::@\libglobal{atomic_thread_fence}@; // \seebelow -using std::@\libglobal{atomic_signal_fence}@; // \seebelow -\end{codeblock} - -\pnum -Each \grammarterm{using-declaration} for some name $A$ in the synopsis above -makes available the same entity as \tcode{std::$A$} -declared in \libheaderrefx{atomic}{atomics.syn}. -Each macro listed above other than \tcode{_Atomic(T)} -is defined as in \libheader{atomic}. -It is unspecified whether \libheader{stdatomic.h} makes available -any declarations in namespace \tcode{std}. - -\pnum -Each of the \grammarterm{using-declaration}s for -\tcode{int$N$_t}, \tcode{uint$N$_t}, \tcode{intptr_t}, and \tcode{uintptr_t} -listed above is defined if and only if the implementation defines -the corresponding \grammarterm{typedef-name} in \ref{atomics.syn}. - -\pnum -Neither the \tcode{_Atomic} macro, -nor any of the non-macro global namespace declarations, -are provided by any \Cpp{} standard library header -other than \libheader{stdatomic.h}. - -\pnum -\recommended -Implementations should ensure -that C and \Cpp{} representations of atomic objects are compatible, -so that the same object can be accessed as both an \tcode{_Atomic(T)} -from C code and an \tcode{atomic} from \Cpp{} code. -The representations should be the same, and -the mechanisms used to ensure atomicity and memory ordering -should be compatible. diff --git a/source/basic.tex b/source/basic.tex index 89184d41a6..ab94c86677 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -50,7 +50,7 @@ \item \grammarterm{declaration}, \grammarterm{block-declaration}, or -\grammarterm{member-declaration} (\ref{dcl.pre}, \ref{class.mem}), +\grammarterm{member-declaration}\iref{dcl.pre,class.mem}, \item \grammarterm{init-declarator}\iref{dcl.decl}, \item @@ -178,7 +178,7 @@ \item \indextext{declaration!static member@\tcode{static} member}% it declares a non-inline static data member in a class -definition~(\ref{class.mem}, \ref{class.static}), +definition\iref{class.mem,class.static}, \item it declares a static data member outside a class definition and the variable was defined within the class with the \keyword{constexpr} @@ -318,7 +318,7 @@ \indextext{type!incomplete}% In the definition of an object, the type of that object shall not be -an incomplete type\iref{basic.types.general}, +an incomplete type\iref{term.incomplete.type}, an abstract class type\iref{class.abstract}, or a (possibly multi-dimensional) array thereof. @@ -329,11 +329,22 @@ \indextext{enumerator!definition}% \indextext{one-definition rule|(}% +\pnum +Each of the following is termed a \defnadj{definable}{item}: +\begin{itemize} +\item a class type\iref{class}, +\item an enumeration type\iref{dcl.enum}, +\item a function\iref{dcl.fct}, +\item a variable\iref{basic.pre}, +\item a templated entity\iref{temp.pre}, +\item a default argument for a parameter +(for a function in a given scope)\iref{dcl.fct.default}, or +\item a default template argument\iref{temp.param}. +\end{itemize} + \pnum No translation unit shall contain more than one definition of any -variable, function, class type, enumeration type, template, -default argument for a parameter (for a function in a given scope), or -default template argument. +definable item. \pnum \indextext{expression!potentially evaluated}% @@ -393,7 +404,7 @@ \item A function is named by an expression or conversion if it is the selected member - of an overload set~(\ref{basic.lookup}, \ref{over.match}, \ref{over.over}) + of an overload set\iref{basic.lookup,over.match,over.over} in an overload resolution performed as part of forming that expression or conversion, unless it is a pure virtual function and either @@ -402,7 +413,7 @@ the expression forms a pointer to member\iref{expr.unary.op}. \begin{note} This covers - taking the address of functions~(\ref{conv.func}, \ref{expr.unary.op}), + taking the address of functions\iref{conv.func,expr.unary.op}, calls to named functions\iref{expr.call}, operator overloading\iref{over}, user-defined conversions\iref{class.conv.fct}, @@ -455,7 +466,7 @@ \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~(\ref{class.mfct.non-static})). +member function\iref{class.mfct.non.static}). \pnum A virtual member @@ -527,7 +538,7 @@ \end{example} \pnum -Every program shall contain exactly one definition of every non-inline +Every program shall contain at least one definition of every function or variable that is odr-used in that program outside of a discarded statement\iref{stmt.if}; no diagnostic required. The definition can appear explicitly in the program, it can be found in @@ -586,8 +597,8 @@ a glvalue referring to an object of type \tcode{T}\iref{conv.lval}, or \item an expression is converted (either implicitly or explicitly) to -type \tcode{T} (\ref{conv}, \ref{expr.type.conv}, -\ref{expr.dynamic.cast}, \ref{expr.static.cast}, \ref{expr.cast}), or +type \tcode{T}\iref{conv,expr.type.conv, +expr.dynamic.cast,expr.static.cast,expr.cast}, or \item an expression that is not a null pointer constant, and has type other than \cv{}~\tcode{\keyword{void}*}, is converted to the type pointer to \tcode{T} or reference to \tcode{T} using a standard conversion\iref{conv}, @@ -611,20 +622,19 @@ \end{note} \pnum -There can be more than one definition of a +For any definable item \tcode{D} with definitions in multiple translation units, \begin{itemize} -\item class type\iref{class}, -\item enumeration type\iref{dcl.enum}, -\item inline function or variable\iref{dcl.inline}, -\item templated entity\iref{temp.pre}, -\item default argument for a parameter (for a function in a given scope)% -\iref{dcl.fct.default}, or -\item default template argument\iref{temp.param} +\item +if \tcode{D} is a non-inline non-templated function or variable, or +\item +if the definitions in different translation units +do not satisfy the following requirements, \end{itemize} -in a program provided that -each definition appears in a different translation unit and -the definitions satisfy the following requirements. -Given such an entity \tcode{D} defined in more than one translation unit, +the program is ill-formed; +a diagnostic is required only +if the definable item is attached to a named module and +a prior definition is reachable at the point where a later definition occurs. +Given such an item, for all definitions of \tcode{D}, or, if \tcode{D} is an unnamed enumeration, for all definitions of \tcode{D} that are reachable at any given program point, @@ -680,7 +690,7 @@ is subject to the requirements described in this paragraph (recursively). \item If \tcode{D} is a class with an implicitly-declared -constructor (\ref{class.default.ctor}, \ref{class.copy.ctor}), +constructor\iref{class.default.ctor,class.copy.ctor}, it is as if the constructor was implicitly defined in every translation unit where it is odr-used, and the implicit definition in every translation unit shall call the same @@ -745,13 +755,6 @@ might still denote different types in different translation units. \end{note} -\pnum -If these definitions do not satisfy these requirements, -then the program is ill-formed; -a diagnostic is required only if -the entity is attached to a named module and -a prior definition is reachable at the point where a later definition occurs. - \pnum \begin{example} \begin{codeblock} @@ -950,7 +953,7 @@ enum E : int { a }; void f(int); // \#1 void f(Int) {} // defines \#1 -void f(E) {} // OK: another overload +void f(E) {} // OK, another overload struct X { static void f(); @@ -960,9 +963,9 @@ void g() &; // error: redeclaration void h(this X&, int); - void h(int) &&; // OK: another overload + void h(int) &&; // OK, another overload void j(this const X&); - void j() const&; // error: redeclaration + void j() const &; // error: redeclaration void k(); void k(this X&); // error: redeclaration }; @@ -993,9 +996,9 @@ enum { f }; // error: different entity for \tcode{::f} namespace A {} namespace B = A; -namespace B = A; // OK: no effect -namespace B = B; // OK: no effect -namespace A = B; // OK: no effect +namespace B = A; // OK, no effect +namespace B = B; // OK, no effect +namespace A = B; // OK, no effect namespace B {} // error: different entity for \tcode{B} \end{codeblock} \end{example} @@ -1187,7 +1190,7 @@ Each \begin{itemize} \item -selection or iteration statement (\ref{stmt.select}, \ref{stmt.iter}), +selection or iteration statement\iref{stmt.select,stmt.iter}, \item substatement of such a statement, \item @@ -1222,7 +1225,8 @@ \grammarterm{compound-statement} of a \grammarterm{lambda-expression}, \grammarterm{function-body}, or \grammarterm{function-try-block}, \item -substatement of a selection or iteration statement, or +substatement of a selection or iteration statement +that is not itself a selection or iteration statement, or \item \grammarterm{handler} of a \grammarterm{function-try-block} \end{itemize} @@ -1396,7 +1400,7 @@ if the declarations found by name lookup do not all denote the same entity, \indextext{lookup!ambiguous}% they are \defn{ambiguous} and the program is ill-formed. -Overload resolution~(\ref{over.match}, \ref{over.over}) +Overload resolution\iref{over.match,over.over} takes place after name lookup has succeeded. The access rules\iref{class.access} are considered only once name lookup and function overload resolution (if applicable) have succeeded. Only after @@ -1452,7 +1456,7 @@ \begin{codeblocktu}{Translation unit \#3} import R; -int main() { return sq(9); } // OK: \tcode{sq} from module \tcode{Q} +int main() { return sq(9); } // OK, \tcode{sq} from module \tcode{Q} \end{codeblocktu} \end{example} \end{note} @@ -1616,9 +1620,9 @@ struct D : B, C { }; void f(D* pd) { - pd->v++; // OK: only one \tcode{v} (virtual) - pd->s++; // OK: only one \tcode{s} (static) - int i = pd->e; // OK: only one \tcode{e} (enumerator) + pd->v++; // OK, only one \tcode{v} (virtual) + pd->s++; // OK, only one \tcode{s} (static) + int i = pd->e; // OK, only one \tcode{e} (enumerator) pd->a++; // error: ambiguous: two \tcode{a}{s} in \tcode{D} } \end{codeblock} @@ -1658,8 +1662,8 @@ right-hand instance of \tcode{W} are not hidden at all. \begin{codeblock} void D::glorp() { - x++; // OK: \tcode{B::x} hides \tcode{V::x} - f(); // OK: \tcode{B::f()} hides \tcode{V::f()} + x++; // OK, \tcode{B::x} hides \tcode{V::x} + f(); // OK, \tcode{B::f()} hides \tcode{V::f()} y++; // error: \tcode{B::y} and \tcode{C}'s \tcode{W::y} g(); // error: \tcode{B::g()} and \tcode{C}'s \tcode{W::g()} } @@ -1685,7 +1689,7 @@ D d; B* pb = &d; A* pa = &d; // error: ambiguous: \tcode{C}'s \tcode{A} or \tcode{B}'s \tcode{A}? - V* pv = &d; // OK: only one \tcode{V} subobject + V* pv = &d; // OK, only one \tcode{V} subobject } \end{codeblock} \end{example} @@ -1694,7 +1698,7 @@ \begin{note} Even if the result of name lookup is unambiguous, use of a name found in multiple subobjects might still be -ambiguous~(\ref{conv.mem}, \ref{expr.ref}, \ref{class.access.base}). +ambiguous\iref{conv.mem,expr.ref,class.access.base}. \end{note} \begin{example} \begin{codeblock} @@ -1886,7 +1890,7 @@ void g() { N::S s; - f(s); // OK: calls \tcode{N::f} + f(s); // OK, calls \tcode{N::f} (f)(s); // error: \tcode{N::f} not considered; parentheses prevent argument-dependent lookup } \end{codeblock} @@ -1913,8 +1917,8 @@ template int h(T); } -int x = f(N::A()); // OK: lookup of \tcode{f} finds nothing, \tcode{f} treated as template name -int y = g(N::A()); // OK: lookup of \tcode{g} finds a function, \tcode{g} treated as template name +int x = f(N::A()); // OK, lookup of \tcode{f} finds nothing, \tcode{f} treated as template name +int y = g(N::A()); // OK, lookup of \tcode{g} finds a function, \tcode{g} treated as template name int z = h(N::A()); // error: \tcode{h<} does not begin a \grammarterm{template-id} \end{codeblock} @@ -2021,7 +2025,7 @@ have the same innermost enclosing non-inline namespace scope as a declaration of an associated entity attached to \tcode{M}\iref{basic.link}. \end{itemize} -If the lookup is for a dependent name (\ref{temp.dep}, \ref{temp.dep.candidate}), +If the lookup is for a dependent name\iref{temp.dep,temp.dep.candidate}, the above lookup is also performed from each point in the instantiation context\iref{module.context} of the lookup, additionally ignoring any declaration that @@ -2086,9 +2090,9 @@ NS::T parm; void g(NS::T, float); int main() { - f(parm); // OK: calls \tcode{NS::f} + f(parm); // OK, calls \tcode{NS::f} extern void g(NS::T, float); - g(parm, 1); // OK: calls \tcode{g(NS::T, float)} + g(parm, 1); // OK, calls \tcode{g(NS::T, float)} } \end{codeblock} \end{example} @@ -2215,8 +2219,8 @@ template void g(T *p) { // as instantiated for \tcode{g}: p->X<0>::f(); // error: \tcode{A::X} not found in \tcode{((p->X) < 0) > ::f()} - p->template X<0>::f(); // OK: \tcode{::X} found in definition context - p->B::f(); // OK: non-type \tcode{A::B} ignored + p->template X<0>::f(); // OK, \tcode{::X} found in definition context + p->B::f(); // OK, non-type \tcode{A::B} ignored p->template C<0>::f(); // error: \tcode{A::C} is not a template p->template D<0>::f(); // error: \tcode{A::D<0>} is not a class type p->T::f(); // error: \tcode{A::T} is not a class type @@ -2405,7 +2409,7 @@ void f() { - BC::a++; // OK: \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ + BC::a++; // OK, \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ } namespace D { @@ -2419,7 +2423,7 @@ void g() { - BD::a++; // OK: \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ + BD::a++; // OK, \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ } \end{codeblock} \end{example} @@ -2445,10 +2449,10 @@ void f() { - A::a++; // OK: \tcode{a} declared directly in \tcode{A}, \tcode{S} is $\{ \tcode{A::a} \}$ - B::a++; // OK: both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{A::a} \}$ - A::b++; // OK: both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{B::b} \}$ - B::b++; // OK: \tcode{b} declared directly in \tcode{B}, \tcode{S} is $\{ \tcode{B::b} \}$ + A::a++; // OK, \tcode{a} declared directly in \tcode{A}, \tcode{S} is $\{ \tcode{A::a} \}$ + B::a++; // OK, both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{A::a} \}$ + A::b++; // OK, both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{B::b} \}$ + B::b++; // OK, \tcode{b} declared directly in \tcode{B}, \tcode{S} is $\{ \tcode{B::b} \}$ } \end{codeblock} \end{example} @@ -2509,31 +2513,31 @@ \begin{example} \begin{codeblock} struct Node { - struct Node* Next; // OK: Refers to injected-class-name \tcode{Node} - struct Data* Data; // OK: Declares type \tcode{Data} at global scope and member \tcode{Data} + struct Node* Next; // OK, refers to injected-class-name \tcode{Node} + struct Data* Data; // OK, declares type \tcode{Data} at global scope and member \tcode{Data} }; struct Data { - struct Node* Node; // OK: Refers to \tcode{Node} at global scope + struct Node* Node; // OK, refers to \tcode{Node} at global scope friend struct ::Glob; // error: \tcode{Glob} is not declared, cannot introduce a qualified type\iref{dcl.type.elab} - friend struct Glob; // OK: Refers to (as yet) undeclared \tcode{Glob} at global scope. + friend struct Glob; // OK, refers to (as yet) undeclared \tcode{Glob} at global scope. @\commentellip@ }; struct Base { - struct Data; // OK: Declares nested \tcode{Data} - struct ::Data* thatData; // OK: Refers to \tcode{::Data} - struct Base::Data* thisData; // OK: Refers to nested \tcode{Data} - friend class ::Data; // OK: global \tcode{Data} is a friend - friend class Data; // OK: nested \tcode{Data} is a friend + struct Data; // OK, declares nested \tcode{Data} + struct ::Data* thatData; // OK, refers to \tcode{::Data} + struct Base::Data* thisData; // OK, refers to nested \tcode{Data} + friend class ::Data; // OK, global \tcode{Data} is a friend + friend class Data; // OK, nested \tcode{Data} is a friend struct Data { @\commentellip@ }; // Defines nested \tcode{Data} }; -struct Data; // OK: Redeclares \tcode{Data} at global scope +struct Data; // OK, redeclares \tcode{Data} at global scope struct ::Data; // error: cannot introduce a qualified type\iref{dcl.type.elab} struct Base::Data; // error: cannot introduce a qualified type\iref{dcl.type.elab} struct Base::Datum; // error: \tcode{Datum} undefined -struct Base::Data* pBase; // OK: refers to nested \tcode{Data} +struct Base::Data* pBase; // OK, refers to nested \tcode{Data} \end{codeblock} \end{example} \indextext{lookup!elaborated type specifier|)}% @@ -2699,7 +2703,7 @@ \pnum Two declarations of entities declare the same entity if, considering declarations of unnamed types to introduce their names -for linkage purposes, if any (\ref{dcl.typedef}, \ref{dcl.enum}), +for linkage purposes, if any\iref{dcl.typedef,dcl.enum}, they correspond\iref{basic.scope.scope}, have the same target scope that is not a function or template parameter scope, and either @@ -2712,8 +2716,8 @@ they both declare names with external linkage. \end{itemize} \begin{note} -There are other circumstances in which declarations declare the same entity -(\ref{dcl.link}, \ref{temp.type}, \ref{temp.spec.partial}). +There are other circumstances in which declarations declare the same entity% +\iref{dcl.link,temp.type,temp.spec.partial}. \end{note} \pnum @@ -2739,7 +2743,7 @@ module; #include "decls.h" export module M; -export using ::f; // OK: does not declare an entity, exports \#1 +export using ::f; // OK, does not declare an entity, exports \#1 int g(); // error: matches \#2, but attached to \tcode{M} export int h(); // \#3 export int k(); // \#4 @@ -2799,7 +2803,7 @@ \begin{codeblock} int f(int x, int x); // error: different entities for \tcode{x} void g(); // \#1 -void g(int); // OK: different entity from \#1 +void g(int); // OK, different entity from \#1 int g(); // error: same entity as \#1 with different type void h(); // \#2 namespace h {} // error: same entity as \#2, but not a function @@ -3068,7 +3072,7 @@ by an operation that implicitly creates objects (see below), when implicitly changing the active member of a union\iref{class.union}, or -when a temporary object is created~(\ref{conv.rval}, \ref{class.temporary}). +when a temporary object is created\iref{conv.rval,class.temporary}. An object occupies a region of storage in its period of construction\iref{class.cdtor}, throughout its lifetime\iref{basic.life}, @@ -3323,8 +3327,8 @@ implicitly creates objects in the returned region of storage and returns a pointer to a suitable created object. \begin{note} -Some functions in the C++ standard library implicitly create objects -(\ref{allocator.traits.members}, \ref{c.malloc}, \ref{cstring.syn}, \ref{bit.cast}). +Some functions in the \Cpp{} standard library implicitly create objects% +\iref{allocator.traits.members,c.malloc,cstring.syn,bit.cast}. \end{note} \indextext{object model|)} @@ -3347,7 +3351,7 @@ \end{itemize} except that if the object is a union member or subobject thereof, its lifetime only begins if that union member is the -initialized member in the union~(\ref{dcl.init.aggr}, \ref{class.base.init}), +initialized member in the union\iref{dcl.init.aggr,class.base.init}, or as described in \ref{class.union} and \ref{class.copy.ctor}, and except as described in \ref{allocator.members}. The lifetime of an object \placeholder{o} of type \tcode{T} ends when: @@ -3458,8 +3462,8 @@ void* p = std::malloc(sizeof(D1) + sizeof(D2)); B* pb = new (p) D1; pb->mutate(); - *pb; // OK: \tcode{pb} points to valid memory - void* q = pb; // OK: \tcode{pb} points to valid memory + *pb; // OK, \tcode{pb} points to valid memory + void* q = pb; // OK, \tcode{pb} points to valid memory pb->f(); // undefined behavior: lifetime of \tcode{*pb} has ended } \end{codeblock} @@ -3635,8 +3639,8 @@ \item the right operand of a comma expression\iref{expr.comma}, \item - the operand of a cast or conversion~(\ref{conv.integral}, - \ref{expr.type.conv}, \ref{expr.static.cast}, \ref{expr.cast}) + the operand of a cast or conversion\iref{conv.integral, + expr.type.conv,expr.static.cast,expr.cast} to an unsigned ordinary character type or \tcode{std::byte} type\iref{cstddef.syn}, or \item @@ -3739,7 +3743,7 @@ \end{itemize} have \defn{static storage duration}. The storage for these entities lasts for the duration of the -program~(\ref{basic.start.static}, \ref{basic.start.term}). +program\iref{basic.start.static,basic.start.term}. \pnum If a variable with static storage duration has initialization or a @@ -3810,10 +3814,13 @@ \grammarterm{new-expression}{s}\iref{expr.new}, and destroyed using \indextext{\idxcode{delete}}% \grammarterm{delete-expression}{s}\iref{expr.delete}. A \Cpp{} implementation -provides access to, and management of, dynamic storage via the global -\defn{allocation functions} \tcode{\keyword{operator} \keyword{new}} and \tcode{\keyword{operator} -\keyword{new}[]} and the global \defn{deallocation functions} \tcode{\keyword{operator} -\keyword{delete}} and \tcode{\keyword{operator} \keyword{delete}[]}. +provides access to, and management of, dynamic storage via +the global \defnx{allocation functions}{allocation function} +\tcode{\keyword{operator} \keyword{new}} and +\tcode{\keyword{operator} \keyword{new}[]} and +the global \defnx{deallocation functions}{deallocation function} +\tcode{\keyword{operator} \keyword{delete}} and +\tcode{\keyword{operator} \keyword{delete}[]}. \begin{note} The non-allocating forms described in \ref{new.delete.placement} do not perform allocation or deallocation. @@ -4060,7 +4067,7 @@ \rSec2[basic.align]{Alignment} \pnum -Object types have \defnx{alignment requirements}{alignment requirement!implementation-defined}~(\ref{basic.fundamental}, \ref{basic.compound}) +Object types have \defnx{alignment requirements}{alignment requirement!implementation-defined}\iref{basic.fundamental,basic.compound} which place restrictions on the addresses at which an object of that type may be allocated. An \defn{alignment} is an \impldef{alignment} integer value representing the number of bytes between successive addresses @@ -4188,16 +4195,16 @@ Temporary objects are materialized: \begin{itemize} \item -when binding a reference to a prvalue~(\ref{dcl.init.ref}, \ref{expr.type.conv}, -\ref{expr.dynamic.cast}, \ref{expr.static.cast}, \ref{expr.const.cast}, \ref{expr.cast}), +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~(\ref{expr.ref}, \ref{expr.mptr.oper}), +when performing member access on a class prvalue\iref{expr.ref,expr.mptr.oper}, \item -when performing an array-to-pointer conversion or subscripting on an array prvalue~(\ref{conv.array}, \ref{expr.sub}), +when performing an array-to-pointer conversion or subscripting on an array prvalue\iref{conv.array,expr.sub}, \item when initializing an object of type \tcode{std::initializer_list} from a \grammarterm{braced-init-list}\iref{dcl.init.list}, \item -for certain unevaluated operands~(\ref{expr.typeid}, \ref{expr.sizeof}), and +for certain unevaluated operands\iref{expr.typeid,expr.sizeof}, and \item when a prvalue that has type other than \cv{}~\keyword{void} appears as a discarded-value expression\iref{expr.context}. \end{itemize} @@ -4272,7 +4279,7 @@ \indextext{temporary!destructor for}% \indextext{temporary!destruction of}% When an implementation introduces a temporary object of a class that has a -non-trivial constructor~(\ref{class.default.ctor}, \ref{class.copy.ctor}), +non-trivial constructor\iref{class.default.ctor,class.copy.ctor}, it shall ensure that a constructor is called for the temporary object. Similarly, the destructor shall be called for a temporary with a non-trivial destructor\iref{class.dtor}. @@ -4298,7 +4305,7 @@ The first context is when a default constructor is called to initialize an element of an array with no corresponding initializer\iref{dcl.init}. The second context is when a copy constructor is called to copy an element of -an array while the entire array is copied~(\ref{expr.prim.lambda.capture}, \ref{class.copy.ctor}). +an array while the entire array is copied\iref{expr.prim.lambda.capture,class.copy.ctor}. In either case, if the constructor has one or more default arguments, the destruction of every temporary created in a default argument is sequenced before the construction of the next array element, if any. @@ -4364,7 +4371,7 @@ \end{codeblock} \end{example} \begin{note} -An explicit type conversion~(\ref{expr.type.conv}, \ref{expr.cast}) +An explicit type conversion\iref{expr.type.conv,expr.cast} is interpreted as a sequence of elementary casts, covered above. @@ -4423,7 +4430,7 @@ completion of their construction. In addition, the destruction of temporaries bound to references shall take into account the ordering of destruction of objects with static, thread, or -automatic storage duration~(\ref{basic.stc.static}, \ref{basic.stc.thread}, \ref{basic.stc.auto}); +automatic storage duration\iref{basic.stc.static,basic.stc.thread,basic.stc.auto}; that is, if \tcode{obj1} is an object with the same storage duration as the temporary and @@ -4588,6 +4595,7 @@ \indextext{object!byte copying and|)} \pnum +\label{term.object.representation}% The \defnx{object representation}{representation!object} of an object of type \tcode{T} is the sequence of \placeholder{N} \tcode{\keyword{unsigned} \keyword{char}} objects taken up @@ -4596,6 +4604,7 @@ The \defnx{value representation}{representation!value} of an object of type \tcode{T} is the set of bits that participate in representing a value of type \tcode{T}. +\label{term.padding.bits}% Bits in the object representation that are not part of the value representation are \defn{padding bits}. For trivially copyable types, the value representation is @@ -4618,8 +4627,9 @@ The size and layout of an instance of an incompletely-defined object type is unknown. \end{footnote} +\label{term.incomplete.type}% Incompletely-defined object types and \cv{}~\keyword{void} are -\defnx{incomplete types}{type!incomplete}\iref{basic.fundamental}. +\defnadjx{incomplete}{types}{type}\iref{basic.fundamental}. \begin{note} Objects cannot be defined to have an incomplete type\iref{basic.def}. \end{note} @@ -4651,7 +4661,7 @@ void foo() { xp++; // error: \tcode{X} is incomplete arrp++; // error: incomplete type - arrpp++; // OK: sizeof \tcode{UNKA*} is known + arrpp++; // OK, sizeof \tcode{UNKA*} is known } struct X { int i; }; // now \tcode{X} is a complete type @@ -4661,7 +4671,7 @@ void bar() { xp = &x; // OK; type is ``pointer to \tcode{X}'' arrp = &arr; // OK; qualification conversion\iref{conv.qual} - xp++; // OK: \tcode{X} is complete + xp++; // OK, \tcode{X} is complete arrp++; // error: \tcode{UNKA} can't be completed } \end{codeblock} @@ -4674,6 +4684,7 @@ \end{note} \pnum +\label{term.object.type}% An \defn{object type} is a (possibly cv-qualified) type that is not a function type, not a reference type, and not \cv{}~\keyword{void}. @@ -4681,6 +4692,7 @@ \indextext{class!trivial}% \indextext{class!trivially copyable}% \indextext{class!standard-layout}% +\label{term.scalar.type}% Arithmetic types\iref{basic.fundamental}, enumeration types, pointer types, pointer-to-member types\iref{basic.compound}, \tcode{std::nullptr_t}, @@ -4688,13 +4700,17 @@ cv-qualified\iref{basic.type.qualifier} versions of these types are collectively called \defnadjx{scalar}{types}{type}. +\label{term.trivially.copyable.type}% Scalar types, trivially copyable class types\iref{class.prop}, arrays of such types, and cv-qualified versions of these types are collectively called \defnadjx{trivially copyable}{types}{type}. +\label{term.trivial.type}% Scalar types, trivial class types\iref{class.prop}, arrays of such types and cv-qualified versions of these types are collectively called -\defnadjx{trivial}{types}{type}. Scalar types, standard-layout class +\defnadjx{trivial}{types}{type}. +\label{term.standard.layout.type}% +Scalar types, standard-layout class types\iref{class.prop}, arrays of such types and cv-qualified versions of these types are collectively called \defnadjx{standard-layout}{types}{type}. @@ -4703,6 +4719,7 @@ are collectively called \defnadjx{implicit-lifetime}{types}{type}. \pnum +\label{term.literal.type}% A type is a \defnadj{literal}{type} if it is: \begin{itemize} \item \cv{}~\keyword{void}; or @@ -4734,9 +4751,9 @@ \end{note} \pnum -\indextext{layout-compatible type}% +\label{term.layout.compatible.type}% Two types \cvqual{cv1} \tcode{T1} and \cvqual{cv2} \tcode{T2} are -\defn{layout-compatible} types +\defnadjx{layout-compatible}{types}{type} if \tcode{T1} and \tcode{T2} are the same type, layout-compatible enumerations\iref{dcl.enum}, or layout-compatible standard-layout class types\iref{class.mem}. @@ -4985,13 +5002,18 @@ This document imposes no requirements on the accuracy of floating-point operations; see also~\ref{support.limits}. \end{note} + +\pnum Integral and floating-point types are collectively termed \defnx{arithmetic types}{type!arithmetic}. -\indextext{\idxcode{numeric_limits}!specializations for arithmetic types}% -Specializations of the standard library template -\tcode{std::numeric_limits}\iref{support.limits} shall specify the -maximum and minimum values of each arithmetic type for an -implementation. +\begin{note} +Properties of the arithmetic types, +such as their minimum and maximum representable value, +can be queried using the facilities in the standard library headers +\libheaderref{limits}, +\libheaderref{climits}, and +\libheaderref{cfloat}. +\end{note} \pnum \indextext{type!\idxcode{void}}% @@ -4999,8 +5021,8 @@ is an incomplete type that cannot be completed; such a type has an empty set of values. It is used as the return type for functions that do not return a value. Any expression can be -explicitly converted to type \cv{}~\keyword{void}~(\ref{expr.type.conv}, -\ref{expr.static.cast}, \ref{expr.cast}). +explicitly converted to type +\cv{}~\keyword{void}\iref{expr.type.conv,expr.static.cast,expr.cast}. An expression of type \cv{}~\keyword{void} shall be used only as an expression statement\iref{stmt.expr}, as an operand of a comma expression\iref{expr.comma}, as a second or third operand @@ -5013,7 +5035,7 @@ \pnum 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~(\ref{conv.ptr}, \ref{conv.mem}). +pointer-to-member conversions\iref{conv.ptr,conv.mem}. \tcode{\keyword{sizeof}(std::nullptr_t)} shall be equal to \tcode{\keyword{sizeof}(\keyword{void}*)}. \pnum @@ -5143,7 +5165,7 @@ see \ref{basic.stc}. \end{note} For purposes of pointer arithmetic\iref{expr.add} -and comparison~(\ref{expr.rel}, \ref{expr.eq}), +and comparison\iref{expr.rel,expr.eq}, a pointer past the end of the last element of an array \tcode{x} of $n$ elements is considered to be equivalent to @@ -5171,8 +5193,7 @@ the other is a non-static data member of that object\iref{class.union}, or \item one is a standard-layout class object and -the other is the first non-static data member of that object, or, -if the object has no non-static data members, +the other is the first non-static data member of that object or any base class subobject of that object\iref{class.mem}, or \item there exists an object \placeholder{c} such that @@ -6304,7 +6325,7 @@ \indextext{program!startup|(}% A program shall contain exactly one function called \tcode{main} that belongs to the global scope. -Executing a program starts a main thread of execution~(\ref{intro.multithread}, \ref{thread.threads}) +Executing a program starts a main thread of execution\iref{intro.multithread,thread.threads} in which the \tcode{main} function is invoked. \indextext{implementation!freestanding}% It is \impldef{defining \tcode{main} in freestanding environment} @@ -6346,11 +6367,9 @@ the initial character of a \ntmbs{} that represents the name used to invoke the program or \tcode{""}. The value of \tcode{argc} shall be non-negative. The value of \tcode{argv[argc]} shall be 0. -\begin{note} -It -is recommended that any further (optional) parameters be added after -\tcode{argv}. -\end{note} + +\recommended +Any further (optional) parameters should be added after \tcode{argv}. \pnum The function \tcode{main} shall not be used within @@ -6386,7 +6405,7 @@ without leaving the current block (e.g., by calling the function \tcode{std::exit(int)}\iref{support.start.term}) does not destroy any objects with automatic storage duration\iref{class.dtor}. If -\tcode{std::exit} is called to end a program during the destruction of +\tcode{std::exit} is invoked during the destruction of an object with static or thread storage duration, the program has undefined behavior. @@ -6557,7 +6576,7 @@ A non-block variable with static storage duration having initialization with side effects is initialized in this case, -even if it is not itself odr-used~(\ref{term.odr.use}, \ref{basic.stc.static}). +even if it is not itself odr-used\iref{term.odr.use,basic.stc.static}. \end{footnote} It is \impldef{threads and program points at which deferred dynamic initialization is performed} in which threads and at which points in the program such deferred dynamic initialization occurs. diff --git a/source/classes.tex b/source/classes.tex index 62a8de403a..fa73256323 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -128,12 +128,12 @@ \begin{example} \begin{codeblock} struct A; -struct A final {}; // OK: definition of \tcode{struct A}, +struct A final {}; // OK, definition of \tcode{struct A}, // not value-initialization of variable \tcode{final} struct X { struct C { constexpr operator int() { return 5; } }; - struct B final : C{}; // OK: definition of nested class \tcode{B}, + struct B final : C{}; // OK, definition of nested class \tcode{B}, // not declaration of a bit-field member \tcode{final} }; \end{codeblock} @@ -149,8 +149,8 @@ \pnum \begin{note} -Class objects can be assigned~(\ref{over.ass}, \ref{class.copy.assign}), -passed as arguments to functions~(\ref{dcl.init}, \ref{class.copy.ctor}), and +Class objects can be assigned\iref{over.ass,class.copy.assign}, +passed as arguments to functions\iref{dcl.init,class.copy.ctor}, and returned by functions (except objects of classes for which copying or moving has been restricted; see~\ref{dcl.fct.def.delete} and \ref{class.access}). Other plausible operators, such as equality comparison, @@ -165,7 +165,7 @@ \item that has at least one eligible copy constructor, move constructor, copy assignment operator, or -move assignment operator~(\ref{special}, \ref{class.copy.ctor}, \ref{class.copy.assign}), +move assignment operator\iref{special,class.copy.ctor,class.copy.assign}, \item where each eligible copy constructor, move constructor, copy assignment operator, and move assignment operator is trivial, and \item that has a trivial, non-deleted destructor\iref{class.dtor}. @@ -539,7 +539,7 @@ A \defn{data member} is a non-function member introduced by a \grammarterm{member-declarator}. A \defn{member function} is a member that is a function. -Nested types are classes~(\ref{class.name}, \ref{class.nest}) and +Nested types are classes\iref{class.name,class.nest} and enumerations\iref{dcl.enum} declared in the class and arbitrary types declared as members by use of a typedef declaration\iref{dcl.typedef} or \grammarterm{alias-declaration}. @@ -555,7 +555,7 @@ of the class. Any other data member or member function is a \defnadj{non-static}{member} (a \defnadj{non-static}{data member} or -\defnadj{non-static}{member function}~(\ref{class.mfct.non-static}), respectively). +\defnadj{non-static}{member function}\iref{class.mfct.non.static}, respectively). \begin{note} A non-static data member of non-reference type is a member subobject of a class object\iref{intro.object}. @@ -580,7 +580,7 @@ A redeclaration of a class member outside its class definition shall be a definition, an explicit specialization, or -an explicit instantiation (\ref{temp.expl.spec}, \ref{temp.explicit}). +an explicit instantiation\iref{temp.expl.spec,temp.explicit}. The member shall not be a non-static data member. \pnum @@ -602,7 +602,7 @@ \pnum A class is considered a completely-defined object -type\iref{basic.types} (or complete type) at the closing \tcode{\}} of +type\iref{term.incomplete.type} (or complete type) at the closing \tcode{\}} of the \grammarterm{class-specifier}. The class is regarded as complete within its complete-class contexts; otherwise it is regarded as incomplete within its own class @@ -619,8 +619,8 @@ \begin{codeblock} struct S { using T = void(); - T * p = 0; // OK: \grammarterm{brace-or-equal-initializer} - virtual T f = 0; // OK: \grammarterm{pure-specifier} + T * p = 0; // OK, \grammarterm{brace-or-equal-initializer} + virtual T f = 0; // OK, \grammarterm{pure-specifier} }; \end{codeblock} \end{example} @@ -689,7 +689,7 @@ \pnum \indextext{class object!member}% The type of a non-static data member shall not be an -incomplete type\iref{basic.types}, +incomplete type\iref{term.incomplete.type}, an abstract class type\iref{class.abstract}, or a (possibly multi-dimensional) array thereof. \begin{note} @@ -782,7 +782,7 @@ types is the longest sequence of non-static data members and bit-fields in declaration order, starting with the first such entity in each of the structs, such that corresponding entities -have layout-compatible types, +have layout-compatible types\iref{basic.types}, either both entities are declared with the \tcode{no_unique_address} attribute\iref{dcl.attr.nouniqueaddr} or neither is, @@ -812,7 +812,7 @@ Two standard-layout unions are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in any order) have layout-compatible -types\iref{basic.types}. +types\iref{term.layout.compatible.type}. \pnum In a standard-layout union with an active member\iref{class.union} @@ -848,7 +848,7 @@ \end{note} \begin{note} The object and its first subobject are -pointer-interconvertible~(\ref{basic.compound}, \ref{expr.static.cast}). +pointer-interconvertible\iref{basic.compound,expr.static.cast}. \end{note} \rSec2[class.mfct]{Member functions}% @@ -913,7 +913,7 @@ Also see~\ref{temp.arg}. \end{note} -\rSec2[class.mfct.non-static]{Non-static member functions}% +\rSec2[class.mfct.non.static]{Non-static member functions}% \indextext{member function!non-static} @@ -921,9 +921,9 @@ A non-static member function may be called for an object of its class type, or for an object of a class derived\iref{class.derived} from its class type, using the class member -access syntax~(\ref{expr.ref}, \ref{over.match.call}). A non-static +access syntax\iref{expr.ref,over.match.call}. A non-static member function may also be called directly using the function call -syntax~(\ref{expr.call}, \ref{over.match.call}) from within +syntax\iref{expr.call,over.match.call} from within its class or a class derived from its class, or a member thereof, as described below. @@ -1208,12 +1208,13 @@ most derived object\iref{intro.object} ends. \pnum -\indextext{restriction!constructor}% -A -\tcode{return} -statement in the body of a constructor shall not specify a return value. \indextext{constructor!address of}% The address of a constructor shall not be taken. +\indextext{restriction!constructor}% +\begin{note} +A \tcode{return} statement in the body of a constructor +cannot specify a return value\iref{stmt.return}. +\end{note} \pnum A constructor shall not be a coroutine. @@ -1304,7 +1305,7 @@ is \defnx{implicitly defined}{constructor!implicitly defined} when it is odr-used\iref{term.odr.use} -to create an object of its class type\iref{intro.object}, +to initialize an object of its class type\iref{intro.object}, when it is needed for constant evaluation\iref{expr.const}, or when it is explicitly defaulted after its first declaration. The implicitly-defined default constructor performs the set of @@ -1329,19 +1330,12 @@ \end{note} \pnum -\indextext{constructor!implicitly called}% -Default constructors are called implicitly to create class objects of static, thread, -or automatic storage duration~(\ref{basic.stc.static}, \ref{basic.stc.thread}, \ref{basic.stc.auto}) defined -without an initializer\iref{dcl.init}, -are called to create class objects of dynamic storage duration\iref{basic.stc.dynamic} created by a -\grammarterm{new-expression} -in which the -\grammarterm{new-initializer} -is omitted\iref{expr.new}, or -are called when the explicit type conversion syntax\iref{expr.type.conv} is -used. -A program is ill-formed if the default constructor for an object -is implicitly used and the constructor is not accessible\iref{class.access}. +\begin{note} +\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}. +\end{note} \pnum \begin{note} @@ -1570,7 +1564,7 @@ \begin{note} A defaulted move constructor that is defined as deleted is ignored by overload -resolution~(\ref{over.match}, \ref{over.over}). +resolution\iref{over.match,over.over}. Such a constructor would otherwise interfere with initialization from an rvalue which can use the copy constructor instead. \end{note} @@ -1616,7 +1610,7 @@ when it is explicitly defaulted after its first declaration. \begin{note} The copy/move constructor is implicitly defined even if the implementation elided -its odr-use~(\ref{term.odr.use}, \ref{class.temporary}). +its odr-use\iref{term.odr.use,class.temporary}. \end{note} If the implicitly-defined constructor would satisfy the requirements of a constexpr constructor\iref{dcl.constexpr}, the implicitly-defined @@ -1665,7 +1659,7 @@ \pnum The implicitly-defined copy/move constructor for a union -\tcode{X} copies the object representation\iref{basic.types} of \tcode{X}. +\tcode{X} copies the object representation\iref{term.object.representation} of \tcode{X}. For each object nested within\iref{intro.object} the object that is the source of the copy, a corresponding object $o$ nested within the destination @@ -1859,7 +1853,7 @@ \begin{note} A defaulted move assignment operator that is defined as deleted is ignored by -overload resolution~(\ref{over.match}, \ref{over.over}). +overload resolution\iref{over.match,over.over}. \end{note} \pnum @@ -1870,11 +1864,13 @@ a base class copy/move assignment operator is always hidden by the corresponding assignment operator of a derived class\iref{over.ass}. \begin{note} -A \grammarterm{using-declaration} that names an assignment operator -with a parameter type that could be that of a -copy/move assignment operator for a -derived class does not suppress the implicit declaration of the derived class -operator\iref{namespace.udecl}. +A \grammarterm{using-declaration} in a derived class \tcode{C} +that names an assignment operator from a base class +never suppresses the implicit declaration of +an assignment operator of \tcode{C}, +even if the base class assignment operator would be +a copy or move assignment operator +if declared as a member of \tcode{C}. \end{note} \pnum @@ -1988,7 +1984,7 @@ \pnum The implicitly-defined copy assignment operator for a -union \tcode{X} copies the object representation\iref{basic.types} of \tcode{X}. +union \tcode{X} copies the object representation\iref{term.object.representation} of \tcode{X}. If the source and destination of the assignment are not the same object, then for each object nested within\iref{intro.object} the object that is the source of the copy, @@ -2076,8 +2072,13 @@ the selected destructor may be deleted\iref{dcl.fct.def.delete}. \pnum -\indextext{restriction!destructor}% +\indextext{destructor!address of}% The address of a destructor shall not be taken. +\indextext{restriction!destructor}% +\begin{note} +A \tcode{return} statement in the body of a destructor +cannot specify a return value\iref{stmt.return}. +\end{note} \indextext{\idxcode{const}!destructor and}% \indextext{\idxcode{volatile}!destructor and}% A destructor can be invoked for a @@ -2211,7 +2212,7 @@ \item for a constructed object with automatic storage duration\iref{basic.stc.auto} when the block in which an object is created exits\iref{stmt.dcl}, -\item for a constructed temporary object when its lifetime ends~(\ref{conv.rval}, \ref{class.temporary}). +\item for a constructed temporary object when its lifetime ends\iref{conv.rval,class.temporary}. \end{itemize} \indextext{\idxcode{delete}!destructor and}% @@ -2364,11 +2365,11 @@ \defnx{user-defined conversions}{conversion!user-defined} and are used for implicit type conversions\iref{conv}, for initialization\iref{dcl.init}, -and for explicit type conversions~(\ref{expr.type.conv}, \ref{expr.cast}, -\ref{expr.static.cast}). +and for explicit type conversions\iref{expr.type.conv,expr.cast, +expr.static.cast}. \pnum -User-defined conversions are applied only where they are unambiguous~(\ref{class.member.lookup}, \ref{class.conv.fct}). +User-defined conversions are applied only where they are unambiguous\iref{class.member.lookup,class.conv.fct}. Conversions obey the access control rules\iref{class.access}. Access control is applied after ambiguity resolution\iref{basic.lookup}. @@ -2394,7 +2395,7 @@ Y a; int b = a; // error: no viable conversion (\tcode{a.operator X().operator int()} not considered) -int c = X(a); // OK: \tcode{a.operator X().operator int()} +int c = X(a); // OK, \tcode{a.operator X().operator int()} \end{codeblock} \end{example} @@ -2431,7 +2432,7 @@ \begin{note} An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax\iref{dcl.init} -or where casts~(\ref{expr.static.cast}, \ref{expr.cast}) are explicitly +or where casts\iref{expr.static.cast,expr.cast} are explicitly used; see also~\ref{over.match.copy}. A default constructor can be an explicit constructor; such a constructor will be used to perform default-initialization @@ -2444,15 +2445,15 @@ explicit Z(int, int); }; -Z a; // OK: default-initialization performed -Z b{}; // OK: direct initialization syntax used +Z a; // OK, default-initialization performed +Z b{}; // OK, direct initialization syntax used Z c = {}; // error: copy-list-initialization Z a1 = 1; // error: no implicit conversion -Z a3 = Z(1); // OK: direct initialization syntax used -Z a2(1); // OK: direct initialization syntax used -Z* p = new Z(1); // OK: direct initialization syntax used -Z a4 = (Z)1; // OK: explicit cast used -Z a5 = static_cast(1); // OK: explicit cast used +Z a3 = Z(1); // OK, direct initialization syntax used +Z a2(1); // OK, direct initialization syntax used +Z* p = new Z(1); // OK, direct initialization syntax used +Z a4 = (Z)1; // OK, explicit cast used +Z a5 = static_cast(1); // OK, explicit cast used Z a6 = { 3, 4 }; // error: no implicit conversion \end{codeblock} \end{example} @@ -2471,8 +2472,6 @@ \indextext{fundamental type conversion|see{conversion, user-defined}}% \indextext{conversion!user-defined}% -\pnum -A member function of a class \tcode{X} with a name of the form \begin{bnf} \nontermdef{conversion-function-id}\br \keyword{operator} conversion-type-id @@ -2487,25 +2486,59 @@ \nontermdef{conversion-declarator}\br ptr-operator \opt{conversion-declarator} \end{bnf} -shall have no non-object parameters and -specifies a conversion from \tcode{X} to + +\pnum +A declaration +whose \grammarterm{declarator-id} has +an \grammarterm{unqualified-id} that is a \grammarterm{conversion-function-id} +declares a \defnadj{conversion}{function}; +its \grammarterm{declarator} shall be +a function declarator\iref{dcl.fct} of the form +\begin{ncsimplebnf} +ptr-declarator \terminal{(} parameter-declaration-clause \terminal{)} \opt{cv-qualifier-seq}\br +\bnfindent \opt{ref-qualifier-seq} \opt{noexcept-specifier} \opt{attribute-specifier-seq} +\end{ncsimplebnf} +where the \grammarterm{ptr-declarator} consists solely of +an \grammarterm{id-expression}, +an optional \grammarterm{attribute-specifier-seq}, and +optional surrounding parentheses, and +the \grammarterm{id-expression} has one of the following forms: +\begin{itemize} +\item +in a \grammarterm{member-declaration} that belongs to +the \grammarterm{member-specification} of a class or class template +but is not a friend declaration\iref{class.friend}, +the \grammarterm{id-expression} is a \grammarterm{conversion-function-id}; +\item +otherwise, the \grammarterm{id-expression} is a \grammarterm{qualified-id} +whose \grammarterm{unqualified-id} is a \grammarterm{conversion-function-id}. +\end{itemize} + +\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}; +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}. -Such functions are called \defnx{conversion functions}{conversion function}. A \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq} -of a conversion function (if any) shall be neither -a \grammarterm{defining-type-specifier} nor \keyword{static}. +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\iref{dcl.fct} is -``function taking no parameter returning -\grammarterm{conversion-type-id}''. +The type of the conversion function is +``\opt{\tcode{noexcept}} function taking no parameter +\opt{\grammarterm{cv-qualifier-seq}} \opt{\grammarterm{ref-qualifier}} +returning \grammarterm{conversion-type-id}''. + +\pnum A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), or to \cv{}~\keyword{void}. \begin{footnote} These conversions are considered -as standard conversions for the purposes of overload resolution~(\ref{over.best.ics}, \ref{over.ics.ref}) and therefore initialization\iref{dcl.init} and explicit casts\iref{expr.static.cast}. A conversion to \keyword{void} does not invoke any conversion function\iref{expr.static.cast}. +as standard conversions for the purposes of overload resolution\iref{over.best.ics,over.ics.ref} and therefore initialization\iref{dcl.init} and explicit casts\iref{expr.static.cast}. A conversion to \keyword{void} does not invoke any conversion function\iref{expr.static.cast}. Even though never directly called to perform a conversion, such conversion functions can be declared and can potentially be reached through a call to a virtual conversion function in a base class. @@ -2537,9 +2570,9 @@ }; void h(Z z) { - Y y1(z); // OK: direct-initialization + Y y1(z); // OK, direct-initialization Y y2 = z; // error: no conversion function candidate for copy-initialization - Y y3 = (Y)z; // OK: cast notation + Y y3 = (Y)z; // OK, cast notation } void g(X a, X b) { @@ -2646,7 +2679,7 @@ process& g(); void f() { - process::reschedule(); // OK: no object necessary + process::reschedule(); // OK, no object necessary g().reschedule(); // \tcode{g()} is called } \end{codeblock} @@ -2782,7 +2815,7 @@ to the entity being declared. A bit-field shall not be a static member. \indextext{bit-field!type of}% -A bit-field shall have integral or enumeration type; +A bit-field shall have integral or (possibly cv-qualified) enumeration type; the bit-field semantic property is not part of the type of the class member. The \grammarterm{constant-expression} shall be an integral constant expression with a value greater than or equal to zero and @@ -2790,7 +2823,7 @@ If the width of a bit-field is larger than the width of the bit-field's type (or, in case of an enumeration type, of its underlying type), -the extra bits are padding bits\iref{basic.types}. +the extra bits are padding bits\iref{term.padding.bits}. \indextext{allocation!implementation-defined bit-field}% Allocation of bit-fields within a class object is \impldef{allocation of bit-fields within a class object}. @@ -2863,6 +2896,149 @@ \end{codeblock} \end{example} +\rSec2[class.free]{Allocation and deallocation functions}% +\indextext{free store}% + +\pnum +\indextext{\idxcode{new}!type of}% +\indextext{allocation function!class-specific}% +Any allocation function for a class +\tcode{T} +is a static member (even if not explicitly declared +\keyword{static}). + +\pnum +\begin{example} +\begin{codeblock} +class Arena; +struct B { + void* operator new(std::size_t, Arena*); +}; +struct D1 : B { +}; + +Arena* ap; +void foo(int i) { + new (ap) D1; // calls \tcode{B::operator new(std::size_t, Arena*)} + new D1[i]; // calls \tcode{::operator new[](std::size_t)} + new D1; // error: \tcode{::operator new(std::size_t)} hidden +} +\end{codeblock} +\end{example} + +\pnum +\indextext{\idxcode{delete}!type of}% +\indextext{deallocation function!class-specific}% +Any deallocation function for a class +\tcode{X} +is a static member (even if not explicitly declared +\keyword{static}). +\begin{example} +\begin{codeblock} +class X { + void operator delete(void*); + void operator delete[](void*, std::size_t); +}; + +class Y { + void operator delete(void*, std::size_t); + void operator delete[](void*); +}; +\end{codeblock} +\end{example} + +\pnum +Since member allocation and deallocation functions are +\keyword{static} +they cannot be virtual. +\begin{note} +However, when the +\grammarterm{cast-expression} +of a +\grammarterm{delete-expression} +refers to an object of class type with a virtual destructor, +because the deallocation function is chosen by the destructor +of the dynamic type of the object, the effect is the same in that case. +For example, +\begin{codeblock} +struct B { + virtual ~B(); + void operator delete(void*, std::size_t); +}; + +struct D : B { + void operator delete(void*); +}; + +struct E : B { + void log_deletion(); + void operator delete(E *p, std::destroying_delete_t) { + p->log_deletion(); + p->~E(); + ::operator delete(p); + } +}; + +void f() { + B* bp = new D; + delete bp; // 1: uses \tcode{D::operator delete(void*)} + bp = new E; + delete bp; // 2: uses \tcode{E::operator delete(E*, std::destroying_delete_t)} +} +\end{codeblock} +Here, storage for the object of class +\tcode{D} +is deallocated by +\tcode{D::operator delete()}, +and +the object of class \tcode{E} is destroyed +and its storage is deallocated +by \tcode{E::operator delete()}, +due to the virtual destructor. +\end{note} +\begin{note} +Virtual destructors have no effect on the deallocation function actually +called when the +\grammarterm{cast-expression} +of a +\grammarterm{delete-expression} +refers to an array of objects of class type. +For example, +\begin{codeblock} +struct B { + virtual ~B(); + void operator delete[](void*, std::size_t); +}; + +struct D : B { + void operator delete[](void*, std::size_t); +}; + +void f(int i) { + D* dp = new D[i]; + delete [] dp; // uses \tcode{D::operator delete[](void*, std::size_t)} + B* bp = new D[i]; + delete[] bp; // undefined behavior +} +\end{codeblock} +\end{note} + +\pnum +Access to the deallocation function is checked statically, +even if a different one is actually executed. +\begin{example} +For the call on line ``// 1'' above, +if +\tcode{B::operator delete()} +had been private, the delete expression would have been ill-formed. +\end{example} + +\pnum +\begin{note} +If a deallocation function has no explicit \grammarterm{noexcept-specifier}, it +has a non-throwing exception specification\iref{except.spec}. +\end{note} + \rSec2[class.nest]{Nested class declarations}% \indextext{definition!nested class}% @@ -2885,14 +3061,14 @@ struct inner { void f(int i) { - int a = sizeof(x); // OK: operand of sizeof is an unevaluated operand + int a = sizeof(x); // OK, operand of sizeof is an unevaluated operand x = i; // error: assign to \tcode{enclose::x} - s = i; // OK: assign to \tcode{enclose::s} - ::x = i; // OK: assign to global \tcode{x} - y = i; // OK: assign to global \tcode{y} + s = i; // OK, assign to \tcode{enclose::s} + ::x = i; // OK, assign to global \tcode{x} + y = i; // OK, assign to global \tcode{y} } void g(enclose* p, int i) { - p->x = i; // OK: assign to \tcode{enclose::x} + p->x = i; // OK, assign to \tcode{enclose::x} } }; }; @@ -2971,7 +3147,7 @@ as if it were the sole member of a non-union class. \begin{note} A union object and its non-static data members are -pointer-interconvertible~(\ref{basic.compound}, \ref{expr.static.cast}). +pointer-interconvertible\iref{basic.compound,expr.static.cast}. As a consequence, all non-static data members of a union object have the same address. \end{note} @@ -3067,9 +3243,9 @@ union C { B b; int k; }; int f() { C c; // does not start lifetime of any union member - c.b.a.y[3] = 4; // OK: $S($\tcode{c.b.a.y[3]}$)$ contains \tcode{c.b} and \tcode{c.b.a.y}; + c.b.a.y[3] = 4; // OK, $S($\tcode{c.b.a.y[3]}$)$ contains \tcode{c.b} and \tcode{c.b.a.y}; // creates objects to hold union members \tcode{c.b} and \tcode{c.b.a.y} - return c.b.a.y[3]; // OK: \tcode{c.b.a.y} refers to newly created object (see \ref{basic.life}) + return c.b.a.y[3]; // OK, \tcode{c.b.a.y} refers to newly created object (see \ref{basic.life}) } struct X { const int a; int b; }; @@ -3077,7 +3253,7 @@ void g() { Y y = { { 1, 2 } }; // OK, \tcode{y.x} is active union member\iref{class.mem} int n = y.x.a; - y.k = 4; // OK: ends lifetime of \tcode{y.x}, \tcode{y.k} is active member of union + y.k = 4; // OK, ends lifetime of \tcode{y.x}, \tcode{y.k} is active member of union y.x.b = n; // undefined behavior: \tcode{y.x.b} modified outside its lifetime, // $S($\tcode{y.x.b}$)$ is empty because \tcode{X}'s default constructor is deleted, // so union member \tcode{y.x}'s lifetime does not implicitly start @@ -3226,7 +3402,7 @@ int h() { return s; } // OK int k() { return ::x; } // OK int l() { return q(); } // OK - int m() { return N; } // OK: not an odr-use + int m() { return N; } // OK, not an odr-use int* n() { return &N; } // error: odr-use of non-odr-usable variable \tcode{N} int p() { return y; } // error: odr-use of non-odr-usable structured binding \tcode{y} }; @@ -3457,7 +3633,7 @@ The order of derivation is not significant except as specified by the semantics of initialization by constructor\iref{class.base.init}, cleanup\iref{class.dtor}, and storage -layout~(\ref{class.mem}, \ref{class.access.spec}). +layout\iref{class.mem,class.access.spec}. \end{note} \pnum @@ -3611,7 +3787,7 @@ in a class $D$ derived (directly or indirectly) from $B$, a declaration of a member function $G$ corresponds\iref{basic.scope.scope} to a declaration of $F$, -ignoring \grammarterm{trailing requires-clause}s, +ignoring trailing \grammarterm{requires-clause}s, \indextext{override|see{function, virtual, override}}% then $G$ \defnx{overrides}{function!virtual!override} \begin{footnote} @@ -3654,7 +3830,7 @@ struct A { virtual void f(); }; struct B : A { }; struct C : A { void f(); }; -struct D : B, C { }; // OK: \tcode{A::f} and \tcode{C::f} are the final overriders +struct D : B, C { }; // OK, \tcode{A::f} and \tcode{C::f} are the final overriders // for the \tcode{B} and \tcode{C} subobjects, respectively \end{codeblock} \end{example} @@ -3785,7 +3961,7 @@ void vf1(); // virtual and overrides \tcode{Base::vf1()} void vf2(int); // not virtual, hides \tcode{Base::vf2()} char vf3(); // error: invalid difference in return type only - D* vf4(); // OK: returns pointer to derived class + D* vf4(); // OK, returns pointer to derived class A* vf5(); // error: returns pointer to incomplete class void f(); }; @@ -3975,7 +4151,7 @@ An abstract class can be used only as a base class of some other class; no objects of an abstract class can be created except as subobjects of a class -derived from it~(\ref{basic.def}, \ref{class.mem}). +derived from it\iref{basic.def,class.mem}. \end{note} \indextext{definition!pure virtual function}% A pure virtual function need be defined only if called with, or as if @@ -4013,8 +4189,8 @@ a function being defined\iref{dcl.fct} or called\iref{expr.call}, except as specified in \ref{dcl.type.simple}. Further, an abstract class type cannot be used as -the type of an explicit type conversion~(\ref{expr.static.cast}, -\ref{expr.reinterpret.cast}, \ref{expr.const.cast}), +the type of an explicit type conversion\iref{expr.static.cast, +expr.reinterpret.cast,expr.const.cast}, because the resulting prvalue would be of abstract class type\iref{basic.lval}. However, pointers and references to abstract class types can appear in such contexts. @@ -4267,8 +4443,7 @@ \pnum Member declarations can be labeled by an -\grammarterm{access-specifier} -(\ref{class.derived}): +\grammarterm{access-specifier}\iref{class.derived}: \begin{ncsimplebnf} access-specifier \terminal{:} \opt{member-specification} @@ -4430,7 +4605,7 @@ A member of a private base class can be inaccessible as inherited, but accessible directly. Because of the rules on pointer conversions\iref{conv.ptr} and -explicit casts~(\ref{expr.type.conv}, \ref{expr.static.cast}, \ref{expr.cast}), +explicit casts\iref{expr.type.conv,expr.static.cast,expr.cast}, a conversion from a pointer to a derived class to a pointer to an inaccessible base class can be ill-formed if an implicit conversion is used, but well-formed if an explicit cast is used. @@ -4457,7 +4632,7 @@ ::B::si = 3; // OK ::B* bp1 = this; // error: \tcode{B} is a private base class ::B* bp2 = (::B*)this; // OK with cast - bp2->mi = 3; // OK: access through a pointer to \tcode{B}. + bp2->mi = 3; // OK, access through a pointer to \tcode{B}. } \end{codeblock} \end{note} @@ -4536,7 +4711,7 @@ \pnum If a base class is accessible, one can implicitly convert a pointer to -a derived class to a pointer to that base class~(\ref{conv.ptr}, \ref{conv.mem}). +a derived class to a pointer to that base class\iref{conv.ptr,conv.mem}. \begin{note} It follows that members and friends of a class @@ -4630,7 +4805,7 @@ }; class B : public A { }; void f(B* p) { - p->i = 1; // OK: \tcode{B*} can be implicitly converted to \tcode{A*}, and \tcode{f} has access to \tcode{i} in \tcode{A} + p->i = 1; // OK, \tcode{B*} can be implicitly converted to \tcode{A*}, and \tcode{f} has access to \tcode{i} in \tcode{A} } \end{codeblock} \end{example} @@ -4697,10 +4872,10 @@ friend class X; }; -struct X : A::B { // OK: \tcode{A::B} accessible to friend - A::B mx; // OK: \tcode{A::B} accessible to member of friend +struct X : A::B { // OK, \tcode{A::B} accessible to friend + A::B mx; // OK, \tcode{A::B} accessible to member of friend class Y { - A::B my; // OK: \tcode{A::B} accessible to nested member of friend + A::B my; // OK, \tcode{A::B} accessible to nested member of friend }; }; \end{codeblock} @@ -4734,8 +4909,8 @@ \begin{note} A friend declaration can be the -\grammarterm{declaration} in a \grammarterm{template-declaration} -(\ref{temp.pre}, \ref{temp.friend}). +\grammarterm{declaration} in +a \grammarterm{template-declaration}\iref{temp.pre,temp.friend}. \end{note} If the type specifier in a \keyword{friend} declaration designates a (possibly @@ -4747,13 +4922,13 @@ typedef C Ct; class X1 { - friend C; // OK: \tcode{class C} is a friend + friend C; // OK, \tcode{class C} is a friend }; class X2 { - friend Ct; // OK: \tcode{class C} is a friend + friend Ct; // OK, \tcode{class C} is a friend friend D; // error: \tcode{D} not found - friend class D; // OK: elaborated-type-specifier declares new class + friend class D; // OK, elaborated-type-specifier declares new class }; template class R { @@ -4761,7 +4936,7 @@ }; R rc; // \tcode{class C} is a friend of \tcode{R} -R Ri; // OK: \tcode{"friend int;"} is ignored +R Ri; // OK, \tcode{"friend int;"} is ignored \end{codeblock} \end{example} @@ -4861,8 +5036,7 @@ \indextext{local class!friend}% \indextext{friend!local class and}% \begin{note} -A friend declaration never binds any names -(\ref{dcl.meaning}, \ref{dcl.type.elab}). +A friend declaration never binds any names\iref{dcl.meaning,dcl.type.elab}. \end{note} \begin{example} \begin{codeblock} @@ -5006,7 +5180,7 @@ B* pb = &d; D* pd = &d; - pb->f(); // OK: \tcode{B::f()} is public, \tcode{D::f()} is invoked + pb->f(); // OK, \tcode{B::f()} is public, \tcode{D::f()} is invoked pd->f(); // error: \tcode{D::f()} is private } \end{codeblock} @@ -5061,10 +5235,10 @@ class B { }; class I { - B b; // OK: \tcode{E::I} can access \tcode{E::B} + B b; // OK, \tcode{E::I} can access \tcode{E::B} int y; void f(E* p, int i) { - p->x = i; // OK: \tcode{E::I} can access \tcode{E::x} + p->x = i; // OK, \tcode{E::I} can access \tcode{E::x} } }; @@ -5457,10 +5631,10 @@ struct C { C() { } // initializes members as follows: - A a; // OK: calls \tcode{A::A()} + 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 j = 5; // OK: \tcode{j} has the value \tcode{5} + int i; // OK, \tcode{i} has indeterminate value + int j = 5; // OK, \tcode{j} has the value \tcode{5} }; \end{codeblock} \end{example} @@ -5730,7 +5904,7 @@ }; void test() { - D1 d(2, 3, 4); // OK: \tcode{B1} is initialized by calling \tcode{B1(2, 3, 4)}, + D1 d(2, 3, 4); // OK, \tcode{B1} is initialized by calling \tcode{B1(2, 3, 4)}, // then \tcode{d.x} is default-initialized (no initialization is performed), // then \tcode{d.y} is initialized by calling \tcode{get()} D1 e; // error: \tcode{D1} has a deleted default constructor @@ -5747,7 +5921,7 @@ struct X : virtual W { using W::W; X() = delete; }; struct Y : X { using X::X; }; struct Z : Y, virtual W { using Y::Y; }; -Z z(0); // OK: initialization of \tcode{Y} does not invoke default constructor of \tcode{X} +Z z(0); // OK, initialization of \tcode{Y} does not invoke default constructor of \tcode{X} template struct Log : T { using T::T; // inherits all constructors from class \tcode{T} @@ -5784,14 +5958,14 @@ }; D1 d1(0); // error: ambiguous -D2 d2(0); // OK: initializes virtual \tcode{B} base class, which initializes the \tcode{A} base class +D2 d2(0); // OK, initializes virtual \tcode{B} base class, which initializes the \tcode{A} base class // then initializes the \tcode{V1} and \tcode{V2} base classes as if by a defaulted default constructor struct M { M(); M(int); }; struct N : M { using M::M; }; struct O : M {}; struct P : N, O { using N::N; using O::O; }; -P p(0); // OK: use \tcode{M(0)} to initialize \tcode{N}{'s} base class, +P p(0); // OK, use \tcode{M(0)} to initialize \tcode{N}{'s} base class, // use \tcode{M()} to initialize \tcode{O}{'s} base class \end{codeblock} \end{example} @@ -6238,11 +6412,11 @@ Thing f(bool b) { Thing t; if (b) - throw t; // OK: \tcode{Thing(Thing\&\&)} used (or elided) to throw \tcode{t} - return t; // OK: \tcode{Thing(Thing\&\&)} used (or elided) to return \tcode{t} + throw t; // OK, \tcode{Thing(Thing\&\&)} used (or elided) to throw \tcode{t} + return t; // OK, \tcode{Thing(Thing\&\&)} used (or elided) to return \tcode{t} } -Thing t2 = f(false); // OK: no extra copy/move performed, \tcode{t2} constructed by call to \tcode{f} +Thing t2 = f(false); // OK, no extra copy/move performed, \tcode{t2} constructed by call to \tcode{f} struct Weird { Weird(); @@ -6251,7 +6425,7 @@ Weird g() { Weird w; - return w; // OK: first overload resolution fails, second overload resolution selects \tcode{Weird(Weird\&)} + return w; // OK, first overload resolution fails, second overload resolution selects \tcode{Weird(Weird\&)} } \end{codeblock} \end{example} @@ -6633,145 +6807,4 @@ \end{codeblock} \end{example} -\rSec1[class.free]{Free store}% -\indextext{free store}% - -\pnum -\indextext{\idxcode{new}!type of} -Any allocation function for a class -\tcode{T} -is a static member (even if not explicitly declared -\keyword{static}). - -\pnum -\begin{example} -\begin{codeblock} -class Arena; -struct B { - void* operator new(std::size_t, Arena*); -}; -struct D1 : B { -}; - -Arena* ap; -void foo(int i) { - new (ap) D1; // calls \tcode{B::operator new(std::size_t, Arena*)} - new D1[i]; // calls \tcode{::operator new[](std::size_t)} - new D1; // error: \tcode{::operator new(std::size_t)} hidden -} -\end{codeblock} -\end{example} - -\pnum -\indextext{\idxcode{delete}!type of}% -Any deallocation function for a class -\tcode{X} -is a static member (even if not explicitly declared -\keyword{static}). -\begin{example} -\begin{codeblock} -class X { - void operator delete(void*); - void operator delete[](void*, std::size_t); -}; - -class Y { - void operator delete(void*, std::size_t); - void operator delete[](void*); -}; -\end{codeblock} -\end{example} - -\pnum -Since member allocation and deallocation functions are -\keyword{static} -they cannot be virtual. -\begin{note} -However, when the -\grammarterm{cast-expression} -of a -\grammarterm{delete-expression} -refers to an object of class type with a virtual destructor, -because the deallocation function is chosen by the destructor -of the dynamic type of the object, the effect is the same in that case. -For example, -\begin{codeblock} -struct B { - virtual ~B(); - void operator delete(void*, std::size_t); -}; - -struct D : B { - void operator delete(void*); -}; - -struct E : B { - void log_deletion(); - void operator delete(E *p, std::destroying_delete_t) { - p->log_deletion(); - p->~E(); - ::operator delete(p); - } -}; - -void f() { - B* bp = new D; - delete bp; // 1: uses \tcode{D::operator delete(void*)} - bp = new E; - delete bp; // 2: uses \tcode{E::operator delete(E*, std::destroying_delete_t)} -} -\end{codeblock} -Here, storage for the object of class -\tcode{D} -is deallocated by -\tcode{D::operator delete()}, -and -the object of class \tcode{E} is destroyed -and its storage is deallocated -by \tcode{E::operator delete()}, -due to the virtual destructor. -\end{note} -\begin{note} -Virtual destructors have no effect on the deallocation function actually -called when the -\grammarterm{cast-expression} -of a -\grammarterm{delete-expression} -refers to an array of objects of class type. -For example, -\begin{codeblock} -struct B { - virtual ~B(); - void operator delete[](void*, std::size_t); -}; - -struct D : B { - void operator delete[](void*, std::size_t); -}; - -void f(int i) { - D* dp = new D[i]; - delete [] dp; // uses \tcode{D::operator delete[](void*, std::size_t)} - B* bp = new D[i]; - delete[] bp; // undefined behavior -} -\end{codeblock} -\end{note} - -\pnum -Access to the deallocation function is checked statically, -even if a different one is actually executed. -\begin{example} -For the call on line ``// 1'' above, -if -\tcode{B::operator delete()} -had been private, the delete expression would have been ill-formed. -\end{example} - -\pnum -\begin{note} -If a deallocation function has no explicit \grammarterm{noexcept-specifier}, it -has a non-throwing exception specification\iref{except.spec}. -\end{note} - \indextext{class|)} diff --git a/source/compatibility.tex b/source/compatibility.tex index 595f0b9e29..6070af42ea 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -55,6 +55,22 @@ // now equivalent to \tcode{arr.operator[](1, 2)} or ill-formed \end{codeblock} +\rSec2[diff.cpp20.library]{\ref{library}: library introduction} + +\diffref{headers} +\change +New headers. +\rationale +New functionality. +\effect +The following \Cpp{} headers are new: +\libheaderref{expected}, +\libheaderref{stdatomic.h}, +\libheaderref{spanstream}, and +\libheaderref{stacktrace}. +Valid \CppXX{} code that \tcode{\#include}{s} headers with these names may be +invalid in this revision of \Cpp{}. + \rSec2[diff.cpp20.utilities]{\ref{utilities}: general utilities library} \diffref{format} @@ -1516,8 +1532,7 @@ \diffref{temp.param} \change -Repurpose \keyword{export} for modules -(\ref{module}, \ref{cpp.module}, \ref{cpp.import}). +Repurpose \keyword{export} for modules\iref{module,cpp.module,cpp.import}. \rationale No implementation consensus for the \CppIII{} meaning of \keyword{export}. \effect @@ -1592,7 +1607,7 @@ \libheaderrefx{system_error}{system.error.syn}, \libheaderref{thread}, \libheaderref{tuple}, -\libheaderrefx{typeindex}{type.index.synopsis}, +\libheaderrefx{type\-index}{type.index.synopsis}, \libheaderrefx{type_traits}{meta.type.synop}, \libheaderrefx{unordered_map}{unord.map.syn}, and @@ -1990,9 +2005,9 @@ \begin{codeblock} char* p = "abc"; // valid in C, invalid in \Cpp{} void f(char*) { - char* p = (char*)"abc"; // OK: cast added + char* p = (char*)"abc"; // OK, cast added f(p); - f((char*)"def"); // OK: cast added + f((char*)"def"); // OK, cast added } \end{codeblock} @@ -2116,7 +2131,7 @@ \diffref{conv.ptr} \change -Converting \tcode{void*} to a pointer-to-object type requires casting. +Converting \tcode{\keyword{void}*} to a pointer-to-object type requires casting. \begin{codeblock} char a[10]; @@ -2126,9 +2141,9 @@ } \end{codeblock} -ISO C will accept this usage of pointer to void being assigned +ISO C accepts this usage of pointer to \keyword{void} being assigned to a pointer to object type. -\Cpp{} will not. +\Cpp{} does not. \rationale \Cpp{} tries harder than C to enforce compile-time type safety. \effect @@ -2166,19 +2181,19 @@ \diffref{expr.post.incr,expr.pre.incr} \change -Decrement operator is not allowed with \tcode{bool} operand. +Decrement operator is not allowed with \keyword{bool} operand. \rationale Feature with surprising semantics. \effect A valid ISO C expression utilizing the decrement operator on -a \tcode{bool} lvalue +a \keyword{bool} lvalue (for instance, via the C typedef in \libheaderref{stdbool.h}) is ill-formed in \Cpp{}. \diffref{expr.sizeof,expr.cast} \change In \Cpp{}, types can only be defined in declarations, not in expressions.\\ -In C, a sizeof expression or cast expression may define a new type. +In C, a \keyword{sizeof} expression or cast expression may define a new type. For example, \begin{codeblock} p = (void*)(struct x {int i;} *)0; @@ -2261,7 +2276,7 @@ promising to return a value of a given type, and then not returning such a value, has always been recognized to be a questionable practice, tolerated only because very-old C had no distinction between -void functions and int functions. +functions with \keyword{void} and \keyword{int} return types. \effect Deletion of semantically well-defined feature. \difficulty @@ -2570,7 +2585,7 @@ \diffref{dcl.enum} \change -In \Cpp{}, the type of an enumerator is its enumeration. In C, the type of an enumerator is \tcode{int}. +In \Cpp{}, the type of an enumerator is its enumeration. In C, the type of an enumerator is \keyword{int}. Example: \begin{codeblock} @@ -2653,7 +2668,7 @@ \rationale Several alternatives were debated at length. Changing the parameter to -\tcode{volatile} +\keyword{volatile} \keyword{const} \tcode{X\&} would greatly complicate the generation of @@ -2683,7 +2698,7 @@ \diffref{class.bit} \change \indextext{bit-field!implementation-defined sign of}% -Bit-fields of type plain \tcode{int} are signed. +Bit-fields of type plain \keyword{int} are signed. \rationale Leaving the choice of signedness to implementations could lead to inconsistent definitions of template specializations. For consistency, @@ -2849,18 +2864,18 @@ \pnum The tokens -\tcode{and}, -\tcode{and_eq}, -\tcode{bitand}, -\tcode{bitor}, -\tcode{compl}, -\tcode{not}, -\tcode{not_eq}, -\tcode{or}, -\tcode{or_eq}, -\tcode{xor}, +\keyword{and}, +\keyword{and_eq}, +\keyword{bitand}, +\keyword{bitor}, +\keyword{compl}, +\keyword{not}, +\keyword{not_eq}, +\keyword{or}, +\keyword{or_eq}, +\keyword{xor}, and -\tcode{xor_eq} +\keyword{xor_eq} are keywords in \Cpp{}\iref{lex.key}, and are not introduced as macros by \libheaderref{iso646.h}. @@ -2869,7 +2884,7 @@ \indexhdr{stdalign.h}% \pnum -The token \tcode{alignas} is a keyword in \Cpp{}\iref{lex.key}, +The token \keyword{alignas} is a keyword in \Cpp{}\iref{lex.key}, and is not introduced as a macro by \libheaderref{stdalign.h}. @@ -2877,7 +2892,7 @@ \indexhdr{stdbool.h}% \pnum -The tokens \tcode{bool}, \tcode{true}, and \tcode{false} +The tokens \keyword{bool}, \keyword{true}, and \keyword{false} are keywords in \Cpp{}\iref{lex.key}, and are not introduced as macros by \libheaderref{stdbool.h}. diff --git a/source/concepts.tex b/source/concepts.tex index 1359fb4608..ac641ec5ce 100644 --- a/source/concepts.tex +++ b/source/concepts.tex @@ -38,7 +38,7 @@ invocations of the library function templates \tcode{std::move}, \tcode{std::forward}, and -\tcode{std::declval}~(\ref{forward}, \ref{declval}). +\tcode{std::declval}\iref{forward,declval}. \end{itemize} \begin{example} The operands of the expression \tcode{a = std::move(b)} are @@ -637,7 +637,7 @@ \tcode{S} is an expression that exchanges the denoted values. \tcode{S} is a constant expression if \begin{itemize} - \item \tcode{T} is a literal type\iref{basic.types}, + \item \tcode{T} is a literal type\iref{term.literal.type}, \item both \tcode{E1 = std::move(E2)} and \tcode{E2 = std::move(E1)} are constant subexpressions\iref{defns.const.subexpr}, and \item the full-expressions of the initializers in the declarations @@ -854,8 +854,7 @@ The exposition-only \exposconcept{boolean-testable} concept specifies the requirements on expressions that are convertible to \tcode{bool} and -for which the logical operators~% -(\ref{expr.log.and}, \ref{expr.log.or}, \ref{expr.unary.op}) +for which the logical operators\iref{expr.log.and,expr.log.or,expr.unary.op} have the conventional semantics. \begin{itemdecl} diff --git a/source/config.tex b/source/config.tex index cd2cfe4c57..5f56bc933e 100644 --- a/source/config.tex +++ b/source/config.tex @@ -1,8 +1,8 @@ %!TEX root = std.tex %%-------------------------------------------------- %% Version numbers -\newcommand{\docno}{N4901} -\newcommand{\prevdocno}{N4892} +\newcommand{\docno}{N4910} +\newcommand{\prevdocno}{N4901} \newcommand{\cppver}{202002L} %% Release date diff --git a/source/containers.tex b/source/containers.tex index 2393a6a8d7..258a4e7ffb 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -31,10 +31,10 @@ \end{libsumtab} -\rSec1[container.requirements]{Container requirements}% +\rSec1[container.requirements]{Requirements}% \indextext{requirements!container} -\rSec2[container.requirements.general]{General container requirements} +\rSec2[container.requirements.pre]{Preamble} \pnum Containers are objects that store other objects. @@ -54,7 +54,7 @@ \end{example} \pnum -Allocator-aware containers (\tref{container.alloc.req}) +Allocator-aware containers\iref{container.alloc.reqmts} other than \tcode{basic_string} construct elements using the function \tcode{allocator_traits::rebind_traits::\brk{}construct} and destroy elements using the function @@ -69,10 +69,12 @@ aligned buffers and call \tcode{construct} to place the element into the buffer. \end{note} +\rSec2[container.gen.reqmts]{General containers} + +\rSec3[container.requirements.general]{General} + \pnum -In Tables~\ref{tab:container.req}, -\ref{tab:container.rev.req}, and -\ref{tab:container.opt}, +In subclause \ref{container.gen.reqmts}, \begin{itemize} \item \tcode{X} denotes a container class containing objects of type \tcode{T}, @@ -88,3030 +90,5670 @@ \tcode{rv} denotes a non-const rvalue of type \tcode{X}. \end{itemize} -\begin{libreqtab5} -{Container requirements} -{container.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{semantics} & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{semantics} & \chdr{pre-/post-condition} & \\ \capsep -\endhead - -\tcode{X::value_type} & - \tcode{T} & - & - \expects \tcode{T} is \oldconcept{Erasable} from \tcode{X} (see~\ref{container.requirements.general}, below) & - compile time \\ \rowsep - -\tcode{X::reference} & - \tcode{T\&} & - & - & - compile time \\ \rowsep - -\tcode{X::const_reference} & - \tcode{const T\&} & - & - & - compile time \\ \rowsep - -\tcode{X::iterator} & - iterator type whose value type is \tcode{T} & - & - any iterator category - that meets the forward iterator requirements. - convertible to \tcode{X::const_iterator}. & - compile time \\ \rowsep - -\tcode{X::const_iterator} & - constant iterator type whose value type is \tcode{T} & - & - any iterator category - that meets the forward iterator requirements. & - compile time \\ \rowsep - -\tcode{X::dif\-ference_type} & - signed integer type & - & - is identical to the difference type of \tcode{X::iterator} and \tcode{X::const_iterator} & - compile time \\ \rowsep - -\tcode{X::size_type} & - unsigned integer type & - & - \tcode{size_type} can represent any non-negative value of \tcode{difference_type} & - compile time \\ \rowsep - -\tcode{X u;} & - & - & - \ensures \tcode{u.empty()} & - constant \\ \rowsep - -\tcode{X()} & - & - & - \ensures \tcode{X().empty()} & - constant \\ \rowsep - -\tcode{X(a)} & - & - & - \expects \tcode{T} is \oldconcept{CopyInsertable} - into \tcode{X} (see below).\br \ensures \tcode{a == X(a)}. & - linear \\ \rowsep - -\tcode{X u(a);}\br -\tcode{X u = a;} & - & - & - \expects \tcode{T} is \oldconcept{CopyInsertable} - into \tcode{X} (see below).\br - \ensures \tcode{u == a} & - linear \\ \rowsep - -\tcode{X u(rv);}\br -\tcode{X u = rv;} & - & - & - \ensures \tcode{u} is equal to the value that \tcode{rv} had before this construction - & - (Note B) \\ \rowsep - -\tcode{a = rv} & - \tcode{X\&} & - All existing elements of \tcode{a} are either move assigned to or destroyed & - \ensures If \tcode{a} and \tcode{rv} do not refer to the same object, - \tcode{a} is equal to the value that \tcode{rv} - had before this assignment. & - linear \\ \rowsep - -\tcode{a.\~X()} & - \keyword{void} & - & - \effects destroys every element of \tcode{a}; any memory obtained is deallocated. & - linear \\ \rowsep - -\tcode{a.begin()} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a} & - & - & - constant \\ \rowsep - -\tcode{a.end()} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a} & - & - & - constant \\ \rowsep - -\tcode{a.cbegin()} & - \tcode{const_iterator} & - \tcode{const_cast<\brk{}X const\&\brk{}>(a)\brk{}.begin();} & - & - constant \\ \rowsep - -\tcode{a.cend()} & - \tcode{const_iterator} & - \tcode{const_cast<\brk{}X const\&\brk{}>(a)\brk{}.end();} & - & - constant \\ \rowsep - -\tcode{i <=> j} & - \tcode{strong_ordering} & - & - \constraints \tcode{X::iterator} meets the random access iterator requirements. & - constant \\ \rowsep - -\tcode{a == b} & - convertible to \tcode{bool} & - \tcode{==} is an equivalence relation. - \tcode{equal(\brk{}a.begin(), a.end(), b.begin(), b.end())} & - \expects \tcode{T} meets the \oldconcept{\-Equal\-ity\-Compar\-a\-ble} requirements & - Constant if \tcode{a.size() != b.size()}, - linear otherwise \\ \rowsep - -\tcode{a != b} & - convertible to \tcode{bool} & - Equivalent to \tcode{!(a == b)} & - & - linear \\ \rowsep - -\tcode{a.swap(b)} & - \keyword{void} & - & - \effects exchanges the contents of \tcode{a} and \tcode{b} & - (Note A) \\ \rowsep - -\tcode{swap(a, b)} & - \keyword{void} & - Equivalent to \tcode{a.swap(b)} & - & - (Note A) \\ \rowsep - -\tcode{r = a} & - \tcode{X\&} & - & - \ensures \tcode{r == a}. & - linear \\ \rowsep - -\tcode{a.size()} & - \tcode{size_type} & - \tcode{distance(\brk{}a.begin(), a.end())} & - & - constant \\ \rowsep - -\tcode{a.max_size()} & - \tcode{size_type} & - \tcode{distance(\brk{}begin(), end())} - for the largest possible container & - & - constant \\ \rowsep - -\tcode{a.empty()} & - convertible to \tcode{bool} & - \tcode{a.begin() == a.end()} & - & -constant \\ - -\end{libreqtab5} - -Those entries marked ``(Note A)'' or ``(Note B)'' -have linear complexity for \tcode{array} and have constant complexity -for all other standard containers. -\begin{note} -The algorithm \tcode{equal} is defined in \ref{algorithms}. -\end{note} +\rSec3[container.reqmts]{Containers} + +% Local command to index names as members of all containers. +\newcommand{\indexcont}[1]{% +\indexlibrarymisc{#1}{containers}% +\indexlibrarymemberx{array}{#1}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +\indexlibrarymemberx{map}{#1}% +\indexlibrarymemberx{set}{#1}% +\indexlibrarymemberx{multiset}{#1}% +\indexlibrarymemberx{multimap}{#1}% +\indexlibrarymemberx{unordered_map}{#1}% +\indexlibrarymemberx{unordered_set}{#1}% +\indexlibrarymemberx{unordered_multiset}{#1}% +\indexlibrarymemberx{unordered_multimap}{#1}% +} \pnum -The member function \tcode{size()} returns the number of elements in the container. -The number of elements is defined by the rules of -constructors, inserts, and erases. +A type \tcode{X} meets the \defn{container} requirements +if the following types, statements, and expressions are well-formed and +have the specified semantics. +\indexcont{value_type}% +\begin{itemdecl} +typename X::value_type +\end{itemdecl} + +\begin{itemdescr} \pnum -\tcode{begin()} -returns an iterator referring to the first element in the container. -\tcode{end()} -returns an iterator which is the past-the-end value for the container. -If the container is empty, then -\tcode{begin() == end()}. +\result +\tcode{T} \pnum -In the expressions -\begin{codeblock} -i == j -i != j -i < j -i <= j -i >= j -i > j -i <=> j -i - j -\end{codeblock} -where \tcode{i} and \tcode{j} denote objects of a container's \tcode{iterator} -type, either or both may be replaced by an object of the container's -\tcode{const_iterator} type referring to the same element with no change in semantics. +\expects +\tcode{T} is \oldconcept{Erasable} from \tcode{X} +(see~\ref{container.alloc.reqmts}, below). +\end{itemdescr} + +\indexcont{reference}% +\begin{itemdecl} +typename X::reference +\end{itemdecl} +\begin{itemdescr} \pnum -Unless otherwise specified, all containers defined in this Clause obtain memory -using an allocator (see~\ref{allocator.requirements}). -\begin{note} -In particular, containers and iterators do not store references -to allocated elements other than through the allocator's pointer type, -i.e., as objects of type \tcode{P} or -\tcode{pointer_traits

::template re\-bind<\unspec>}, -where \tcode{P} is \tcode{allocator_traits::pointer}. -\end{note} -Copy constructors for these container types obtain an allocator by calling -\tcode{allocator_traits::select_on_container_copy_construction} -on the allocator belonging to the container being copied. -Move constructors obtain an allocator by move construction from the allocator belonging to -the container being moved. Such move construction of the allocator shall not exit via an -exception. -All other constructors for these container types take a -\tcode{const allocator_type\&} argument. -\begin{note} -If an invocation of a constructor uses the default value of an optional -allocator argument, then the allocator type must support value-initialization. -\end{note} -A copy of this allocator is used for any memory allocation and element construction -performed, by these constructors and by all member functions, -during the lifetime of each container object -or until the allocator is replaced. The allocator may be replaced only via assignment or -\tcode{swap()}. Allocator replacement is performed by -copy assignment, move assignment, or swapping of the allocator only if -\begin{itemize} -\item \tcode{allocator_traits::propagate_on_container_copy_assignment::value}, -\item \tcode{allocator_traits::propagate_on_container_move_assignment::value}, -or -\item \tcode{allocator_traits::propagate_on_container_swap::value} -\end{itemize} -is \tcode{true} -within the implementation of the corresponding container operation. -In all container types defined in this Clause, the member \tcode{get_allocator()} -returns a copy of the allocator used to construct the container or, if that allocator -has been replaced, a copy of the most recent replacement. +\result +\tcode{T\&} +\end{itemdescr} +\indexcont{const_reference}% +\begin{itemdecl} +typename X::const_reference +\end{itemdecl} + +\begin{itemdescr} \pnum -The expression \tcode{a.swap(b)}, for containers \tcode{a} and \tcode{b} of a standard -container type other than \tcode{array}, shall exchange the values of \tcode{a} and -\tcode{b} without invoking any move, copy, or swap operations on the individual -container elements. -Lvalues of any \tcode{Compare}, \tcode{Pred}, or \tcode{Hash} types -belonging to \tcode{a} and \tcode{b} shall be swappable -and shall be exchanged by calling \tcode{swap} -as described in~\ref{swappable.requirements}. If -\tcode{allocator_traits::propagate_on_container_swap::value} is -\tcode{true}, then -lvalues of type \tcode{allocator_type} shall be swappable and -the allocators of \tcode{a} and \tcode{b} shall also be exchanged -by calling \tcode{swap} as described in~\ref{swappable.requirements}. -Otherwise, the allocators shall not be swapped, and the behavior is -undefined unless \tcode{a.get_allocator() == b.get_allocator()}. Every iterator -referring to an element in one container before the swap shall refer to the same -element in the other container after the swap. It is unspecified whether an iterator -with value \tcode{a.end()} before the swap will have value \tcode{b.end()} after the -swap. +\result +\tcode{const T\&} +\end{itemdescr} +\indexcont{iterator}% +\begin{itemdecl} +typename X::iterator +\end{itemdecl} + +\begin{itemdescr} \pnum -\indextext{reversible container|see{container, reversible}}% -If the iterator type of a container belongs to the bidirectional or -random access iterator categories\iref{iterator.requirements}, -the container is called -\defnx{reversible}{container!reversible} -and meets the additional requirements -in \tref{container.rev.req}. - -\begin{libreqtab4a} -{Reversible container requirements} -{container.rev.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endhead -\tcode{X::reverse_iterator} & -iterator type whose value type is \tcode{T} & - \tcode{reverse_iterator} & - compile time \\ \rowsep -\tcode{X::const_reverse_iterator} & - constant iterator type whose value type is \tcode{T} & - \tcode{reverse_iterator} & - compile time \\ \rowsep -\tcode{a.rbegin()} & - \tcode{reverse_iterator; const_reverse_iterator} for constant \tcode{a} & - \tcode{reverse_iterator(end())} & - constant \\ \rowsep -\tcode{a.rend()} & - \tcode{reverse_iterator; const_reverse_iterator} for constant \tcode{a} & - \tcode{reverse_iterator(begin())} & - constant \\ \rowsep -\tcode{a.crbegin()} & - \tcode{const_reverse_iterator} & - \tcode{const_cast(a).rbegin()} & - constant \\ \rowsep -\tcode{a.crend()} & - \tcode{const_reverse_iterator} & - \tcode{const_cast(a).rend()} & - constant \\ -\end{libreqtab4a} +\result +A type that meets the forward iterator requirements\iref{forward.iterators} +with value type \tcode{T}. +The type \tcode{X::iterator} is convertible to \tcode{X::const_iterator}. +\end{itemdescr} + +\indexcont{const_iterator}% +\begin{itemdecl} +typename X::const_iterator +\end{itemdecl} +\begin{itemdescr} \pnum -Unless otherwise specified (see~\ref{associative.reqmts.except}, \ref{unord.req.except}, \ref{deque.modifiers}, and -\ref{vector.modifiers}) -all container types defined in this Clause meet -the following additional requirements: +\result +A type that meets the requirements of a constant iterator and +those of a forward iterator with value type \tcode{T}. +\end{itemdescr} -\begin{itemize} -\item -if an exception is thrown by an -\tcode{insert()} or \tcode{emplace()} -function while inserting a single element, that -function has no effects. -\item -if an exception is thrown by a -\tcode{push_back()}, -\tcode{push_front()}, -\tcode{emplace_back()}, or \tcode{emplace_front()} -function, that function has no effects. -\item -no -\tcode{erase()}, -\tcode{clear()}, -\tcode{pop_back()} -or -\tcode{pop_front()} -function throws an exception. -\item -no copy constructor or assignment operator of a returned iterator -throws an exception. -\item -no -\tcode{swap()} -function throws an exception. -\item -no -\tcode{swap()} -function invalidates any references, -pointers, or iterators referring to the elements -of the containers being swapped. -\begin{note} -The \tcode{end()} iterator does not refer to any element, so it can be invalidated. -\end{note} -\end{itemize} +\indexcont{difference_type}% +\begin{itemdecl} +typename X::difference_type +\end{itemdecl} +\begin{itemdescr} \pnum -Unless otherwise specified (either explicitly or by defining a -function in terms of other functions), invoking a container member -function or passing a container as an argument to a library function -shall not invalidate iterators to, or change the values of, objects -within that container. +\result +A signed integer type, +identical to the difference type of +\tcode{X::iterator} and \tcode{X::const_iterator}. +\end{itemdescr} +\indexcont{size_type}% +\begin{itemdecl} +typename X::size_type +\end{itemdecl} + +\begin{itemdescr} \pnum -A \defnadj{contiguous}{container} -is a container -whose member types \tcode{iterator} and \tcode{const_iterator} -meet the -\oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators} and -model \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}. +\result +An unsigned integer type +that can represent any non-negative value of \tcode{X::difference_type}. +\end{itemdescr} + +\begin{itemdecl}{} +X u; +X u = X(); +\end{itemdecl} +\begin{itemdescr} \pnum -\tref{container.opt} lists operations that are provided -for some types of containers but not others. Those containers for which the -listed operations are provided shall implement the semantics described in -\tref{container.opt} unless otherwise stated. -If the iterators passed to \tcode{lexicographical_compare_three_way} -meet the constexpr iterator requirements\iref{iterator.requirements.general} -then the operations described in \tref{container.opt} -are implemented by constexpr functions. +\ensures +\tcode{u.empty()} -\begin{libreqtab5} -{Optional container operations} -{container.opt} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{semantics} & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{semantics} & \chdr{pre-/post-condition} & \\ \capsep -\endhead - -\tcode{a <=> b} & - \tcode{\placeholdernc{synth-three-\brk{}way-result}\brk{}} & - \tcode{lexicographical_compare_three_way(a.begin(), a.end(), - b.begin(), b.end(), \placeholdernc{synth-three-way})} & - \expects - Either \tcode{<=>} is defined for values of type (possibly const) \tcode{T}, - or \tcode{<} is defined for values of type (possibly const) \tcode{T} and - \tcode{<} is a total ordering relationship. & - linear \\ -\end{libreqtab5} +\pnum +\complexity +Constant. +\end{itemdescr} -\begin{note} -The algorithm \tcode{lexicographical_compare_three_way} -is defined in \ref{algorithms}. -\end{note} +\begin{itemdecl} +X u(a); +X u = a; +\end{itemdecl} +\begin{itemdescr} \pnum -All of the containers defined in this Clause and in~\ref{basic.string} except \tcode{array} -meet the additional requirements of an allocator-aware container, as described in -\tref{container.alloc.req}. +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} (see below). \pnum -Given an allocator type \tcode{A} -and given a container type \tcode{X} having a \tcode{value_type} identical to \tcode{T} -and an \tcode{allocator_type} identical to \tcode{allocator_traits::rebind_alloc} -and given an lvalue \tcode{m} of type \tcode{A}, -a pointer \tcode{p} of type \tcode{T*}, -an expression \tcode{v} of type (possibly \keyword{const}) \tcode{T}, -and an rvalue \tcode{rv} of type \tcode{T}, -the following terms are defined. If \tcode{X} -is not allocator-aware or is a specialization of \tcode{basic_string}, -the terms below are defined as if \tcode{A} were -\tcode{allocator} --- no allocator object needs to be created -and user specializations of \tcode{allocator} are not instantiated: +\ensures +\tcode{u == a} -\begin{itemize} -\item -\tcode{T} is \defnx{\oldconcept{DefaultInsertable} into \tcode{X}} -{\oldconceptname{DefaultInsertable} into X@\oldconcept{DefaultInsertable} into \tcode{X}} -means that the following expression is well-formed: -\begin{codeblock} -allocator_traits::construct(m, p) -\end{codeblock} +\pnum +\complexity +Linear. +\end{itemdescr} -\item -An element of \tcode{X} is \defn{default-inserted} if it is initialized -by evaluation of the expression -\begin{codeblock} -allocator_traits::construct(m, p) -\end{codeblock} -where \tcode{p} is the address of the uninitialized storage for the element -allocated within \tcode{X}. +\begin{itemdecl} +X u(rv); +X u = rv; +\end{itemdecl} -\item -\tcode{T} is \defnx{\oldconcept{MoveInsertable} into \tcode{X}} -{\oldconceptname{MoveInsertable} into X@\oldconcept{MoveInsertable} into \tcode{X}} -means that the following expression -is well-formed: -\begin{codeblock} -allocator_traits::construct(m, p, rv) -\end{codeblock} -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 -\end{note} +\begin{itemdescr} +\pnum +\ensures +\tcode{u} is equal to the value that \tcode{rv} had before this construction. -\item -\tcode{T} is \defnx{\oldconcept{CopyInsertable} into \tcode{X}} -{\oldconceptname{CopyInsertable} into X@\oldconcept{CopyInsertable} into \tcode{X}} -means that, in addition to \tcode{T} being \oldconcept{MoveInsertable} into -\tcode{X}, the following expression is well-formed: -\begin{codeblock} -allocator_traits::construct(m, p, v) -\end{codeblock} -and its evaluation causes the following postcondition to hold: -The value of \tcode{v} is unchanged and is equivalent to \tcode{*p}. +\pnum +\complexity +Linear for \tcode{array} and constant for all other standard containers. +\end{itemdescr} -\item -\tcode{T} is -\defnx{\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}} -{\oldconceptname{EmplaceConstructible} into X from args@\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}}, -for zero -or more arguments \tcode{args}, means that the following expression is well-formed: -\begin{codeblock} -allocator_traits::construct(m, p, args) -\end{codeblock} - -\item -\tcode{T} is -\defnx{\oldconcept{Erasable} from \tcode{X}} -{\oldconceptname{Erasable} from X@\oldconcept{Erasable} from \tcode{X}} -means that the following expression is well-formed: -\begin{codeblock} -allocator_traits::destroy(m, p) -\end{codeblock} -\end{itemize} - -\begin{note} -A container calls \tcode{allocator_traits::construct(m, p, args)} -to construct an element at \tcode{p} using \tcode{args}, -with \tcode{m == get_allocator()}. -The default \tcode{construct} in \tcode{allocator} will -call \tcode{::new((void*)p) T(args)}, -but specialized allocators can choose a different definition. -\end{note} +\begin{itemdecl} +a = rv +\end{itemdecl} +\begin{itemdescr} \pnum -In \tref{container.alloc.req}, -\begin{itemize} -\item -\tcode{X} denotes an allocator-aware container class -with a \tcode{value_type} of \tcode{T} using allocator of type \tcode{A}, -\item -\tcode{u} denotes a variable, -\item -\tcode{a} and \tcode{b} denote non-const lvalues of type \tcode{X}, -\item -\tcode{t} denotes an lvalue or a const rvalue of type \tcode{X}, -\item -\tcode{rv} denotes a non-const rvalue of type \tcode{X}, and -\item -\tcode{m} is a value of type \tcode{A}. -\end{itemize} - -\begin{libreqtab4a} -{Allocator-aware container requirements} -{container.alloc.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline - -\lhdr{Expression} & \chdr{Return type} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endhead - -\tcode{allocator_type} & - \tcode{A} & - \mandates \tcode{allocator_type::value_type} is the same as \tcode{X::value_type}. & - compile time \\ \rowsep - -\tcode{get_-} \tcode{allocator()} & - \tcode{A} & - & - constant \\ \rowsep - -\tcode{X()}\br -\tcode{X u;} & - & - \expects \tcode{A} meets the \oldconcept{DefaultConstructible} requirements.\br - \ensures \tcode{u.empty()} returns \tcode{true}, - \tcode{u.get_allocator() == A()} & - constant \\ \rowsep - -\tcode{X(m)} & - & - \ensures - \tcode{u.empty()} returns \tcode{true}, & - constant \\ -\tcode{X u(m);} & - & -\tcode{u.get_allocator() == m} & - \\ \rowsep - -\tcode{X(t, m)}\br -\tcode{X u(t, m);} & - & - \expects - \tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}.\br - \ensures - \tcode{u == t}, \tcode{u.get_allocator() == m} & - linear \\ \rowsep - -\tcode{X(rv)}\br -\tcode{X u(rv);} - & - & - \ensures \tcode{u} has the same elements as \tcode{rv} had before this - construction; the value of \tcode{u.get_allocator()} is the same as the - value of \tcode{rv.get_allocator()} before this construction. & - constant \\ \rowsep - -\tcode{X(rv, m)}\br -\tcode{X u(rv, m);} & - & - \expects \tcode{T} is - \oldconcept{MoveInsertable} into \tcode{X}.\br - \ensures \tcode{u} has the same elements, - or copies of the elements, that \tcode{rv} had before - this construction, \tcode{u.get_allocator() == m} & - constant if \tcode{m ==} \tcode{rv.get_allocator()}, otherwise linear \\ \rowsep - -\tcode{a = t} & - \tcode{X\&} & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X} - and \oldconcept{CopyAssignable}.\br - \ensures \tcode{a == t} & - linear \\ \rowsep - -\tcode{a = rv} & - \tcode{X\&} & - \expects If \tcode{allocator_-}\br - \tcode{traits}\br - \tcode{::propagate_on_container_-}\br - \tcode{move_assignment::value} is\br - \tcode{false}, \tcode{T} is - \oldconcept{MoveInsertable} into \tcode{X} and - \oldconcept{MoveAssignable}.\br - \effects All existing elements of \tcode{a} - are either move assigned to or destroyed.\br - \ensures If \tcode{a} and \tcode{rv} do not refer to the same object, - \tcode{a} is equal to the value that \tcode{rv} had before - this assignment. & - linear \\ \rowsep - -\tcode{a.swap(b)} & - \keyword{void} & - \effects exchanges the contents of \tcode{a} and \tcode{b} & - constant \\ \rowsep - -\end{libreqtab4a} +\result +\tcode{X\&}. \pnum -The behavior of certain container member functions and deduction guides -depends on whether types qualify as input iterators or allocators. -The extent to which an implementation determines that a type cannot be an input -iterator is unspecified, except that as a minimum integral types shall not qualify -as input iterators. -Likewise, the extent to which an implementation determines that a type cannot be -an allocator is unspecified, except that as a minimum a type \tcode{A} shall not qualify -as an allocator unless it meets both of the following conditions: +\effects +All existing elements of \tcode{a} are either move assigned to or destroyed. -\begin{itemize} -\item The \grammarterm{qualified-id} \tcode{A::value_type} -is valid and denotes a type\iref{temp.deduct}. +\pnum +\ensures +If \tcode{a} and \tcode{rv} do not refer to the same object, +\tcode{a} is equal to the value that \tcode{rv} had before this assignment. -\item The expression \tcode{declval().allocate(size_t\{\})} -is well-formed when treated as an unevaluated operand. -\end{itemize} +\pnum +\complexity +Linear. +\end{itemdescr} -\rSec2[container.requirements.dataraces]{Container data races} +\begin{itemdecl} +a.~X() +\end{itemdecl} +\begin{itemdescr} \pnum -For purposes of avoiding data races\iref{res.on.data.races}, implementations shall -consider the following functions to be \keyword{const}: \tcode{begin}, \tcode{end}, -\tcode{rbegin}, \tcode{rend}, \tcode{front}, \tcode{back}, \tcode{data}, \tcode{find}, -\tcode{lower_bound}, \tcode{upper_bound}, \tcode{equal_range}, \tcode{at} and, except in -associative or unordered associative containers, \tcode{operator[]}. +\result +\keyword{void} \pnum -Notwithstanding~\ref{res.on.data.races}, implementations are required to avoid data -races when the contents of the contained object in different elements in the same -container, excepting \tcode{vector}, are modified concurrently. +\effects +Destroys every element of \tcode{a}; any memory obtained is deallocated. \pnum -\begin{note} -For a \tcode{vector x} with a size greater than one, \tcode{x[1] = 5} -and \tcode{*x.begin() = 10} can be executed concurrently without a data race, but -\tcode{x[0] = 5} and \tcode{*x.begin() = 10} executed concurrently can result in a data -race. -As an exception to the general rule, for a \tcode{vector y}, \tcode{y[0] = true} -can race with \tcode{y[1] = true}. -\end{note} - -\rSec2[sequence.reqmts]{Sequence containers} +\complexity +Linear. +\end{itemdescr} -\pnum -A sequence container organizes a finite set of objects, all of the same type, into a strictly -linear arrangement. The library provides four basic kinds of sequence containers: -\tcode{vector}, \tcode{forward_list}, \tcode{list}, and \tcode{deque}. In addition, -\tcode{array} is provided as a sequence container which provides limited sequence operations -because it has a fixed number of elements. The library also provides container adaptors that -make it easy to construct abstract data types, such as \tcode{stack}s or \tcode{queue}s, out of -the basic sequence container kinds (or out of other kinds of sequence containers that the user defines). +\indexcont{begin}% +\begin{itemdecl} +a.begin() +\end{itemdecl} +\begin{itemdescr} \pnum -\begin{note} -The sequence containers -offer the programmer different complexity trade-offs. -\tcode{vector} -is appropriate in most circumstances. -\tcode{array} -has a fixed size known during translation. -\tcode{list} or \tcode{forward_list} -support frequent insertions and deletions from the -middle of the sequence. -\tcode{deque} -supports efficient insertions and deletions taking place at the beginning or at the -end of the sequence. -When choosing a container, remember \tcode{vector} is best; -leave a comment to explain if you choose from the rest! -\end{note} +\result +\tcode{iterator}; +\tcode{const_iterator} for constant \tcode{a}. \pnum -In Tables~\ref{tab:container.seq.req} -and \ref{tab:container.seq.opt}, -\begin{itemize} -\item -\tcode{X} denotes a sequence container class, -\item -\tcode{a} denotes a value of type \tcode{X} containing elements of type \tcode{T}, -\item -\tcode{u} denotes the name of a variable being declared, -\item -\tcode{A} denotes \tcode{X::allocator_type} if -the \grammarterm{qualified-id} \tcode{X::allocator_type} is valid and denotes a -type\iref{temp.deduct} and -\tcode{allocator} if it doesn't, -\item -\tcode{i} and \tcode{j} -denote iterators that meet the \oldconcept{InputIterator} requirements -and refer to elements implicitly convertible to \tcode{value_type}, -\item -\tcode{[i, j)} denotes a valid range, -\item -\tcode{il} designates an object of type \tcode{initializer_list}, -\item -\tcode{n} denotes a value of type \tcode{X::size_type}, -\item -\tcode{p} denotes a valid constant iterator to \tcode{a}, -\item -\tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a}, -\item -\tcode{[q1, q2)} denotes a valid range of constant iterators in \tcode{a}, -\item -\tcode{t} denotes an lvalue or a const rvalue of \tcode{X::value_type}, and -\item -\tcode{rv} denotes a non-const rvalue of \tcode{X::value_type}. -\item -\tcode{Args} denotes a template parameter pack; -\item -\tcode{args} denotes a function parameter pack with the pattern \tcode{Args\&\&}. -\end{itemize} +\returns +An iterator referring to the first element in the container. \pnum -The complexities of the expressions are sequence dependent. +\complexity +Constant. +\end{itemdescr} -\begin{libreqtab3} -{Sequence container requirements (in addition to container)} -{container.seq.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \rhdr{Assertion/note} \\ - & & \rhdr{pre-/post-condition} \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \rhdr{Assertion/note} \\ - & & \rhdr{pre-/post-condition} \\ \capsep -\endhead -\tcode{X(n, t)}\br -\tcode{X u(n, t);} & - & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \ensures \tcode{distance(begin(), end()) == n}\br - \effects Constructs a sequence container with \tcode{n} copies of \tcode{t} \\ \rowsep - -\tcode{X(i, j)}\br -\tcode{X u(i, j);} & - & - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. - For \tcode{vector}, if the iterator does - not meet the \oldconcept{\-Forward\-Iterator} requirements\iref{forward.iterators}, \tcode{T} - is also - \oldconcept{MoveInsertable} into \tcode{X}.\br - \ensures \tcode{distance(begin(), end()) ==} - \tcode{distance(i, j)}\br - \effects Constructs a sequence container equal to the range \tcode{[i, j)}. - Each iterator in the range \range{i}{j} is dereferenced exactly once. \\ \rowsep - -\tcode{X(il)} & - & - Equivalent to \tcode{X(il.begin(), il.end())} \\ \rowsep - -\tcode{a = il} & - \tcode{X\&} & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X} - and \oldconcept{CopyAssignable}.\br - \effects Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. All existing - elements of \tcode{a} are either assigned to or destroyed.\br - \returns\ \tcode{*this}. - \\ \rowsep - -\tcode{a.emplace(p, args)} & - \tcode{iterator} & - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. For \tcode{vector} and \tcode{deque}, - \tcode{T} is also - \oldconcept{MoveInsertable} into \tcode{X} and \oldconcept{MoveAssignable}.\br - \effects Inserts an object of type \tcode{T} constructed with - \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...} before \tcode{p}. - \begin{tailnote} -\tcode{args} can directly or indirectly refer to - a value in \tcode{a}. -\end{tailnote} - \\ \rowsep - -\tcode{a.insert(p,t)} & - \tcode{iterator} & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X}. For \tcode{vector} and \tcode{deque}, - \tcode{T} is also \oldconcept{CopyAssignable}.\br - \effects\ Inserts a copy of \tcode{t} before \tcode{p}. \\ \rowsep - -\tcode{a.insert(p,rv)} & - \tcode{iterator} & - \expects \tcode{T} is - \oldconcept{MoveInsertable} into \tcode{X}. For \tcode{vector} and \tcode{deque}, - \tcode{T} is also \oldconcept{MoveAssignable}.\br - \effects\ Inserts a copy of \tcode{rv} before \tcode{p}. \\ \rowsep - -\tcode{a.insert(p,n,t)} & - \tcode{iterator} & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X} - and \oldconcept{CopyAssignable}.\br - \effects Inserts \tcode{n} copies of \tcode{t} before \tcode{p}. \\ \rowsep - -\tcode{a.insert(p,i,j)} & - \tcode{iterator} & - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. - For \tcode{vector} and \tcode{deque}, \tcode{T} is also - \oldconcept{MoveInsertable} into \tcode{X}, \oldconcept{MoveConstructible}, \oldconcept{MoveAssignable}, - and swappable\iref{swappable.requirements}. - Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.\br - \effects Inserts copies of elements in \tcode{[i, j)} before \tcode{p}. - Each iterator in the range \range{i}{j} shall be dereferenced exactly once. \\ \rowsep - -\tcode{a.insert(p, il)} & - \tcode{iterator} & - \tcode{a.insert(p, il.begin(), il.end())}. \\ \rowsep - -\tcode{a.erase(q)} & - \tcode{iterator} & - \expects For \tcode{vector} and \tcode{deque}, - \tcode{T} is \oldconcept{MoveAssignable}.\br - \effects\ Erases the element pointed to by \tcode{q}. \\ \rowsep - -\tcode{a.erase(q1,q2)} & - \tcode{iterator} & - \expects For \tcode{vector} and \tcode{deque}, - \tcode{T} is \oldconcept{MoveAssignable}.\br - \effects\ Erases the elements in the range \tcode{[q1, q2)}. \\ \rowsep - -\tcode{a.clear()} & - \keyword{void} & - \effects Destroys all elements in \tcode{a}. Invalidates all references, pointers, and - iterators referring to the elements of \tcode{a} and may invalidate the past-the-end iterator.\br - \ensures \tcode{a.empty()} is \tcode{true}.\br - \complexity Linear. \\ \rowsep - -\tcode{a.assign(i,j)} & - \keyword{void} & - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i} - and assignable from \tcode{*i}. For \tcode{vector}, if the iterator does not - meet the forward iterator requirements\iref{forward.iterators}, \tcode{T} - is also - \oldconcept{MoveInsertable} into \tcode{X}. - Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.\br - \effects - Replaces elements in \tcode{a} with a copy of \tcode{[i, j)}. - Invalidates all references, pointers and iterators - referring to the elements of \tcode{a}. - For \tcode{vector} and \tcode{deque}, - also invalidates the past-the-end iterator. - Each iterator in the range \range{i}{j} shall be dereferenced exactly once. \\ \rowsep - -\tcode{a.assign(il)} & - \keyword{void} & - \tcode{a.assign(il.begin(), il.end())}. \\ \rowsep - -\tcode{a.assign(n,t)} & - \keyword{void} & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X} - and \oldconcept{CopyAssignable}. - \tcode{t} is not a reference into \tcode{a}.\br - \effects Replaces elements in \tcode{a} with \tcode{n} copies of \tcode{t}. - Invalidates all references, pointers and iterators - referring to the elements of \tcode{a}. - For \tcode{vector} and \tcode{deque}, - also invalidates the past-the-end iterator. \\ -\end{libreqtab3} - -\pnum -The iterator returned from -\tcode{a.insert(p, t)} -points to the copy of -\tcode{t} -inserted into -\tcode{a}. - -\pnum -The iterator returned from \tcode{a.insert(p, rv)} points to the copy of \tcode{rv} -inserted into \tcode{a}. - -\pnum -The iterator returned from \tcode{a.insert(p, n, t)} points to the copy of the first -element inserted into \tcode{a}, or \tcode{p} if \tcode{n == 0}. - -\pnum -The iterator returned from \tcode{a.insert(p, i, j)} points to the copy of the first -element inserted into \tcode{a}, or \tcode{p} if \tcode{i == j}. - -\pnum -The iterator returned from \tcode{a.insert(p, il)} points to the copy of the first -element inserted into \tcode{a}, or \tcode{p} if \tcode{il} is empty. - -\pnum -The iterator returned from \tcode{a.emplace(p, args)} points to the new element -constructed from \tcode{args} into \tcode{a}. - -\pnum -The iterator returned from -\tcode{a.erase(q)} -points to the element immediately following -\tcode{q} -prior to the element being erased. -If no such element exists, -\tcode{a.end()} -is returned. +\indexcont{end}% +\begin{itemdecl} +a.end() +\end{itemdecl} +\begin{itemdescr} \pnum -The iterator returned by -\tcode{a.erase(q1, q2)} -points to the element pointed to by -\tcode{q2} -prior to any elements being erased. -If no such element exists, -\tcode{a.end()} -is returned. +\result +\tcode{iterator}; +\tcode{const_iterator} for constant \tcode{a}. \pnum -For every sequence container defined in this Clause and in \ref{strings}: -\begin{itemize} -\item If the constructor -\begin{codeblock} -template - X(InputIterator first, InputIterator last, - const allocator_type& alloc = allocator_type()); -\end{codeblock} -is called with a type \tcode{InputIterator} that does not qualify as an input -iterator, then the constructor -shall not participate in overload resolution. +\returns +An iterator which is the past-the-end value for the container. -\item If the member functions of the forms: -\begin{codeblock} -template - @\placeholdernc{return-type}@ @\placeholdernc{F}@(const_iterator p, - InputIterator first, InputIterator last); // such as \tcode{insert} +\pnum +\complexity +Constant. +\end{itemdescr} -template - @\placeholdernc{return-type}@ @\placeholdernc{F}@(InputIterator first, InputIterator last); // such as \tcode{append}, \tcode{assign} +\indexcont{cbegin}% +\begin{itemdecl} +a.cbegin() +\end{itemdecl} -template - @\placeholdernc{return-type}@ @\placeholdernc{F}@(const_iterator i1, const_iterator i2, - InputIterator first, InputIterator last); // such as \tcode{replace} -\end{codeblock} -are called with a type \tcode{InputIterator} that does not qualify as an input -iterator, then these functions -shall not participate in overload resolution. +\begin{itemdescr} +\pnum +\result +\tcode{const_iterator}. -\item A deduction guide for a sequence container shall not participate in overload resolution -if it has an \tcode{InputIterator} template parameter and a type that does not -qualify as an input iterator is deduced for that parameter, -or if it has an \tcode{Allocator} template parameter and a type that does not -qualify as an allocator is deduced for that parameter. -\end{itemize} +\pnum +\returns +\tcode{const_cast(a).begin()} \pnum -\tref{container.seq.opt} lists operations -that are provided for some types of -sequence containers but not others. -An implementation shall provide -these operations for all container types shown in the ``container'' -column, and shall implement them so as to take amortized constant -time. - -\begin{libreqtab4a} -{Optional sequence container operations} -{container.seq.opt} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational semantics} & \rhdr{Container} \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational semantics} & \rhdr{Container} \\ \capsep -\endhead - -\tcode{a.front()} & - \tcode{reference; const_reference} for constant \tcode{a} & - \tcode{*a.begin()} & - \tcode{basic_string}, - \tcode{array}, - \tcode{deque}, - \tcode{forward_list}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a.back()} & - \tcode{reference; const_reference} for constant \tcode{a} & - \tcode{\{ auto tmp = a.end();}\br - \tcode{ --tmp;}\br - \tcode{ return *tmp; \}} & - \tcode{basic_string}, - \tcode{array}, - \tcode{deque}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a.emplace_\-front(args)} & - \tcode{reference} & - \effects Prepends an object of type \tcode{T} constructed with \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...}.\br - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \returns \tcode{a.front()}. & - \tcode{deque}, - \tcode{forward_list}, - \tcode{list} - \\ \rowsep - -\tcode{a.emplace_\-back(args)} & - \tcode{reference} & - \effects Appends an object of type \tcode{T} constructed with \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...}.\br - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. For \tcode{vector}, \tcode{T} - is also - \oldconcept{MoveInsertable} into \tcode{X}. - \returns \tcode{a.back()}. & - \tcode{deque}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a.push_front(t)} & - \keyword{void} & - \effects Prepends a copy of \tcode{t}.\br - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X}. - & - \tcode{deque}, - \tcode{forward_list}, - \tcode{list} - \\ \rowsep - -\tcode{a.push_front(rv)} & - \keyword{void} & - \effects Prepends a copy of \tcode{rv}.\br - \expects \tcode{T} is - \oldconcept{MoveInsertable} into \tcode{X}. - & - \tcode{deque}, - \tcode{forward_list}, - \tcode{list} - \\ \rowsep - -\tcode{a.push_back(t)} & - \keyword{void} & - \effects Appends a copy of \tcode{t}.\br - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X}. - & - \tcode{basic_string}, - \tcode{deque}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a.push_back(rv)} & - \keyword{void} & - \effects Appends a copy of \tcode{rv}.\br - \expects \tcode{T} is - \oldconcept{MoveInsertable} into \tcode{X}. - & - \tcode{basic_string}, - \tcode{deque}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a.pop_front()} & - \keyword{void} & - \effects Destroys the first element.\br - \expects \tcode{a.empty()} is \tcode{false}. & - \tcode{deque}, - \tcode{forward_list}, - \tcode{list} - \\ \rowsep - -\tcode{a.pop_back()} & - \keyword{void} & - \effects Destroys the last element.\br - \expects \tcode{a.empty()} is \tcode{false}. & - \tcode{basic_string}, - \tcode{deque}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a[n]} & - \tcode{reference; const_reference} for constant \tcode{a} & - \tcode{*(a.begin() + n)} & - \tcode{basic_string}, - \tcode{array}, - \tcode{deque}, - \tcode{vector} - \\ \rowsep - -\tcode{a.at(n)} & - \tcode{reference; const_reference} for constant \tcode{a} & - \tcode{*(a.begin() + n)} & - \tcode{basic_string}, - \tcode{array}, - \tcode{deque}, - \tcode{vector} - \\ - -\end{libreqtab4a} - -\pnum -The member function -\tcode{at()} -provides bounds-checked access to container elements. -\tcode{at()} -throws -\tcode{out_of_range} -if -\tcode{n >= a.size()}. +\complexity +Constant. +\end{itemdescr} +\indexcont{cend}% +\begin{itemdecl} +a.cend() +\end{itemdecl} -\rSec2[container.node]{Node handles} +\begin{itemdescr} +\pnum +\result +\tcode{const_iterator}. -\rSec3[container.node.overview]{Overview} +\pnum +\returns +\tcode{const_cast(a).end()} \pnum -A \defn{node handle} is an object that accepts ownership of a single element -from an associative container\iref{associative.reqmts} or an unordered -associative container\iref{unord.req}. It may be used to transfer that -ownership to another container with compatible nodes. Containers with -compatible nodes have the same node handle type. Elements may be transferred in -either direction between container types in the same row of -\tref{container.node.compat}. +\complexity +Constant. +\end{itemdescr} -\begin{floattable}{Container types with compatible nodes}{container.node.compat} -{ll} -\topline -\tcode{map} & \tcode{map} \\ -\rowsep -\tcode{map} & \tcode{multimap} \\ -\rowsep -\tcode{set} & \tcode{set} \\ -\rowsep -\tcode{set} & \tcode{multiset} \\ -\rowsep -\tcode{unordered_map} & \tcode{unordered_map} \\ -\rowsep -\tcode{unordered_map} & \tcode{unordered_multimap} \\ -\rowsep -\tcode{unordered_set} & \tcode{unordered_set} \\ -\rowsep -\tcode{unordered_set} & \tcode{unordered_multiset} \\ -\end{floattable} +\begin{itemdecl} +i <=> j +\end{itemdecl} +\begin{itemdescr} \pnum -If a node handle is not empty, then it contains an allocator that is equal to -the allocator of the container when the element was extracted. If a node handle -is empty, it contains no allocator. +\result +\tcode{strong_ordering}. \pnum -Class \exposid{node-handle} is for exposition only. +\constraints +\tcode{X::iterator} meets the random access iterator requirements. \pnum -If a user-defined specialization of \tcode{pair} exists for -\tcode{pair} or \tcode{pair}, where \tcode{Key} is the -container's \tcode{key_type} and \tcode{T} is the container's -\tcode{mapped_type}, the behavior of operations involving node handles is -undefined. - -\begin{codeblock} -template<@\unspecnc@> -class @\placeholder{node-handle}@ { -public: - // These type declarations are described in Tables \ref{tab:container.assoc.req} and \ref{tab:container.hash.req}. - using value_type = @\seebelownc{}@; // not present for map containers - using key_type = @\seebelownc{}@; // not present for set containers - using mapped_type = @\seebelownc{}@; // not present for set containers - using allocator_type = @\seebelownc{}@; - -private: - using container_node_type = @\unspecnc@; // \expos - using ator_traits = allocator_traits; // \expos - - typename ator_traits::template - rebind_traits::pointer ptr_; // \expos - optional alloc_; // \expos +\complexity +Constant. +\end{itemdescr} -public: - // \ref{container.node.cons}, constructors, copy, and assignment - constexpr @\placeholdernc{node-handle}@() noexcept : ptr_(), alloc_() {} - @\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&&) noexcept; - @\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&&); +\indexcont{operator==}% +\begin{itemdecl} +a == b +\end{itemdecl} - // \ref{container.node.dtor}, destructor - ~@\placeholdernc{node-handle}@(); +\begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{EqualityComparable} requirements. - // \ref{container.node.observers}, observers - value_type& value() const; // not present for map containers - key_type& key() const; // not present for set containers - mapped_type& mapped() const; // not present for set containers +\pnum +\result +Convertible to \tcode{bool}. - allocator_type get_allocator() const; - explicit operator bool() const noexcept; - [[nodiscard]] bool empty() const noexcept; +\pnum +\returns +\tcode{equal(a.begin(), a.end(), b.begin(), b.end())} - // \ref{container.node.modifiers}, modifiers - void swap(@\placeholdernc{node-handle}@&) - noexcept(ator_traits::propagate_on_container_swap::value || - ator_traits::is_always_equal::value); +\begin{note} +The algorithm \tcode{equal} is defined in \ref{alg.equal}. +\end{note} - friend void swap(@\placeholdernc{node-handle}@& x, @\placeholdernc{node-handle}@& y) noexcept(noexcept(x.swap(y))) { - x.swap(y); - } -}; -\end{codeblock} +\pnum +\complexity +Constant if \tcode{a.size() != b.size()}, linear otherwise. -\rSec3[container.node.cons]{Constructors, copy, and assignment} +\pnum +\remarks +\tcode{==} is an equivalence relation. +\end{itemdescr} +\indexcont{operator"!=}% \begin{itemdecl} -@\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&& nh) noexcept; +a != b \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs a \exposid{node-handle} object initializing -\tcode{ptr_} with \tcode{nh.ptr_}. Move constructs \tcode{alloc_} with -\tcode{nh.alloc_}. Assigns \keyword{nullptr} to \tcode{nh.ptr_} and assigns -\tcode{nullopt} to \tcode{nh.alloc_}. +Equivalent to \tcode{!(a == b)}. \end{itemdescr} +\indexcont{swap}% \begin{itemdecl} -@\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&& nh); +a.swap(b) \end{itemdecl} \begin{itemdescr} \pnum -\expects -Either \tcode{!alloc_}, or -\tcode{ator_traits::propagate_on_container_move_assignment::\-value} -is \tcode{true}, or \tcode{alloc_ == nh.alloc_}. +\result +\keyword{void} \pnum \effects -\begin{itemize} -\item -If \tcode{ptr_ != nullptr}, destroys the \tcode{value_type} -subobject in the \tcode{container_node_type} object pointed to by \tcode{ptr_} -by calling \tcode{ator_traits::destroy}, then deallocates \tcode{ptr_} by -calling \tcode{ator_traits::template rebind_traits::deallocate}. -\item -Assigns \tcode{nh.ptr_} to \tcode{ptr_}. -\item -If \tcode{!alloc\textunderscore} or \tcode{ator_traits::propagate_on_container_move_assignment::value} -is \tcode{true}, \linebreak -move assigns \tcode{nh.alloc_} to \tcode{alloc_}. -\item -Assigns -\keyword{nullptr} to \tcode{nh.ptr_} and assigns \tcode{nullopt} to -\tcode{nh.alloc_}. -\end{itemize} - -\pnum -\returns -\tcode{*this}. +Exchanges the contents of \tcode{a} and \tcode{b}. \pnum -\throws -Nothing. +\complexity +Linear for \tcode{array} and constant for all other standard containers. \end{itemdescr} -\rSec3[container.node.dtor]{Destructor} - \begin{itemdecl} -~@\placeholdernc{node-handle}@(); +swap(a, b) \end{itemdecl} \begin{itemdescr} \pnum \effects -If \tcode{ptr_ != nullptr}, destroys the \tcode{value_type} subobject -in the \tcode{container_node_type} object pointed to by \tcode{ptr_} by calling -\tcode{ator_traits::destroy}, then deallocates \tcode{ptr_} by calling -\tcode{ator_traits::template rebind_traits::deallocate}. +Equivalent to \tcode{a.swap(b)}. \end{itemdescr} -\rSec3[container.node.observers]{Observers} - +\indexcont{operator=}% \begin{itemdecl} -value_type& value() const; +r = a \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{empty() == false}. +\result +\tcode{X\&}. \pnum -\returns -A reference to the \tcode{value_type} subobject in the -\tcode{container_node_type} object pointed to by \tcode{ptr_}. +\ensures +\tcode{r == a}. \pnum -\throws -Nothing. +\complexity +Linear. \end{itemdescr} +\indexcont{size}% \begin{itemdecl} -key_type& key() const; +a.size() \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{empty() == false}. +\result +\tcode{size_type}. \pnum \returns -A non-const reference to the \tcode{key_type} member of the -\tcode{value_type} subobject in the \tcode{contain\-er_node_type} object -pointed to by \tcode{ptr_}. +\tcode{distance(a.begin(), a.end())}, +i.e. the number of elements in the container. \pnum -\throws -Nothing. +\complexity +Constant. \pnum \remarks -Modifying the key through the returned reference is permitted. +The number of elements is defined by the rules of +constructors, inserts, and erases. \end{itemdescr} +\indexcont{max_size}% \begin{itemdecl} -mapped_type& mapped() const; +a.max_size() \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{empty() == false}. +\result +\tcode{size_type}. \pnum \returns -A reference to the \tcode{mapped_type} member of the -\tcode{value_type} subobject in the \tcode{container_node_type} object -pointed to by \tcode{ptr_}. +\tcode{distance(begin(), end())} for the largest possible container. \pnum -\throws -Nothing. +\complexity +Constant. \end{itemdescr} - +\indexcont{empty}% \begin{itemdecl} -allocator_type get_allocator() const; +a.empty() \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{empty() == false}. +\result +Convertible to \tcode{bool}. \pnum \returns -\tcode{*alloc_}. +\tcode{a.begin() == a.end()} \pnum -\throws -Nothing. +\complexity +Constant. + +\pnum +\remarks +If the container is empty, then \tcode{a.empty()} is true. \end{itemdescr} +\pnum +In the expressions +\begin{codeblock} +i == j +i != j +i < j +i <= j +i >= j +i > j +i <=> j +i - j +\end{codeblock} +where \tcode{i} and \tcode{j} denote objects of a container's \tcode{iterator} +type, either or both may be replaced by an object of the container's +\tcode{const_iterator} type referring to the same element with no change in semantics. + +\pnum +Unless otherwise specified, all containers defined in this Clause obtain memory +using an allocator (see~\ref{allocator.requirements}). +\begin{note} +In particular, containers and iterators do not store references +to allocated elements other than through the allocator's pointer type, +i.e., as objects of type \tcode{P} or +\tcode{pointer_traits

::template re\-bind<\unspec>}, +where \tcode{P} is \tcode{allocator_traits::pointer}. +\end{note} +Copy constructors for these container types obtain an allocator by calling +\tcode{allocator_traits::select_on_container_copy_construction} +on the allocator belonging to the container being copied. +Move constructors obtain an allocator by move construction from the allocator belonging to +the container being moved. Such move construction of the allocator shall not exit via an +exception. +All other constructors for these container types take a +\tcode{const allocator_type\&} argument. +\begin{note} +If an invocation of a constructor uses the default value of an optional +allocator argument, then the allocator type must support value-initialization. +\end{note} +A copy of this allocator is used for any memory allocation and element construction +performed, by these constructors and by all member functions, +during the lifetime of each container object +or until the allocator is replaced. The allocator may be replaced only via assignment or +\tcode{swap()}. Allocator replacement is performed by +copy assignment, move assignment, or swapping of the allocator only if +\begin{itemize} +\item \tcode{allocator_traits::propagate_on_container_copy_assignment::value}, +\item \tcode{allocator_traits::propagate_on_container_move_assignment::value}, +or +\item \tcode{allocator_traits::propagate_on_container_swap::value} +\end{itemize} +is \tcode{true} +within the implementation of the corresponding container operation. +In all container types defined in this Clause, the member \tcode{get_allocator()} +returns a copy of the allocator used to construct the container or, if that allocator +has been replaced, a copy of the most recent replacement. + +\pnum +The expression \tcode{a.swap(b)}, for containers \tcode{a} and \tcode{b} of a standard +container type other than \tcode{array}, shall exchange the values of \tcode{a} and +\tcode{b} without invoking any move, copy, or swap operations on the individual +container elements. +Lvalues of any \tcode{Compare}, \tcode{Pred}, or \tcode{Hash} types +belonging to \tcode{a} and \tcode{b} shall be swappable +and shall be exchanged by calling \tcode{swap} +as described in~\ref{swappable.requirements}. If +\tcode{allocator_traits::propagate_on_container_swap::value} is +\tcode{true}, then +lvalues of type \tcode{allocator_type} shall be swappable and +the allocators of \tcode{a} and \tcode{b} shall also be exchanged +by calling \tcode{swap} as described in~\ref{swappable.requirements}. +Otherwise, the allocators shall not be swapped, and the behavior is +undefined unless \tcode{a.get_allocator() == b.get_allocator()}. Every iterator +referring to an element in one container before the swap shall refer to the same +element in the other container after the swap. It is unspecified whether an iterator +with value \tcode{a.end()} before the swap will have value \tcode{b.end()} after the +swap. + +\rSec3[container.rev.reqmts]{Reversible container requirements} + +% Local command to index names as members of all containers. +\renewcommand{\indexcont}[1]{% +\indexlibrarymisc{#1}{reversible containers}% +\indexlibrarymemberx{array}{#1}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +\indexlibrarymemberx{map}{#1}% +\indexlibrarymemberx{set}{#1}% +\indexlibrarymemberx{multiset}{#1}% +\indexlibrarymemberx{multimap}{#1}% +\indexlibrarymemberx{unordered_map}{#1}% +\indexlibrarymemberx{unordered_set}{#1}% +\indexlibrarymemberx{unordered_multiset}{#1}% +\indexlibrarymemberx{unordered_multimap}{#1}% +} + +\pnum +A type \tcode{X} meets the \defnadj{reversible}{container} requirements if +\tcode{X} meets the container requirements, +the iterator type of \tcode{X} belongs to the +bidirectional or random access iterator categories\iref{iterator.requirements}, +and +the following types and expressions are well-formed and have +the specified semantics. + +\indexcont{reverse_iterator}% \begin{itemdecl} -explicit operator bool() const noexcept; +typename X::reverse_iterator \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{ptr_ != nullptr}. +\result +The type \tcode{reverse_iterator}, +an iterator type whose value type is \tcode{T}. \end{itemdescr} +\indexcont{const_reverse_iterator}% \begin{itemdecl} -[[nodiscard]] bool empty() const noexcept; +typename X::const_reverse_iterator \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{ptr_ == nullptr}. +\result +The type \tcode{reverse_iterator}, +a constant iterator type whose value type is \tcode{T}. \end{itemdescr} -\rSec3[container.node.modifiers]{Modifiers} - +\indexcont{rbegin}% \begin{itemdecl} -void swap(@\placeholdernc{node-handle}@& nh) - noexcept(ator_traits::propagate_on_container_swap::value || - ator_traits::is_always_equal::value); +a.rbegin() \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{!alloc_}, or \tcode{!nh.alloc_}, or -\tcode{ator_traits::propagate_on_container_swap::value} is \tcode{true}, -or \tcode{alloc_ == nh.alloc_}. +\result +\tcode{reverse_iterator}; +\tcode{const_reverse_iterator} for constant \tcode{a}. \pnum -\effects -Calls \tcode{swap(ptr_, nh.ptr_)}. If \tcode{!alloc_}, or -\tcode{!nh.alloc_}, or \tcode{ator_traits::propagate_on_container_swap::value} -is \tcode{true} calls \tcode{swap(alloc_, nh.alloc_)}. +\returns +\tcode{reverse_iterator(end())} + +\pnum +\complexity +Constant. \end{itemdescr} -\rSec2[container.insert.return]{Insert return type} +\indexcont{rend}% +\begin{itemdecl} +a.rend() +\end{itemdecl} +\begin{itemdescr} \pnum -The associative containers with unique keys and the unordered containers with unique keys -have a member function \tcode{insert} that returns a nested type \tcode{insert_return_type}. -That return type is a specialization of the template specified in this subclause. - -\begin{codeblock} -template -struct @\placeholder{insert-return-type}@ -{ - Iterator position; - bool inserted; - NodeType node; -}; -\end{codeblock} +\result +\tcode{reverse_iterator}; +\tcode{const_reverse_iterator} for constant \tcode{a}. \pnum -The name \exposid{insert-return-type} is exposition only. -\exposid{insert-return-type} has the template parameters, -data members, and special members specified above. -It has no base classes or members other than those specified. +\returns +\tcode{reverse_iterator(begin())} -\rSec2[associative.reqmts]{Associative containers} +\pnum +\complexity +Constant. +\end{itemdescr} -\rSec3[associative.reqmts.general]{General} +\indexcont{crbegin}% +\begin{itemdecl} +a.crbegin() +\end{itemdecl} +\begin{itemdescr} \pnum -Associative containers provide fast retrieval of data based on keys. -The library provides four basic kinds of associative containers: -\tcode{set}, -\tcode{multiset}, -\tcode{map} -and -\tcode{multimap}. +\result +\tcode{const_reverse_iterator}. \pnum -Each associative container is parameterized on -\tcode{Key} -and an ordering relation -\tcode{Compare} -that induces a strict weak ordering\iref{alg.sorting} on -elements of -\tcode{Key}. -In addition, -\tcode{map} -and -\tcode{multimap} -associate an arbitrary \term{mapped type} -\tcode{T} -with the -\tcode{Key}. -The object of type -\tcode{Compare} -is called the -\term{comparison object} -of a container. +\returns +\tcode{\keyword{const_cast}(a).rbegin()} \pnum -The phrase ``equivalence of keys'' means the equivalence relation imposed by the -comparison object. -That is, two keys -\tcode{k1} -and -\tcode{k2} -are considered to be equivalent if for the -comparison object -\tcode{comp}, -\tcode{comp(k1, k2) == false \&\& comp(k2, k1) == false}. -\begin{note} -This is not necessarily the same as the result of \tcode{k1 == k2}. -\end{note} -For any two keys -\tcode{k1} -and -\tcode{k2} -in the same container, calling -\tcode{comp(k1, k2)} -shall always return the same value. +\complexity +Constant. +\end{itemdescr} -\pnum -An associative container supports \term{unique keys} if it may contain at -most one element for each key. Otherwise, it supports \term{equivalent keys}. -The \tcode{set} and \tcode{map} classes support unique keys; the \tcode{multiset} -and \tcode{multimap} classes support equivalent keys. -For \tcode{multiset} and \tcode{multimap}, -\tcode{insert}, \tcode{emplace}, and \tcode{erase} preserve the relative ordering -of equivalent elements. +\indexcont{crend}% +\begin{itemdecl} +a.crend() +\end{itemdecl} +\begin{itemdescr} \pnum -For \tcode{set} and \tcode{multiset} the value type is the same as the key type. -For \tcode{map} and \tcode{multimap} it is equal to \tcode{pair}. +\result +\tcode{const_reverse_iterator}. \pnum -\tcode{iterator} -of an associative container is of the bidirectional iterator category. -For associative containers where the value type is the same as the key type, both -\tcode{iterator} -and -\tcode{const_iterator} -are constant iterators. It is unspecified whether or not -\tcode{iterator} -and -\tcode{const_iterator} -are the same type. -\begin{note} -\tcode{iterator} and \tcode{const_iterator} have identical semantics in this case, and \tcode{iterator} is convertible to \tcode{const_iterator}. Users can avoid violating the one-definition rule by always using \tcode{const_iterator} in their function parameter lists. -\end{note} +\returns +\tcode{\keyword{const_cast}(a).rend()} \pnum -The associative containers meet all the requirements of Allocator-aware -containers\iref{container.requirements.general}, except that for -\tcode{map} and \tcode{multimap}, the requirements placed on \tcode{value_type} -in \tref{container.alloc.req} apply instead to \tcode{key_type} -and \tcode{mapped_type}. -\begin{note} -For example, in some cases \tcode{key_type} and \tcode{mapped_type} -are required to be \oldconcept{CopyAssignable} even though the associated -\tcode{value_type}, \tcode{pair}, is not -\oldconcept{CopyAssignable}. -\end{note} +\complexity +Constant. +\end{itemdescr} \pnum -In \tref{container.assoc.req}, +Unless otherwise specified (see~\ref{associative.reqmts.except}, \ref{unord.req.except}, \ref{deque.modifiers}, and +\ref{vector.modifiers}) +all container types defined in this Clause meet +the following additional requirements: + \begin{itemize} \item -\tcode{X} denotes an associative container class, -\item -\tcode{a} denotes a value of type \tcode{X}, -\item -\tcode{a2} denotes a value of a type with nodes compatible with type -\tcode{X} (\tref{container.node.compat}), -\item -\tcode{b} denotes a possibly \keyword{const} value of type \tcode{X}, -\item -\tcode{u} denotes the name of a variable being declared, -\item -\tcode{a_uniq} denotes a value of type \tcode{X} -when \tcode{X} supports unique keys, -\item -\tcode{a_eq} denotes a value of type \tcode{X} -when \tcode{X} supports multiple keys, -\item -\tcode{a_tran} denotes a possibly \keyword{const} value of type \tcode{X} -when the \grammarterm{qualified-id} -\tcode{X::key_compare::is_transpa\-rent} is valid -and denotes a type\iref{temp.deduct}, -\item -\tcode{i} and \tcode{j} -meet the \oldconcept{InputIterator} requirements and refer to elements -implicitly convertible to -\tcode{value_type}, -\item -\range{i}{j} denotes a valid range, -\item -\tcode{p} denotes a valid constant iterator to \tcode{a}, -\item -\tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a}, -\item -\tcode{r} denotes a valid dereferenceable iterator to \tcode{a}, -\item -\tcode{[q1, q2)} denotes a valid range of constant iterators in \tcode{a}, -\item -\tcode{il} designates an object of type \tcode{initializer_list}, -\item -\tcode{t} denotes a value of type \tcode{X::value_type}, -\item -\tcode{k} denotes a value of type \tcode{X::key_type}, and -\item -\tcode{c} denotes a possibly \keyword{const} value of type \tcode{X::key_compare}; -\item -\tcode{kl} is a value such that \tcode{a} is partitioned\iref{alg.sorting} -with respect to \tcode{c(r, kl)}, with \tcode{r} the key value of \tcode{e} -and \tcode{e} in \tcode{a}; -\item -\tcode{ku} is a value such that \tcode{a} is partitioned with respect to -\tcode{!c(ku, r)}; -\item -\tcode{ke} is a value such that \tcode{a} is partitioned with respect to -\tcode{c(r, ke)} and \tcode{!c(ke, r)}, with \tcode{c(r, ke)} implying -\tcode{!c(ke, r)}; +if an exception is thrown by an +\tcode{insert()} or \tcode{emplace()} +function while inserting a single element, that +function has no effects. \item -\tcode{kx} is a value such that -\begin{itemize} +if an exception is thrown by a +\tcode{push_back()}, +\tcode{push_front()}, +\tcode{emplace_back()}, or \tcode{emplace_front()} +function, that function has no effects. \item -\tcode{a} is partitioned with respect to \tcode{c(r, rx)} and \tcode{!c(kx, r)}, -with \tcode{c(r, kx)} implying \tcode{!c(kx, r)}, and +no +\tcode{erase()}, +\tcode{clear()}, +\tcode{pop_back()} +or +\tcode{pop_front()} +function throws an exception. \item -\tcode{kx} is not convertible to -either \tcode{iterator} or \tcode{const_iterator}; and -\end{itemize} +no copy constructor or assignment operator of a returned iterator +throws an exception. \item -\tcode{A} denotes the storage allocator used by \tcode{X}, if any, or \tcode{allocator} otherwise, +no +\tcode{swap()} +function throws an exception. \item -\tcode{m} denotes an allocator of a type convertible to \tcode{A}, -and \tcode{nh} denotes a non-const rvalue of type \tcode{X::node_type}. +no +\tcode{swap()} +function invalidates any references, +pointers, or iterators referring to the elements +of the containers being swapped. +\begin{note} +The \tcode{end()} iterator does not refer to any element, so it can be invalidated. +\end{note} \end{itemize} -% Local command to index names as members of all ordered containers. -\newcommand{\indexordmem}[1]{% -\indexlibrary{\idxcode{#1}!ordered associative containers}% -\indexlibrary{\idxcode{set}!\idxcode{#1}}% -\indexlibrary{\idxcode{map}!\idxcode{#1}}% -\indexlibrary{\idxcode{multiset}!\idxcode{#1}}% -\indexlibrary{\idxcode{multimap}!\idxcode{#1}}% -} - -\begin{libreqtab4b} -{Associative container requirements (in addition to container)} -{container.assoc.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endhead +\pnum +Unless otherwise specified (either explicitly or by defining a +function in terms of other functions), invoking a container member +function or passing a container as an argument to a library function +shall not invalidate iterators to, or change the values of, objects +within that container. -\indexordmem{key_type}% -\tcode{X::key_type} & - \tcode{Key} & - & - compile time \\ \rowsep +\pnum +A \defnadj{contiguous}{container} +is a container +whose member types \tcode{iterator} and \tcode{const_iterator} +meet the +\oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators} and +model \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}. -\indexordmem{mapped_type}% -\tcode{X::mapped_type} (\tcode{map} and \tcode{multimap} only) & - \tcode{T} & - & - compile time \\ \rowsep +\rSec3[container.opt.reqmts]{Optional container requirements} -\indexordmem{value_type}% -\tcode{X::value_type} (\tcode{set} and \tcode{multiset} only) & - \tcode{Key} & - \expects \tcode{value_type} is \oldconcept{Erasable} from \tcode{X} & - compile time \\ \rowsep +\pnum +The following operations are provided +for some types of containers but not others. Those containers for which the +listed operations are provided shall implement the semantics as described +unless otherwise stated. +If the iterators passed to \tcode{lexicographical_compare_three_way} +meet the constexpr iterator requirements\iref{iterator.requirements.general} +then the operations described below +are implemented by constexpr functions. -\tcode{X::value_type} (\tcode{map} and \tcode{multimap} only) & - \tcode{pair} & - \expects \tcode{value_type} is \oldconcept{Erasable} from \tcode{X} & - compile time \\ \rowsep +\begin{itemdecl} +a <=> b +\end{itemdecl} -\indexordmem{key_compare}% -\tcode{X::key_compare} & - \tcode{Compare} & - \expects \tcode{key_compare} is \oldconcept{CopyConstructible}. & - compile time \\ \rowsep +\begin{itemdescr} +\pnum +\result +\tcode{\exposid{synth-three-way-result}}. -\indexordmem{value_compare}% -\tcode{X::value_compare} & - a binary predicate type & - is the same as \tcode{key_compare} for \tcode{set} and - \tcode{multiset}; is an ordering relation on pairs induced by the - first component (i.e., \tcode{Key}) for \tcode{map} and \tcode{multimap}. & - compile time \\ \rowsep +\pnum +\expects +Either \tcode{<=>} is defined for values of type (possibly const) \tcode{T}, +or \tcode{<} is defined for values of type (possibly const) \tcode{T} and +\tcode{<} is a total ordering relationship. -\indexordmem{node_type}% -\tcode{X::node_type} & - A specialization of a \exposid{node-handle} - class template, such that the public nested types are - the same types as the corresponding types in \tcode{X}. & - see~\ref{container.node} & - compile time \\ \rowsep +\pnum +\returns +\tcode{lexicographical_compare_three_way(a.begin(), a.end(), +b.begin(), b.end(),\newline \exposidnc{synth-three-way})} +\begin{note} +The algorithm \tcode{lexicographical_compare_three_way} +is defined in \ref{algorithms}. +\end{note} -\indexlibraryctor{set}% -\indexlibraryctor{map}% -\indexlibraryctor{multiset}% -\indexlibraryctor{multimap}% -\tcode{X(c)}\br -\tcode{X u(c);} & - & - \effects\ Constructs an empty container. - Uses a copy of \tcode{c} as a comparison object. & - constant \\ \rowsep - -\tcode{X()}\br\tcode{X u;} & - & - \expects \tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements.\br - \effects\ Constructs an empty container. - Uses \tcode{Compare()} as a comparison object & - constant \\ \rowsep - -\tcode{X(i,j,c)}\br -\tcode{X~u(i,j,c);} & - & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Constructs an empty container and inserts elements from the - range \tcode{[i, j)} into it; uses \tcode{c} as a comparison object. & - $N \log N$ in general, where $N$ has the value \tcode{distance(i, j)}; - linear if \tcode{[i, j)} is sorted with \tcode{value_comp()} \\ \rowsep - -\tcode{X(i,j)}\br\tcode{X~u(i,j);} & - & - \expects \tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements. - \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Same as above, but uses \tcode{Compare()} as a comparison object. & - same as above \\ \rowsep - -\tcode{X(il)} & - & - same as \tcode{X(il.begin(), il.end())} & - same as \tcode{X(il.begin(), il.end())} \\ \rowsep - -\tcode{X(il,c)} & - & - same as \tcode{X(il.begin(), il.end(), c)} & - same as \tcode{X(il.begin(), il.end(), c)} \\ \rowsep - -\tcode{a = il} & - \tcode{X\&} & - \expects \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X} - and \oldconcept{CopyAssignable}.\br - \effects Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. All - existing elements of \tcode{a} are either assigned to or destroyed. & - $N \log N$ in general, where $N$ has the value \tcode{il.size() + a.size()}; - linear if \range{il.begin()}{il.end()} is sorted with \tcode{value_comp()} - \\ \rowsep +\pnum +\complexity +Linear. +\end{itemdescr} -\indexordmem{key_comp}% -\tcode{b.key_comp()} & - \tcode{X::key_compare} & - \returns the comparison object out of which \tcode{b} was constructed. & - constant \\ \rowsep +\rSec3[container.alloc.reqmts]{Allocator-aware containers} -\indexordmem{value_comp}% -\tcode{b.value_comp()} & - \tcode{X::value_compare} & - \returns an object of \tcode{value_compare} constructed out of the comparison object & - constant \\ \rowsep +\pnum +All of the containers defined in \ref{containers} and in~\ref{basic.string} except \tcode{array} +meet the additional requirements of an \defnadj{allocator-aware}{container}, +as described below. -\indexordmem{emplace}% -\tcode{a_uniq.\brk{}emplace(\brk{}args)} & - \tcode{pair<\brk{}iterator, bool>} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \effects\ Inserts a \tcode{value_type} object \tcode{t} constructed with - \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...} if and only if there is no - element in the container with key equivalent to the key of \tcode{t}. - The \tcode{bool} component of the returned - pair is \tcode{true} if and only if the insertion takes place, and the iterator - component of the pair points to the element with key equivalent to the - key of \tcode{t}. & - logarithmic \\ \rowsep - -\tcode{a_eq.\brk{}emplace(\brk{}args)} & - \tcode{iterator} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \effects\ Inserts a \tcode{value_type} object \tcode{t} constructed with - \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...} and returns the iterator pointing - to the newly inserted element. - If a range containing elements equivalent to \tcode{t} exists in \tcode{a_eq}, - \tcode{t} is inserted at the end of that range. & - logarithmic \\ \rowsep +\pnum +Given an allocator type \tcode{A} +and given a container type \tcode{X} having a \tcode{value_type} identical to \tcode{T} +and an \tcode{allocator_type} identical to \tcode{allocator_traits::rebind_alloc} +and given an lvalue \tcode{m} of type \tcode{A}, +a pointer \tcode{p} of type \tcode{T*}, +an expression \tcode{v} of type (possibly \keyword{const}) \tcode{T}, +and an rvalue \tcode{rv} of type \tcode{T}, +the following terms are defined. If \tcode{X} +is not allocator-aware or is a specialization of \tcode{basic_string}, +the terms below are defined as if \tcode{A} were +\tcode{allocator} --- no allocator object needs to be created +and user specializations of \tcode{allocator} are not instantiated: -\indexordmem{emplace_hint}% -\tcode{a.emplace_\-hint(\brk{}p, args)} & - \tcode{iterator} & - \effects - Equivalent to \tcode{a.emplace(} \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...)}. - Return value is an iterator pointing to the element with the key equivalent - to the newly inserted element. - The element is inserted as close as possible to the position just prior - to \tcode{p}. & - logarithmic in general, but amortized constant if the element - is inserted right before \tcode{p} \\ \rowsep +\begin{itemize} +\item +\tcode{T} is \defnx{\oldconcept{DefaultInsertable} into \tcode{X}} +{\oldconceptname{DefaultInsertable} into X@\oldconcept{DefaultInsertable} into \tcode{X}} +means that the following expression is well-formed: +\begin{codeblock} +allocator_traits::construct(m, p) +\end{codeblock} -\indexordmem{insert}% -\tcode{a_uniq.\brk{}insert(\brk{}t)} & - \tcode{pair<\brk{}iterator, bool>} & - \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects\ Inserts \tcode{t} if and only if there is no element in the container - with key equivalent to the key of \tcode{t}. The \tcode{bool} component of - the returned pair is \tcode{true} if and only if the insertion - takes place, and the \tcode{iterator} - component of the pair points to the element with key - equivalent to the key of \tcode{t}. & - logarithmic \\ \rowsep - -\tcode{a_eq.\brk{}insert(\brk{}t)} & - \tcode{iterator} & - \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects\ Inserts \tcode{t} and returns the iterator pointing - to the newly inserted element. - If a range containing elements equivalent to - \tcode{t} exists in \tcode{a_eq}, \tcode{t} - is inserted at the end of that range. & - logarithmic \\ \rowsep - -\tcode{a.\brk{}insert(\brk{}p, t)} & - \tcode{iterator} & - \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects\ Inserts \tcode{t} if and only if there is no element with key - equivalent to the key of \tcode{t} in containers with unique keys; - always inserts \tcode{t} in containers with equivalent keys. Always - returns the iterator pointing to the element with key equivalent to - the key of \tcode{t}. \tcode{t} is inserted as close as possible to the position - just prior to \tcode{p}.& - logarithmic in general, but amortized constant if \tcode{t} - is inserted right before \tcode{p}. \\ \rowsep - -\tcode{a.\brk{}insert(\brk{}i, j)} & - \keyword{void} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. - Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.\br - \effects Inserts each element from the range \range{i}{j} if and only if there - is no element with key equivalent to the key of that element in containers - with unique keys; always inserts that element in containers with equivalent keys. & - $N \log (\tcode{a.size()} + N)$, where $N$ has the value \tcode{distance(i, j)} \\ \rowsep - -\tcode{a.\brk{}insert(\brk{}il)} & - \keyword{void} & - \effects - Equivalent to \tcode{a.insert(il.begin(), il.end())} & - \\ \rowsep - -\tcode{a_uniq.\brk{}insert(\brk{}nh)} & - \tcode{insert_return_type} & - \expects \tcode{nh} is empty or - \tcode{a_uniq.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect. Otherwise, inserts the - element owned by \tcode{nh} if and only if there is no element in the - container with a key equivalent to \tcode{nh.key()}.\br - \ensures If \tcode{nh} is empty, \tcode{inserted} is \tcode{false}, - \tcode{position} is \tcode{end()}, and \tcode{node} is empty. - Otherwise if the insertion took place, \tcode{inserted} is \tcode{true}, - \tcode{position} points to the inserted element, and \tcode{node} is empty; - if the insertion failed, \tcode{inserted} is \tcode{false}, - \tcode{node} has the previous value of \tcode{nh}, and \tcode{position} - points to an element with a key equivalent to \tcode{nh.key()}. & - logarithmic \\ \rowsep - -\tcode{a_eq.\brk{}insert(\brk{}nh)} & - \tcode{iterator} & - \expects \tcode{nh} is empty or - \tcode{a_eq.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect and returns \tcode{a_eq.end()}. - Otherwise, inserts the element owned by \tcode{nh} and returns an iterator - pointing to the newly inserted element. If a range containing elements with - keys equivalent to \tcode{nh.key()} exists in \tcode{a_eq}, the element is - inserted at the end of that range.\br - \ensures \tcode{nh} is empty. & - logarithmic \\ \rowsep - -\tcode{a.\brk{}insert(\brk{}p, nh)} & - \tcode{iterator} & - \expects \tcode{nh} is empty or - \tcode{a.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect and returns \tcode{a.end()}. - Otherwise, inserts the element owned by \tcode{nh} if and only if there - is no element with key equivalent to \tcode{nh.key()} in containers with - unique keys; always inserts the element owned by \tcode{nh} in containers - with equivalent keys. Always returns the iterator pointing to the element - with key equivalent to \tcode{nh.key()}. The element is inserted as close - as possible to the position just prior to \tcode{p}.\br - \ensures \tcode{nh} is empty if insertion succeeds, unchanged if insertion fails. & - logarithmic in general, but amortized constant if the element is inserted right - before \tcode{p}. \\ \rowsep +\item +An element of \tcode{X} is \defn{default-inserted} if it is initialized +by evaluation of the expression +\begin{codeblock} +allocator_traits::construct(m, p) +\end{codeblock} +where \tcode{p} is the address of the uninitialized storage for the element +allocated within \tcode{X}. -\indexordmem{extract}% -\tcode{a.\brk{}extract(\brk{}k)} & - \tcode{node_type} & - \effects Removes the first element in the container with key equivalent to \tcode{k}.\br - \returns A \tcode{node_type} owning the element if found, otherwise an empty - \tcode{node_type}. & - $\log (\tcode{a.size()})$ \\ \rowsep - -\tcode{a_tran.\brk{}extract(\brk{}kx)} & - \tcode{node_type} & - \effects Removes the first element in the container with key \tcode{r} - such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}.\br - \returns A \tcode{node_type} owning the element if found, - otherwise an empty \tcode{node_type}. & - $\log(\tcode{a_tran.size()})$ \\ \rowsep - -\tcode{a.\brk{}extract(\brk{}q)} & - \tcode{node_type} & - \effects Removes the element pointed to by \tcode{q}.\br - \returns A \tcode{node_type} owning that element. & - amortized constant \\ \rowsep +\item +\tcode{T} is \defnx{\oldconcept{MoveInsertable} into \tcode{X}} +{\oldconceptname{MoveInsertable} into X@\oldconcept{MoveInsertable} into \tcode{X}} +means that the following expression +is well-formed: +\begin{codeblock} +allocator_traits::construct(m, p, rv) +\end{codeblock} +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 +\end{note} -\indexordmem{merge}% -\tcode{a.merge(a2)} & - \keyword{void} & - \expects \tcode{a.get_allocator() == a2.get_allocator()}.\br - \effects Attempts to extract each element in \tcode{a2} and insert it into \tcode{a} - using the comparison object of \tcode{a}. In containers with unique keys, - if there is an element in \tcode{a} with key equivalent to the key of an - element from \tcode{a2}, then that element is not extracted from \tcode{a2}.\br - \ensures Pointers and references to the transferred elements of \tcode{a2} - refer to those same elements but as members of \tcode{a}. Iterators referring - to the transferred elements will continue to refer to their elements, but - they now behave as iterators into \tcode{a}, not into \tcode{a2}.\br - \throws Nothing unless the comparison object throws. & - $N \log(\tcode{a.size()+} N)$, where $N$ has the value \tcode{a2.size()}. \\ \rowsep +\item +\tcode{T} is \defnx{\oldconcept{CopyInsertable} into \tcode{X}} +{\oldconceptname{CopyInsertable} into X@\oldconcept{CopyInsertable} into \tcode{X}} +means that, in addition to \tcode{T} being \oldconcept{MoveInsertable} into +\tcode{X}, the following expression is well-formed: +\begin{codeblock} +allocator_traits::construct(m, p, v) +\end{codeblock} +and its evaluation causes the following postcondition to hold: +The value of \tcode{v} is unchanged and is equivalent to \tcode{*p}. -\indexordmem{erase}% -\tcode{a.erase(k)} & - \tcode{size_type} & - \effects Erases all elements in the container with key equivalent to - \tcode{k}.\br - \returns The number of erased elements. & - $\log (\tcode{a.size()}) + \tcode{a.count(k)}$ \\ \rowsep - -\tcode{a_tran.\brk{}erase(kx)} & - \tcode{size_type} & - \effects Erases all elements in the container with key \tcode{r} - such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}.\br - \returns The number of erased elements. & - $\log(\tcode{a_tran.size())} + \tcode{a_tran.count(kx)}$ \\ \rowsep - -\tcode{a.erase(q)} & - \tcode{iterator} & - \effects Erases the element pointed to by \tcode{q}.\br - \returns An iterator pointing to - the element immediately following \tcode{q} prior to the element being erased. - If no such element exists, returns \tcode{a.end()}. & - amortized constant \\ \rowsep - -\tcode{a.erase(r)} & - \tcode{iterator} & - \effects Erases the element pointed to by \tcode{r}.\br - \returns An iterator pointing to - the element immediately following \tcode{r} prior to the element being erased. - If no such element exists, returns \tcode{a.end()}. & - amortized constant \\ \rowsep - -\tcode{a.erase(}\br - \tcode{q1, q2)} & - \tcode{iterator} & - \effects Erases all the elements in the range \range{q1}{q2}.\br - \returns An iterator pointing to - the element pointed to by \tcode{q2} prior to any elements being erased. If no such element - exists, \tcode{a.end()} is returned. & - $\log(\tcode{a.size()}) + N$, where $N$ has the value \tcode{distance(q1, q2)}. \\ \rowsep +\item +\tcode{T} is +\defnx{\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}} +{\oldconceptname{EmplaceConstructible} into X from args@\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}}, +for zero +or more arguments \tcode{args}, means that the following expression is well-formed: +\begin{codeblock} +allocator_traits::construct(m, p, args) +\end{codeblock} -\indexordmem{clear}% -\tcode{a.clear()} & - \keyword{void} & - \effects Equivalent to \tcode{a.erase(a.begin(), a.end())}.\br - \ensures \tcode{a.empty()} is \tcode{true}. & - linear in \tcode{a.size()}. \\ \rowsep +\item +\tcode{T} is +\defnx{\oldconcept{Erasable} from \tcode{X}} +{\oldconceptname{Erasable} from X@\oldconcept{Erasable} from \tcode{X}} +means that the following expression is well-formed: +\begin{codeblock} +allocator_traits::destroy(m, p) +\end{codeblock} +\end{itemize} -\indexordmem{find}% -\tcode{b.find(k)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. & - \returns An iterator pointing to an element with the key equivalent - to \tcode{k}, or \tcode{b.end()} if such an element is not found. & - logarithmic \\ \rowsep - -\tcode{a_tran.}\br - \tcode{find(ke)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. & - \returns An iterator pointing to an element with key \tcode{r} such that - \tcode{!c(r, ke) \&\& !c(ke, r)}, or \tcode{a_tran.end()} if such an element - is not found. & - logarithmic \\ \rowsep +\begin{note} +A container calls \tcode{allocator_traits::construct(m, p, args)} +to construct an element at \tcode{p} using \tcode{args}, +with \tcode{m == get_allocator()}. +The default \tcode{construct} in \tcode{allocator} will +call \tcode{::new((void*)p) T(args)}, +but specialized allocators can choose a different definition. +\end{note} -\indexordmem{count}% -\tcode{b.count(k)} & - \tcode{size_type} & - \returns The number of elements with key equivalent to \tcode{k}. & - $\log (\tcode{b.size()}) + \tcode{b.count(k)}$ \\ \rowsep - -\tcode{a_tran.}\br - \tcode{count(ke)} & - \tcode{size_type} & - \returns The number of elements with key \tcode{r} such that - \tcode{!c(r, ke) \&\& !c(ke, r)} & - $\log (\tcode{a_tran.size()}) + \tcode{a_tran.count(ke)}$ \\ \rowsep +\pnum +The following exposition-only concept is used in the definition of containers: +\begin{codeblock} +template +concept @\defexposconcept{container-compatible-range}@ = // \expos + ranges::@\libconcept{input_range}@ && @\libconcept{convertible_to}@, T>; +\end{codeblock} -\indexordmem{contains}% -\tcode{b.}\br - \tcode{contains(k)} & - \tcode{bool} & - \effects Equivalent to: \tcode{return b.find(k) != b.end();} & - logarithmic \\ \rowsep - -\tcode{a_tran.}\br - \tcode{con\-tains(ke)} & - \tcode{bool} & - \effects Equivalent to: \tcode{return a_tran.find(ke) != a_tran.end();} & - logarithmic \\ \rowsep +\pnum +In this subclause, +\begin{itemize} +\item +\tcode{X} denotes an allocator-aware container class +with a \tcode{value_type} of \tcode{T} using an allocator of type \tcode{A}, +\item +\tcode{u} denotes a variable, +\item +\tcode{a} and \tcode{b} denote non-const lvalues of type \tcode{X}, +\item +\tcode{c} denotes an lvalue of type \tcode{\keyword{const} X}, +\item +\tcode{t} denotes an lvalue or a const rvalue of type \tcode{X}, +\item +\tcode{rv} denotes a non-const rvalue of type \tcode{X}, and +\item +\tcode{m} is a value of type \tcode{A}. +\end{itemize} -\indexordmem{lower_bound}% -\tcode{b.lower_bound(k)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. & - \returns An iterator pointing to the first element with - key not less than \tcode{k}, - or \tcode{b.end()} if such an element is not found. & - logarithmic \\ \rowsep - -\tcode{a_tran.}\br - \tcode{lower_bound(kl)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. & - \returns An iterator pointing to the first element with - key \tcode{r} such that \tcode{!c(r, kl)}, - or \tcode{a_tran.end()} if such an element is not found. & - logarithmic \\ \rowsep +% Local command to index names as members of all containers. +\renewcommand{\indexcont}[1]{% +\indexlibrarymisc{#1}{allocator-aware containers}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +\indexlibrarymemberx{map}{#1}% +\indexlibrarymemberx{set}{#1}% +\indexlibrarymemberx{multiset}{#1}% +\indexlibrarymemberx{multimap}{#1}% +\indexlibrarymemberx{unordered_map}{#1}% +\indexlibrarymemberx{unordered_set}{#1}% +\indexlibrarymemberx{unordered_multiset}{#1}% +\indexlibrarymemberx{unordered_multimap}{#1}% +} -\indexordmem{upper_bound}% -\tcode{b.upper_bound(k)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. & - \returns An iterator pointing to the first element with - key greater than \tcode{k}, - or \tcode{b.end()} if such an element is not found. & - logarithmic \\ \rowsep - -\tcode{a_tran.}\br - \tcode{upper_bound(ku)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. & - \returns An iterator pointing to the first element with - key \tcode{r} such that \tcode{c(ku, r)}, - or \tcode{a_tran.end()} if such an element is not found. & - logarithmic \\ \rowsep +A type \tcode{X} meets the allocator-aware container requirements +if \tcode{X} meets the container requirements and +the following types, statements, and expressions are well-formed and have +the specified semantics. -\indexordmem{equal_range}% -\tcode{b.equal_range(k)} & - \tcode{pair<\brk{}iterator, iterator>}; - \tcode{pair<\brk{}const_iterator, const_iterator>} for constant \tcode{b}. & - \effects Equivalent to: \tcode{return make_pair(b.lower_bound(k), b.upper_bound(k));} & - logarithmic \\ \rowsep - -\tcode{a_tran.}\br - \tcode{equal_range(ke)} & - \tcode{pair<\brk{}iterator, iterator>}; - \tcode{pair<\brk{}const_iterator, const_iterator>} for constant \tcode{a_tran}. & - \effects Equivalent to: \tcode{return make_pair(}\br - \tcode{a_tran.lower_bound(ke), a_tran.upper_bound(ke));} & - logarithmic \\ -\end{libreqtab4b} - -\pnum -The \tcode{insert} and \tcode{emplace} members shall not affect the validity of -iterators and references to the container, -and the \tcode{erase} members shall invalidate only iterators and -references to the erased elements. +\indexcont{allocator_type}% +\begin{itemdecl} +typename X::allocator_type +\end{itemdecl} +\begin{itemdescr} \pnum -The \tcode{extract} members invalidate only iterators to the removed element; -pointers and references to the removed element remain valid. However, accessing -the element through such pointers and references while the element is owned by -a \tcode{node_type} is undefined behavior. References and pointers to an element -obtained while it is owned by a \tcode{node_type} are invalidated if the element -is successfully inserted. +\result +\tcode{A} \pnum -The fundamental property of iterators of associative containers is that they iterate through the containers -in the non-descending order of keys where non-descending is defined by the comparison that was used to -construct them. -For any two dereferenceable iterators -\tcode{i} -and -\tcode{j} -such that distance from -\tcode{i} -to -\tcode{j} -is positive, the following condition holds: +\expects +\tcode{allocator_type::value_type} is the same as \tcode{X::value_type}. +\end{itemdescr} -\begin{codeblock} -value_comp(*j, *i) == false -\end{codeblock} +\indexcont{get_allocator}% +\begin{itemdecl} +c.get_allocator() +\end{itemdecl} +\begin{itemdescr} \pnum -For associative containers with unique keys the stronger condition holds: +\result +\tcode{A} -\begin{codeblock} -value_comp(*i, *j) != false -\end{codeblock} +\pnum +\complexity +Constant. +\end{itemdescr} + +\begin{itemdecl} +X u; +X u = X(); +\end{itemdecl} +\begin{itemdescr} \pnum -When an associative container is constructed by passing a comparison object the -container shall not store a pointer or reference to the passed object, -even if that object is passed by reference. -When an associative container is copied, through either a copy constructor -or an assignment operator, -the target container shall then use the comparison object from the container -being copied, -as if that comparison object had been passed to the target container in -its constructor. +\expects +\tcode{A} meets the \oldconcept{DefaultConstructible} requirements. \pnum -The member function templates -\tcode{find}, \tcode{count}, \tcode{contains}, -\tcode{lower_bound}, \tcode{upper_bound}, \tcode{equal_range}, -\tcode{erase}, and \tcode{extract} -shall not participate in overload resolution unless -the \grammarterm{qualified-id} \tcode{Compare::is_transparent} is valid -and denotes a type\iref{temp.deduct}. -Additionally, the member function templates \tcode{extract} and \tcode{erase} -shall not participate in overload resolution if -\tcode{is_convertible_v || is_convertible_v} -is \tcode{true}, -where \tcode{K} is the type substituted as the first template argument. +\ensures +\tcode{u.empty()} returns \tcode{true}, \tcode{u.get_allocator() == A()}. \pnum -A deduction guide for an associative container shall not participate in overload resolution -if any of the following are true: -\begin{itemize} -\item It has an \tcode{InputIterator} template parameter -and a type that does not qualify as an input iterator is deduced for that parameter. +\complexity +Constant. +\end{itemdescr} -\item It has an \tcode{Allocator} template parameter -and a type that does not qualify as an allocator is deduced for that parameter. +\begin{itemdecl} +X u(m); +\end{itemdecl} -\item It has a \tcode{Compare} template parameter -and a type that qualifies as an allocator is deduced for that parameter. -\end{itemize} +\begin{itemdescr} +\pnum +\ensures +\tcode{u.empty()} returns \tcode{true}, \tcode{u.get_allocator() == m}. -\rSec3[associative.reqmts.except]{Exception safety guarantees}% -\indextext{associative containers!exception safety}% -\indextext{associative containers!requirements}% +\pnum +\complexity +Constant. +\end{itemdescr} + +\begin{itemdecl} +X u(t, m); +\end{itemdecl} +\begin{itemdescr} \pnum -For associative containers, no \tcode{clear()} function throws an exception. -\tcode{erase(k)} does not throw an exception unless that exception is thrown -by the container's \tcode{Compare} object (if any). +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}. \pnum -For associative containers, if an exception is thrown by any operation from -within an \tcode{insert} or \tcode{emplace} function inserting a single element, the -insertion has no effect. +\ensures +\tcode{u == t}, \tcode{u.get_allocator() == m} \pnum -For associative containers, no \tcode{swap} function throws an exception unless -that exception is thrown by the -swap of the container's \tcode{Compare} object (if any). +\complexity +Linear. +\end{itemdescr} -\rSec2[unord.req]{Unordered associative containers}% -\indextext{associative containers!unordered|see{unordered associative containers}} -\indextext{hash tables|see{unordered associative containers}} +\begin{itemdecl} +X u(rv); +\end{itemdecl} -\rSec3[unord.req.general]{General} +\begin{itemdescr} +\pnum +\ensures +\tcode{u} has the same elements as \tcode{rv} had before this construction; +the value of \tcode{u.get_allocator()} is the same as +the value of \tcode{rv.get_allocator()} before this construction. \pnum -\indextext{unordered associative containers!complexity}% -Unordered associative containers provide an ability for fast retrieval -of data based on keys. The worst-case complexity for most operations -is linear, but the average case is much faster. The library provides -four unordered associative containers: \tcode{unordered_set}, -\tcode{unordered_map}, \tcode{unordered_multiset}, and -\tcode{unordered_multimap}. +\complexity +Constant. +\end{itemdescr} + +\begin{itemdecl} +X u(rv, m); +\end{itemdecl} +\begin{itemdescr} \pnum -\indextext{unordered associative containers!lack of comparison functions}% -\indextext{unordered associative containers!requirements}% -\indextext{requirements!container!not required for unordered associated containers}% -Unordered associative containers conform to the requirements for -Containers\iref{container.requirements}, except that -the expressions -\tcode{a == b} and \tcode{a != b} have different semantics than for the other -container types. +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}. \pnum -Each unordered associative container is parameterized by \tcode{Key}, -by a function object type \tcode{Hash} that meets the \oldconcept{Hash} -requirements\iref{hash.requirements} and acts as a hash function for -argument values of type \tcode{Key}, and by a binary predicate \tcode{Pred} -that induces an equivalence relation on values of type \tcode{Key}. -Additionally, \tcode{unordered_map} and \tcode{unordered_multimap} associate -an arbitrary \textit{mapped type} \tcode{T} with the \tcode{Key}. +\ensures +\tcode{u} has the same elements, or copies of the elements, +that \tcode{rv} had before this construction, +\tcode{u.get_allocator() == m}. \pnum -\indextext{unordered associative containers!hash function}% -\indextext{hash function}% -The container's object of type \tcode{Hash} --- denoted by -\tcode{hash} --- is called the \term{hash function} of the -container. The container's object of type \tcode{Pred} --- -denoted by \tcode{pred} --- is called the -\term{key equality predicate} of the container. +\complexity +Constant if \tcode{m == rv.get_allocator()}, otherwise linear. +\end{itemdescr} + +\begin{itemdecl} +a = t +\end{itemdecl} +\begin{itemdescr} \pnum -\indextext{unordered associative containers!equality function}% -Two values \tcode{k1} and \tcode{k2} are -considered equivalent if the container's -key equality predicate -\tcode{pred(k1, k2)} is valid and returns -\tcode{true} when passed those values. If \tcode{k1} and -\tcode{k2} are equivalent, the container's hash function shall -return the same value for both. -\begin{note} -Thus, when an unordered associative container is instantiated with -a non-default \tcode{Pred} parameter it usually needs a non-default \tcode{Hash} -parameter as well. -\end{note} -For any two keys \tcode{k1} and \tcode{k2} in the same container, -calling \tcode{pred(k1, k2)} shall always return the same value. -For any key \tcode{k} in a container, calling \tcode{hash(k)} -shall always return the same value. +\result +\tcode{X\&}. \pnum -\indextext{unordered associative containers!unique keys}% -\indextext{unordered associative containers!equivalent keys}% -An unordered associative container supports \textit{unique keys} if it -may contain at most one element for each key. Otherwise, it supports -\textit{equivalent keys}. \tcode{unordered_set} and \tcode{unordered_map} -support unique keys. \tcode{unordered_multiset} and \tcode{unordered_multimap} -support equivalent keys. In containers that support equivalent keys, -elements with equivalent keys are adjacent to each other -in the iteration order of the container. Thus, although the absolute order -of elements in an unordered container is not specified, its elements are -grouped into \defnx{equivalent-key groups}{equivalent-key group} such that all elements of each -group have equivalent keys. Mutating operations on unordered containers shall -preserve the relative order of elements within each equivalent-key group -unless otherwise specified. +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} and +\oldconcept{CopyAssignable}. \pnum -For \tcode{unordered_set} and \tcode{unordered_multiset} the value type is -the same as the key type. For \tcode{unordered_map} and -\tcode{unordered_multimap} it is \tcode{pair}. +\ensures +\tcode{a == t} is \tcode{true}. + +\pnum +\complexity +Linear. +\end{itemdescr} + +\indexcont{operator=}% +\begin{itemdecl} +a = rv +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&}. + +\pnum +\expects +If +\tcode{allocator_traits::propagate_on_container_move_assign\-ment::value} +is \tcode{false}, +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X} and +\oldconcept{MoveAssignable}. + +\pnum +\effects +All existing elements of \tcode{a} are either move assigned to or destroyed. + +\pnum +\ensures +If \tcode{a} and \tcode{rv} do not refer to the same object, +\tcode{a} is equal to the value that \tcode{rv} had before this assignment. + +\pnum +\complexity +Linear. +\end{itemdescr} + +\indexcont{swap}% +\begin{itemdecl} +a.swap(b) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\effects +Exchanges the contents of \tcode{a} and \tcode{b}. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\pnum +The behavior of certain container member functions and deduction guides +depends on whether types qualify as input iterators or allocators. +The extent to which an implementation determines that a type cannot be an input +iterator is unspecified, except that as a minimum integral types shall not qualify +as input iterators. +Likewise, the extent to which an implementation determines that a type cannot be +an allocator is unspecified, except that as a minimum a type \tcode{A} shall not qualify +as an allocator unless it meets both of the following conditions: + +\begin{itemize} +\item The \grammarterm{qualified-id} \tcode{A::value_type} +is valid and denotes a type\iref{temp.deduct}. + +\item The expression \tcode{declval().allocate(size_t\{\})} +is well-formed when treated as an unevaluated operand. +\end{itemize} + +\rSec2[container.requirements.dataraces]{Container data races} + +\pnum +For purposes of avoiding data races\iref{res.on.data.races}, implementations shall +consider the following functions to be \keyword{const}: \tcode{begin}, \tcode{end}, +\tcode{rbegin}, \tcode{rend}, \tcode{front}, \tcode{back}, \tcode{data}, \tcode{find}, +\tcode{lower_bound}, \tcode{upper_bound}, \tcode{equal_range}, \tcode{at} and, except in +associative or unordered associative containers, \tcode{operator[]}. + +\pnum +Notwithstanding~\ref{res.on.data.races}, implementations are required to avoid data +races when the contents of the contained object in different elements in the same +container, excepting \tcode{vector}, are modified concurrently. \pnum -For unordered containers where the value type is the same as the key -type, both \tcode{iterator} and \tcode{const_iterator} are constant -iterators. It is unspecified whether or not \tcode{iterator} and -\tcode{const_iterator} are the same type. \begin{note} -\tcode{iterator} and \tcode{const_iterator} have identical -semantics in this case, and \tcode{iterator} is convertible to -\tcode{const_iterator}. Users can avoid violating the one-definition rule -by always using \tcode{const_iterator} in their function parameter lists. +For a \tcode{vector x} with a size greater than one, \tcode{x[1] = 5} +and \tcode{*x.begin() = 10} can be executed concurrently without a data race, but +\tcode{x[0] = 5} and \tcode{*x.begin() = 10} executed concurrently can result in a data +race. +As an exception to the general rule, for a \tcode{vector y}, \tcode{y[0] = true} +can race with \tcode{y[1] = true}. \end{note} +\rSec2[sequence.reqmts]{Sequence containers} + \pnum -\indextext{buckets}% -\indextext{hash code}% -The elements of an unordered associative container are organized into -\textit{buckets}. Keys with the same hash code appear in the same -bucket. The number of buckets is automatically increased as elements -are added to an unordered associative container, so that the average -number of elements per bucket is kept below a bound. Rehashing -invalidates iterators, changes ordering between elements, and changes -which buckets elements appear in, but does not invalidate pointers or -references to elements. For \tcode{unordered_multiset} and -\tcode{unordered_multimap}, rehashing preserves the relative ordering of -equivalent elements. +A sequence container organizes a finite set of objects, all of the same type, into a strictly +linear arrangement. The library provides four basic kinds of sequence containers: +\tcode{vector}, \tcode{forward_list}, \tcode{list}, and \tcode{deque}. In addition, +\tcode{array} is provided as a sequence container which provides limited sequence operations +because it has a fixed number of elements. The library also provides container adaptors that +make it easy to construct abstract data types, such as \tcode{stack}s or \tcode{queue}s, out of +the basic sequence container kinds (or out of other kinds of sequence containers that the user defines). \pnum -The unordered associative containers meet all the requirements of Allocator-aware -containers\iref{container.requirements.general}, except that for -\tcode{unordered_map} and \tcode{unordered_multimap}, the requirements placed on \tcode{value_type} -in \tref{container.alloc.req} 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} even though the associated -\tcode{value_type}, \tcode{pair}, is not -\oldconcept{CopyAssignable}. +The sequence containers +offer the programmer different complexity trade-offs. +\tcode{vector} +is appropriate in most circumstances. +\tcode{array} +has a fixed size known during translation. +\tcode{list} or \tcode{forward_list} +support frequent insertions and deletions from the +middle of the sequence. +\tcode{deque} +supports efficient insertions and deletions taking place at the beginning or at the +end of the sequence. +When choosing a container, remember \tcode{vector} is best; +leave a comment to explain if you choose from the rest! \end{note} \pnum -\indextext{unordered associative containers}% -\indextext{unordered associative containers!requirements}% -\indextext{requirements!unordered associative container}% -\indextext{unordered associative containers!unique keys}% -\indextext{unordered associative containers!equivalent keys}% -\indextext{requirements!container}% -In \tref{container.hash.req}, +In this subclause, \begin{itemize} \item -\tcode{X} denotes an unordered associative container class, -\item -\tcode{a} denotes a value of type \tcode{X}, -\item -\tcode{a2} denotes a value of a type with nodes compatible - with type \tcode{X} (\tref{container.node.compat}), -\item -\tcode{b} denotes a possibly const value of type \tcode{X}, +\tcode{X} denotes a sequence container class, \item -\tcode{a_uniq} denotes a value of type \tcode{X} - when \tcode{X} supports unique keys, +\tcode{a} denotes a value of type \tcode{X} containing elements of type \tcode{T}, \item -\tcode{a_eq} denotes a value of type \tcode{X} - when \tcode{X} supports equivalent keys, +\tcode{u} denotes the name of a variable being declared, \item -\tcode{a_tran} denotes a possibly const value of type \tcode{X} - when the \grammarterm{qualified-id}s - \tcode{X::key_equal::is_transparent} and - \tcode{X::hasher::is_transparent} - are both valid and denote types\iref{temp.deduct}, +\tcode{A} denotes \tcode{X::allocator_type} if +the \grammarterm{qualified-id} \tcode{X::allocator_type} is valid and denotes a +type\iref{temp.deduct} and +\tcode{allocator} if it doesn't, \item -\tcode{i} and \tcode{j} denote input iterators - that refer to \tcode{value_type}, +\tcode{i} and \tcode{j} +denote iterators that meet the \oldconcept{InputIterator} requirements +and refer to elements implicitly convertible to \tcode{value_type}, \item \tcode{[i, j)} denotes a valid range, \item -\tcode{p} and \tcode{q2} denote valid constant iterators to \tcode{a}, -\item -\tcode{q} and \tcode{q1} denote - valid dereferenceable constant iterators to \tcode{a}, +\tcode{rg} denotes a value of a type \tcode{R} +that models \tcode{\exposconcept{container-compatible-range}}, \item -\tcode{r} denotes a valid dereferenceable iterator to \tcode{a}, +\tcode{il} designates an object of type \tcode{initializer_list}, \item -\tcode{[q1, q2)} denotes a valid range in \tcode{a}, +\tcode{n} denotes a value of type \tcode{X::size_type}, \item -\tcode{il} denotes a value of type \tcode{initializer_list}, +\tcode{p} denotes a valid constant iterator to \tcode{a}, \item -\tcode{t} denotes a value of type \tcode{X::value_type}, +\tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a}, \item -\tcode{k} denotes a value of type \tcode{key_type}, +\tcode{[q1, q2)} denotes a valid range of constant iterators in \tcode{a}, \item -\tcode{hf} denotes a possibly const value of type \tcode{hasher}, +\tcode{t} denotes an lvalue or a const rvalue of \tcode{X::value_type}, and \item -\tcode{eq} denotes a possibly const value of type \tcode{key_equal}, +\tcode{rv} denotes a non-const rvalue of \tcode{X::value_type}. \item -\tcode{ke} is a value such that - \begin{itemize} - \item \tcode{eq(r1, ke) == eq(ke, r1)}, - \item \tcode{hf(r1) == hf(ke)} if \tcode{eq(r1, ke)} is \tcode{true}, and - \item \tcode{(eq(r1, ke) \&\& eq(r1, r2)) == eq(r2, ke)}, - \end{itemize} - where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran}, +\tcode{Args} denotes a template parameter pack; \item -\tcode{kx} is a value such that - \begin{itemize} - \item \tcode{eq(r1, kx) == eq(kx, r1)}, - \item \tcode{hf(r1) == hf(kx)} if \tcode{eq(r1, kx)} is \tcode{true}, - \item \tcode{(eq(r1, kx) \&\& eq(r1, r2)) == eq(r2, kx)}, and - \item \tcode{kx} is not convertible to - either \tcode{iterator} or \tcode{const_iterator}, - \end{itemize} - where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran}, -\item -\tcode{n} denotes a value of type \tcode{size_type}, -\item -\tcode{z} denotes a value of type \tcode{float}, and -\item -\tcode{nh} denotes a non-const rvalue of type \tcode{X::node_type}. +\tcode{args} denotes a function parameter pack with the pattern \tcode{Args\&\&}. \end{itemize} -% Local command to index names as members of all unordered containers. -\newcommand{\indexunordmem}[1]{% -\indexlibrary{\idxcode{#1}!unordered associative containers}% -\indexlibrary{\idxcode{unordered_set}!\idxcode{#1}}% -\indexlibrary{\idxcode{unordered_map}!\idxcode{#1}}% -\indexlibrary{\idxcode{unordered_multiset}!\idxcode{#1}}% -\indexlibrary{\idxcode{unordered_multimap}!\idxcode{#1}}% +\pnum +The complexities of the expressions are sequence dependent. + +% Local command to index names as members of all containers. +\renewcommand{\indexcont}[1]{% +\indexlibrarymisc{#1}{sequence containers}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% } -\begin{libreqtab4d} - {Unordered associative container requirements (in addition to container)} - {container.hash.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endhead -%% -\indexunordmem{key_type}% -\tcode{X::key_type} & - \tcode{Key} & - & - compile time \\ \rowsep +\pnum +A type \tcode{X} meets the \defnadj{sequence}{container} requirements +if \tcode{X} meets the container requirements and +the following statements and expressions are well-formed and have +the specified semantics. + +\begin{itemdecl} +X u(n, t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Constructs a sequence container with \tcode{n} copies of \tcode{t}. + +\pnum +\ensures +\tcode{distance(u.begin(), u.end()) == n} is \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +X u(i, j); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. +For \tcode{vector}, +if the iterator does not meet +the \oldconcept{ForwardIterator} requirements\iref{forward.iterators}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Constructs a sequence container equal to the range \tcode{[i, j)}. +Each iterator in the range \range{i}{j} is dereferenced exactly once. + +\pnum +\ensures +\tcode{distance(u.begin(), u.end()) == distance(i, j)} is \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +X(from_range, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector}, +if \tcode{R} models +neither \libconcept{sized_range} nor \libconcept{forward_range}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Constructs a sequence container equal to the range \tcode{rg}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. + +\pnum +\ensures +\tcode{distance(begin(), end()) == ranges::distance(rg)} is \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +X(il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end())}. +\end{itemdescr} + +\begin{itemdecl} +a = il +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&}. + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} and +\oldconcept{CopyAssignable}. + +\pnum +\effects +Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. +All existing elements of \tcode{a} are either assigned to or destroyed. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexcont{emplace}% +\begin{itemdecl} +a.emplace(p, args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. +For \tcode{vector} and \tcode{deque}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X} and +\oldconcept{MoveAssignable}. + +\pnum +\effects +Inserts an object of type \tcode{T} +constructed with \tcode{std::forward(args)...} +before \tcode{p}. +\begin{note} +\tcode{args} can directly or indirectly refer to a value in \tcode{a}. +\end{note} + +\pnum +\returns +An iterator that points to +the new element constructed from \tcode{args} into \tcode{a}. +\end{itemdescr} + +\indexcont{insert}% +\begin{itemdecl} +a.insert(p, t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}. +For \tcode{vector} and \tcode{deque}, +\tcode{T} is also \oldconcept{CopyAssignable}. + +\pnum +\effects +Inserts a copy of \tcode{t} before \tcode{p}. + +\pnum +\returns +An iterator that points to the copy of \tcode{t} inserted into \tcode{a}. +\end{itemdescr} + +\begin{itemdecl} +a.insert(p, rv) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}. +For \tcode{vector} and \tcode{deque}, +\tcode{T} is also \oldconcept{MoveAssignable}. + +\pnum +\effects +Inserts a copy of \tcode{rv} before \tcode{p}. + +\pnum +\returns +An iterator that points to the copy of \tcode{rv} inserted into \tcode{a}. +\end{itemdescr} + +\begin{itemdecl} +a.insert(p, n, t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} +and \oldconcept{CopyAssignable}. + +\pnum +\effects +Inserts \tcode{n} copies of \tcode{t} before \tcode{p}. + +\pnum +\returns +An iterator +that points to the copy of the first element inserted into \tcode{a}, or +\tcode{p} if \tcode{n == 0}. +\end{itemdescr} + +\begin{itemdecl} +a.insert(p, i, j) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. +For \tcode{vector} and \tcode{deque}, +\tcode{T} is also +\oldconcept{MoveInsertable} into \tcode{X}, +\oldconcept{MoveConstructible}, +\oldconcept{MoveAssignable}, and +swappable\iref{swappable.requirements}. +Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}. + +\pnum +\effects +Inserts copies of elements in \tcode{[i, j)} before \tcode{p}. +Each iterator in the range \range{i}{j} shall be dereferenced exactly once. + +\pnum +\returns +An iterator +that points to the copy of the first element inserted into \tcode{a}, or +\tcode{p} if \tcode{i == j}. +\end{itemdescr} + +\indexcont{insert_range}% +\begin{itemdecl} +a.insert_range(p, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector} and \tcode{deque}, +\tcode{T} is also +\oldconcept{MoveInsertable} into \tcode{X}, +\oldconcept{MoveConstructible}, +\oldconcept{MoveAssignable}, and +swappable\iref{swappable.requirements}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Inserts copies of elements in \tcode{rg} before \tcode{p}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. + +\pnum +\returns +An iterator +that points to the copy of the first element inserted into \tcode{a}, or +\tcode{p} if \tcode{rg} is empty. +\end{itemdescr} + +\begin{itemdecl} +a.insert(p, il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a.insert(p, il.begin(), il.end())}. +\end{itemdescr} + +\indexcont{erase}% +\begin{itemdecl} +a.erase(q) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +For \tcode{vector} and \tcode{deque}, +\tcode{T} is \oldconcept{MoveAssignable}. + +\pnum +\effects +Erases the element pointed to by \tcode{q}. + +\pnum +\returns +An iterator that points to the element immediately following \tcode{q} +prior to the element being erased. +If no such element exists, \tcode{a.end()} is returned. +\end{itemdescr} + +\begin{itemdecl} +a.erase(q1, q2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +For \tcode{vector} and \tcode{deque}, \tcode{T} is \oldconcept{MoveAssignable}. + +\pnum +\effects +Erases the elements in the range \tcode{[q1, q2)}. + +\pnum +\returns +An iterator that points to the element pointed to by \tcode{q2} +prior to any elements being erased. +If no such element exists, \tcode{a.end()} is returned. +\end{itemdescr} + +\indexcont{clear}% +\begin{itemdecl} +a.clear() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\effects +Destroys all elements in \tcode{a}. +Invalidates all references, pointers, and iterators +referring to the elements of \tcode{a} and +may invalidate the past-the-end iterator. + +\pnum +\ensures +\tcode{a.empty()} is \tcode{true}. + +\pnum +\complexity +Linear. +\end{itemdescr} + +\indexcont{assign}% +\begin{itemdecl} +a.assign(i, j) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i} +and assignable from \tcode{*i}. +For \tcode{vector}, +if the iterator does not meet +the forward iterator requirements\iref{forward.iterators}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. +Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}. + +\pnum +\effects +Replaces elements in \tcode{a} with a copy of \tcode{[i, j)}. +Invalidates all references, pointers and iterators +referring to the elements of \tcode{a}. +For \tcode{vector} and \tcode{deque}, +also invalidates the past-the-end iterator. +Each iterator in the range \range{i}{j} is dereferenced exactly once. +\end{itemdescr} + +\indexcont{assign_range}% +\begin{itemdecl} +a.assign_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\mandates +\tcode{\libconcept{assignable_from}>} +is modeled. + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector}, +if \tcode{R} models +neither \libconcept{sized_range} nor \libconcept{forward_range}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Replaces elements in \tcode{a} with a copy of each element in \tcode{rg}. +Invalidates all references, pointers, and iterators +referring to the elements of \tcode{a}. +For \tcode{vector} and \tcode{deque}, +also invalidates the past-the-end iterator. +Each iterator in the range \tcode{rg} is dereferenced exactly once. +\end{itemdescr} + +\begin{itemdecl} +a.assign(il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a.assign(il.begin(), il.end())}. +\end{itemdescr} + +\begin{itemdecl} +a.assign(n, t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} +and \oldconcept{CopyAssignable}. +\tcode{t} is not a reference into \tcode{a}. + +\pnum +\effects +Replaces elements in \tcode{a} with \tcode{n} copies of \tcode{t}. +Invalidates all references, pointers and iterators +referring to the elements of \tcode{a}. +For \tcode{vector} and \tcode{deque}, +also invalidates the past-the-end iterator. +\end{itemdescr} + +\pnum +For every sequence container defined in this Clause and in \ref{strings}: +\begin{itemize} +\item If the constructor +\begin{codeblock} +template + X(InputIterator first, InputIterator last, + const allocator_type& alloc = allocator_type()); +\end{codeblock} +is called with a type \tcode{InputIterator} that does not qualify as an input +iterator, then the constructor +shall not participate in overload resolution. + +\item If the member functions of the forms: +\begin{codeblock} +template + @\placeholdernc{return-type}@ @\placeholdernc{F}@(const_iterator p, + InputIterator first, InputIterator last); // such as \tcode{insert} + +template + @\placeholdernc{return-type}@ @\placeholdernc{F}@(InputIterator first, InputIterator last); // such as \tcode{append}, \tcode{assign} + +template + @\placeholdernc{return-type}@ @\placeholdernc{F}@(const_iterator i1, const_iterator i2, + InputIterator first, InputIterator last); // such as \tcode{replace} +\end{codeblock} +are called with a type \tcode{InputIterator} that does not qualify as an input +iterator, then these functions +shall not participate in overload resolution. + +\item A deduction guide for a sequence container shall not participate in overload resolution +if it has an \tcode{InputIterator} template parameter and a type that does not +qualify as an input iterator is deduced for that parameter, +or if it has an \tcode{Allocator} template parameter and a type that does not +qualify as an allocator is deduced for that parameter. +\end{itemize} + +\pnum +The following operations are provided for +some types of sequence containers but not others. +An implementation shall implement them so as to take amortized constant time. + +\begin{itemdecl} +a.front() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference; const_reference} for constant \tcode{a}. + +\pnum +\returns +\tcode{*a.begin()} + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{array}, +\tcode{deque}, +\tcode{forward_list}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.back() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference; const_reference} for constant \tcode{a}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = a.end(); +--tmp; +return *tmp; +\end{codeblock} + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{array}, +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.emplace_front(args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. + +\pnum +\effects +Prepends an object of type \tcode{T} +constructed with \tcode{std::forward(args)...}. + +\pnum +\returns +\tcode{a.front()}. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{forward_list}, and +\tcode{list}. +\end{itemdescr} + +\begin{itemdecl} +a.emplace_back(args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. +For \tcode{vector}, +\tcode{T} is also \oldconcept{MoveIn\-sert\-able} into \tcode{X}. + +\pnum +\effects +Appends an object of type \tcode{T} +constructed with \tcode{std::forward(args)...}. + +\pnum +\returns +\tcode{a.back()}. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.push_front(t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Prepends a copy of \tcode{t}. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{forward_list}, and +\tcode{list}. +\end{itemdescr} + +\begin{itemdecl} +a.push_front(rv) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Prepends a copy of \tcode{rv}. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{forward_list}, and +\tcode{list}. +\end{itemdescr} + +\begin{itemdecl} +a.prepend_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Inserts copies of elements in \tcode{rg} before \tcode{begin()}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. +\begin{note} +The order of elements in \tcode{rg} is not reversed. +\end{note} + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{forward_list}, and +\tcode{list}. +\end{itemdescr} + +\begin{itemdecl} +a.push_back(t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Appends a copy of \tcode{t}. + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.push_back(rv) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Appends a copy of \tcode{rv}. + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.append_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector}, +\tcode{T} is also +\oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Inserts copies of elements in \tcode{rg} before \tcode{end()}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.pop_front() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{a.empty()} is \tcode{false}. + +\pnum +\effects +Destroys the first element. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{forward_list}, and +\tcode{list}. +\end{itemdescr} + +\begin{itemdecl} +a.pop_back() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{a.empty()} is \tcode{false}. + +\pnum +\effects +Destroys the last element. + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a[n] +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference; const_reference} for constant \tcode{a} + +\pnum +\returns +\tcode{*(a.begin() + n)} + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{array}, +\tcode{deque}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.at(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference; const_reference} for constant \tcode{a} + +\pnum +\returns +\tcode{*(a.begin() + n)} + +\pnum +\throws +\tcode{out_of_range} if \tcode{n >= a.size()}. + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{array}, +\tcode{deque}, and +\tcode{vector}. +\end{itemdescr} + +\rSec2[container.node]{Node handles} + +\rSec3[container.node.overview]{Overview} + +\pnum +A \defn{node handle} is an object that accepts ownership of a single element +from an associative container\iref{associative.reqmts} or an unordered +associative container\iref{unord.req}. It may be used to transfer that +ownership to another container with compatible nodes. Containers with +compatible nodes have the same node handle type. Elements may be transferred in +either direction between container types in the same row of +\tref{container.node.compat}. + +\begin{floattable}{Container types with compatible nodes}{container.node.compat} +{ll} +\topline +\tcode{map} & \tcode{map} \\ +\rowsep +\tcode{map} & \tcode{multimap} \\ +\rowsep +\tcode{set} & \tcode{set} \\ +\rowsep +\tcode{set} & \tcode{multiset} \\ +\rowsep +\tcode{unordered_map} & \tcode{unordered_map} \\ +\rowsep +\tcode{unordered_map} & \tcode{unordered_multimap} \\ +\rowsep +\tcode{unordered_set} & \tcode{unordered_set} \\ +\rowsep +\tcode{unordered_set} & \tcode{unordered_multiset} \\ +\end{floattable} + +\pnum +If a node handle is not empty, then it contains an allocator that is equal to +the allocator of the container when the element was extracted. If a node handle +is empty, it contains no allocator. + +\pnum +Class \exposid{node-handle} is for exposition only. + +\pnum +If a user-defined specialization of \tcode{pair} exists for +\tcode{pair} or \tcode{pair}, where \tcode{Key} is the +container's \tcode{key_type} and \tcode{T} is the container's +\tcode{mapped_type}, the behavior of operations involving node handles is +undefined. + +\begin{codeblock} +template<@\unspecnc@> +class @\placeholder{node-handle}@ { +public: + // These type declarations are described in \ref{associative.reqmts} and \ref{unord.req}. + using value_type = @\seebelownc{}@; // not present for map containers + using key_type = @\seebelownc{}@; // not present for set containers + using mapped_type = @\seebelownc{}@; // not present for set containers + using allocator_type = @\seebelownc{}@; + +private: + using container_node_type = @\unspecnc@; // \expos + using ator_traits = allocator_traits; // \expos + + typename ator_traits::template + rebind_traits::pointer ptr_; // \expos + optional alloc_; // \expos + +public: + // \ref{container.node.cons}, constructors, copy, and assignment + constexpr @\placeholdernc{node-handle}@() noexcept : ptr_(), alloc_() {} + @\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&&) noexcept; + @\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&&); + + // \ref{container.node.dtor}, destructor + ~@\placeholdernc{node-handle}@(); + + // \ref{container.node.observers}, observers + value_type& value() const; // not present for map containers + key_type& key() const; // not present for set containers + mapped_type& mapped() const; // not present for set containers + + allocator_type get_allocator() const; + explicit operator bool() const noexcept; + [[nodiscard]] bool empty() const noexcept; + + // \ref{container.node.modifiers}, modifiers + void swap(@\placeholdernc{node-handle}@&) + noexcept(ator_traits::propagate_on_container_swap::value || + ator_traits::is_always_equal::value); + + friend void swap(@\placeholdernc{node-handle}@& x, @\placeholdernc{node-handle}@& y) noexcept(noexcept(x.swap(y))) { + x.swap(y); + } +}; +\end{codeblock} + +\rSec3[container.node.cons]{Constructors, copy, and assignment} + +\begin{itemdecl} +@\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&& nh) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \exposid{node-handle} object initializing +\tcode{ptr_} with \tcode{nh.ptr_}. Move constructs \tcode{alloc_} with +\tcode{nh.alloc_}. Assigns \keyword{nullptr} to \tcode{nh.ptr_} and assigns +\tcode{nullopt} to \tcode{nh.alloc_}. +\end{itemdescr} + +\begin{itemdecl} +@\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&& nh); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +Either \tcode{!alloc_}, or +\tcode{ator_traits::propagate_on_container_move_assignment::\-value} +is \tcode{true}, or \tcode{alloc_ == nh.alloc_}. + +\pnum +\effects +\begin{itemize} +\item +If \tcode{ptr_ != nullptr}, destroys the \tcode{value_type} +subobject in the \tcode{container_node_type} object pointed to by \tcode{ptr_} +by calling \tcode{ator_traits::destroy}, then deallocates \tcode{ptr_} by +calling \tcode{ator_traits::template rebind_traits::deallocate}. +\item +Assigns \tcode{nh.ptr_} to \tcode{ptr_}. +\item +If \tcode{!alloc\textunderscore} or \tcode{ator_traits::propagate_on_container_move_assignment::value} +is \tcode{true}, \linebreak +move assigns \tcode{nh.alloc_} to \tcode{alloc_}. +\item +Assigns +\keyword{nullptr} to \tcode{nh.ptr_} and assigns \tcode{nullopt} to +\tcode{nh.alloc_}. +\end{itemize} + +\pnum +\returns +\tcode{*this}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\rSec3[container.node.dtor]{Destructor} + +\begin{itemdecl} +~@\placeholdernc{node-handle}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{ptr_ != nullptr}, destroys the \tcode{value_type} subobject +in the \tcode{container_node_type} object pointed to by \tcode{ptr_} by calling +\tcode{ator_traits::destroy}, then deallocates \tcode{ptr_} by calling +\tcode{ator_traits::template rebind_traits::deallocate}. +\end{itemdescr} + +\rSec3[container.node.observers]{Observers} + +\begin{itemdecl} +value_type& value() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{empty() == false}. + +\pnum +\returns +A reference to the \tcode{value_type} subobject in the +\tcode{container_node_type} object pointed to by \tcode{ptr_}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +key_type& key() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{empty() == false}. + +\pnum +\returns +A non-const reference to the \tcode{key_type} member of the +\tcode{value_type} subobject in the \tcode{contain\-er_node_type} object +pointed to by \tcode{ptr_}. + +\pnum +\throws +Nothing. + +\pnum +\remarks +Modifying the key through the returned reference is permitted. +\end{itemdescr} + +\begin{itemdecl} +mapped_type& mapped() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{empty() == false}. + +\pnum +\returns +A reference to the \tcode{mapped_type} member of the +\tcode{value_type} subobject in the \tcode{container_node_type} object +pointed to by \tcode{ptr_}. + +\pnum +\throws +Nothing. +\end{itemdescr} + + +\begin{itemdecl} +allocator_type get_allocator() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{empty() == false}. + +\pnum +\returns +\tcode{*alloc_}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +explicit operator bool() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{ptr_ != nullptr}. +\end{itemdescr} + +\begin{itemdecl} +[[nodiscard]] bool empty() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{ptr_ == nullptr}. +\end{itemdescr} + +\rSec3[container.node.modifiers]{Modifiers} + +\begin{itemdecl} +void swap(@\placeholdernc{node-handle}@& nh) + noexcept(ator_traits::propagate_on_container_swap::value || + ator_traits::is_always_equal::value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{!alloc_}, or \tcode{!nh.alloc_}, or +\tcode{ator_traits::propagate_on_container_swap::value} is \tcode{true}, +or \tcode{alloc_ == nh.alloc_}. + +\pnum +\effects +Calls \tcode{swap(ptr_, nh.ptr_)}. If \tcode{!alloc_}, or +\tcode{!nh.alloc_}, or \tcode{ator_traits::propagate_on_container_swap::value} +is \tcode{true} calls \tcode{swap(alloc_, nh.alloc_)}. +\end{itemdescr} + +\rSec2[container.insert.return]{Insert return type} + +\pnum +The associative containers with unique keys and the unordered containers with unique keys +have a member function \tcode{insert} that returns a nested type \tcode{insert_return_type}. +That return type is a specialization of the template specified in this subclause. + +\begin{codeblock} +template +struct @\placeholder{insert-return-type}@ +{ + Iterator position; + bool inserted; + NodeType node; +}; +\end{codeblock} + +\pnum +The name \exposid{insert-return-type} is exposition only. +\exposid{insert-return-type} has the template parameters, +data members, and special members specified above. +It has no base classes or members other than those specified. + +\rSec2[associative.reqmts]{Associative containers} + +\rSec3[associative.reqmts.general]{General} + +\pnum +Associative containers provide fast retrieval of data based on keys. +The library provides four basic kinds of associative containers: +\tcode{set}, +\tcode{multiset}, +\tcode{map} +and +\tcode{multimap}. + +\pnum +Each associative container is parameterized on +\tcode{Key} +and an ordering relation +\tcode{Compare} +that induces a strict weak ordering\iref{alg.sorting} on +elements of +\tcode{Key}. +In addition, +\tcode{map} +and +\tcode{multimap} +associate an arbitrary \term{mapped type} +\tcode{T} +with the +\tcode{Key}. +The object of type +\tcode{Compare} +is called the +\term{comparison object} +of a container. + +\pnum +The phrase ``equivalence of keys'' means the equivalence relation imposed by the +comparison object. +That is, two keys +\tcode{k1} +and +\tcode{k2} +are considered to be equivalent if for the +comparison object +\tcode{comp}, +\tcode{comp(k1, k2) == false \&\& comp(k2, k1) == false}. +\begin{note} +This is not necessarily the same as the result of \tcode{k1 == k2}. +\end{note} +For any two keys +\tcode{k1} +and +\tcode{k2} +in the same container, calling +\tcode{comp(k1, k2)} +shall always return the same value. + +\pnum +An associative container supports \term{unique keys} if it may contain at +most one element for each key. Otherwise, it supports \term{equivalent keys}. +The \tcode{set} and \tcode{map} classes support unique keys; the \tcode{multiset} +and \tcode{multimap} classes support equivalent keys. +For \tcode{multiset} and \tcode{multimap}, +\tcode{insert}, \tcode{emplace}, and \tcode{erase} preserve the relative ordering +of equivalent elements. + +\pnum +For \tcode{set} and \tcode{multiset} the value type is the same as the key type. +For \tcode{map} and \tcode{multimap} it is equal to \tcode{pair}. + +\pnum +\tcode{iterator} +of an associative container is of the bidirectional iterator category. +For associative containers where the value type is the same as the key type, both +\tcode{iterator} +and +\tcode{const_iterator} +are constant iterators. It is unspecified whether or not +\tcode{iterator} +and +\tcode{const_iterator} +are the same type. +\begin{note} +\tcode{iterator} and \tcode{const_iterator} have identical semantics in this case, and \tcode{iterator} is convertible to \tcode{const_iterator}. Users can avoid violating the one-definition rule by always using \tcode{const_iterator} in their function parameter lists. +\end{note} + +\pnum +In this subclause, +\begin{itemize} +\item +\tcode{X} denotes an associative container class, +\item +\tcode{a} denotes a value of type \tcode{X}, +\item +\tcode{a2} denotes a value of a type with nodes compatible with type +\tcode{X} (\tref{container.node.compat}), +\item +\tcode{b} denotes a possibly \keyword{const} value of type \tcode{X}, +\item +\tcode{u} denotes the name of a variable being declared, +\item +\tcode{a_uniq} denotes a value of type \tcode{X} +when \tcode{X} supports unique keys, +\item +\tcode{a_eq} denotes a value of type \tcode{X} +when \tcode{X} supports multiple keys, +\item +\tcode{a_tran} denotes a possibly \keyword{const} value of type \tcode{X} +when the \grammarterm{qualified-id} +\tcode{X::key_compare::is_transpa\-rent} is valid +and denotes a type\iref{temp.deduct}, +\item +\tcode{i} and \tcode{j} +meet the \oldconcept{InputIterator} requirements and refer to elements +implicitly convertible to +\tcode{value_type}, +\item +\range{i}{j} denotes a valid range, +\item +\tcode{rg} denotes a value of a type \tcode{R} +that models \tcode{\exposconcept{container-compatible-range}}, +\item +\tcode{p} denotes a valid constant iterator to \tcode{a}, +\item +\tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a}, +\item +\tcode{r} denotes a valid dereferenceable iterator to \tcode{a}, +\item +\tcode{[q1, q2)} denotes a valid range of constant iterators in \tcode{a}, +\item +\tcode{il} designates an object of type \tcode{initializer_list}, +\item +\tcode{t} denotes a value of type \tcode{X::value_type}, +\item +\tcode{k} denotes a value of type \tcode{X::key_type}, and +\item +\tcode{c} denotes a possibly \keyword{const} value of type \tcode{X::key_compare}; +\item +\tcode{kl} is a value such that \tcode{a} is partitioned\iref{alg.sorting} +with respect to \tcode{c(x, kl)}, +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; +\item +\tcode{ku} is a value such that \tcode{a} is partitioned with respect to +\tcode{!c(ku, x)}, +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; +\item +\tcode{ke} is a value such that \tcode{a} is partitioned with respect to +\tcode{c(x, ke)} and \tcode{!c(ke, x)}, with \tcode{c(x, ke)} implying +\tcode{!c(ke, x)} and +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; +\item +\tcode{kx} is a value such that +\begin{itemize} +\item +\tcode{a} is partitioned with respect to \tcode{c(x, kx)} and \tcode{!c(kx, x)}, +with \tcode{c(x, kx)} implying \tcode{!c(kx, x)} and +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}, and +\item +\tcode{kx} is not convertible to +either \tcode{iterator} or \tcode{const_iterator}; and +\end{itemize} +\item +\tcode{A} denotes the storage allocator used by \tcode{X}, if any, or \tcode{allocator} otherwise, +\item +\tcode{m} denotes an allocator of a type convertible to \tcode{A}, +and \tcode{nh} denotes a non-const rvalue of type \tcode{X::node_type}. +\end{itemize} + +\pnum +A type \tcode{X} meets the \defnadj{associative}{container} requirements +if \tcode{X} meets all the requirements of an allocator-aware +container\iref{container.requirements.general} and +the following types, statements, and expressions are well-formed and +have the specified semantics, +except that for +\tcode{map} and \tcode{multimap}, the requirements placed on \tcode{value_type} +in \ref{container.alloc.reqmts} apply instead to \tcode{key_type} +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 +\tcode{value_type}, \tcode{pair}, is not +\oldconcept{CopyAssignable}. +\end{note} + +% Local command to index names as members of all ordered containers. +\newcommand{\indexordmem}[1]{% +\indexlibrary{\idxcode{#1}!ordered associative containers}% +\indexlibrary{\idxcode{set}!\idxcode{#1}}% +\indexlibrary{\idxcode{map}!\idxcode{#1}}% +\indexlibrary{\idxcode{multiset}!\idxcode{#1}}% +\indexlibrary{\idxcode{multimap}!\idxcode{#1}}% +} + +\indexordmem{key_type}% +\begin{itemdecl} +typename X::key_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Key}. +\end{itemdescr} + +\indexordmem{mapped_type}% +\begin{itemdecl} +typename X::mapped_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{T}. + +\pnum +\remarks +For \tcode{map} and \tcode{multimap} only. +\end{itemdescr} + +\indexordmem{value_type}% +\begin{itemdecl} +typename X::value_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Key} for \tcode{set} and \tcode{multiset} only; +\tcode{pair} for \tcode{map} and \tcode{multimap} only. + +\pnum +\expects +\tcode{X::value_type} is \oldconcept{Erasable} from \tcode{X}. +\end{itemdescr} + +\indexordmem{key_compare}% +\begin{itemdecl} +typename X::key_compare +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Compare}. + +\pnum +\expects +\tcode{key_compare} is \oldconcept{CopyConstructible}. +\end{itemdescr} + +\indexordmem{value_compare}% +\begin{itemdecl} +typename X::value_compare +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A binary predicate type. +It is the same as \tcode{key_compare} for \tcode{set} and +\tcode{multiset}; is an ordering relation on pairs induced by the +first component (i.e., \tcode{Key}) for \tcode{map} and \tcode{multimap}. +\end{itemdescr} + +\indexordmem{node_type}% +\begin{itemdecl} +typename X::node_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A specialization of +the \exposid{node-handle} class template\iref{container.node}, +such that the public nested types are +the same types as the corresponding types in \tcode{X}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty container. +Uses a copy of \tcode{c} as a comparison object. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X u = X(); +X u; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements. + +\pnum +\effects +Constructs an empty container. +Uses \tcode{Compare()} as a comparison object. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(i, j, c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container and +inserts elements from the range \range{i}{j} into it; +uses \tcode{c} as a comparison object. + +\pnum +\complexity +$N \log N$ in general, where $N$ has the value \tcode{distance(i, j)}; +linear if \range{i}{j} is sorted with \tcode{value_comp()}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(i, j) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container and +inserts elements from the range \range{i}{j} into it; +uses \tcode{Compare()} as a comparison object. + +\pnum +\complexity +$N \log N$ in general, where $N$ has the value \tcode{distance(i, j)}; +linear if \range{i}{j} is sorted with \tcode{value_comp()}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(from_range, rg, c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*range::begin(rg)}. + +\pnum +\effects +Constructs an empty container and +inserts each element from \tcode{rg} into it. +Uses \tcode{c} as the comparison object. + +\pnum +\complexity +$N \log N$ in general, where $N$ has the value \tcode{ranges::distance(rg)}; +linear if \tcode{rg} is sorted with \tcode{value_comp()}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(from_range, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container and +inserts each element from \tcode{rg} into it. +Uses \tcode{Compare()} as the comparison object. + +\pnum +\complexity +Same as \tcode{X(from_range, rg, c)}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(il, c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end(), c)}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end())}. +\end{itemdescr} + +\begin{itemdecl} +a = il +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&} + +\pnum +\expects +\tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X} +and \oldconcept{CopyAssignable}. + +\pnum +\effects +Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. +All existing elements of \tcode{a} are either assigned to or destroyed. + +\pnum +\complexity +$N \log N$ in general, where $N$ has the value \tcode{il.size() + a.size()}; +linear if \range{il.begin()}{il.end()} is sorted with \tcode{value_comp()}. +\end{itemdescr} + +\indexordmem{key_comp}% +\begin{itemdecl} +b.key_comp() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::key_compare} + +\pnum +\returns +The comparison object out of which \tcode{b} was constructed. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexordmem{value_comp}% +\begin{itemdecl} +b.value_comp() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::value_compare} + +\pnum +\returns +An object of \tcode{value_compare} constructed out of the comparison object. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexordmem{emplace}% +\begin{itemdecl} +a_uniq.emplace(args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. + +\pnum +\effects +Inserts a \tcode{value_type} object \tcode{t} +constructed with \tcode{std::forward(args)...} +if and only if there is no element in the container +with key equivalent to the key of \tcode{t}. + +\pnum +\returns +The \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion takes place, and +the iterator component of the pair points to +the element with key equivalent to the key of \tcode{t}. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{emplace}% +\begin{itemdecl} +a_eq.emplace(args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. + +\pnum +\effects +Inserts a \tcode{value_type} object \tcode{t} +constructed with \tcode{std::forward(args)...}. +If a range containing elements equivalent to \tcode{t} exists in \tcode{a_eq}, +\tcode{t} is inserted at the end of that range. + +\pnum +\returns +An iterator pointing to the newly inserted element. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{emplace_hint}% +\begin{itemdecl} +a.emplace_hint(p, args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Equivalent to \tcode{a.emplace(std::forward(args)...)}, +except that the element is inserted as close as possible to +the position just prior to \tcode{p}. + +\pnum +\returns +An iterator pointing to the element +with the key equivalent to the newly inserted element. + +\pnum +\complexity +Logarithmic in general, but +amortized constant if the element is inserted right before \tcode{p}. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a_uniq.insert(t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair} + +\pnum +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Inserts \tcode{t} if and only if there is no element in the container +with key equivalent to the key of \tcode{t}. + +\pnum +\returns +The \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion takes place, and +the \tcode{iterator} component of the pair points to +the element with key equivalent to the key of \tcode{t}. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a_eq.insert(t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Inserts \tcode{t} and returns the iterator pointing to +the newly inserted element. +If a range containing elements equivalent to \tcode{t} exists in \tcode{a_eq}, +\tcode{t} is inserted at the end of that range. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a.insert(p, t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Inserts \tcode{t} if and only if there is no element +with key equivalent to the key of \tcode{t} in containers with unique keys; +always inserts \tcode{t} in containers with equivalent keys. +\tcode{t} is inserted as close as possible to +the position just prior to \tcode{p}. + +\pnum +\returns +An iterator pointing to the element with key equivalent to the key of \tcode{t}. + +\pnum +\complexity +Logarithmic in general, but +amortized constant if \tcode{t} is inserted right before \tcode{p}. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a.insert(i, j) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. +Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}. + +\pnum +\effects +Inserts each element from the range \range{i}{j} +if and only if there is no element +with key equivalent to the key of that element in containers with unique keys; +always inserts that element in containers with equivalent keys. + +\pnum +\complexity +$N \log (\tcode{a.size()} + N)$, where $N$ has the value \tcode{distance(i, j)}. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a.insert_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Inserts each element from \tcode{rg} if and only if +there is no element with key equivalent to the key of that element +in containers with unique keys; +always inserts that element in containers with equivalent keys. + +\pnum +\complexity +$N \log (\tcode{a.size()} + N)$, +where $N$ has the value \tcode{ranges::distance(rg)}. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a.insert(il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a.insert(il.begin(), il.end())}. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a_uniq.insert(nh) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{insert_return_type} + +\pnum +\expects +\tcode{nh} is empty or +\tcode{a_uniq.get_allocator() == nh.get_allocator()} is \tcode{true}. + +\pnum +\effects +If \tcode{nh} is empty, has no effect. +Otherwise, inserts the element owned by \tcode{nh} if and only if +there is no element in the container with a key equivalent to \tcode{nh.key()}. + +\pnum +\returns +If \tcode{nh} is empty, \tcode{inserted} is \tcode{false}, +\tcode{position} is \tcode{end()}, and \tcode{node} is empty. +Otherwise if the insertion took place, \tcode{inserted} is \tcode{true}, +\tcode{position} points to the inserted element, and \tcode{node} is empty; +if the insertion failed, \tcode{inserted} is \tcode{false}, +\tcode{node} has the previous value of \tcode{nh}, and +\tcode{position} points to an element with a key equivalent to \tcode{nh.key()}. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a_eq.insert(nh) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +\tcode{nh} is empty or +\tcode{a_eq.get_allocator() == nh.get_allocator()} is \tcode{true}. + +\pnum +\effects +If \tcode{nh} is empty, has no effect and returns \tcode{a_eq.end()}. +Otherwise, inserts the element owned by \tcode{nh} and +returns an iterator pointing to the newly inserted element. +If a range containing elements with keys equivalent to \tcode{nh.key()} +exists in \tcode{a_eq}, +the element is inserted at the end of that range. + +\pnum +\ensures +\tcode{nh} is empty. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a.insert(p, nh) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +\tcode{nh} is empty or +\tcode{a.get_allocator() == nh.get_allocator()} is \tcode{true}. + +\pnum +\effects +If \tcode{nh} is empty, has no effect and returns \tcode{a.end()}. +Otherwise, inserts the element owned by \tcode{nh} if and only if +there is no element with key equivalent to \tcode{nh.key()} +in containers with unique keys; +always inserts the element owned by \tcode{nh} +in containers with equivalent keys. +The element is inserted as close as possible to +the position just prior to \tcode{p}. + +\pnum +\ensures +\tcode{nh} is empty if insertion succeeds, unchanged if insertion fails. + +\pnum +\returns +An iterator pointing to the element with key equivalent to \tcode{nh.key()}. + +\pnum +\complexity +Logarithmic in general, but +amortized constant if the element is inserted right before \tcode{p}. +\end{itemdescr} + + +\indexordmem{extract}% +\begin{itemdecl} +a.extract(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{node_type} + +\pnum +\effects +Removes the first element in the container with key equivalent to \tcode{k}. + +\pnum +\returns +A \tcode{node_type} owning the element if found, +otherwise an empty \tcode{node_type}. + +\pnum +\complexity +$\log (\tcode{a.size()})$ +\end{itemdescr} + +\indexordmem{extract}% +\begin{itemdecl} +a_tran.extract(kx) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{node_type} + +\pnum +\effects +Removes the first element in the container with key \tcode{r} +such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}. + +\pnum +\returns +A \tcode{node_type} owning the element if found, +otherwise an empty \tcode{node_type}. + +\pnum +\complexity +$\log(\tcode{a_tran.size()})$ +\end{itemdescr} + +\indexordmem{extract}% +\begin{itemdecl} +a.extract(q) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{node_type} + +\pnum +\effects +Removes the element pointed to by \tcode{q}. + +\pnum +\returns +A \tcode{node_type} owning that element. + +\pnum +\complexity +Amortized constant. +\end{itemdescr} + +\indexordmem{merge}% +\begin{itemdecl} +a.merge(a2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{a.get_allocator() == a2.get_allocator()}. + +\pnum +\effects +Attempts to extract each element in \tcode{a2} and insert it into \tcode{a} +using the comparison object of \tcode{a}. +In containers with unique keys, +if there is an element in \tcode{a} with key equivalent to +the key of an element from \tcode{a2}, +then that element is not extracted from \tcode{a2}. + +\pnum +\ensures +Pointers and references to the transferred elements of \tcode{a2} +refer to those same elements but as members of \tcode{a}. +Iterators referring to the transferred elements +will continue to refer to their elements, +but they now behave as iterators into \tcode{a}, not into \tcode{a2}. + +\pnum +\throws +Nothing unless the comparison object throws. + +\pnum +\complexity +$N \log(\tcode{a.size()+} N)$, where $N$ has the value \tcode{a2.size()}. +\end{itemdescr} + +\indexordmem{erase}% +\begin{itemdecl} +a.erase(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\effects +Erases all elements in the container with key equivalent to \tcode{k}. + +\pnum +\returns +The number of erased elements. + +\pnum +\complexity +$\log (\tcode{a.size()}) + \tcode{a.count(k)}$ +\end{itemdescr} + +\indexordmem{erase}% +\begin{itemdecl} +a_tran.erase(kx) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\effects +Erases all elements in the container with key \tcode{r} +such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}. + +\pnum +\returns +The number of erased elements. + +\pnum +\complexity +$\log(\tcode{a_tran.size())} + \tcode{a_tran.count(kx)}$ +\end{itemdescr} + +\indexordmem{erase}% +\begin{itemdecl} +a.erase(q) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Erases the element pointed to by \tcode{q}. + +\pnum +\returns +An iterator pointing to the element immediately following \tcode{q} +prior to the element being erased. +If no such element exists, returns \tcode{a.end()}. + +\pnum +\complexity +Amortized constant. +\end{itemdescr} + +\indexordmem{erase}% +\begin{itemdecl} +a.erase(r) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Erases the element pointed to by \tcode{r}. + +\pnum +\returns +An iterator pointing to the element immediately following \tcode{r} +prior to the element being erased. +If no such element exists, returns \tcode{a.end()}. + +\pnum +\complexity +Amortized constant. +\end{itemdescr} + +\indexordmem{erase}% +\begin{itemdecl} +a.erase(q1, q2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Erases all the elements in the range \range{q1}{q2}. + +\pnum +\returns +An iterator pointing to the element pointed to by \tcode{q2} +prior to any elements being erased. +If no such element exists, \tcode{a.end()} is returned. + +\pnum +\complexity +$\log(\tcode{a.size()}) + N$, where $N$ has the value \tcode{distance(q1, q2)}. +\end{itemdescr} + +\indexordmem{clear}% +\begin{itemdecl} +a.clear() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a.erase(a.begin(), a.end())}. + +\pnum +\ensures +\tcode{a.empty()} is \tcode{true}. + +\pnum +\complexity +Linear in \tcode{a.size()}. +\end{itemdescr} + +\indexordmem{find}% +\begin{itemdecl} +b.find(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. + +\pnum +\returns +An iterator pointing to an element with the key equivalent to \tcode{k}, or +\tcode{b.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{find}% +\begin{itemdecl} +a_tran.find(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. + +\pnum +\returns +An iterator pointing to an element with key \tcode{r} +such that \tcode{!c(r, ke) \&\& !c(ke, r)} is \tcode{true}, or +\tcode{a_tran.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{count}% +\begin{itemdecl} +b.count(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\returns +The number of elements with key equivalent to \tcode{k}. + +\pnum +\complexity +$\log (\tcode{b.size()}) + \tcode{b.count(k)}$ +\end{itemdescr} + +\indexordmem{count}% +\begin{itemdecl} +a_tran.count(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\returns +The number of elements with key \tcode{r} +such that \tcode{!c(r, ke) \&\& !c(ke, r)}. + +\pnum +\complexity +$\log (\tcode{a_tran.size()}) + \tcode{a_tran.count(ke)}$ +\end{itemdescr} + +\indexordmem{contains}% +\begin{itemdecl} +b.contains(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\effects +Equivalent to: \tcode{return b.find(k) != b.end();} +\end{itemdescr} + +\indexordmem{contains}% +\begin{itemdecl} +a_tran.contains(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\effects +Equivalent to: \tcode{return a_tran.find(ke) != a_tran.end();} +\end{itemdescr} + +\indexordmem{lower_bound}% +\begin{itemdecl} +b.lower_bound(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. + +\pnum +\returns +An iterator pointing to the first element with key not less than \tcode{k}, +or \tcode{b.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{lower_bound}% +\begin{itemdecl} +a_tran.lower_bound(kl) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. + +\pnum +\returns +An iterator pointing to the first element with key \tcode{r} +such that \tcode{!c(r, kl)}, +or \tcode{a_tran.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{upper_bound}% +\begin{itemdecl} +b.upper_bound(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. + +\pnum +\returns +An iterator pointing to the first element with key greater than \tcode{k}, +or \tcode{b.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic, +\end{itemdescr} + +\indexordmem{upper_bound}% +\begin{itemdecl} +a_tran.upper_bound(ku) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. + +\pnum +\returns +An iterator pointing to the first element with key \tcode{r} +such that \tcode{c(ku, r)}, +or \tcode{a_tran.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{equal_range}% +\begin{itemdecl} +b.equal_range(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair}; +\tcode{pair} for constant \tcode{b}. + +\pnum +\effects +Equivalent to: \tcode{return make_pair(b.lower_bound(k), b.upper_bound(k));} + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{equal_range}% +\begin{itemdecl} +a_tran.equal_range(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair}; +\tcode{pair} for constant \tcode{a_tran}. + +\pnum +\effects +Equivalent to: +\tcode{return make_pair(a_tran.lower_bound(ke), a_tran.upper_bound(ke));} + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\pnum +The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members +shall not affect the validity of +iterators and references to the container, +and the \tcode{erase} members shall invalidate only iterators and +references to the erased elements. + +\pnum +The \tcode{extract} members invalidate only iterators to the removed element; +pointers and references to the removed element remain valid. However, accessing +the element through such pointers and references while the element is owned by +a \tcode{node_type} is undefined behavior. References and pointers to an element +obtained while it is owned by a \tcode{node_type} are invalidated if the element +is successfully inserted. + +\pnum +The fundamental property of iterators of associative containers is that they iterate through the containers +in the non-descending order of keys where non-descending is defined by the comparison that was used to +construct them. +For any two dereferenceable iterators +\tcode{i} +and +\tcode{j} +such that distance from +\tcode{i} +to +\tcode{j} +is positive, the following condition holds: + +\begin{codeblock} +value_comp(*j, *i) == false +\end{codeblock} + +\pnum +For associative containers with unique keys the stronger condition holds: + +\begin{codeblock} +value_comp(*i, *j) != false +\end{codeblock} + +\pnum +When an associative container is constructed by passing a comparison object the +container shall not store a pointer or reference to the passed object, +even if that object is passed by reference. +When an associative container is copied, through either a copy constructor +or an assignment operator, +the target container shall then use the comparison object from the container +being copied, +as if that comparison object had been passed to the target container in +its constructor. + +\pnum +The member function templates +\tcode{find}, \tcode{count}, \tcode{contains}, +\tcode{lower_bound}, \tcode{upper_bound}, \tcode{equal_range}, +\tcode{erase}, and \tcode{extract} +shall not participate in overload resolution unless +the \grammarterm{qualified-id} \tcode{Compare::is_transparent} is valid +and denotes a type\iref{temp.deduct}. +Additionally, the member function templates \tcode{extract} and \tcode{erase} +shall not participate in overload resolution if +\tcode{is_convertible_v || is_convertible_v} +is \tcode{true}, +where \tcode{K} is the type substituted as the first template argument. + +\pnum +A deduction guide for an associative container shall not participate in overload resolution +if any of the following are true: +\begin{itemize} +\item It has an \tcode{InputIterator} template parameter +and a type that does not qualify as an input iterator is deduced for that parameter. + +\item It has an \tcode{Allocator} template parameter +and a type that does not qualify as an allocator is deduced for that parameter. + +\item It has a \tcode{Compare} template parameter +and a type that qualifies as an allocator is deduced for that parameter. +\end{itemize} + +\rSec3[associative.reqmts.except]{Exception safety guarantees}% +\indextext{associative containers!exception safety}% +\indextext{associative containers!requirements}% + +\pnum +For associative containers, no \tcode{clear()} function throws an exception. +\tcode{erase(k)} does not throw an exception unless that exception is thrown +by the container's \tcode{Compare} object (if any). + +\pnum +For associative containers, if an exception is thrown by any operation from +within an \tcode{insert} or \tcode{emplace} function inserting a single element, the +insertion has no effect. + +\pnum +For associative containers, no \tcode{swap} function throws an exception unless +that exception is thrown by the +swap of the container's \tcode{Compare} object (if any). + +\rSec2[unord.req]{Unordered associative containers}% +\indextext{associative containers!unordered|see{unordered associative containers}} +\indextext{hash tables|see{unordered associative containers}} + +\rSec3[unord.req.general]{General} + +\pnum +\indextext{unordered associative containers!complexity}% +Unordered associative containers provide an ability for fast retrieval +of data based on keys. The worst-case complexity for most operations +is linear, but the average case is much faster. The library provides +four unordered associative containers: \tcode{unordered_set}, +\tcode{unordered_map}, \tcode{unordered_multiset}, and +\tcode{unordered_multimap}. + +\pnum +\indextext{unordered associative containers!lack of comparison functions}% +\indextext{unordered associative containers!requirements}% +\indextext{requirements!container!not required for unordered associated containers}% +Unordered associative containers conform to the requirements for +Containers\iref{container.requirements}, except that +the expressions +\tcode{a == b} and \tcode{a != b} have different semantics than for the other +container types. + +\pnum +Each unordered associative container is parameterized by \tcode{Key}, +by a function object type \tcode{Hash} that meets the \oldconcept{Hash} +requirements\iref{hash.requirements} and acts as a hash function for +argument values of type \tcode{Key}, and by a binary predicate \tcode{Pred} +that induces an equivalence relation on values of type \tcode{Key}. +Additionally, \tcode{unordered_map} and \tcode{unordered_multimap} associate +an arbitrary \textit{mapped type} \tcode{T} with the \tcode{Key}. + +\pnum +\indextext{unordered associative containers!hash function}% +\indextext{hash function}% +The container's object of type \tcode{Hash} --- denoted by +\tcode{hash} --- is called the \term{hash function} of the +container. The container's object of type \tcode{Pred} --- +denoted by \tcode{pred} --- is called the +\term{key equality predicate} of the container. + +\pnum +\indextext{unordered associative containers!equality function}% +Two values \tcode{k1} and \tcode{k2} are +considered equivalent if the container's +key equality predicate +\tcode{pred(k1, k2)} is valid and returns +\tcode{true} when passed those values. If \tcode{k1} and +\tcode{k2} are equivalent, the container's hash function shall +return the same value for both. +\begin{note} +Thus, when an unordered associative container is instantiated with +a non-default \tcode{Pred} parameter it usually needs a non-default \tcode{Hash} +parameter as well. +\end{note} +For any two keys \tcode{k1} and \tcode{k2} in the same container, +calling \tcode{pred(k1, k2)} shall always return the same value. +For any key \tcode{k} in a container, calling \tcode{hash(k)} +shall always return the same value. + +\pnum +\indextext{unordered associative containers!unique keys}% +\indextext{unordered associative containers!equivalent keys}% +An unordered associative container supports \textit{unique keys} if it +may contain at most one element for each key. Otherwise, it supports +\textit{equivalent keys}. \tcode{unordered_set} and \tcode{unordered_map} +support unique keys. \tcode{unordered_multiset} and \tcode{unordered_multimap} +support equivalent keys. In containers that support equivalent keys, +elements with equivalent keys are adjacent to each other +in the iteration order of the container. Thus, although the absolute order +of elements in an unordered container is not specified, its elements are +grouped into \defnx{equivalent-key groups}{equivalent-key group} such that all elements of each +group have equivalent keys. Mutating operations on unordered containers shall +preserve the relative order of elements within each equivalent-key group +unless otherwise specified. + +\pnum +For \tcode{unordered_set} and \tcode{unordered_multiset} the value type is +the same as the key type. For \tcode{unordered_map} and +\tcode{unordered_multimap} it is \tcode{pair}. + +\pnum +For unordered containers where the value type is the same as the key +type, both \tcode{iterator} and \tcode{const_iterator} are constant +iterators. It is unspecified whether or not \tcode{iterator} and +\tcode{const_iterator} are the same type. +\begin{note} +\tcode{iterator} and \tcode{const_iterator} have identical +semantics in this case, and \tcode{iterator} is convertible to +\tcode{const_iterator}. Users can avoid violating the one-definition rule +by always using \tcode{const_iterator} in their function parameter lists. +\end{note} + +\pnum +\indextext{buckets}% +\indextext{hash code}% +The elements of an unordered associative container are organized into +\textit{buckets}. Keys with the same hash code appear in the same +bucket. The number of buckets is automatically increased as elements +are added to an unordered associative container, so that the average +number of elements per bucket is kept below a bound. Rehashing +invalidates iterators, changes ordering between elements, and changes +which buckets elements appear in, but does not invalidate pointers or +references to elements. For \tcode{unordered_multiset} and +\tcode{unordered_multimap}, rehashing preserves the relative ordering of +equivalent elements. + +\pnum +\indextext{unordered associative containers}% +\indextext{unordered associative containers!requirements}% +\indextext{requirements!unordered associative container}% +\indextext{unordered associative containers!unique keys}% +\indextext{unordered associative containers!equivalent keys}% +\indextext{requirements!container}% +In this subclause, +\begin{itemize} +\item +\tcode{X} denotes an unordered associative container class, +\item +\tcode{a} denotes a value of type \tcode{X}, +\item +\tcode{a2} denotes a value of a type with nodes compatible + with type \tcode{X} (\tref{container.node.compat}), +\item +\tcode{b} denotes a possibly const value of type \tcode{X}, +\item +\tcode{a_uniq} denotes a value of type \tcode{X} + when \tcode{X} supports unique keys, +\item +\tcode{a_eq} denotes a value of type \tcode{X} + when \tcode{X} supports equivalent keys, +\item +\tcode{a_tran} denotes a possibly const value of type \tcode{X} + when the \grammarterm{qualified-id}s + \tcode{X::key_equal::is_transparent} and + \tcode{X::hasher::is_transparent} + are both valid and denote types\iref{temp.deduct}, +\item +\tcode{i} and \tcode{j} denote input iterators + that refer to \tcode{value_type}, +\item +\tcode{[i, j)} denotes a valid range, +\item +\tcode{rg} denotes a value of a type \tcode{R} +that models \tcode{\exposconcept{container-compatible-range}}, +\item +\tcode{p} and \tcode{q2} denote valid constant iterators to \tcode{a}, +\item +\tcode{q} and \tcode{q1} denote + valid dereferenceable constant iterators to \tcode{a}, +\item +\tcode{r} denotes a valid dereferenceable iterator to \tcode{a}, +\item +\tcode{[q1, q2)} denotes a valid range in \tcode{a}, +\item +\tcode{il} denotes a value of type \tcode{initializer_list}, +\item +\tcode{t} denotes a value of type \tcode{X::value_type}, +\item +\tcode{k} denotes a value of type \tcode{key_type}, +\item +\tcode{hf} denotes a possibly const value of type \tcode{hasher}, +\item +\tcode{eq} denotes a possibly const value of type \tcode{key_equal}, +\item +\tcode{ke} is a value such that + \begin{itemize} + \item \tcode{eq(r1, ke) == eq(ke, r1)}, + \item \tcode{hf(r1) == hf(ke)} if \tcode{eq(r1, ke)} is \tcode{true}, and + \item \tcode{(eq(r1, ke) \&\& eq(r1, r2)) == eq(r2, ke)}, + \end{itemize} + where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran}, +\item +\tcode{kx} is a value such that + \begin{itemize} + \item \tcode{eq(r1, kx) == eq(kx, r1)}, + \item \tcode{hf(r1) == hf(kx)} if \tcode{eq(r1, kx)} is \tcode{true}, + \item \tcode{(eq(r1, kx) \&\& eq(r1, r2)) == eq(r2, kx)}, and + \item \tcode{kx} is not convertible to + either \tcode{iterator} or \tcode{const_iterator}, + \end{itemize} + where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran}, +\item +\tcode{n} denotes a value of type \tcode{size_type}, +\item +\tcode{z} denotes a value of type \tcode{float}, and +\item +\tcode{nh} denotes a non-const rvalue of type \tcode{X::node_type}. +\end{itemize} + +\pnum +A type \tcode{X} meets +the \defnadj{unordered associative}{container} requirements +if \tcode{X} meets all the requirements of +an allocator-aware container\iref{container.requirements.general} and +the following types, statements, and expressions are well-formed and +have the specified semantics, +except that for \tcode{unordered_map} and \tcode{unordered_multimap}, +the requirements placed on \tcode{value_type} in \ref{container.alloc.reqmts} +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} +even though the associated \tcode{value_type}, +\tcode{pair}, +is not \oldconcept{CopyAssignable}. +\end{note} + +% Local command to index names as members of all unordered containers. +\newcommand{\indexunordmem}[1]{% +\indexlibrary{\idxcode{#1}!unordered associative containers}% +\indexlibrary{\idxcode{unordered_set}!\idxcode{#1}}% +\indexlibrary{\idxcode{unordered_map}!\idxcode{#1}}% +\indexlibrary{\idxcode{unordered_multiset}!\idxcode{#1}}% +\indexlibrary{\idxcode{unordered_multimap}!\idxcode{#1}}% +} + +\indexunordmem{key_type}% +\begin{itemdecl} +typename X::key_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Key}. +\end{itemdescr} + +\indexunordmem{mapped_type}% +\begin{itemdecl} +typename X::mapped_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{T}. + +\pnum +\remarks +For \tcode{unordered_map} and \tcode{unordered_multimap} only. +\end{itemdescr} + +\indexunordmem{value_type}% +\begin{itemdecl} +typename X::value_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Key} for \tcode{unordered_set} and \tcode{unordered_multiset} only; +\tcode{pair} +for \tcode{unordered_map} and \tcode{unordered_multimap} only. + +\pnum +\expects +\tcode{value_type} is \oldconcept{Erasable} from \tcode{X}. +\end{itemdescr} + +\indexunordmem{hasher}% +\begin{itemdecl} +typename X::hasher +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Hash}. + +\pnum +\expects +\tcode{Hash} is a unary function object type +such that the expression \tcode{hf(k)} has type \tcode{size_t}. +\end{itemdescr} + +\indexunordmem{key_equal}% +\begin{itemdecl} +typename X::key_equal +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Pred}. + +\pnum +\expects +\tcode{Pred} meets the \oldconcept{CopyConstructible} requirements. +\tcode{Pred} is a binary predicate that takes two arguments of type \tcode{Key}. +\tcode{Pred} is an equivalence relation. +\end{itemdescr} + +\indexunordmem{local_iterator}% +\begin{itemdecl} +typename X::local_iterator +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +An iterator type +whose category, value type, difference type, and pointer and reference types +are the same as \tcode{X::iterator}'s. +\begin{note} +A \tcode{local_iterator} object can be used to iterate through a single bucket, +but cannot be used to iterate across buckets. +\end{note} +\end{itemdescr} + +\indexunordmem{const_local_iterator}% +\begin{itemdecl} +typename X::const_local_iterator +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +An iterator type +whose category, value type, difference type, and pointer and reference types +are the same as \tcode{X::const_iterator}'s. +\begin{note} +A \tcode{const_local_iterator} object can be used to iterate +through a single bucket, +but cannot be used to iterate across buckets. +\end{note} +\end{itemdescr} + +\indexunordmem{node_type}% +\begin{itemdecl} +typename X::node_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A specialization of a \exposid{node-handle} class template\iref{container.node}, +such that the public nested types are the same types +as the corresponding types in \tcode{X}. +\end{itemdescr} + +\indexlibraryctor{unordered_set}% +\indexlibraryctor{unordered_map}% +\indexlibraryctor{unordered_multiset}% +\indexlibraryctor{unordered_multimap}% +\begin{itemdecl} +X(n, hf, eq) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{eq} as the key equality predicate. + +\pnum +\complexity +\bigoh{\tcode{n}} +\end{itemdescr} + +\begin{itemdecl} +X(n, hf) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{key_equal()} as the key equality predicate. + +\pnum +\complexity +\bigoh{\tcode{n}} +\end{itemdescr} + +\begin{itemdecl} +X(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} +meet the \oldconcept{DefaultConstructible} requirements. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate. + +\pnum +\complexity +\bigoh{\tcode{n}} +\end{itemdescr} + +\begin{itemdecl} +X a = X(); +X a; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. + +\pnum +\effects +Constructs an empty container with an unspecified number of buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\begin{itemdecl} +X(i, j, n, hf, eq) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{eq} as the key equality predicate, and +inserts elements from \range{i}{j} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(i, j, n, hf) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{\-EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \range{i}{j} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(i, j, n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \range{i}{j} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(i, j) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container with an unspecified number of buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \range{i}{j} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(from_range, rg, n, hf, eq) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{eq} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(from_range, rg, n, hf) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{\-EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(from_range, rg, n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(from_range, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with an unspecified number of buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end())}. +\end{itemdescr} + +\begin{itemdecl} +X(il, n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end(), n)}. +\end{itemdescr} + +\begin{itemdecl} +X(il, n, hf) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end(), n, hf)}. +\end{itemdescr} + +\begin{itemdecl} +X(il, n, hf, eq) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end(), n, hf, eq)}. +\end{itemdescr} + +\begin{itemdecl} +X(b) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +In addition to the container requirements\iref{container.requirements.general}, +copies the hash function, predicate, and maximum load factor. + +\pnum +\complexity +Average case linear in \tcode{b.size()}, worst case quadratic. +\end{itemdescr} + +\begin{itemdecl} +a = b +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&} + +\pnum +\effects +In addition to the container requirements, +copies the hash function, predicate, and maximum load factor. + +\pnum +\complexity +Average case linear in \tcode{b.size()}, worst case quadratic. +\end{itemdescr} + +\begin{itemdecl} +a = il +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&} + +\pnum +\expects +\tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X} +and \oldconcept{CopyAssignable}. + +\pnum +\effects +Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. +All existing elements of \tcode{a} are either assigned to or destroyed. + +\pnum +\complexity +Average case linear in \tcode{il.size()}, worst case quadratic. +\end{itemdescr} + +\indexunordmem{hash_function}% +\begin{itemdecl} +b.hash_function() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{hasher} + +\pnum +\returns +\tcode{b}'s hash function. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexunordmem{key_eq}% +\begin{itemdecl} +b.key_eq() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{key_equal} + +\pnum +\returns +\tcode{b}'s key equality predicate. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexunordmem{emplace}% +\begin{itemdecl} +a_uniq.emplace(args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. + +\pnum +\effects +Inserts a \tcode{value_type} object \tcode{t} +constructed with \tcode{std::forward(args)...} if and only if +there is no element in the container +with key equivalent to the key of \tcode{t}. + +\pnum +\returns +The \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion takes place, and +the iterator component of the pair points to +the element with key equivalent to the key of \tcode{t}. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.size()}}. +\end{itemdescr} + +\indexunordmem{emplace}% +\begin{itemdecl} +a_eq.emplace(args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. + +\pnum +\effects +Inserts a \tcode{value_type} object \tcode{t} +constructed with \tcode{std::forward(args)...} and + +\pnum +\returns +An iterator pointing to the newly inserted element. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.size()}}. +\end{itemdescr} + +\indexunordmem{emplace_hint}% +\begin{itemdecl} +a.emplace_hint(p, args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. + +\pnum +\effects +Equivalent to \tcode{a.emplace(std::forward(args)...)}. + +\pnum +\returns +An iterator pointing to the element +with the key equivalent to the newly inserted element. +The \tcode{const_iterator} \tcode{p} is a hint +pointing to where the search should start. +Implementations are permitted to ignore the hint. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a_uniq.insert(t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair} + +\pnum +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Inserts \tcode{t} if and only if there is no element in the container +with key equivalent to the key of \tcode{t}. + +\pnum +\returns +The \tcode{bool} component of the returned pair indicates +whether the insertion takes place, and +the \tcode{iterator} component points to +the element with key equivalent to the key of \tcode{t}. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.size()}}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a_eq.insert(t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Inserts \tcode{t}. + +\pnum +\returns +An iterator pointing to the newly inserted element. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.size()}}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a.insert(p, t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Equivalent to \tcode{a.insert(t)}. +The iterator \tcode{p} is a hint pointing to where the search should start. +Implementations are permitted to ignore the hint. + +\pnum +\returns +An iterator pointing to +the element with the key equivalent to that of \tcode{t}. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a.insert(i, j) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. +Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}. + +\pnum +\effects +Equivalent to \tcode{a.insert(t)} for each element in \tcode{[i,j)}. + +\pnum +\complexity +Average case \bigoh{N}, where $N$ is \tcode{distance(i, j)}, +worst case \bigoh{N(\tcode{a.size()} + 1)}. +\end{itemdescr} + +\indexunordmem{insert_range}% +\begin{itemdecl} +a.insert_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Equivalent to \tcode{a.insert(t)} for each element \tcode{t} in \tcode{rg}. + +\pnum +\complexity +Average case \bigoh{N}, where $N$ is \tcode{ranges::distance(rg)}, +worst case \bigoh{N(\tcode{a.size()} + 1)}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a.insert(il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a.insert(il.begin(), il.end())}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a_uniq.insert(nh) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{insert_return_type} + +\pnum +\expects +\tcode{nh} is empty or +\tcode{a_uniq.get_allocator() == nh.get_allocator()} is \tcode{true}. + +\pnum +\effects +If \tcode{nh} is empty, has no effect. +Otherwise, inserts the element owned by \tcode{nh} if and only if +there is no element in the container with a key equivalent to \tcode{nh.key()}. + +\pnum +\ensures +If \tcode{nh} is empty, \tcode{inserted} is \tcode{false}, +\tcode{position} is \tcode{end()}, and \tcode{node} is empty. +Otherwise if the insertion took place, \tcode{inserted} is \tcode{true}, +\tcode{position} points to the inserted element, and \tcode{node} is empty; +if the insertion failed, \tcode{inserted} is \tcode{false}, +\tcode{node} has the previous value of \tcode{nh}, and \tcode{position} +points to an element with a key equivalent to \tcode{nh.key()}. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.size()}}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a_eq.insert(nh) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +\tcode{nh} is empty or +\tcode{a_eq.get_allocator() == nh.get_allocator()} is \tcode{true}. + +\pnum +\effects +If \tcode{nh} is empty, has no effect and returns \tcode{a_eq.end()}. +Otherwise, inserts the element owned by \tcode{nh} and +returns an iterator pointing to the newly inserted element. + +\pnum +\ensures +\tcode{nh} is empty. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.size()}}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a.insert(q, nh) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +\tcode{nh} is empty or +\tcode{a.get_allocator() == nh.get_allocator()} is \tcode{true}. + +\pnum +\effects +If \tcode{nh} is empty, has no effect and returns \tcode{a.end()}. +Otherwise, inserts the element owned by \tcode{nh} if and only if +there is no element with key equivalent to \tcode{nh.key()} +in containers with unique keys; +always inserts the element owned by \tcode{nh} +in containers with equivalent keys. +The iterator \tcode{q} is a hint pointing to where the search should start. +Implementations are permitted to ignore the hint. + +\pnum +\ensures +\tcode{nh} is empty if insertion succeeds, unchanged if insertion fails. + +\pnum +\returns +An iterator pointing to the element with key equivalent to \tcode{nh.key()}. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} + +\indexunordmem{extract}% +\begin{itemdecl} +a.extract(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{node_type} + +\pnum +\effects +Removes an element in the container with key equivalent to \tcode{k}. + +\pnum +\returns +A \tcode{node_type} owning the element if found, +otherwise an empty \tcode{node_type}. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} + +\indexunordmem{extract}% +\begin{itemdecl} +a_tran.extract(kx) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{node_type} + +\pnum +\effects +Removes an element in the container with key equivalent to \tcode{kx}. + +\pnum +\returns +A \tcode{node_type} owning the element if found, +otherwise an empty \tcode{node_type}. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_tran.size()}}. +\end{itemdescr} + +\indexunordmem{extract}% +\begin{itemdecl} +a.extract(q) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{node_type} + +\pnum +\effects +Removes the element pointed to by \tcode{q}. + +\pnum +\returns +A \tcode{node_type} owning that element. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} + +\indexunordmem{merge}% +\begin{itemdecl} +a.merge(a2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{a.get_allocator() == a2.get_allocator()}. + +\pnum +\effects +Attempts to extract each element in \tcode{a2} and insert it into \tcode{a} +using the hash function and key equality predicate of \tcode{a}. +In containers with unique keys, if there is an element in \tcode{a} +with key equivalent to the key of an element from \tcode{a2}, +then that element is not extracted from \tcode{a2}. + +\pnum +\ensures +Pointers and references to the transferred elements of \tcode{a2} refer to +those same elements but as members of \tcode{a}. +Iterators referring to the transferred elements and +all iterators referring to \tcode{a} will be invalidated, +but iterators to elements remaining in \tcode{a2} will remain valid. + +\pnum +\complexity +Average case \bigoh{N}, where $N$ is \tcode{a2.size()}, +worst case \bigoh{N\tcode{*a.size() + N}}. +\end{itemdescr} + +\indexunordmem{erase}% +\begin{itemdecl} +a.erase(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\effects +Erases all elements with key equivalent to \tcode{k}. + +\pnum +\returns +The number of elements erased. + +\pnum +\complexity +Average case \bigoh{\tcode{a.count(k)}}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} + +\indexunordmem{erase}% +\begin{itemdecl} +a_tran.erase(kx) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\effects +Erases all elements with key equivalent to \tcode{kx}. + +\pnum +\returns +The number of elements erased. + +\pnum +\complexity +Average case \bigoh{\tcode{a_tran.count(kx)}}, +worst case \bigoh{\tcode{a_tran.size()}}. +\end{itemdescr} + +\indexunordmem{erase}% +\begin{itemdecl} +a.erase(q) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Erases the element pointed to by \tcode{q}. + +\pnum +\returns +The iterator immediately following \tcode{q} prior to the erasure. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} + +\indexunordmem{erase}% +\begin{itemdecl} +a.erase(r) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Erases the element pointed to by \tcode{r}. + +\pnum +\returns +The iterator immediately following \tcode{r} prior to the erasure. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} + +\indexunordmem{erase}% +\begin{itemdecl} +a.erase(q1, q2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Erases all elements in the range \tcode{[q1, q2)}. + +\pnum +\returns +The iterator immediately following the erased elements prior to the erasure. + +\pnum +\complexity +Average case linear in \tcode{distance(q1, q2)}, +worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} + +\indexunordmem{clear}% +\begin{itemdecl} +a.clear() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\effects +Erases all elements in the container. + +\pnum +\ensures +\tcode{a.empty()} is \tcode{true}. + +\pnum +\complexity +Linear in \tcode{a.size()}. +\end{itemdescr} + +\indexunordmem{find}% +\begin{itemdecl} +b.find(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for const \tcode{b}. + +\pnum +\returns +An iterator pointing to an element with key equivalent to \tcode{k}, or +\tcode{b.end()} if no such element exists. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{b.size()}}. +\end{itemdescr} + +\indexunordmem{find}% +\begin{itemdecl} +a_tran.find(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for const \tcode{a_tran}. + +\pnum +\returns +An iterator pointing to an element with key equivalent to \tcode{ke}, or +\tcode{a_tran.end()} if no such element exists. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_tran.size()}}. +\end{itemdescr} + +\indexunordmem{count}% +\begin{itemdecl} +b.count(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\returns +The number of elements with key equivalent to \tcode{k}. + +\pnum +\complexity +Average case \bigoh{\tcode{b.count(k)}}, worst case \bigoh{\tcode{b.size()}}. +\end{itemdescr} + +\indexunordmem{count}% +\begin{itemdecl} +a_tran.count(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\returns +The number of elements with key equivalent to \tcode{ke}. + +\pnum +\complexity +Average case \bigoh{\tcode{a_tran.count(ke)}}, +worst case \bigoh{\tcode{a_tran.size()}}. +\end{itemdescr} + +\indexunordmem{contains}% +\begin{itemdecl} +b.contains(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{b.find(k) != b.end()}. +\end{itemdescr} + +\indexunordmem{contains}% +\begin{itemdecl} +a_tran.contains(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a_tran.find(ke) != a_tran.end()}. +\end{itemdescr} + +\indexunordmem{equal_range}% +\begin{itemdecl} +b.equal_range(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair}; +\tcode{pair} for const \tcode{b}. + +\pnum +\returns +A range containing all elements with keys equivalent to \tcode{k}. +Returns \tcode{make_pair(b.end(), b.end())} if no such elements exist. + +\pnum +\complexity +Average case \bigoh{\tcode{b.count(k)}}, worst case \bigoh{\tcode{b.size()}}. +\end{itemdescr} + +\indexunordmem{equal_range}% +\begin{itemdecl} +a_tran.equal_range(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair}; +\tcode{pair} for const \tcode{a_tran}. + +\pnum +\returns +A range containing all elements with keys equivalent to \tcode{ke}. +Returns \tcode{make_pair(a_tran.end(), a_tran.end())} if no such elements exist. + +\pnum +\complexity +Average case \bigoh{\tcode{a_tran.count(ke)}}, +worst case \bigoh{\tcode{a_tran.size()}}. +\end{itemdescr} + +\indexunordmem{bucket_count}% +\begin{itemdecl} +b.bucket_count() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\returns +The number of buckets that \tcode{b} contains. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexunordmem{max_bucket_count}% +\begin{itemdecl} +b.max_bucket_count() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\returns +An upper bound on the number of buckets that \tcode{b} can ever contain. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexunordmem{bucket}% +\begin{itemdecl} +b.bucket(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\expects +\tcode{b.bucket_count() > 0}. -\indexunordmem{mapped_type}% -\tcode{X::mapped_type} (\tcode{unordered_map} and \tcode{unordered_multimap} only) & - \tcode{T} & - & - compile time \\ \rowsep +\pnum +\returns +The index of the bucket +in which elements with keys equivalent to \tcode{k} would be found, +if any such element existed. +The return value is in the range \tcode{[0, b.bucket_count())}. -\indexunordmem{value_type}% -\tcode{X::value_type} (\tcode{unordered_set} and \tcode{unordered_multiset} only) & - \tcode{Key} & - \expects \tcode{value_type} is \oldconcept{Erasable} from \tcode{X} & - compile time \\ \rowsep +\pnum +\complexity +Constant. +\end{itemdescr} -\tcode{X::value_type} (\tcode{unordered_map} and \tcode{unordered_multimap} only) & - \tcode{pair} & - \expects \tcode{value_type} is \oldconcept{Erasable} from \tcode{X} & - compile time \\ \rowsep +\indexunordmem{bucket_size}% +\begin{itemdecl} +b.bucket_size(n) +\end{itemdecl} -\indexunordmem{hasher}% -\tcode{X::hasher} -& \tcode{Hash} -& \expects \tcode{Hash} is a unary function object type such that the expression - \tcode{hf(k)} has type \tcode{size_t}.% -& compile time -\\ \rowsep -% -\indexunordmem{key_equal}% -\tcode{X::key_equal} -& \tcode{Pred} -& \expects \tcode{Pred} meets the \oldconcept{CopyConstructible} requirements.\br - \tcode{Pred} is a binary predicate that takes two arguments - of type \tcode{Key}. \tcode{Pred} is an equivalence relation.% -& compile time -\\ \rowsep -% -\indexunordmem{local_iterator}% -\tcode{X::local_iterator} -& An iterator type whose category, value type, - difference type, and pointer and reference types are the same as - \tcode{X::iterator}'s. \indextext{\idxcode{local_iterator}} -& A \tcode{local_iterator} object may be used to iterate through a - single bucket, but may not be used to iterate across - buckets.% -& compile time -\\ \rowsep -% -\indexunordmem{const_local_iterator}% -\tcode{X::const_local_iterator} -& An iterator type whose category, value type, - difference type, and pointer and reference types are the same as - \tcode{X::const_iterator}'s. \indextext{\idxcode{const_local_iterator}} -& A \tcode{const_local_iterator} object may be used to iterate through a - single bucket, but may not be used to iterate across - buckets.% -& compile time -\\ \rowsep -% -\indexunordmem{node_type}% -\tcode{X::node_type} & - a specialization of a \exposid{node-handle} - class template, such that the public nested types are - the same types as the corresponding types in \tcode{X}. & - see~\ref{container.node} & - compile time \\ \rowsep -% -\indexlibraryctor{unordered_set}% -\indexlibraryctor{unordered_map}% -\indexlibraryctor{unordered_multiset}% -\indexlibraryctor{unordered_multimap}% -\tcode{X(n, hf, eq)}\br \tcode{X a(n, hf, eq);} -& \tcode{X} -& \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hf} as the hash function and \tcode{eq} as the key -equality predicate. -& \bigoh{\tcode{n}} -\\ \rowsep -% -\tcode{X(n, hf)}\br \tcode{X a(n, hf);} -& \tcode{X} -& \expects \tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements.\br - \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hf} as the hash function and \tcode{key_equal()} as the key -equality predicate. -& \bigoh{\tcode{n}} -\\ \rowsep -% -\tcode{X(n)}\br \tcode{X a(n);} -& \tcode{X} -& \expects \tcode{hasher} and \tcode{key_equal} meet the \oldconcept{DefaultConstructible} requirements.\br - \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hasher()} as the hash function and \tcode{key_equal()} -as the key equality predicate. -& \bigoh{\tcode{n}} -\\ \rowsep -% -\tcode{X()}\br \tcode{X a;} -& \tcode{X} -& \expects \tcode{hasher} and \tcode{key_equal} meet the \oldconcept{DefaultConstructible} requirements.\br - \effects\ Constructs an empty container with an unspecified number of - buckets, using \tcode{hasher()} as the hash function and - \tcode{key_equal()} as the key equality predicate. -& constant -\\ \rowsep -% -\tcode{X(i, j, n, hf, eq)}\br \tcode{X a(i, j, n, hf, eq);} -& \tcode{X} -& \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hf} as the hash function and \tcode{eq} as the key -equality predicate, and inserts elements from \tcode{[i, j)} into it. -& Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case -\bigoh{N^2} -\\ \rowsep -% -\tcode{X(i, j, n, hf)}\br \tcode{X a(i, j, n, hf);} -& \tcode{X} -& \expects \tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements. - \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hf} as the hash function and \tcode{key_equal()} as the key -equality predicate, and inserts elements from \tcode{[i, j)} into it. -& Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case -\bigoh{N^2} -\\ \rowsep -% -\tcode{X(i, j, n)}\br \tcode{X a(i, j, n);} -& \tcode{X} -& \expects \tcode{hasher} and \tcode{key_equal} meet the \oldconcept{DefaultConstructible} requirements. - \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hasher()} as the hash function and \tcode{key_equal()} -as the key equality predicate, and inserts elements from \tcode{[i, j)} -into it. -& Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case -\bigoh{N^2} -\\ \rowsep -% -\tcode{X(i, j)}\br \tcode{X a(i, j);} -& \tcode{X} -& \expects \tcode{hasher} and \tcode{key_equal} meet the \oldconcept{DefaultConstructible} requirements. - \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Constructs an empty container with an unspecified number of -buckets, using \tcode{hasher()} as the hash function and -\tcode{key_equal()} as the key equality predicate, and inserts elements -from \tcode{[i, j)} into it. -& Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case -\bigoh{N^2} -\\ \rowsep -% -\tcode{X(il)} -& \tcode{X} -& Same as \tcode{X(il.begin(), il.end())}. -& Same as \tcode{X(il.begin(),} \tcode{il.end())}. -\\ \rowsep -% -\tcode{X(il, n)} -& \tcode{X} -& Same as \tcode{X(il.begin(), il.end(), n)}. -& Same as \tcode{X(il.begin(),} \tcode{il.end(), n)}. -\\ \rowsep -% -\tcode{X(il, n, hf)} -& \tcode{X} -& Same as \tcode{X(il.begin(), il.end(), n, hf)}. -& Same as \tcode{X(il.begin(),} \tcode{il.end(), n, hf)}. -\\ \rowsep -% -\tcode{X(il, n, hf, eq)} -& \tcode{X} -& Same as \tcode{X(il.begin(), il.end(), n, hf, eq)}. -& Same as \tcode{X(il.begin(),} \tcode{il.end(), n, hf, eq)}. -\\ \rowsep -% -\tcode{X(b)}\br \tcode{X a(b);} -& \tcode{X} -& Copy constructor. In addition to the requirements - of \tref{container.req}, copies the - hash function, predicate, and maximum load factor. -& Average case linear in \tcode{b.size()}, worst case quadratic. -\\ \rowsep -% -\tcode{a = b} -& \tcode{X\&} -& Copy assignment operator. In addition to the - requirements of \tref{container.req}, copies - the hash function, predicate, and maximum load factor. -& Average case linear in \tcode{b.size()}, worst case quadratic. -\\ \rowsep -% -\tcode{a = il} -& \tcode{X\&} -& \expects \tcode{value_type} is -\oldconcept{CopyInsertable} into \tcode{X} -and \oldconcept{CopyAssignable}.\br - \effects\ Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. All - existing elements of \tcode{a} are either assigned to or destroyed. -& Same as \tcode{a = X(il)}. -\\ \rowsep -% -\indexunordmem{hash_function}% -\tcode{b.hash_function()} -& \tcode{hasher} -& \returns \tcode{b}'s hash function.% -& constant -\\ \rowsep -% -\indexunordmem{key_eq}% -\tcode{b.key_eq()} -& \tcode{key_equal} -& \returns \tcode{b}'s key equality predicate.% -& constant -\\ \rowsep -% +\begin{itemdescr} +\pnum +\result +\tcode{size_type} -\indexunordmem{emplace}% -\tcode{a_uniq.} \tcode{emplace(args)} & - \tcode{pair} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \effects\ Inserts a \tcode{value_type} object \tcode{t} constructed with - \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...} if and only if there is no - element in the container with key equivalent to the key of \tcode{t}. - The \tcode{bool} component of the returned - pair is \tcode{true} if and only if the insertion takes place, and the iterator - component of the pair points to the element with key equivalent to the - key of \tcode{t}. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.}\br\tcode{size()}}. -\\ \rowsep - -\tcode{a_eq.}\tcode{emplace(args)} & - \tcode{iterator} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \effects\ Inserts a \tcode{value_type} object \tcode{t} constructed with - \tcode{std::forward<\brk{}Args>(\brk{}args)...} and returns the iterator pointing - to the newly inserted element. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.}\br\tcode{size()}}. -\\ \rowsep +\pnum +\expects +\tcode{n} shall be in the range \tcode{[0, b.bucket_count())}. -\indexunordmem{emplace_hint}% -\tcode{a.emplace_hint(p, args)} & - \tcode{iterator} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \effects\ Equivalent to \tcode{a.emplace(} \tcode{std::forward<\brk{}Args>(\brk{}args)...)}. - Return value is an iterator pointing to the element with the key equivalent - to the newly inserted element. The \tcode{const_iterator} \tcode{p} - is a hint pointing to where the search should start. Implementations are - permitted to ignore the hint. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a.} \tcode{size()}}. -\\ \rowsep +\pnum +\returns +The number of elements in the $\tcode{n}^\text{th}$ bucket. + +\pnum +\complexity +\bigoh{\tcode{b.bucket_size(n)}} +\end{itemdescr} -\indexunordmem{insert}% -\tcode{a_uniq.insert(t)} -& \tcode{pair} -& \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects\ Inserts \tcode{t} if and only if there is no element in the container - with key equivalent to the key of \tcode{t}. The \tcode{bool} - component of the returned pair indicates whether the insertion - takes place, and the \tcode{iterator} component points to the element - with key equivalent to the key of \tcode{t}.% -& Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.}\br\tcode{size()}}. -\\ \rowsep -% -\tcode{a_eq.insert(t)} -& \tcode{iterator} -& \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects\ Inserts \tcode{t}, and returns an iterator pointing to the newly - inserted element. -& Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.}\br\tcode{size()}}. -\\ \rowsep -% -\tcode{a.insert(p, t)} -& \tcode{iterator} -& \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects Equivalent to \tcode{a.insert(t)}. Return value is an iterator pointing -to the element with the key equivalent to that of \tcode{t}. The -iterator \tcode{p} is a hint pointing to where the search should -start. Implementations are permitted to ignore the hint.% -& Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. -\\ \rowsep -% -\tcode{a.insert(i, j)} -& \keyword{void} -& \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. - Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.\br - \effects Equivalent to \tcode{a.insert(t)} for each element in \tcode{[i,j)}.% -& Average case \bigoh{N}, where $N$ is \tcode{distance(i, j)}, - worst case \bigoh{N(\tcode{a.size()}\brk{}+\brk{}1)}. -\\ \rowsep -% -\tcode{a.insert(il)} -& \keyword{void} -& Same as \tcode{a.insert(il.begin(), il.end())}. -& Same as \tcode{a.insert(} \tcode{il.begin(),} \tcode{il.end())}. -\\ \rowsep -% -\tcode{a_uniq.}\br - \tcode{insert(nh)} & - \tcode{insert_return_type} & - \expects \tcode{nh} is empty or - \tcode{a_uniq.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect. Otherwise, inserts the - element owned by \tcode{nh} if and only if there is no element in the - container with a key equivalent to \tcode{nh.key()}.\br - \ensures If \tcode{nh} is empty, \tcode{inserted} is \tcode{false}, - \tcode{position} is \tcode{end()}, and \tcode{node} is empty. - Otherwise if the insertion took place, \tcode{inserted} is \tcode{true}, - \tcode{position} points to the inserted element, and \tcode{node} is empty; - if the insertion failed, \tcode{inserted} is \tcode{false}, - \tcode{node} has the previous value of \tcode{nh}, and \tcode{position} - points to an element with a key equivalent to \tcode{nh.key()}. & - Average case \bigoh{1}, worst case \bigoh{\brk{}\tcode{a_uniq.}\brk{}\tcode{size()}}. \\ \rowsep -% -\tcode{a_eq.}\br - \tcode{insert(nh)} & - \tcode{iterator} & - \expects \tcode{nh} is empty or - \tcode{a_eq.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect and returns \tcode{a_eq.end()}. - Otherwise, inserts the element owned by \tcode{nh} and returns an iterator - pointing to the newly inserted element.\br - \ensures \tcode{nh} is empty. & - Average case \bigoh{1}, worst case \bigoh{\brk{}\tcode{a_eq.}\brk{}\tcode{size()}}. \\ \rowsep -% -\tcode{a.insert(q, nh)} & - \tcode{iterator} & - \expects \tcode{nh} is empty or - \tcode{a.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect and returns \tcode{a.end()}. - Otherwise, inserts the element owned by \tcode{nh} if and only if there - is no element with key equivalent to \tcode{nh.key()} in containers with - unique keys; always inserts the element owned by \tcode{nh} in containers - with equivalent keys. Always returns the iterator pointing to the element - with key equivalent to \tcode{nh.key()}. The iterator \tcode{q} is a hint - pointing to where the search should start. Implementations are permitted - to ignore the hint.\br - \ensures \tcode{nh} is empty if insertion succeeds, unchanged if insertion fails. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. \\ \rowsep -% -\indexunordmem{extract}% -\tcode{a.extract(k)} & - \tcode{node_type} & - \effects Removes an element in the container with key equivalent to \tcode{k}.\br - \returns A \tcode{node_type} owning the element if found, otherwise an empty - \tcode{node_type}. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. \\ \rowsep -% -\tcode{a_tran.\brk{}extract(kx)} & - \tcode{node_type} & - \effects Removes an element in the container with key equivalent to \tcode{kx}.\br - \returns A \tcode{node_type} owning the element if found, - otherwise an empty \tcode{node_type}. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. \\ \rowsep -% -\tcode{a.extract(q)} & - \tcode{node_type} & - \effects Removes the element pointed to by \tcode{q}.\br - \returns A \tcode{node_type} owning that element. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. \\ \rowsep -% -\indexunordmem{merge}% -\tcode{a.merge(a2)} & - \keyword{void} & - \expects \tcode{a.get_allocator() == a2.get_allocator()}.\br - Attempts to extract each element in \tcode{a2} and insert it into \tcode{a} - using the hash function and key equality predicate of \tcode{a}. - In containers with unique keys, if there is an element in \tcode{a} with - key equivalent to the key of an element from \tcode{a2}, then that - element is not extracted from \tcode{a2}.\par - \ensures Pointers and references to the transferred elements of \tcode{a2} - refer to those same elements but as members of \tcode{a}. Iterators referring - to the transferred elements and all iterators referring to \tcode{a} will - be invalidated, but iterators to elements remaining in \tcode{a2} will - remain valid. & - Average case \bigoh{N}, where $N$ is \tcode{a2.size()}, - worst case \bigoh{N\tcode{*a.size()}\br\tcode{+} N}. \\ \rowsep -% -\indexunordmem{erase}% -\tcode{a.erase(k)} -& \tcode{size_type} -& \effects Erases all elements with key equivalent to \tcode{k}.\br - \returns The number of elements erased. -& Average case \bigoh{\tcode{a.count(k)}}, worst case - \bigoh{\tcode{a.size()}}. -\\ \rowsep -% -\tcode{a_tran.\brk{}erase(kx)} -& \tcode{size_type} -& \effects Erases all elements with key equivalent to \tcode{kx}.\br - \returns The number of elements erased. -& Average case \bigoh{\tcode{a_tran.}\br{}\tcode{count(kx)}}, worst case - \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. -\\ \rowsep -% -\tcode{a.erase(q)} -& \tcode{iterator} -& \effects Erases the element pointed to by \tcode{q}.\br - \returns The iterator immediately following \tcode{q} prior to the erasure. -& Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. -\\ \rowsep -% -\tcode{a.erase(r)} -& \tcode{iterator} -& \effects Erases the element pointed to by \tcode{r}.\br - \returns The iterator immediately following \tcode{r} prior to the erasure. -& Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. -\\ \rowsep -% -\tcode{a.erase(q1, q2)} -& \tcode{iterator} -& \effects Erases all elements in the range \tcode{[q1, q2)}.\br - \returns The iterator immediately following the erased elements prior to the - erasure. -& Average case linear in \tcode{distance(q1, q2)}, - worst case \bigoh{\tcode{a.size()}}. -\\ \rowsep -% -\indexunordmem{clear}% -\tcode{a.clear()} -& \keyword{void} -& \effects Erases all elements in the container.\br - \ensures \tcode{a.empty()} is \tcode{true}% -& Linear in \tcode{a.size()}. -\\ \rowsep -% -\indexunordmem{find}% -\tcode{b.find(k)} -& \tcode{iterator}; \br \tcode{const_iterator} for const \tcode{b}. -& \returns An iterator pointing to an element with key equivalent to - \tcode{k}, or \tcode{b.end()} if no such element exists. -& Average case \bigoh{1}, worst case \bigoh{\tcode{b.size()}}. -\\ \rowsep -% -\tcode{a_tran.find(ke)} -& \tcode{iterator}; \br \tcode{const_iterator} for const \tcode{a_tran}. -& \returns An iterator pointing to an element with key equivalent to - \tcode{ke}, or \tcode{a_tran.end()} if no such element exists. -& Average case \bigoh{1}, - worst case \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. % avoid overfull -\\ \rowsep -% -\indexunordmem{count}% -\tcode{b.count(k)} -& \tcode{size_type} -& \returns The number of elements with key equivalent to \tcode{k}.% -& Average case \bigoh{\tcode{b.count(k)}}, worst case \bigoh{\tcode{b.size()}}. -\\ \rowsep -% -\tcode{a_tran.count(ke)} -& \tcode{size_type} -& \returns The number of elements with key equivalent to \tcode{ke}.% -& Average case - \bigoh{\tcode{a_tran.}\br{}\tcode{count(ke)}}, % avoid overfull - worst case \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. % avoid overfull -\\ \rowsep -% -\indexunordmem{contains}% -\tcode{b.contains(k)} -& \tcode{bool} -& \effects Equivalent to \tcode{b.find(k) != b.end()}% -& Average case \bigoh{1}, worst case \bigoh{\tcode{b.size()}}. -\\ \rowsep -% -\tcode{a_tran.contains(ke)} -& \tcode{bool} -& \effects Equivalent to \tcode{a_tran.find(ke) != a_tran.end()}% -& Average case \bigoh{1}, - worst case \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. % avoid overfull -\\ \rowsep -% -\indexunordmem{equal_range}% -\tcode{b.equal_range(k)} -& \tcode{pair}; \br - \tcode{pair} for const \tcode{b}. -& \returns A range containing all elements with keys equivalent to - \tcode{k}. Returns \tcode{make_pair(b.end(), b.end())} if - no such elements exist.% -& Average case \bigoh{\tcode{b.count(k)}}, worst case - \bigoh{\tcode{b.size()}}. -\\ \rowsep -% -\tcode{a_tran.equal_range(ke)} -& \tcode{pair}; \br - \tcode{pair} for const \tcode{a_tran}. -& \returns A range containing all elements with keys equivalent to - \tcode{ke}. Returns \tcode{make_pair(a_tran.end(), a_tran.end())} if - no such elements exist.% -& Average case - \bigoh{\tcode{a_tran.}\br{}\tcode{count(ke)}}, % avoid overfull - worst case \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. % avoid overfull -\\ \rowsep -% -\indexunordmem{bucket_count}% -\tcode{b.bucket_count()} -& \tcode{size_type} -& \returns The number of buckets that \tcode{b} contains.% -& Constant -\\ \rowsep -% -\indexunordmem{max_bucket_count}% -\tcode{b.max_bucket_count()} -& \tcode{size_type} -& \returns An upper bound on the number of buckets that \tcode{b} can - ever contain.% -& Constant -\\ \rowsep -% -\indexunordmem{bucket}% -\tcode{b.bucket(k)} -& \tcode{size_type} -& - \expects \tcode{b.bucket_count() > 0}.\br - \returns The index of the bucket in which elements with keys equivalent - to \tcode{k} would be found, if any such element existed.\br - \ensures The return value is in the range \tcode{[0, b.bucket_count())}.% -& Constant -\\ \rowsep -% -\indexunordmem{bucket_size}% -\tcode{b.bucket_size(n)} -& \tcode{size_type} -& \expects \tcode{n} shall be in the range \tcode{[0, b.bucket_count())}. - \returns The number of elements in the $\tcode{n}^\text{th}$ bucket.% -& \bigoh{\tcode{b.bucket_}\-\tcode{size(n)}} -\\ \rowsep -% \indexunordmem{begin}% -\tcode{b.begin(n)} -& \tcode{local_iterator}; \br - \tcode{const_local_iterator} for const \tcode{b}. -& \expects \tcode{n} is in the range \tcode{[0, b.bucket_count())}.\br - \returns An iterator referring to the - first element in the bucket. If the bucket is empty, then - \tcode{b.begin(n) == b.end(n)}.% -& Constant -\\ \rowsep -% +\begin{itemdecl} +b.begin(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{local_iterator}; \tcode{const_local_iterator} for const \tcode{b}. + +\pnum +\expects +\tcode{n} is in the range \tcode{[0, b.bucket_count())}. + +\pnum +\returns +An iterator referring to the first element in the bucket. +If the bucket is empty, then \tcode{b.begin(n) == b.end(n)}. + +\pnum +\complexity +Constant. +\end{itemdescr} + \indexunordmem{end}% -\tcode{b.end(n)} -& \tcode{local_iterator}; \br - \tcode{const_local_iterator} for const \tcode{b}. -& \expects \tcode{n} is in the range \tcode{[0, b.bucket_count())}.\br - \returns An iterator which is the past-the-end - value for the bucket.% -& Constant -\\ \rowsep -% +\begin{itemdecl} +b.end(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{local_iterator}; \tcode{const_local_iterator} for const \tcode{b}. + +\pnum +\expects +\tcode{n} is in the range \tcode{[0, b.bucket_count())}. + +\pnum +\returns +An iterator which is the past-the-end value for the bucket. + +\pnum +\complexity +Constant. +\end{itemdescr} + \indexunordmem{cbegin}% -\tcode{b.cbegin(n)} -& \tcode{const_local_iterator} -& \expects \tcode{n} shall be in the range \tcode{[0, b.bucket_count())}.\br - \returns An iterator referring to the - first element in the bucket. If the bucket is empty, then - \tcode{b.cbegin(n) == b.cend(n)}.% -& Constant -\\ \rowsep -% +\begin{itemdecl} +b.cbegin(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{const_local_iterator} + +\pnum +\expects +\tcode{n} shall be in the range \tcode{[0, b.bucket_count())}. + +\pnum +\returns +An iterator referring to the first element in the bucket. +If the bucket is empty, then \tcode{b.cbegin(n) == b.cend(n)}. + +\pnum +\complexity +Constant. +\end{itemdescr} + \indexunordmem{cend}% -\tcode{b.cend(n)} -& \tcode{const_local_iterator} -& \expects \tcode{n} is in the range \tcode{[0, b.bucket_count())}.\br - \returns An iterator which is the past-the-end - value for the bucket.% -& Constant -\\ \rowsep -% +\begin{itemdecl} +b.cend(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{const_local_iterator} + +\pnum +\expects +\tcode{n} is in the range \tcode{[0, b.bucket_count())}. + +\pnum +\returns +An iterator which is the past-the-end value for the bucket. + +\pnum +\complexity +Constant. +\end{itemdescr} + \indexunordmem{load_factor}% -\tcode{b.load_factor()} -& \tcode{float} -& \returns The average number of elements per bucket.% -& Constant -\\ \rowsep -% +\begin{itemdecl} +b.load_factor() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{float} + +\pnum +\returns +The average number of elements per bucket. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexunordmem{max_load_factor}% +\begin{itemdecl} +b.max_load_factor() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{float} + +\pnum +\returns +A positive number +that the container attempts to keep the load factor less than or equal to. +The container automatically increases the number of buckets as necessary +to keep the load factor below this number. + +\pnum +\complexity +Constant. +\end{itemdescr} + \indexunordmem{max_load_factor}% -\tcode{b.max_load_factor()} -& \tcode{float} -& \returns A positive number that the container attempts to keep the load factor - less than or equal to. The container automatically increases the - number of buckets as necessary to keep the load factor below this - number.% -& Constant -\\ \rowsep -% -\tcode{a.max_load_factor(z)} -& \keyword{void} -& \expects \tcode{z} is positive. - May change the container's maximum load factor, using \tcode{z} as a hint.% -& Constant -\\ \rowsep -% +\begin{itemdecl} +a.max_load_factor(z) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{z} is positive. +May change the container's maximum load factor, using \tcode{z} as a hint. + +\pnum +\complexity +Constant. +\end{itemdescr} + \indexunordmem{rehash}% -\tcode{a.rehash(n)} -& \keyword{void} -& \ensures \tcode{a.bucket_count() >= a.size() / a.max_load_factor()} and - \tcode{a.bucket_count() >= n}.% -& Average case linear in \tcode{a.size()}, worst case quadratic. -\\ \rowsep +\begin{itemdecl} +a.rehash(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\ensures +\tcode{a.bucket_count() >= a.size() / a.max_load_factor()} and +\tcode{a.bucket_count() >= n}.% + +\pnum +\complexity +Average case linear in \tcode{a.size()}, worst case quadratic. +\end{itemdescr} \indexunordmem{reserve}% -\tcode{a.reserve(n)} & - \keyword{void} & - Same as \tcode{a.rehash(ceil(n /} \tcode{a.max_load_factor()))}. & - Average case linear in \tcode{a.size()}, worst case quadratic. \\ +\begin{itemdecl} +a.reserve(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a.rehash(ceil(n / a.max_load_factor()))}. +\end{itemdescr} -\end{libreqtab4d} \pnum Two unordered containers \tcode{a} and \tcode{b} compare equal if \tcode{a.size() == b.size()} and, for every equivalent-key group @@ -3156,7 +5798,8 @@ \pnum \indextext{unordered associative containers!iterator invalidation}% -The \tcode{insert} and \tcode{emplace} members shall not affect the validity of references to +The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members +shall not affect the validity of references to container elements, but may invalidate all iterators to the container. The \tcode{erase} members shall invalidate only iterators and references to the erased elements, and preserve the relative order of the @@ -3165,7 +5808,8 @@ \pnum \indextext{unordered associative containers!iterator invalidation}% \indextext{unordered associative containers!requirements}% -The \tcode{insert} and \tcode{emplace} members shall not affect the validity of iterators if +The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members +shall not affect the validity of iterators if \tcode{(N+n) <= z * B}, where \tcode{N} is the number of elements in the container prior to the insert operation, \tcode{n} is the number of elements inserted, \tcode{B} is the container's bucket count, and @@ -3475,10 +6119,12 @@ \pnum \indextext{requirements!container}% -An \tcode{array} meets all of the requirements of a container and -of a reversible container\iref{container.requirements}, except that a default -constructed \tcode{array} object is not empty and that \tcode{swap} does not have constant -complexity. An \tcode{array} meets some of the requirements of a sequence +An \tcode{array} meets all of the requirements +of a container\iref{container.reqmts} and +of a reversible container\iref{container.rev.reqmts}, +except that a default +constructed \tcode{array} object is not empty if $\tcode{N} > 0$. +An \tcode{array} meets some of the requirements of a sequence container\iref{sequence.reqmts}. Descriptions are provided here only for operations on \tcode{array} that are not described in @@ -3571,7 +6217,7 @@ \indextext{requirements!container}% The conditions for an aggregate\iref{dcl.init.aggr} shall be met. Class \tcode{array} relies on the implicitly-declared special -member functions~(\ref{class.default.ctor}, \ref{class.dtor}, and \ref{class.copy.ctor}) to +member functions\iref{class.default.ctor,class.dtor,class.copy.ctor} to conform to the container requirements table in~\ref{container.requirements}. In addition to the requirements specified in the container requirements table, the implicit move constructor and move assignment operator for \tcode{array} @@ -3790,11 +6436,12 @@ Storage management is handled automatically. \pnum -A -\tcode{deque} -meets all of the requirements of a container, of a reversible container -(given in tables in~\ref{container.requirements}), of a sequence container, -including the optional sequence container requirements\iref{sequence.reqmts}, and of an allocator-aware container (\tref{container.alloc.req}). +A \tcode{deque} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of a sequence container, +including the optional sequence container requirements\iref{sequence.reqmts}. Descriptions are provided here only for operations on \tcode{deque} that are not described in one of these tables @@ -3826,6 +6473,8 @@ deque(size_type n, const T& value, const Allocator& = Allocator()); template deque(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + deque(from_range_t, R&& rg, const Allocator& = Allocator()); deque(const deque& x); deque(deque&&); deque(const deque&, const type_identity_t&); @@ -3839,6 +6488,8 @@ deque& operator=(initializer_list); template void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list); allocator_type get_allocator() const noexcept; @@ -3883,14 +6534,20 @@ void push_front(const T& x); void push_front(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); iterator insert(const_iterator position, const T& x); iterator insert(const_iterator position, T&& x); iterator insert(const_iterator position, size_type n, const T& x); template iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list); void pop_front(); @@ -3906,6 +6563,10 @@ template>> deque(InputIterator, InputIterator, Allocator = Allocator()) -> deque<@\placeholder{iter-value-type}@, Allocator>; + + template>> + deque(from_range_t, R&&, Allocator = Allocator()) + -> deque, Allocator>; } \end{codeblock} @@ -3990,6 +6651,23 @@ Linear in \tcode{distance(first, last)}. \end{itemdescr} +\indexlibraryctor{deque}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + deque(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{deque} with the elements of the range \tcode{rg}, +using the specified allocator. + +\pnum +\complexity +Linear in \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[deque.capacity]{Capacity} \indexlibrarymember{resize}{deque}% @@ -4076,6 +6754,8 @@ template iterator insert(const_iterator position, InputIterator first, InputIterator last); +template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list); template reference emplace_front(Args&&... args); @@ -4083,8 +6763,12 @@ template iterator emplace(const_iterator position, Args&&... args); void push_front(const T& x); void push_front(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -4206,14 +6890,15 @@ \end{note} \pnum -A \tcode{forward_list} meets all of the requirements of a container -(\tref{container.req}), except that the \tcode{size()} -member function is not provided and \tcode{operator==} has linear complexity. -A \tcode{forward_list} also meets all of the requirements for an allocator-aware -container (\tref{container.alloc.req}). In addition, a \tcode{forward_list} -provides the \tcode{assign} member functions -(\tref{container.seq.req}) and several of the optional -container requirements (\tref{container.seq.opt}). +A \tcode{forward_list} meets all of the requirements +of a container\iref{container.reqmts}, +except that the \tcode{size()} member function is not provided and +\tcode{operator==} has linear complexity, +A \tcode{forward_list} also meets all of the requirements +for an allocator-aware container\iref{container.alloc.reqmts}. +In addition, a \tcode{forward_list} +provides the \tcode{assign} member functions and +several of the optional sequence container requirements\iref{sequence.reqmts}. Descriptions are provided here only for operations on \tcode{forward_list} that are not described in that table or for operations where there is additional semantic information. @@ -4251,6 +6936,8 @@ forward_list(size_type n, const T& value, const Allocator& = Allocator()); template forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); forward_list(const forward_list& x); forward_list(forward_list&& x); forward_list(const forward_list& x, const type_identity_t&); @@ -4263,6 +6950,8 @@ forward_list& operator=(initializer_list); template void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list); allocator_type get_allocator() const noexcept; @@ -4291,6 +6980,8 @@ template reference emplace_front(Args&&... args); void push_front(const T& x); void push_front(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void pop_front(); template iterator emplace_after(const_iterator position, Args&&... args); @@ -4301,6 +6992,8 @@ template iterator insert_after(const_iterator position, InputIterator first, InputIterator last); iterator insert_after(const_iterator position, initializer_list il); + template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range_after(const_iterator position, R&& rg); iterator erase_after(const_iterator position); iterator erase_after(const_iterator position, const_iterator last); @@ -4341,6 +7034,10 @@ template>> forward_list(InputIterator, InputIterator, Allocator = Allocator()) -> forward_list<@\placeholder{iter-value-type}@, Allocator>; + + template>> + forward_list(from_range_t, R&&, Allocator = Allocator()) + -> forward_list, Allocator>; } \end{codeblock} @@ -4423,6 +7120,23 @@ Linear in \tcode{distance(first, last)}. \end{itemdescr} +\indexlibraryctor{forward_list}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{forward_list} object +with the elements of the range \tcode{rg}. + +\pnum +\complexity +Linear in \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[forward.list.iter]{Iterators} \indexlibrarymember{before_begin}{forward_list}% @@ -4499,6 +7213,20 @@ Inserts a copy of \tcode{x} at the beginning of the list. \end{itemdescr} +\indexlibrarymember{prepend_range}{forward_list}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Inserts a copy of each element of \tcode{rg} at the beginning of the list. +\begin{note} +The order of elements is not reversed. +\end{note} +\end{itemdescr} \indexlibrarymember{pop}{forward_list}% \begin{itemdecl} @@ -4574,6 +7302,29 @@ An iterator pointing to the last inserted element or \tcode{position} if \tcode{first == last}. \end{itemdescr} +\indexlibrarymember{insert_range_after}{forward_list}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range_after(const_iterator position, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{position} is \tcode{before_begin()} or +is a dereferenceable iterator in the range \range{begin()}{end()}. +\tcode{rg} and \tcode{*this} do not overlap. + +\pnum +\effects +Inserts copies of elements in the range \tcode{rg} after \tcode{position}. + +\pnum +\returns +An iterator pointing to the last inserted element, +or \tcode{position} if \tcode{rg} is empty. +\end{itemdescr} + \indexlibrarymember{insert_after}{forward_list}% \begin{itemdecl} iterator insert_after(const_iterator position, initializer_list il); @@ -4898,18 +7649,22 @@ \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{comp} be \tcode{less<>{}} for the first two overloads. + \pnum \expects -\tcode{*this} and \tcode{x} are both sorted with respect to -the comparator \tcode{operator<} (for the first two overloads) or -\tcode{comp} (for the last two overloads), and +\tcode{*this} and \tcode{x} are both sorted +with respect to the comparator \tcode{comp}, and \tcode{get_allocator() == x.get_allocator()} is \tcode{true}. \pnum \effects -Merges the two sorted ranges \tcode{[begin(), end())} and -\tcode{[x.begin(), x.end())}. \tcode{x} is empty after the merge. If an -exception is thrown other than by a comparison there are no effects. +If \tcode{addressof(x) == this}, there are no effects. +Otherwise, merges +the two sorted ranges \range{begin()}{end()} and \range{x.begin()}{x.end()}. +The result is a range +that is sorted with respect to the comparator \tcode{comp}. Pointers and references to the moved elements of \tcode{x} now refer to those same elements but as members of \tcode{*this}. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into \tcode{*this}, not into @@ -4918,11 +7673,15 @@ \pnum \complexity At most \tcode{distance(begin(), -end()) + distance(x.begin(), x.end()) - 1} comparisons. +end()) + distance(x.begin(), x.end()) - 1} comparisons +if \tcode{addressof(x) != this}; otherwise, no comparisons are performed. \pnum \remarks Stable\iref{algorithm.stable}. +If \tcode{addressof(x) != this}, \tcode{x} is empty after the merge. +No elements are copied by this operation. +If an exception is thrown other than by a comparison, there are no effects. \end{itemdescr} \indexlibrarymember{sort}{forward_list}% @@ -5007,12 +7766,13 @@ algorithms only need sequential access anyway. \pnum -A \tcode{list} meets all of the requirements of a container, of -a reversible container (given in two tables in -\ref{container.requirements}), of a sequence container, +A \tcode{list} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of a sequence container, including most of the optional sequence container -requirements\iref{sequence.reqmts}, and of an allocator-aware container -(\tref{container.alloc.req}). +requirements\iref{sequence.reqmts}. The exceptions are the \tcode{operator[]} and @@ -5054,6 +7814,8 @@ list(size_type n, const T& value, const Allocator& = Allocator()); template list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + list(from_range_t, R&& rg, const Allocator& = Allocator()); list(const list& x); list(list&& x); list(const list&, const type_identity_t&); @@ -5066,6 +7828,8 @@ list& operator=(initializer_list); template void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list); allocator_type get_allocator() const noexcept; @@ -5103,9 +7867,13 @@ template reference emplace_back(Args&&... args); void push_front(const T& x); void push_front(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void pop_front(); void push_back(const T& x); void push_back(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); void pop_back(); template iterator emplace(const_iterator position, Args&&... args); @@ -5114,6 +7882,8 @@ iterator insert(const_iterator position, size_type n, const T& x); template iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list il); iterator erase(const_iterator position); @@ -5150,6 +7920,10 @@ template>> list(InputIterator, InputIterator, Allocator = Allocator()) -> list<@\placeholder{iter-value-type}@, Allocator>; + + template>> + list(from_range_t, R&&, Allocator = Allocator()) + -> list, Allocator>; } \end{codeblock} @@ -5221,27 +7995,43 @@ \pnum \complexity Linear in -\tcode{n}. +\tcode{n}. +\end{itemdescr} + +\indexlibraryctor{list}% +\begin{itemdecl} +template + list(InputIterator first, InputIterator last, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a +\tcode{list} +equal to the range +\range{first}{last}. + +\pnum +\complexity +Linear in +\tcode{distance(first, last)}. \end{itemdescr} \indexlibraryctor{list}% \begin{itemdecl} -template - list(InputIterator first, InputIterator last, const Allocator& = Allocator()); +template<@\exposconcept{container-compatible-range}@ R> + list(from_range_t, R&& rg, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs a -\tcode{list} -equal to the range -\range{first}{last}. +Constructs a \tcode{list} object with the elements of the range \tcode{rg}. \pnum \complexity -Linear in -\tcode{distance(first, last)}. +Linear in \tcode{ranges::distance(rg)}. \end{itemdescr} \rSec3[list.capacity]{Capacity} @@ -5306,6 +8096,8 @@ template iterator insert(const_iterator position, InputIterator first, InputIterator last); +template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list); template reference emplace_front(Args&&... args); @@ -5313,8 +8105,12 @@ template iterator emplace(const_iterator position, Args&&... args); void push_front(const T& x); void push_front(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -5598,21 +8394,22 @@ \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{comp} be \tcode{less<>{}} for the first two overloads. + \pnum \expects -Both the list and the argument list -shall be sorted with respect to -the comparator \tcode{operator<} (for the first two overloads) or -\tcode{comp} (for the last two overloads), and +\tcode{*this} and \tcode{x} are both sorted +with respect to the comparator \tcode{comp}, and \tcode{get_allocator() == x.get_allocator()} is \tcode{true}. \pnum \effects -If \tcode{addressof(x) == this}, does nothing; otherwise, merges the two sorted ranges \tcode{[begin(), -end())} and \tcode{[x.\brk{}begin(), x.end())}. The result is a range in which the elements -will be sorted in non-decreasing order according to the ordering defined by \tcode{comp}; that -is, for every iterator \tcode{i}, in the range other than the first, the condition -\tcode{comp(*i, *(i - 1))} will be \tcode{false}. +If \tcode{addressof(x) == this}, there are no effects. +Otherwise, merges +the two sorted ranges \range{begin()}{end()} and \range{x.begin()}{x.end()}. +The result is a range +that is sorted with respect to the comparator \tcode{comp}. Pointers and references to the moved elements of \tcode{x} now refer to those same elements but as members of \tcode{*this}. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into \tcode{*this}, not into @@ -5620,18 +8417,16 @@ \pnum \complexity -At most -\tcode{size() + x.size() - 1} -applications of \tcode{comp} if -\tcode{addressof(x) != this}; -otherwise, no applications of \tcode{comp} are performed. -If an exception is thrown other than by a comparison there are no effects. +At most \tcode{size() + x.size() - 1} comparisons +if \tcode{addressof(x) != this}; +otherwise, no comparisons are performed. \pnum \remarks -Stable\iref{algorithm.stable}. If \tcode{addressof(x) != this}, the range \tcode{[x.begin(), x.end())} -is empty after the merge. +Stable\iref{algorithm.stable}. +If \tcode{addressof(x) != this}, \tcode{x} is empty after the merge. No elements are copied by this operation. +If an exception is thrown other than by a comparison there are no effects. \end{itemdescr} \indexlibrarymember{reverse}{list}% @@ -5719,15 +8514,16 @@ to improve efficiency. \pnum -A \tcode{vector} meets all of the requirements of a container and of a -reversible container (given in two tables in~\ref{container.requirements}), of a -sequence container, including most of the optional sequence container -requirements\iref{sequence.reqmts}, of an allocator-aware container -(\tref{container.alloc.req}), +A \tcode{vector} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, +of a sequence container, including most of the optional sequence container +requirements\iref{sequence.reqmts}, and, for an element type other than \tcode{bool}, of a contiguous container\iref{container.requirements.general}. The exceptions are the -\tcode{push_front}, \tcode{pop_front}, and \tcode{emplace_front} member functions, which are not +\tcode{push_front}, \tcode{prepend_range}, \tcode{pop_front}, and \tcode{emplace_front} member functions, which are not provided. Descriptions are provided here only for operations on \tcode{vector} that are not described in one of these tables or for operations where there is additional semantic information. @@ -5762,6 +8558,8 @@ constexpr vector(size_type n, const T& value, const Allocator& = Allocator()); template constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); constexpr vector(const vector& x); constexpr vector(vector&&) noexcept; constexpr vector(const vector&, const type_identity_t&); @@ -5775,6 +8573,8 @@ constexpr vector& operator=(initializer_list); template constexpr void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void assign_range(R&& rg); constexpr void assign(size_type n, const T& u); constexpr void assign(initializer_list); constexpr allocator_type get_allocator() const noexcept; @@ -5822,6 +8622,8 @@ template constexpr reference emplace_back(Args&&... args); constexpr void push_back(const T& x); constexpr void push_back(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); constexpr void pop_back(); template constexpr iterator emplace(const_iterator position, Args&&... args); @@ -5831,6 +8633,8 @@ template constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list il); constexpr iterator erase(const_iterator position); constexpr iterator erase(const_iterator first, const_iterator last); @@ -5843,6 +8647,10 @@ template>> vector(InputIterator, InputIterator, Allocator = Allocator()) -> vector<@\placeholder{iter-value-type}@, Allocator>; + + template>> + vector(from_range_t, R&&, Allocator = Allocator()) + -> vector, Allocator>; } \end{codeblock}% \indexlibrarymember{vector}{operator==}% @@ -5923,7 +8731,6 @@ \end{itemdecl} \begin{itemdescr} - \pnum \effects Constructs a \tcode{vector} equal to the @@ -5949,6 +8756,29 @@ reallocations if they are just input iterators. \end{itemdescr} +\indexlibraryctor{vector}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{vector} object with the elements of the range \tcode{rg}, +using the specified allocator. + +\pnum +\complexity +Initializes exactly $N$ elements +from the results of dereferencing successive iterators of \tcode{rg}, +where $N$ is \tcode{ranges::distance(rg)}. +Performs no reallocations if \tcode{R} models +\tcode{ranges::\libconcept{forward_range}} or \tcode{ranges::\libconcept{sized_range}}; +otherwise, performs order $\log N$ reallocations and +order $N$ calls to the copy or move constructor of \tcode{T}. +\end{itemdescr} + \rSec3[vector.capacity]{Capacity} \indexlibrarymember{capacity}{vector}% @@ -6154,12 +8984,16 @@ constexpr iterator insert(const_iterator position, size_type n, const T& x); template constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); +template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list); template constexpr reference emplace_back(Args&&... args); template constexpr iterator emplace(const_iterator position, Args&&... args); constexpr void push_back(const T& x); constexpr void push_back(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -6307,6 +9141,8 @@ constexpr vector(size_type n, const bool& value, const Allocator& = Allocator()); template constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); constexpr vector(const vector& x); constexpr vector(vector&& x); constexpr vector(const vector&, const type_identity_t&); @@ -6318,6 +9154,8 @@ constexpr vector& operator=(initializer_list); template constexpr void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void assign_range(R&& rg); constexpr void assign(size_type n, const bool& t); constexpr void assign(initializer_list); constexpr allocator_type get_allocator() const noexcept; @@ -6359,6 +9197,8 @@ // modifiers template constexpr reference emplace_back(Args&&... args); constexpr void push_back(const bool& x); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); constexpr void pop_back(); template constexpr iterator emplace(const_iterator position, Args&&... args); constexpr iterator insert(const_iterator position, const bool& x); @@ -6366,6 +9206,8 @@ template constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list il); constexpr iterator erase(const_iterator position); @@ -6462,6 +9304,15 @@ using @\placeholder{iter-to-alloc-type}@ = pair< add_const_t::value_type::first_type>, typename iterator_traits::value_type::second_type>; // \expos +template + using @\exposid{range-key-type}@ = + remove_const_t::first_type>; // \expos +template + using @\exposid{range-mapped-type}@ = typename ranges::range_value_t::second_type; // \expos +template + using @\exposid{range-to-alloc-type}@ = + pair::first_type>, + typename ranges::range_value_t::second_type>; // \expos \end{codeblock} \rSec2[associative.map.syn]{Header \tcode{} synopsis} @@ -6598,10 +9449,11 @@ on the keys. The \tcode{map} class supports bidirectional iterators. \pnum -A -\tcode{map} -meets all of the requirements of a container, of a reversible container\iref{container.requirements}, of -an associative container\iref{associative.reqmts}, and of an allocator-aware container (\tref{container.alloc.req}). +A \tcode{map} meets all of the requirements of +a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}. and +of an associative container\iref{associative.reqmts}. A \tcode{map} also provides most operations described in~\ref{associative.reqmts} @@ -6673,6 +9525,8 @@ template map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); map(const map& x); map(map&& x); explicit map(const Allocator&); @@ -6684,6 +9538,9 @@ template map(InputIterator first, InputIterator last, const Allocator& a) : map(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + map(from_range_t, R&& rg, const Allocator& a)) + : map(from_range, std::forward(rg), Compare(), a) { } map(initializer_list il, const Allocator& a) : map(il, Compare(), a) { } ~map(); @@ -6733,6 +9590,8 @@ iterator insert(const_iterator position, P&&); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -6816,6 +9675,11 @@ map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Compare, Allocator>; + template, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare, Allocator>; + template, class Allocator = allocator>> map(initializer_list>, Compare = Compare(), Allocator = Allocator()) @@ -6826,6 +9690,10 @@ -> map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, less<@\placeholder{iter-key-type}@>, Allocator>; + template + map(from_range_t, R&&, Allocator) + -> map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, Allocator>; + template map(initializer_list>, Allocator) -> map, Allocator>; } @@ -6878,6 +9746,25 @@ is \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{map}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{map} +using the specified comparison object and allocator, +and inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[map.access]{Element access} \indexlibrary{\idxcode{operator[]}!\idxcode{map}}% @@ -7145,11 +10032,11 @@ supports bidirectional iterators. \pnum -A -\tcode{multimap} meets all of the requirements of a container and of a -reversible container\iref{container.requirements}, of an associative -container\iref{associative.reqmts}, and of an allocator-aware container -(\tref{container.alloc.req}). +A \tcode{multimap} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an associative container\iref{associative.reqmts}. A \tcode{multimap} also provides most operations described in~\ref{associative.reqmts} @@ -7221,6 +10108,9 @@ multimap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + multimap(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); multimap(const multimap& x); multimap(multimap&& x); explicit multimap(const Allocator&); @@ -7232,6 +10122,9 @@ template multimap(InputIterator first, InputIterator last, const Allocator& a) : multimap(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + multimap(from_range_t, R&& rg, const Allocator& a)) + : multimap(from_range, std::forward(rg), Compare(), a) { } multimap(initializer_list il, const Allocator& a) : multimap(il, Compare(), a) { } ~multimap(); @@ -7274,6 +10167,8 @@ template iterator insert(const_iterator position, P&& x); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -7341,6 +10236,11 @@ -> multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Compare, Allocator>; + template>, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare, Allocator>; + template, class Allocator = allocator>> multimap(initializer_list>, Compare = Compare(), Allocator = Allocator()) @@ -7351,6 +10251,10 @@ -> multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, less<@\placeholder{iter-key-type}@>, Allocator>; + template + multimap(from_range_t, R&&, Allocator) + -> multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, Allocator>; + template multimap(initializer_list>, Allocator) -> multimap, Allocator>; @@ -7405,6 +10309,25 @@ \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{multimap}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + multimap(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{multimap} +using the specified comparison object and allocator, and +inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[multimap.modifiers]{Modifiers} \indexlibrarymember{insert}{multimap}% @@ -7466,10 +10389,11 @@ supports bidirectional iterators. \pnum -A \tcode{set} meets all of the requirements of a container, of a reversible -container\iref{container.requirements}, of an associative -container\iref{associative.reqmts}, and of an allocator-aware container -(\tref{container.alloc.req}). +A \tcode{set} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}. and +of an associative container\iref{associative.reqmts}. A \tcode{set} also provides most operations described in~\ref{associative.reqmts} @@ -7526,6 +10450,8 @@ template set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); set(const set& x); set(set&& x); explicit set(const Allocator&); @@ -7536,6 +10462,9 @@ template set(InputIterator first, InputIterator last, const Allocator& a) : set(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + set(from_range_t, R&& rg, const Allocator& a)) + : set(from_range, std::forward(rg), Compare(), a) { } set(initializer_list il, const Allocator& a) : set(il, Compare(), a) { } ~set(); @@ -7576,6 +10505,8 @@ iterator insert(const_iterator position, value_type&& x); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -7644,6 +10575,11 @@ Compare = Compare(), Allocator = Allocator()) -> set<@\placeholder{iter-value-type}@, Compare, Allocator>; + template>, + class Allocator = allocator>> + set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> set, Compare, Allocator>; + template, class Allocator = allocator> set(initializer_list, Compare = Compare(), Allocator = Allocator()) -> set; @@ -7653,6 +10589,10 @@ -> set<@\placeholder{iter-value-type}@, less<@\placeholder{iter-value-type}@>, Allocator>; + template + set(from_range_t, R&&, Allocator) + -> set, less>, Allocator>; + template set(initializer_list, Allocator) -> set, Allocator>; } @@ -7703,6 +10643,24 @@ \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{set}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{set} using the specified comparison object and allocator, +and inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[set.erasure]{Erasure} \indexlibrarymember{erase_if}{set}% @@ -7744,10 +10702,11 @@ supports bidirectional iterators. \pnum -A \tcode{multiset} meets all of the requirements of a container, of a -reversible container\iref{container.requirements}, of an associative -container\iref{associative.reqmts}, and of an allocator-aware container -(\tref{container.alloc.req}). +A \tcode{multiset} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, +of an associative container\iref{associative.reqmts}. \tcode{multiset} also provides most operations described in~\ref{associative.reqmts} for duplicate keys. @@ -7802,6 +10761,9 @@ template multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + multiset(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); multiset(const multiset& x); multiset(multiset&& x); explicit multiset(const Allocator&); @@ -7812,6 +10774,9 @@ template multiset(InputIterator first, InputIterator last, const Allocator& a) : multiset(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + multiset(from_range_t, R&& rg, const Allocator& a)) + : multiset(from_range, std::forward(rg), Compare(), a) { } multiset(initializer_list il, const Allocator& a) : multiset(il, Compare(), a) { } ~multiset(); @@ -7852,6 +10817,8 @@ iterator insert(const_iterator position, value_type&& x); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -7920,6 +10887,11 @@ Compare = Compare(), Allocator = Allocator()) -> multiset<@\placeholder{iter-value-type}@, Compare, Allocator>; + template>, + class Allocator = allocator>> + multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> multiset, Compare, Allocator>; + template, class Allocator = allocator> multiset(initializer_list, Compare = Compare(), Allocator = Allocator()) -> multiset; @@ -7929,6 +10901,10 @@ -> multiset<@\placeholder{iter-value-type}@, less<@\placeholder{iter-value-type}@>, Allocator>; + template + multiset(from_range_t, R&&, Allocator) + -> multiset, less>, Allocator>; + template multiset(initializer_list, Allocator) -> multiset, Allocator>; } @@ -7979,6 +10955,25 @@ \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{multiset}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + multiset(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{multiset} +using the specified comparison object and allocator, and +inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[multiset.erasure]{Erasure} \indexlibrarymember{erase_if}{multiset}% @@ -8175,7 +11170,11 @@ supports forward iterators. \pnum -An \tcode{unordered_map} meets all of the requirements of a container, of an unordered associative container, and of an allocator-aware container (\tref{container.alloc.req}). It provides the operations described in the preceding requirements table for unique keys; that is, an \tcode{unordered_map} supports the \tcode{a_uniq} operations in that table, not the \tcode{a_eq} operations. For an \tcode{unordered_map} the \tcode{key type} is \tcode{Key}, the mapped type is \tcode{T}, and the value type is \tcode{pair}. +An \tcode{unordered_map} meets all of the requirements +of a container\iref{container.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an unordered associative container\iref{unord.req}. +It provides the operations described in the preceding requirements table for unique keys; that is, an \tcode{unordered_map} supports the \tcode{a_uniq} operations in that table, not the \tcode{a_eq} operations. For an \tcode{unordered_map} the \tcode{key type} is \tcode{Key}, the mapped type is \tcode{T}, and the value type is \tcode{pair}. \pnum Subclause~\ref{unord.map} only describes operations on \tcode{unordered_map} that @@ -8225,6 +11224,11 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + + template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, size_type n = @\seebelow@, + const hasher& hf = hasher(), const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_map(const unordered_map&); unordered_map(unordered_map&&); explicit unordered_map(const Allocator&); @@ -8246,6 +11250,12 @@ unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_map(from_range, std::forward(rg), n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) + : unordered_map(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_map(initializer_list il, size_type n, const allocator_type& a) : unordered_map(il, n, hasher(), key_equal(), a) { } unordered_map(initializer_list il, size_type n, const hasher& hf, @@ -8283,6 +11293,8 @@ iterator insert(const_iterator hint, value_type&& obj); template iterator insert(const_iterator hint, P&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -8388,6 +11400,13 @@ -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to<@\exposid{range-key-type}@>, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + unordered_map(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator>> unordered_map(initializer_list>, @@ -8412,6 +11431,21 @@ -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, equal_to<@\placeholder{iter-key-type}@>, Allocator>; + template + unordered_map(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_map(from_range_t, R&&, Allocator) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_map(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, + equal_to<@\exposid{range-key-type}@>, Allocator>; + template unordered_map(initializer_list>, typename @\seebelow@::size_type, Allocator) @@ -8466,6 +11500,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_map(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -8481,9 +11521,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_map}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -8699,6 +11738,7 @@ \mandates \tcode{is_assignable_v} is \tcode{true}. +\pnum \expects \tcode{value_type} is \oldconcept{Emplace\-Constructible} into \tcode{unordered_map} from \tcode{std::move(k)}, \tcode{std::\brk{}forward(obj)}. @@ -8767,9 +11807,11 @@ supports forward iterators. \pnum -An \tcode{unordered_multimap} meets all of the requirements of a container, of an -unordered associative container, and of an allocator-aware container -(\tref{container.alloc.req}). It provides the operations described in the +An \tcode{unordered_multimap} meets all of the requirements +of a container\iref{container.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an unordered associative container\iref{unord.req}. +It provides the operations described in the preceding requirements table for equivalent keys; that is, an \tcode{unordered_multimap} supports the \tcode{a_eq} operations in that table, not the \tcode{a_uniq} operations. For an \tcode{unordered_multimap} the \tcode{key type} is \tcode{Key}, the @@ -8822,6 +11864,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multimap(const unordered_multimap&); unordered_multimap(unordered_multimap&&); explicit unordered_multimap(const Allocator&); @@ -8843,6 +11891,14 @@ unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_multimap(from_range, std::forward(rg), + n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_multimap(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_multimap(initializer_list il, size_type n, const allocator_type& a) : unordered_multimap(il, n, hasher(), key_equal(), a) { } unordered_multimap(initializer_list il, size_type n, const hasher& hf, @@ -8880,6 +11936,8 @@ iterator insert(const_iterator hint, value_type&& obj); template iterator insert(const_iterator hint, P&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -8962,6 +12020,14 @@ -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to<@\exposid{range-key-type}@>, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator>> unordered_multimap(initializer_list>, @@ -8987,6 +12053,21 @@ -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, equal_to<@\placeholder{iter-key-type}@>, Allocator>; + template + unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_multimap(from_range_t, R&&, Allocator) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, + equal_to<@\exposid{range-key-type}@>, Allocator>; + template unordered_multimap(initializer_list>, typename @\seebelow@::size_type, Allocator) @@ -9041,6 +12122,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multimap(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -9056,9 +12143,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_multimap}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -9143,7 +12229,11 @@ supports forward iterators. \pnum -An \tcode{unordered_set} meets all of the requirements of a container, of an unordered associative container, and of an allocator-aware container (\tref{container.alloc.req}). It provides the operations described in the preceding requirements table for unique keys; that is, an \tcode{unordered_set} supports the \tcode{a_uniq} operations in that table, not the \tcode{a_eq} operations. For an \tcode{unordered_set} the \tcode{key type} and the value type are both \tcode{Key}. The \tcode{iterator} and \tcode{const_iterator} types are both constant iterator types. It is unspecified whether they are the same type. +An \tcode{unordered_set} meets all of the requirements +of a container\iref{container.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, +of an unordered associative container\iref{unord.req}. +It provides the operations described in the preceding requirements table for unique keys; that is, an \tcode{unordered_set} supports the \tcode{a_uniq} operations in that table, not the \tcode{a_eq} operations. For an \tcode{unordered_set} the \tcode{key type} and the value type are both \tcode{Key}. The \tcode{iterator} and \tcode{const_iterator} types are both constant iterator types. It is unspecified whether they are the same type. \pnum Subclause~\ref{unord.set} only describes operations on \tcode{unordered_set} that @@ -9191,6 +12281,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<@\exposconcept{container-compatible-range}@ R> + unordered_set(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_set(const unordered_set&); unordered_set(unordered_set&&); explicit unordered_set(const Allocator&); @@ -9214,6 +12310,12 @@ : unordered_set(f, l, n, hf, key_equal(), a) { } unordered_set(initializer_list il, size_type n, const allocator_type& a) : unordered_set(il, n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_set(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_set(from_range, std::forward(rg), n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_set(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) + : unordered_set(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_set(initializer_list il, size_type n, const hasher& hf, const allocator_type& a) : unordered_set(il, n, hf, key_equal(), a) { } @@ -9247,6 +12349,8 @@ iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -9328,6 +12432,14 @@ -> unordered_set<@\placeholder{iter-value-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to>, + class Allocator = allocator>> + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, +Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_set, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator> unordered_set(initializer_list, typename @\seebelow@::size_type = @\seebelow@, @@ -9348,6 +12460,21 @@ equal_to<@\placeholder{iter-value-type}@>, Allocator>; + template + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_set, hash>, + equal_to>, Allocator>; + + template + unordered_set(from_range_t, R&&, Allocator) + -> unordered_set, hash>, + equal_to>, Allocator>; + + template + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_set, Hash, + equal_to>, Allocator>; + template unordered_set(initializer_list, typename @\seebelow@::size_type, Allocator) -> unordered_set, equal_to, Allocator>; @@ -9397,6 +12524,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_set(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -9412,9 +12545,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_set}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -9464,9 +12596,11 @@ supports forward iterators. \pnum -An \tcode{unordered_multiset} meets all of the requirements of a container, of an -unordered associative container, and of an allocator-aware container -(\tref{container.alloc.req}). It provides the operations described in the +An \tcode{unordered_multiset} meets all of the requirements +of a container\iref{container.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an unordered associative container\iref{unord.req}. +It provides the operations described in the preceding requirements table for equivalent keys; that is, an \tcode{unordered_multiset} supports the \tcode{a_eq} operations in that table, not the \tcode{a_uniq} operations. For an \tcode{unordered_multiset} the \tcode{key type} and the value type are @@ -9518,6 +12652,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multiset(const unordered_multiset&); unordered_multiset(unordered_multiset&&); explicit unordered_multiset(const Allocator&); @@ -9539,6 +12679,14 @@ unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_multiset(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_multiset(from_range, std::forward(rg), + n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_multiset(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_multiset(initializer_list il, size_type n, const allocator_type& a) : unordered_multiset(il, n, hasher(), key_equal(), a) { } unordered_multiset(initializer_list il, size_type n, const hasher& hf, @@ -9574,6 +12722,8 @@ iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -9655,6 +12805,14 @@ -> unordered_multiset<@\placeholder{iter-value-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to>, + class Allocator = allocator>> + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multiset, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator> unordered_multiset(initializer_list, typename @\seebelow@::size_type = @\seebelow@, @@ -9675,6 +12833,21 @@ equal_to<@\placeholder{iter-value-type}@>, Allocator>; + template + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_multiset, hash>, + equal_to>, Allocator>; + + template + unordered_multiset(from_range_t, R&&, Allocator) + -> unordered_multiset, hash>, + equal_to>, Allocator>; + + template + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_multiset, Hash, equal_to>, + Allocator>; + template unordered_multiset(initializer_list, typename @\seebelow@::size_type, Allocator) -> unordered_multiset, equal_to, Allocator>; @@ -9724,6 +12897,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multiset(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -9739,9 +12918,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_multiset}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -9933,6 +13111,7 @@ explicit queue(const Container&); explicit queue(Container&&); template queue(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> queue(from_range_t, R&& rg); template explicit queue(const Alloc&); template queue(const Container&, const Alloc&); template queue(Container&&, const Alloc&); @@ -9940,6 +13119,8 @@ template queue(queue&&, const Alloc&); template queue(InputIterator first, InputIterator last, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + queue(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } @@ -9949,6 +13130,7 @@ const_reference back() const { return c.back(); } void push(const value_type& x) { c.push_back(x); } void push(value_type&& x) { c.push_back(std::move(x)); } + template<@\exposconcept{container-compatible-range}@ R> void push_range(R&& rg); template decltype(auto) emplace(Args&&... args) { return c.emplace_back(std::forward(args)...); } @@ -9963,6 +13145,9 @@ template queue(InputIterator, InputIterator) -> queue<@\exposid{iter-value-type}@>; + template + queue(from_range_t, R&&) -> queue>; + template queue(Container, Allocator) -> queue; @@ -9971,6 +13156,10 @@ -> queue<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, Allocator>>; + template + queue(from_range_t, R&&, Allocator) + -> queue, deque, Allocator>>; + template struct uses_allocator, Alloc> : uses_allocator::type { }; @@ -10014,6 +13203,18 @@ \tcode{first} as the first argument and \tcode{last} as the second argument. \end{itemdescr} +\indexlibraryctor{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + queue(from_range_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. +\end{itemdescr} + \rSec3[queue.cons.alloc]{Constructors with allocators} \pnum @@ -10094,6 +13295,35 @@ \tcode{alloc} as the third argument. \end{itemdescr} +\indexlibraryctor{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + queue(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with +\tcode{ranges::to(std::forward(rg), a)}. +\end{itemdescr} + +\rSec3[queue.mod]{Modifiers} + +\indexlibrarymember{push_range}{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{c.append_range(std::forward(rg))} +if that is a valid expression, +otherwise \tcode{ranges::copy(rg, back_inserter(c))}. +\end{itemdescr} + \rSec3[queue.ops]{Operators} \indexlibrarymember{operator==}{queue}% @@ -10254,6 +13484,8 @@ template priority_queue(InputIterator first, InputIterator last, const Compare& x, Container&&); + template<@\exposconcept{container-compatible-range}@ R> + priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); template explicit priority_queue(const Alloc&); template priority_queue(const Compare&, const Alloc&); template priority_queue(const Compare&, const Container&, const Alloc&); @@ -10269,12 +13501,18 @@ const Alloc&); template priority_queue(InputIterator, InputIterator, const Compare&, Container&&, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } const_reference top() const { return c.front(); } void push(const value_type& x); void push(value_type&& x); + template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); template void emplace(Args&&... args); void pop(); void swap(priority_queue& q) noexcept(is_nothrow_swappable_v && @@ -10292,6 +13530,10 @@ priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) -> priority_queue<@\exposid{iter-value-type}@, Container, Compare>; + template> + priority_queue(from_range_t, R&&, Compare = Compare()) + -> priority_queue, vector>, Compare>; + template priority_queue(Compare, Container, Allocator) -> priority_queue; @@ -10311,6 +13553,15 @@ priority_queue(InputIterator, InputIterator, Compare, Container, Allocator) -> priority_queue; + template + priority_queue(from_range_t, R&&, Compare, Allocator) + -> priority_queue, vector, Allocator>, + Compare>; + + template + priority_queue(from_range_t, R&&, Allocator) + -> priority_queue, vector, Allocator>>; + // no equality is provided template @@ -10389,6 +13640,24 @@ \tcode{make_heap(c.begin(), c.end(), comp)}. \end{itemdescr} +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x} defines a strict weak ordering\iref{alg.sorting}. + +\pnum +\effects +Initializes \tcode{comp} with \tcode{x} and +\tcode{c} with \tcode{ranges::to(std::forward(rg))} and +finally calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} + \rSec3[priqueue.cons.alloc]{Constructors with allocators} \pnum @@ -10538,6 +13807,34 @@ finally calls \tcode{make_heap(c.begin(), c.end(), comp)}. \end{itemdescr} +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Compare& compare, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{comp} with \tcode{compare} and +\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}; +calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} + +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes +\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}; +calls \tcode{make_heap(c.\linebreak begin(), c.end(), comp)}. +\end{itemdescr} + \rSec3[priqueue.members]{Members} \indexlibrarymember{push}{priority_queue}% @@ -10570,6 +13867,22 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{push_range}{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Insert all elements of \tcode{rg} in \tcode{c}. + +\pnum +\ensures +\tcode{is_heap(c.begin(), c.end(), comp)} is \tcode{true}. +\end{itemdescr} + \indexlibrarymember{emplace}{priority_queue}% \begin{itemdecl} template void emplace(Args&&... args); @@ -10662,6 +13975,7 @@ explicit stack(const Container&); explicit stack(Container&&); template stack(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> stack(from_range_t, R&& rg); template explicit stack(const Alloc&); template stack(const Container&, const Alloc&); template stack(Container&&, const Alloc&); @@ -10669,6 +13983,8 @@ template stack(stack&&, const Alloc&); template stack(InputIterator first, InputIterator last, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + stack(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } @@ -10676,6 +13992,8 @@ const_reference top() const { return c.back(); } void push(const value_type& x) { c.push_back(x); } void push(value_type&& x) { c.push_back(std::move(x)); } + template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); template decltype(auto) emplace(Args&&... args) { return c.emplace_back(std::forward(args)...); } @@ -10690,6 +14008,9 @@ template stack(InputIterator, InputIterator) -> stack<@\exposid{iter-value-type}@>; + template + stack(from_range_t, R&&) -> stack>; + template stack(Container, Allocator) -> stack; @@ -10698,6 +14019,10 @@ -> stack<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, Allocator>>; + template + stack(from_range_t, R&&, Allocator) + -> stack, deque, Allocator>>; + template struct uses_allocator, Alloc> : uses_allocator::type { }; @@ -10741,6 +14066,18 @@ \tcode{first} as the first argument and \tcode{last} as the second argument. \end{itemdescr} +\indexlibraryctor{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + stack(from_range_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. +\end{itemdescr} + \rSec3[stack.cons.alloc]{Constructors with allocators} \pnum @@ -10821,6 +14158,35 @@ \tcode{alloc} as the third argument. \end{itemdescr} +\indexlibraryctor{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + stack(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes +\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}. +\end{itemdescr} + +\rSec3[stack.mod]{Modifiers} + +\indexlibrarymember{push_range}{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{c.append_range(std::forward(rg))} +if that is a valid expression, +otherwise \tcode{ranges::copy(rg, back_inserter(c))}. +\end{itemdescr} + \rSec3[stack.ops]{Operators} \indexlibrarymember{operator==}{stack}% @@ -11063,7 +14429,8 @@ \end{codeblock} \pnum -\tcode{span} is a trivially copyable type\iref{basic.types.general}. +\tcode{span} is +a trivially copyable type\iref{term.trivially.copyable.type}. \pnum \tcode{ElementType} is required to be diff --git a/source/declarations.tex b/source/declarations.tex index 8c86e2ee99..5cbc237f24 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -192,8 +192,8 @@ is declared to be a \grammarterm{typedef-name}, synonymous with its associated type\iref{dcl.typedef}. \begin{note} -Such a \grammarterm{declarator-id} is an \grammarterm{identifier} -(\ref{class.conv.fct}). +Such a \grammarterm{declarator-id} is +an \grammarterm{identifier}\iref{class.conv.fct}. \end{note} If the \grammarterm{decl-specifier-seq} contains no \keyword{typedef} specifier, the @@ -501,7 +501,7 @@ The \keyword{mutable} specifier on a class data member nullifies a \keyword{const} specifier applied to the containing class object and permits modification of the mutable class member even though the rest of -the object is const~(\ref{basic.type.qualifier}, \ref{dcl.type.cv}). +the object is const\iref{basic.type.qualifier,dcl.type.cv}. \end{note} \rSec2[dcl.fct.spec]{Function specifiers}% @@ -559,7 +559,7 @@ \end{codeblock} \end{example} -\rSec2[dcl.typedef]{The \tcode{typedef} specifier}% +\rSec2[dcl.typedef]{The \keyword{typedef} specifier}% \indextext{specifier!\idxcode{typedef}} \pnum @@ -621,7 +621,8 @@ using handler_t = void (*)(int); extern handler_t ignore; extern void (*ignore)(int); // redeclare \tcode{ignore} -using cell = pair; // error +template struct P { }; +using cell = P; // error: \tcode{cell} not found\iref{basic.scope.pdecl} \end{codeblock} \end{example} The \grammarterm{defining-type-specifier-seq} @@ -697,14 +698,14 @@ \end{codeblock} \end{example} -\rSec2[dcl.friend]{The \tcode{friend} specifier}% +\rSec2[dcl.friend]{The \keyword{friend} specifier}% \indextext{specifier!\idxcode{friend}} \pnum The \keyword{friend} specifier is used to specify access to class members; see~\ref{class.friend}. -\rSec2[dcl.constexpr]{The \tcode{constexpr} and \tcode{consteval} specifiers}% +\rSec2[dcl.constexpr]{The \keyword{constexpr} and \keyword{consteval} specifiers}% \indextext{specifier!\idxcode{constexpr}} \indextext{specifier!\idxcode{consteval}} @@ -729,23 +730,23 @@ \end{note} \begin{example} \begin{codeblock} -constexpr void square(int &x); // OK: declaration -constexpr int bufsz = 1024; // OK: definition +constexpr void square(int &x); // OK, declaration +constexpr int bufsz = 1024; // OK, definition constexpr struct pixel { // error: \tcode{pixel} is a type int x; int y; - constexpr pixel(int); // OK: declaration + constexpr pixel(int); // OK, declaration }; constexpr pixel::pixel(int a) - : x(a), y(x) // OK: definition + : x(a), y(x) // OK, definition { square(x); } constexpr pixel small(2); // error: \tcode{square} not defined, so \tcode{small(2)} // not constant\iref{expr.const} so \keyword{constexpr} not satisfied -constexpr void square(int &x) { // OK: definition +constexpr void square(int &x) { // OK, definition x *= x; } -constexpr pixel large(4); // OK: \tcode{square} defined +constexpr pixel large(4); // OK, \tcode{square} defined int next(constexpr int x) { // error: not for parameters return x + 1; } @@ -952,7 +953,7 @@ \end{codeblock} \end{example} -\rSec2[dcl.constinit]{The \tcode{constinit} specifier} +\rSec2[dcl.constinit]{The \keyword{constinit} specifier} \indextext{specifier!\idxcode{constinit}} \pnum @@ -981,7 +982,7 @@ \end{codeblock} \end{example} -\rSec2[dcl.inline]{The \tcode{inline} specifier}% +\rSec2[dcl.inline]{The \keyword{inline} specifier}% \indextext{specifier!\idxcode{inline}} \pnum @@ -991,8 +992,8 @@ \pnum \indextext{specifier!\idxcode{inline}}% \indextext{inline function}% -A function declaration~(\ref{dcl.fct}, \ref{class.mfct}, -\ref{class.friend}) with an \keyword{inline} specifier declares an +A function declaration\iref{dcl.fct,class.mfct,class.friend} +with an \keyword{inline} specifier declares an \defnadj{inline}{function}. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. @@ -1049,7 +1050,7 @@ \begin{note} A constexpr function\iref{dcl.constexpr} is implicitly inline. In the global module, a function defined within a class definition -is implicitly inline~(\ref{class.mfct}, \ref{class.friend}). +is implicitly inline\iref{class.mfct,class.friend}. \end{note} \rSec2[dcl.type]{Type specifiers}% @@ -1197,8 +1198,7 @@ \pnum \indextext{const object!undefined change to}% -Any attempt to modify~(\ref{expr.ass}, -\ref{expr.post.incr}, \ref{expr.pre.incr}) a +Any attempt to modify\iref{expr.ass,expr.post.incr,expr.pre.incr} a const object\iref{basic.type.qualifier} during its lifetime\iref{basic.life} results in undefined behavior. \begin{example} @@ -1208,7 +1208,7 @@ int i = 2; // not cv-qualified const int* cip; // pointer to \tcode{const int} -cip = &i; // OK: cv-qualified access path to unqualified +cip = &i; // OK, cv-qualified access path to unqualified *cip = 4; // error: attempt to modify through ptr to \keyword{const} int* ip; @@ -1505,7 +1505,7 @@ \grammarterm{simple-type-specifier} introduces its \grammarterm{type-name}\iref{dcl.type.simple}. If the \grammarterm{identifier} or \grammarterm{simple-template-id} resolves to a -\grammarterm{typedef-name} (\ref{dcl.typedef}, \ref{temp.names}), +\grammarterm{typedef-name}\iref{dcl.typedef,temp.names}, the \grammarterm{elaborated-type-specifier} is ill-formed. \begin{note} This implies that, within a class template with a template @@ -1560,8 +1560,8 @@ \item otherwise, if $E$ is an unparenthesized \grammarterm{id-expression} naming a non-type \grammarterm{template-parameter}\iref{temp.param}, \tcode{decltype($E$)} is the type of the \grammarterm{template-parameter} -after performing any necessary type deduction -(\ref{dcl.spec.auto}, \ref{dcl.type.class.deduct}); +after performing any necessary +type deduction\iref{dcl.spec.auto,dcl.type.class.deduct}; \item otherwise, if $E$ is an unparenthesized \grammarterm{id-expression} or an unparenthesized @@ -1634,7 +1634,7 @@ template auto f(T) // \#2 -> void; auto g() -> void { - f(42); // OK: calls \#2. (\#1 is not a viable candidate: type deduction + f(42); // OK, calls \#2. (\#1 is not a viable candidate: type deduction // fails\iref{temp.deduct} because \tcode{A::\~{}A()} is implicitly used in its // \grammarterm{decltype-specifier}) } @@ -1714,13 +1714,13 @@ \grammarterm{initializer}. \begin{example} \begin{codeblock} -auto x = 5; // OK: \tcode{x} has type \tcode{int} -const auto *v = &x, u = 6; // OK: \tcode{v} has type \tcode{const int*}, \tcode{u} has type \tcode{const int} -static auto y = 0.0; // OK: \tcode{y} has type \tcode{double} +auto x = 5; // OK, \tcode{x} has type \tcode{int} +const auto *v = &x, u = 6; // OK, \tcode{v} has type \tcode{const int*}, \tcode{u} has type \tcode{const int} +static auto y = 0.0; // OK, \tcode{y} has type \tcode{double} 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 h(); // OK: \tcode{h}'s return type will be deduced when it is defined +auto f() -> int; // OK, \tcode{f} returns \tcode{int} +auto g() { return 0.0; } // OK, \tcode{g} returns \tcode{double} +auto h(); // OK, \tcode{h}'s return type will be deduced when it is defined \end{codeblock} \end{example} The \keyword{auto} \grammarterm{type-specifier} @@ -1754,7 +1754,7 @@ \begin{example} \begin{codeblock} -auto x = 5, *y = &x; // OK: \keyword{auto} is \tcode{int} +auto x = 5, *y = &x; // OK, \keyword{auto} is \tcode{int} auto a = 5, b = { 1, 2 }; // error: different types for \keyword{auto} \end{codeblock} \end{example} @@ -2141,7 +2141,7 @@ \pnum In all contexts, a \grammarterm{declarator} is interpreted as given below. Where an \grammarterm{abstract-declarator} can be used (or omitted) -in place of a \grammarterm{declarator} (\ref{dcl.fct}, \ref{except.pre}), +in place of a \grammarterm{declarator}\iref{dcl.fct,except.pre}, it is as if a unique identifier were included in the appropriate place\iref{dcl.name}. The preceding specifiers indicate @@ -2193,8 +2193,8 @@ \end{codeblock} as opposed to \begin{codeblock} -auto i = 1; // OK: \tcode{i} deduced to have type \tcode{int} -auto j = 2.0; // OK: \tcode{j} deduced to have type \tcode{double} +auto i = 1; // OK, \tcode{i} deduced to have type \tcode{int} +auto j = 2.0; // OK, \tcode{j} deduced to have type \tcode{double} \end{codeblock} \end{note} @@ -2505,8 +2505,8 @@ \grammarterm{explicit-instantiation}\iref{temp.explicit}. \begin{note} An \grammarterm{unqualified-id} that is not an \grammarterm{identifier} -is used to declare certain functions -(\ref{class.conv.fct}, \ref{class.dtor}, \ref{over.oper}, \ref{over.literal}). +is used to declare +certain functions\iref{class.conv.fct,class.dtor,over.oper,over.literal}. \end{note} The optional \grammarterm{attribute-specifier-seq} following a \grammarterm{declarator-id} appertains to the entity that is declared. @@ -2547,7 +2547,7 @@ Otherwise, the terminal name of $E$ is not looked up. The declaration's target scope is the innermost enclosing namespace scope; if the declaration is contained by a block scope, -the declaration shall correspond to a declaration +the declaration shall correspond to a reachable\iref{module.reach} declaration that inhabits the innermost block scope. \end{itemize} @@ -2585,7 +2585,7 @@ } using P::f,P::g; } -template<> void N::f(int*) {} // OK: \#2 is not nominable +template<> void N::f(int*) {} // OK, \#2 is not nominable template void N::g(int); // error: lookup is ambiguous \end{codeblock} \end{example} @@ -2870,7 +2870,7 @@ The optional \grammarterm{attribute-specifier-seq} appertains to the reference type. Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a -\grammarterm{typedef-name}~(\ref{dcl.typedef}, \ref{temp.param}) or +\grammarterm{typedef-name}\iref{dcl.typedef,temp.param} or \grammarterm{decltype-specifier}\iref{dcl.type.decltype}, in which case the cv-qualifiers are ignored. \begin{example} @@ -2997,7 +2997,7 @@ \pnum \indextext{reference collapsing}% -If a \grammarterm{typedef-name}~(\ref{dcl.typedef}, \ref{temp.param}) +If a \grammarterm{typedef-name}\iref{dcl.typedef,temp.param} or a \grammarterm{decltype-specifier}\iref{dcl.type.decltype} denotes a type \tcode{TR} that is a reference to a type \tcode{T}, an attempt to create the type ``lvalue reference to \cv{}~\tcode{TR}'' creates the type ``lvalue reference to \tcode{T}'', while an attempt to create @@ -3174,6 +3174,7 @@ \pnum \indextext{declaration!array}% +\label{term.array.type}% A type of the form ``array of \tcode{N} \tcode{U}'' or ``array of unknown bound of \tcode{U}'' is an \defn{array type}. The optional \grammarterm{attribute-specifier-seq} @@ -3234,8 +3235,8 @@ parameter\iref{dcl.fct}. An array bound may also be omitted when an object (but not a non-static data member) of array type is initialized -and the declarator is followed by an initializer -(\ref{dcl.init}, \ref{class.mem}, \ref{expr.type.conv}, \ref{expr.new}). +and the declarator is followed by +an initializer\iref{dcl.init,class.mem,expr.type.conv,expr.new}. \indextext{array size!default}% In these cases, the array bound is calculated from the number of initial elements (say, \tcode{N}) @@ -3254,8 +3255,8 @@ static int y[10]; }; -int x[]; // OK: bound is 10 -int S::y[]; // OK: bound is 10 +int x[]; // OK, bound is 10 +int S::y[]; // OK, bound is 10 void f() { extern int x[]; @@ -3549,12 +3550,12 @@ \begin{codeblock} void f(char*); // \#1 void f(char[]) {} // defines \#1 -void f(const char*) {} // OK: another overload +void f(const char*) {} // OK, another overload void f(char *const) {} // error: redefines \#1 void g(char(*)[2]); // \#2 void g(char[3][2]) {} // defines \#2 -void g(char[3][3]) {} // OK: another overload +void g(char[3][3]) {} // OK, another overload void h(int x(const int)); // \#3 void h(int (*)(int)) {} // defines \#3 @@ -3624,7 +3625,7 @@ \pnum A function type with a \grammarterm{cv-qualifier-seq} or a \grammarterm{ref-qualifier} (including a type named by -\grammarterm{typedef-name}~(\ref{dcl.typedef}, \ref{temp.param})) +\grammarterm{typedef-name}\iref{dcl.typedef,temp.param}) shall appear only as: \begin{itemize} \item the function type for a non-static member function, @@ -3665,7 +3666,7 @@ \begin{codeblock} typedef void F(); struct S { - const F f; // OK: equivalent to: \tcode{void f();} + const F f; // OK, equivalent to: \tcode{void f();} }; \end{codeblock} \end{example} @@ -3722,9 +3723,9 @@ \begin{example} \begin{codeblock} typedef void F(); -F fv; // OK: equivalent to \tcode{void fv();} +F fv; // OK, equivalent to \tcode{void fv();} F fv { } // error -void fv() { } // OK: definition of \tcode{fv} +void fv() { } // OK, definition of \tcode{fv} \end{codeblock} \end{example} @@ -4365,7 +4366,7 @@ \item if \tcode{T} -is a scalar type\iref{basic.types}, the +is a scalar type\iref{term.scalar.type}, the object is initialized to the value obtained by converting the integer literal \tcode{0} (zero) to @@ -4381,7 +4382,7 @@ if \tcode{T} is a (possibly cv-qualified) non-union class type, -its padding bits\iref{basic.types} are initialized to zero bits and +its padding bits\iref{term.padding.bits} are initialized to zero bits and each non-static data member, each non-virtual base class subobject, and, if the object is not a base class subobject, @@ -4392,7 +4393,7 @@ if \tcode{T} is a (possibly cv-qualified) union type, -its padding bits\iref{basic.types} are initialized to zero bits and +its padding bits\iref{term.padding.bits} are initialized to zero bits and the object's first non-static named data member @@ -4586,8 +4587,8 @@ \tcode{X}. The form \tcode{()} -is permitted in certain other initialization contexts~(\ref{expr.new}, -\ref{expr.type.conv}, \ref{class.base.init}). +is permitted in certain other initialization contexts\iref{expr.new, +expr.type.conv,class.base.init}. \end{note} \item @@ -5587,8 +5588,7 @@ user-defined conversions are considered using the rules for copy-initialization of an object of type ``\cvqual{cv1} \tcode{T1}'' by -user-defined conversion -(\ref{dcl.init}, \ref{over.match.copy}, \ref{over.match.conv}); +user-defined conversion\iref{dcl.init,over.match.copy,over.match.conv}; the program is ill-formed if the corresponding non-reference copy-initialization would be ill-formed. The result of the call to the conversion function, as described for the non-reference @@ -5684,7 +5684,7 @@ \item as a \grammarterm{for-range-initializer}\iref{stmt.iter} \item as a function argument\iref{expr.call} \item as a subscript\iref{expr.sub} -\item as an argument to a constructor invocation~(\ref{dcl.init}, \ref{expr.type.conv}) +\item as an argument to a constructor invocation\iref{dcl.init,expr.type.conv} \item as an initializer for a non-static data member\iref{class.mem} \item in a \grammarterm{mem-initializer}\iref{class.base.init} \item on the right-hand side of an assignment\iref{expr.ass} @@ -5769,7 +5769,7 @@ }; S2 s21 = { 1, 2, 3.0 }; // OK S2 s22 { 1.0, 2, 3 }; // error: narrowing -S2 s23 { }; // OK: default to 0,0,0 +S2 s23 { }; // OK, default to 0,0,0 \end{codeblock} \end{example} @@ -5781,7 +5781,7 @@ \item Otherwise, if \tcode{T} is a class type, constructors are considered. The applicable constructors are enumerated and -the best one is chosen through overload resolution~(\ref{over.match}, \ref{over.match.list}). If a narrowing +the best one is chosen through overload resolution\iref{over.match,over.match.list}. If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed. @@ -5816,9 +5816,9 @@ S(); // \#2 // ... }; -S s1 = { 1, 2, 3.0 }; // OK: invoke \#1 +S s1 = { 1, 2, 3.0 }; // OK, invoke \#1 S s2 { 1.0, 2, 3 }; // error: narrowing -S s3 { }; // OK: invoke \#2 +S s3 { }; // OK, invoke \#2 \end{codeblock} \end{example} @@ -5886,12 +5886,12 @@ S(const std::string&); // \#2 // ... }; -const S& r1 = { 1, 2, 3.0 }; // OK: invoke \#1 -const S& r2 { "Spinach" }; // OK: invoke \#2 +const S& r1 = { 1, 2, 3.0 }; // OK, invoke \#1 +const S& r2 { "Spinach" }; // OK, invoke \#2 S& r3 = { 1, 2, 3 }; // error: initializer is not an lvalue const int& i1 = { 1 }; // OK const int& i2 = { 1.1 }; // error: narrowing -const int (&iar)[2] = { 1, 2 }; // OK: \tcode{iar} is bound to temporary array +const int (&iar)[2] = { 1, 2 }; // OK, \tcode{iar} is bound to temporary array struct A { } a; struct B { explicit B(const A&); }; @@ -6049,18 +6049,18 @@ char c1 = x; // OK, though it potentially narrows (in this case, it does narrow) char c2{x}; // error: potentially narrows char c3{y}; // error: narrows (assuming \tcode{char} is 8 bits) -char c4{z}; // OK: no narrowing needed -unsigned char uc1 = {5}; // OK: no narrowing needed +char c4{z}; // OK, no narrowing needed +unsigned char uc1 = {5}; // OK, no narrowing needed unsigned char uc2 = {-1}; // error: narrows unsigned int ui1 = {-1}; // error: narrows signed int si1 = { (unsigned int)-1 }; // error: narrows int ii = {2.0}; // error: narrows float f1 { x }; // error: potentially narrows -float f2 { 7 }; // OK: 7 can be exactly represented as a \tcode{float} +float f2 { 7 }; // OK, 7 can be exactly represented as a \tcode{float} bool b = {"meow"}; // error: narrows int f(int); -int a[] = { 2, f(2), f(2.0) }; // OK: the \tcode{double}-to-\tcode{int} conversion is not at the top level +int a[] = { 2, f(2), f(2.0) }; // OK, the \tcode{double}-to-\tcode{int} conversion is not at the top level \end{codeblock} \end{example} \indextext{initialization!list-initialization|)}% @@ -6241,7 +6241,7 @@ \pnum An explicitly-defaulted function that is not defined as deleted may be declared \keyword{constexpr} or \keyword{consteval} only -if it is constexpr-compatible (\ref{special}, \ref{class.compare.default}). +if it is constexpr-compatible\iref{special,class.compare.default}. A function explicitly defaulted on its first declaration is implicitly inline\iref{dcl.inline}, and is implicitly constexpr\iref{dcl.constexpr} if it is constexpr-compatible. @@ -6256,9 +6256,9 @@ ~S() noexcept(false) = default; // OK, despite mismatched exception specification private: int i; - S(S&); // OK: private copy constructor + S(S&); // OK, private copy constructor }; -S::S(S&) = default; // OK: defines copy constructor +S::S(S&) = default; // OK, defines copy constructor struct T { T(); @@ -6278,8 +6278,7 @@ Explicitly-defaulted functions and implicitly-declared functions are collectively called \defn{defaulted} functions, and the implementation shall provide implicit definitions -for them~(\ref{class.ctor}, -\ref{class.dtor}, \ref{class.copy.ctor}, \ref{class.copy.assign}), +for them\iref{class.ctor,class.dtor,class.copy.ctor,class.copy.assign}, including possibly defining them as deleted. A defaulted prospective destructor\iref{class.dtor} that is not a destructor is defined as deleted. @@ -6712,7 +6711,7 @@ see~\ref{depr.volatile.type}. First, a variable with a unique name \exposid{e} is introduced. If the \grammarterm{assignment-expression} in the \grammarterm{initializer} -has array type \tcode{A} and no \grammarterm{ref-qualifier} is present, +has array type \cvqual{cv1} \tcode{A} and no \grammarterm{ref-qualifier} is present, \exposid{e} is defined by \begin{ncbnf} \opt{attribute-specifier-seq} \placeholder{S} \cv{} \terminal{A} \exposid{e} \terminal{;} @@ -7097,7 +7096,7 @@ values of type \tcode{color}. \begin{codeblock} color c = 1; // error: type mismatch, no conversion from \tcode{int} to \tcode{color} -int i = yellow; // OK: \tcode{yellow} converted to integral value \tcode{1}, integral promotion +int i = yellow; // OK, \tcode{yellow} converted to integral value \tcode{1}, integral promotion \end{codeblock} Note that this implicit \keyword{enum} to \tcode{int} conversion is not provided for a scoped enumeration: @@ -7479,8 +7478,8 @@ \begin{note} A \grammarterm{using-directive} makes the names in the nominated namespace usable in the scope in which the -\grammarterm{using-directive} appears after the \grammarterm{using-directive} -(\ref{basic.lookup.unqual}, \ref{namespace.qual}). +\grammarterm{using-directive} appears after +the \grammarterm{using-directive}\iref{basic.lookup.unqual,namespace.qual}. During unqualified name lookup, the names appear as if they were declared in the nearest enclosing namespace which contains both the \grammarterm{using-directive} and the nominated @@ -7603,8 +7602,8 @@ void f() { X(1); // error: name \tcode{X} found in two namespaces - g(); // OK: name \tcode{g} refers to the same entity - h(); // OK: overload resolution selects \tcode{A::h} + g(); // OK, name \tcode{g} refers to the same entity + h(); // OK, overload resolution selects \tcode{A::h} } \end{codeblock} \end{note} @@ -7635,7 +7634,7 @@ } using namespace D; -int d1; // OK: no conflict with \tcode{D::d1} +int d1; // OK, no conflict with \tcode{D::d1} namespace E { int e; @@ -7652,10 +7651,10 @@ d1++; // error: ambiguous \tcode{::d1} or \tcode{D::d1}? ::d1++; // OK D::d1++; // OK - d2++; // OK: \tcode{D::d2} - e++; // OK: \tcode{E::e} + d2++; // OK, \tcode{D::d2} + e++; // OK, \tcode{E::e} f(1); // error: ambiguous: \tcode{D::f(int)} or \tcode{E::f(int)}? - f('a'); // OK: \tcode{D::f(char)} + f('a'); // OK, \tcode{D::f(char)} } \end{codeblock} \end{example} @@ -7762,9 +7761,9 @@ }; struct D : B { - using B::f; // OK: \tcode{B} is a base of \tcode{D} - using B::e; // OK: \tcode{e} is an enumerator of base \tcode{B} - using B::x; // OK: \tcode{x} is a union member of base \tcode{B} + using B::f; // OK, \tcode{B} is a base of \tcode{D} + using B::e; // OK, \tcode{e} is an enumerator of base \tcode{B} + using B::x; // OK, \tcode{x} is a union member of base \tcode{B} using C::f; // error: \tcode{C} isn't a base of \tcode{D} void f(int) { f('c'); } // calls \tcode{B::f(char)} void g(int) { g('c'); } // recursively calls \tcode{D::g(int)} @@ -7773,7 +7772,7 @@ struct X : bases... { using bases::f...; }; -X x; // OK: \tcode{B::f} and \tcode{C::f} named +X x; // OK, \tcode{B::f} and \tcode{C::f} named \end{codeblock} \end{example} @@ -7785,7 +7784,7 @@ \end{note} If a constructor or assignment operator brought from a base class into a derived class has the signature of a copy/move constructor or assignment operator -for the derived class~(\ref{class.copy.ctor}, \ref{class.copy.assign}), +for the derived class\iref{class.copy.ctor,class.copy.assign}, the \grammarterm{using-declaration} does not by itself suppress the implicit declaration of the derived class member; the member from the base class is hidden or overridden @@ -7840,8 +7839,8 @@ does not name declarations added to the namespace after it. Thus, additional overloads added after the \grammarterm{using-declaration} are ignored, but default function arguments\iref{dcl.fct.default}, default template -arguments\iref{temp.param}, and template specializations~(\ref{temp.spec.partial}, -\ref{temp.expl.spec}) are considered. +arguments\iref{temp.param}, and +template specializations\iref{temp.spec.partial,temp.expl.spec} are considered. \end{note} \begin{example} \begin{codeblock} @@ -7894,17 +7893,17 @@ struct x { }; void f(int); void f(double); - void g(char); // OK: hides \tcode{struct g} + void g(char); // OK, hides \tcode{struct g} } void func() { int i; using B::i; // error: conflicts void f(char); - using B::f; // OK: each \tcode{f} is a function + using B::f; // OK, each \tcode{f} is a function using A::f; // OK, but interferes with \tcode{B::f(int)} f(1); // error: ambiguous - static_cast(f)(1); // OK: calls \tcode{A::f} + static_cast(f)(1); // OK, calls \tcode{A::f} f(3.5); // calls \tcode{B::f(double)} using B::g; g('a'); // calls \tcode{B::g(char)} @@ -7913,7 +7912,7 @@ void h(); using A::h; // error: conflicts using B::x; - using A::x; // OK: hides \tcode{struct B::x} + using A::x; // OK, hides \tcode{struct B::x} x = 99; // assigns to \tcode{A::x} struct x x1; // \tcode{x1} has class type \tcode{B::x} } @@ -7938,13 +7937,13 @@ struct D : B { using B::f; - void f(int); // OK: \tcode{D::f(int)} overrides \tcode{B::f(int)}; + void f(int); // OK, \tcode{D::f(int)} overrides \tcode{B::f(int)}; using B::g; void g(char); // OK using B::h; - void h(int); // OK: \tcode{D::h(int)} hides \tcode{B::h(int)} + void h(int); // OK, \tcode{D::h(int)} hides \tcode{B::h(int)} }; void k(D* p) @@ -7972,7 +7971,7 @@ struct D2 : B1, B2 { using B1::B1; using B2::B2; - D2(int); // OK: \tcode{D2::D2(int)} hides \tcode{B1::B1(int)} and \tcode{B2::B2(int)} + D2(int); // OK, \tcode{D2::D2(int)} hides \tcode{B1::B1(int)} and \tcode{B2::B2(int)} }; D2 d2(0); // calls \tcode{D2::D2(int)} \end{codeblock} @@ -7995,7 +7994,7 @@ Constructors that are named by a \grammarterm{using-declaration} are treated as though they were constructors of the derived class when looking up the constructors of the derived class\iref{class.qual} -or forming a set of overload candidates~(\ref{over.match.ctor}, \ref{over.match.copy}, \ref{over.match.list}). +or forming a set of overload candidates\iref{over.match.ctor,over.match.copy,over.match.list}. \begin{note} If such a constructor is selected to perform the initialization of an object of class type, all subobjects other than the base class @@ -8128,12 +8127,12 @@ Therefore, a linkage-specification with a \grammarterm{string-literal} that is unknown to the implementation requires a diagnostic. \end{note} -\begin{note} -It is recommended that the spelling of the \grammarterm{string-literal} be + +\recommended +The spelling of the \grammarterm{string-literal} should be taken from the document defining that language. For example, \tcode{Ada} (not \tcode{ADA}) and \tcode{Fortran} or \tcode{FORTRAN}, depending on the vintage. -\end{note} \pnum \indextext{specification!linkage!implementation-defined}% @@ -8191,15 +8190,15 @@ } extern "C" void f5() { - extern void f4(); // OK: Name linkage (internal) and function type linkage (C language linkage) + extern void f4(); // OK, name linkage (internal) and function type linkage (C language linkage) // obtained from previous declaration. } -extern void f4(); // OK: Name linkage (internal) and function type linkage (C language linkage) +extern void f4(); // OK, name linkage (internal) and function type linkage (C language linkage) // obtained from previous declaration. void f6() { - extern void f4(); // OK: Name linkage (internal) and function type linkage (C language linkage) + extern void f4(); // OK, name linkage (internal) and function type linkage (C language linkage) // obtained from previous declaration. } \end{codeblock} @@ -8437,9 +8436,9 @@ \pnum Each \grammarterm{attribute-specifier-seq} is said to \defn{appertain} to some entity or -statement, identified by the syntactic context where it appears -(\ref{stmt.stmt}, \ref{dcl.dcl}, -\ref{dcl.decl}). If an \grammarterm{attribute-specifier-seq} that appertains to some +statement, identified by the syntactic context +where it appears\iref{stmt.stmt,dcl.dcl,dcl.decl}. +If an \grammarterm{attribute-specifier-seq} that appertains to some entity or statement contains an \grammarterm{attribute} or \grammarterm{alignment-specifier} that is not allowed to apply to that entity or statement, the program is ill-formed. If an \grammarterm{attribute-specifier-seq} @@ -8598,12 +8597,11 @@ dependency propagation into and out of functions. No \grammarterm{attribute-argument-clause} shall be present. The attribute may be -applied to the \grammarterm{declarator-id} of a -\grammarterm{parameter-declaration} in a function declaration or lambda, in +applied to a parameter of a function or lambda, in which case it specifies that the initialization of the parameter carries a dependency to\iref{intro.multithread} each lvalue-to-rvalue conversion\iref{conv.lval} of that object. The attribute may also be applied -to the \grammarterm{declarator-id} of a function declaration, in which case it +to a function or a lambda call operator, in which case it specifies that the return value, if any, carries a dependency to the evaluation of the function call expression. @@ -8892,8 +8890,8 @@ \pnum The \grammarterm{attribute-token} \tcode{nodiscard} -may be applied to the \grammarterm{declarator-id} -in a function declaration or to the declaration of a class or enumeration. +may be applied to a function or a lambda call operator or +to the declaration of a class or enumeration. An \grammarterm{attribute-argument-clause} may be present and, if present, shall have the form: @@ -8929,7 +8927,7 @@ whose return type is a nodiscard type, or \item an explicit type - conversion~(\ref{expr.type.conv}, \ref{expr.static.cast}, \ref{expr.cast}) + conversion\iref{expr.type.conv,expr.static.cast,expr.cast} that constructs an object through a constructor declared \tcode{nodiscard} in a reachable declaration, or that initializes an object of a nodiscard type. @@ -8983,9 +8981,9 @@ \pnum The \grammarterm{attribute-token} \tcode{noreturn} specifies that a function does not return. -No -\grammarterm{attribute-argument-clause} shall be present. The attribute may be applied to the -\grammarterm{declarator-id} in a function declaration. The first declaration of a function shall +No \grammarterm{attribute-argument-clause} shall be present. +The attribute may be applied to a function or a lambda call operator. +The first declaration of a function shall specify the \tcode{noreturn} attribute if any declaration of that function specifies the \tcode{noreturn} attribute. If a function is declared with the \tcode{noreturn} attribute in one translation unit and the same function is declared without the \tcode{noreturn} attribute in another diff --git a/source/diagnostics.tex b/source/diagnostics.tex index 438d911c5b..b17a6e6fa0 100644 --- a/source/diagnostics.tex +++ b/source/diagnostics.tex @@ -10,7 +10,8 @@ \pnum The following subclauses describe components for reporting several kinds of exceptional conditions, -documenting program assertions, and +documenting program assertions, +obtaining stacktraces, and a global variable for error number codes, as summarized in \tref{diagnostics.summary}. @@ -18,7 +19,8 @@ \ref{std.exceptions} & Exception classes & \tcode{} \\ \rowsep \ref{assertions} & Assertions & \tcode{} \\ \rowsep \ref{errno} & Error numbers & \tcode{} \\ \rowsep -\ref{syserr} & System error support & \tcode{} \\ +\ref{syserr} & System error support & \tcode{} \\ \rowsep +\ref{stacktrace} & Stacktrace & \tcode{} \\ \end{libsumtab} \rSec1[std.exceptions]{Exception classes} @@ -1044,11 +1046,13 @@ pointer to the string \tcode{"system"}. The object's \tcode{default_error_condition} virtual function shall behave as follows: -If the argument \tcode{ev} corresponds to a POSIX \tcode{errno} value \tcode{posv}, the -function shall return \tcode{error_condition(posv, generic_category())}. -Otherwise, the function shall return \tcode{error_condition(ev, -system_category())}. What constitutes correspondence for any given operating -system is unspecified. +If the argument \tcode{ev} is equal to 0, +the function returns \tcode{error_condition(0, generic_category())}. +Otherwise, +if \tcode{ev} corresponds to a POSIX \tcode{errno} value \tcode{pxv}, +the function returns \tcode{error_condition(pxv, generic_category())}. +Otherwise, the function returns \tcode{error_condition(ev, system_category())}. +What constitutes correspondence for any given operating system is unspecified. \begin{note} The number of potential system error codes is large and unbounded, and some might not correspond to any POSIX \tcode{errno} value. Thus @@ -1677,3 +1681,723 @@ code.message()}. \end{note} \end{itemdescr} + +\rSec1[stacktrace]{Stacktrace} + +\rSec2[stacktrace.general]{General} + +\pnum +Subclause \ref{stacktrace} describes components +that \Cpp{} programs may use to store +the stacktrace of the current thread of execution and +query information about the stored stacktrace at runtime. + +\pnum +The \defn{invocation sequence} of the current evaluation $x_0$ +in the current thread of execution +is a sequence $(x_0, \ldots, x_n)$ of evaluations such that, for $i \geq 0$, +$x_i$ is within the function invocation $x_{i+1}$\iref{intro.execution}. + +\pnum +A \defn{stacktrace} is an approximate representation of +an invocation sequence and consists of stacktrace entries. +A \defn{stacktrace entry} represents an evaluation in a stacktrace. + +\rSec2[stacktrace.syn]{Header \tcode{} synopsis} + +\indexheader{stacktrace}% +\begin{codeblock} +namespace std { + // \ref{stacktrace.entry}, class \tcode{stacktrace_entry} + class stacktrace_entry; + + // \ref{stacktrace.basic}, class template \tcode{basic_stacktrace} + template + class basic_stacktrace; + + // \tcode{basic_stacktrace} \grammarterm{typedef-name}s + using stacktrace = basic_stacktrace>; + + // \ref{stacktrace.basic.nonmem}, non-member functions + template + void swap(basic_stacktrace& a, basic_stacktrace& b) + noexcept(noexcept(a.swap(b))); + + string to_string(const stacktrace_entry& f); + + template + string to_string(const basic_stacktrace& st); + + template + basic_ostream& + operator<<(basic_ostream& os, const stacktrace_entry& f); + + template + basic_ostream& + operator<<(basic_ostream& os, const basic_stacktrace& st); + + namespace pmr { + using stacktrace = basic_stacktrace>; + } + + // \ref{stacktrace.basic.hash}, hash support + template struct hash; + template<> struct hash; + template struct hash>; +} +\end{codeblock} + +\rSec2[stacktrace.entry]{Class \tcode{stacktrace_entry}} + +\rSec3[stacktrace.entry.overview]{Overview} + +\begin{codeblock} +namespace std { + class @\libglobal{stacktrace_entry}@ { + public: + using native_handle_type = @\impdefx{\tcode{stacktrace_entry::native_handle_type}}@; + + // \ref{stacktrace.entry.ctor}, constructors + constexpr stacktrace_entry() noexcept; + constexpr stacktrace_entry(const stacktrace_entry& other) noexcept; + constexpr stacktrace_entry& operator=(const stacktrace_entry& other) noexcept; + + ~stacktrace_entry(); + + // \ref{stacktrace.entry.obs}, observers + constexpr native_handle_type native_handle() const noexcept; + constexpr explicit operator bool() const noexcept; + + // \ref{stacktrace.entry.query}, query + string description() const; + string source_file() const; + uint_least32_t source_line() const; + + // \ref{stacktrace.entry.cmp}, comparison + friend constexpr bool operator==(const stacktrace_entry& x, + const stacktrace_entry& y) noexcept; + friend constexpr strong_ordering operator<=>(const stacktrace_entry& x, + const stacktrace_entry& y) noexcept; + }; +} +\end{codeblock} + +\pnum +An object of type \tcode{stacktrace_entry} is either empty, +or represents a stacktrace entry and +provides operations for querying information about it. +The class \tcode{stacktrace_entry} models +\libconcept{regular}\iref{concepts.object} and +\tcode{\libconcept{three_way_comparable}}\iref{cmp.concept}. + +\rSec3[stacktrace.entry.ctor]{Constructors} + +\indexlibraryctor{stacktrace_entry}% +\begin{itemdecl} +constexpr stacktrace_entry() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{*this} is empty. +\end{itemdescr} + +\rSec3[stacktrace.entry.obs]{Observers} + +\indexlibrarymember{native_handle}{stacktrace_entry}% +\begin{itemdecl} +constexpr native_handle_type native_handle() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The semantics of this function are +\impldef{semantics of \tcode{stacktrace_entry::native_handle}}. + +\pnum +\remarks +Successive invocations of the \tcode{native_handle} function +for an unchanged \tcode{stacktrace_entry} object return identical values. +\end{itemdescr} + +\indexlibrarymember{operator bool}{stacktrace_entry}% +\begin{itemdecl} +constexpr explicit operator bool() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{false} if and only if \tcode{*this} is empty. +\end{itemdescr} + +\rSec3[stacktrace.entry.query]{Query} + +\pnum +\begin{note} +All the \tcode{stacktrace_entry} query functions treat +errors other than memory allocation errors +as ``no information available'' and do not throw in that case. +\end{note} + +\indexlibrarymember{description}{stacktrace_entry}% +\begin{itemdecl} +string description() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A description of the evaluation represented by \tcode{*this}, +or an empty string. + +\pnum +\throws +\tcode{bad_alloc} if memory for +the internal data structures or the resulting string cannot be allocated. +\end{itemdescr} + +\indexlibrarymember{source_file}{stacktrace_entry}% +\begin{itemdecl} +string source_file() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The presumed or actual name of the source file\iref{cpp.predefined} +that lexically contains the expression or statement +whose evaluation is represented by \tcode{*this}, or an empty string. + +\pnum +\throws +\tcode{bad_alloc} if memory for +the internal data structures or the resulting string cannot be allocated. +\end{itemdescr} + +\indexlibrarymember{source_line}{stacktrace_entry}% +\begin{itemdecl} +uint_least32_t source_line() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{0}, or a 1-based line number that lexically relates to the evaluation +represented by \tcode{*this}. +If \tcode{source_file} returns the presumed name of the source file, +returns the presumed line number; +if \tcode{source_file} returns the actual name of the source file, +returns the actual line number. + +\pnum +\throws +\tcode{bad_alloc} if memory for +the internal data structures cannot be allocated. +\end{itemdescr} + +\rSec3[stacktrace.entry.cmp]{Comparison} + +\indexlibrarymember{operator==}{stacktrace_entry}% +\begin{itemdecl} +friend constexpr bool operator==(const stacktrace_entry& x, const stacktrace_entry& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if and only if \tcode{x} and \tcode{y} represent +the same stacktrace entry or both \tcode{x} and \tcode{y} are empty. +\end{itemdescr} + +\rSec2[stacktrace.basic]{Class template \tcode{basic_stacktrace}} + +\rSec3[stacktrace.basic.overview]{Overview} + +\begin{codeblock} +namespace std { + template + class @\libglobal{basic_stacktrace}@ { + public: + using value_type = stacktrace_entry; + using const_reference = const value_type&; + using reference = value_type&; + using const_iterator = @\impdefx{type of \tcode{basic_stacktrace::const_iterator}}@; // see \ref{stacktrace.basic.obs} + using iterator = const_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using difference_type = @\impdefx{type of \tcode{basic_stacktrace::difference_type}}@; + using size_type = @\impdefx{type of \tcode{basic_stacktrace::size_type}}@; + using allocator_type = Allocator; + + // \ref{stacktrace.basic.ctor}, creation and assignment + static basic_stacktrace current(const allocator_type& alloc = allocator_type()) noexcept; + static basic_stacktrace current(size_type skip, + const allocator_type& alloc = allocator_type()) noexcept; + static basic_stacktrace current(size_type skip, size_type max_depth, + const allocator_type& alloc = allocator_type()) noexcept; + + basic_stacktrace() noexcept(is_nothrow_default_constructible_v); + explicit basic_stacktrace(const allocator_type& alloc) noexcept; + + basic_stacktrace(const basic_stacktrace& other); + basic_stacktrace(basic_stacktrace&& other) noexcept; + basic_stacktrace(const basic_stacktrace& other, const allocator_type& alloc); + basic_stacktrace(basic_stacktrace&& other, const allocator_type& alloc); + basic_stacktrace& operator=(const basic_stacktrace& other); + basic_stacktrace& operator=(basic_stacktrace&& other) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); + + ~basic_stacktrace(); + + // \ref{stacktrace.basic.obs}, observers + allocator_type get_allocator() const noexcept; + + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + const_reverse_iterator rbegin() const noexcept; + const_reverse_iterator rend() const noexcept; + + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + const_reverse_iterator crbegin() const noexcept; + const_reverse_iterator crend() const noexcept; + + [[nodiscard]] bool empty() const noexcept; + size_type size() const noexcept; + size_type max_size() const noexcept; + + const_reference operator[](size_type) const; + const_reference at(size_type) const; + + // \ref{stacktrace.basic.cmp}, comparisons + template + friend bool operator==(const basic_stacktrace& x, + const basic_stacktrace& y) noexcept; + template + friend strong_ordering operator<=>(const basic_stacktrace& x, + const basic_stacktrace& y) noexcept; + + // \ref{stacktrace.basic.mod}, modifiers + void swap(basic_stacktrace& other) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); + + private: + vector frames_; // \expos + }; +} +\end{codeblock} + +\pnum +The class template \tcode{basic_stacktrace} satisfies +the requirements +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of a sequence container\iref{sequence.reqmts}, +except that +\begin{itemize} +\item +only move, assignment, swap, and +operations defined for const-qualified sequence containers are supported and, +\item +the semantics of comparison functions +are different from those required for a container. +\end{itemize} + +\rSec3[stacktrace.basic.ctor]{Creation and assignment} + +\indexlibrarymember{current}{basic_stacktrace}% +\begin{itemdecl} +static basic_stacktrace current(const allocator_type& alloc = allocator_type()) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{basic_stacktrace} object +with \tcode{frames_} storing +the stacktrace of the current evaluation in the current thread of execution, or +an empty \tcode{basic_stacktrace} object +if the initialization of \tcode{frames_} failed. +\tcode{alloc} is passed to the constructor of the \tcode{frames_} object. + +\begin{note} +If the stacktrace was successfully obtained, +then \tcode{frames_.front()} is the \tcode{stacktrace_entry} +representing approximately the current evaluation, and +\tcode{frames_.back()} is the \tcode{stacktrace_entry} +representing approximately the initial function of +the current thread of execution. +\end{note} +\end{itemdescr} + +\indexlibrarymember{current}{basic_stacktrace}% +\begin{itemdecl} +static basic_stacktrace current(size_type skip, + const allocator_type& alloc = allocator_type()) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{t} be a stacktrace +as-if obtained via \tcode{basic_stacktrace::current(alloc)}. +Let \tcode{n} be \tcode{t.size()}. + +\pnum +\returns +A \tcode{basic_stacktrace} object +where \tcode{frames_} is direct-non-list-initialized from arguments +\tcode{t.begin() + min(n, skip)}, \tcode{t.end()}, and \tcode{alloc}, +or an empty \tcode{basic_stacktrace} object +if the initialization of \tcode{frames_} failed. +\end{itemdescr} + +\indexlibrarymember{current}{basic_stacktrace}% +\begin{itemdecl} +static basic_stacktrace current(size_type skip, size_type max_depth, + const allocator_type& alloc = allocator_type()) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{t} be a stacktrace +as-if obtained via \tcode{basic_stacktrace::current(alloc)}. +Let \tcode{n} be \tcode{t.size()}. + +\pnum +\expects +\tcode{skip <= skip + max_depth} is \tcode{true}. + +\pnum +\returns +A \tcode{basic_stacktrace} object +where \tcode{frames_} is direct-non-list-initialized from arguments +\tcode{t.begin() + min(n, skip)}, \tcode{t.begin() + min(n, skip + max_depth)}, +and \tcode{alloc}, +or an empty \tcode{basic_stacktrace} object +if the initialization of \tcode{frames_} failed. +\end{itemdescr} + +\indexlibraryctor{basic_stacktrace}% +\begin{itemdecl} +basic_stacktrace() noexcept(is_nothrow_default_constructible_v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{empty()} is \tcode{true}. +\end{itemdescr} + +\indexlibraryctor{basic_stacktrace}% +\begin{itemdecl} +explicit basic_stacktrace(const allocator_type& alloc) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\tcode{alloc} is passed to the \tcode{frames_} constructor. + +\pnum +\ensures +\tcode{empty()} is \tcode{true}. +\end{itemdescr} + +\indexlibraryctor{basic_stacktrace}% +\indexlibrarymember{operator=}{basic_stacktrace}% +\begin{itemdecl} +basic_stacktrace(const basic_stacktrace& other); +basic_stacktrace(const basic_stacktrace& other, const allocator_type& alloc); +basic_stacktrace(basic_stacktrace&& other, const allocator_type& alloc); +basic_stacktrace& operator=(const basic_stacktrace& other); +basic_stacktrace& operator=(basic_stacktrace&& other) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\remarks +Implementations may strengthen the exception specification +for these functions\iref{res.on.exception.handling} +by ensuring that \tcode{empty()} is \tcode{true} on failed allocation. +\end{itemdescr} + +\rSec3[stacktrace.basic.obs]{Observers} + +\indexlibrarymember{const_iterator}{basic_stacktrace}% +\begin{itemdecl} +using const_iterator = @\impdef@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The type models +\libconcept{random_access_iterator}\iref{iterator.concept.random.access} and +meets the +\oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators}. +\end{itemdescr} + +\indexlibrarymember{get_allocator}{basic_stacktrace}% +\begin{itemdecl} +allocator_type get_allocator() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{frames_.get_allocator()}. +\end{itemdescr} + +\indexlibrarymember{begin}{basic_stacktrace}% +\indexlibrarymember{cbegin}{basic_stacktrace}% +\begin{itemdecl} +const_iterator begin() const noexcept; +const_iterator cbegin() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An iterator referring to the first element in \tcode{frames_}. +If \tcode{empty()} is \tcode{true}, +then it returns the same value as \tcode{end()}. +\end{itemdescr} + +\indexlibrarymember{end}{basic_stacktrace}% +\indexlibrarymember{cend}{basic_stacktrace}% +\begin{itemdecl} +const_iterator end() const noexcept; +const_iterator cend() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The end iterator. +\end{itemdescr} + +\indexlibrarymember{rbegin}{basic_stacktrace}% +\indexlibrarymember{crbegin}{basic_stacktrace}% +\begin{itemdecl} +const_reverse_iterator rbegin() const noexcept; +const_reverse_iterator crbegin() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{reverse_iterator(cend())}. +\end{itemdescr} + +\indexlibrarymember{rend}{basic_stacktrace}% +\indexlibrarymember{crend}{basic_stacktrace}% +\begin{itemdecl} +const_reverse_iterator rend() const noexcept; +const_reverse_iterator crend() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{reverse_iterator(cbegin())}. +\end{itemdescr} + +\indexlibrarymember{empty}{basic_stacktrace}% +\begin{itemdecl} +[[nodiscard]] bool empty() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{frames_.empty()}. +\end{itemdescr} + +\indexlibrarymember{size}{basic_stacktrace}% +\begin{itemdecl} +size_type size() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{frames_.size()}. +\end{itemdescr} + +\indexlibrarymember{max_size}{basic_stacktrace}% +\begin{itemdecl} +size_type max_size() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{frames_.max_size()}. +\end{itemdescr} + +\indexlibrarymember{operator[]}{basic_stacktrace}% +\begin{itemdecl} +const_reference operator[](size_type frame_no) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{frame_no < size()} is \tcode{true}. + +\pnum +\returns +\tcode{frames_[frame_no]}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{at}{basic_stacktrace}% +\begin{itemdecl} +const_reference at(size_type frame_no) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{frames_[frame_no]}. + +\pnum +\throws +\tcode{out_of_range} if \tcode{frame_no >= size()}. +\end{itemdescr} + +\rSec3[stacktrace.basic.cmp]{Comparisons} + +\indexlibrarymember{operator==}{basic_stacktrace}% +\begin{itemdecl} +template +friend bool operator==(const basic_stacktrace& x, const basic_stacktrace& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{equal(x.begin(), x.end(), y.begin(), y.end())}. +\end{itemdescr} + +\indexlibrarymember{operator<=>}{basic_stacktrace}% +\begin{itemdecl} +template +friend strong_ordering + operator<=>(const basic_stacktrace& x, const basic_stacktrace& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.size() <=> y.size()} if \tcode{x.size() != y.size()}; +\tcode{lexicographical_compare_three_way(x.begin(), x.end(), y.begin(), y.end())} +otherwise. +\end{itemdescr} + +\rSec3[stacktrace.basic.mod]{Modifiers} + +\indexlibrarymember{swap}{basic_stacktrace}% +\begin{itemdecl} +void swap(basic_stacktrace& other) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Exchanges the contents of \tcode{*this} and \tcode{other}. +\end{itemdescr} + +\rSec3[stacktrace.basic.nonmem]{Non-member functions} + +\indexlibrarymember{swap}{basic_stacktrace}% +\begin{itemdecl} +template +void swap(basic_stacktrace& a, basic_stacktrace& b) + noexcept(noexcept(a.swap(b))); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a.swap(b)}. +\end{itemdescr} + +\indexlibrarymember{to_string}{basic_stacktrace}% +\begin{itemdecl} +string to_string(const stacktrace_entry& f); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A string with a description of \tcode{f}. + +\recommended +The description should provide information about the contained evaluation, +including information from +\tcode{f.source_file()} and \tcode{f.source_line()}. +\end{itemdescr} + +\indexlibrarymember{to_string}{basic_stacktrace}% +\begin{itemdecl} +template +string to_string(const basic_stacktrace& st); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A string with a description of \tcode{st}. +\begin{note} +The number of lines is not guaranteed to be equal to \tcode{st.size()}. +\end{note} +\end{itemdescr} + +\indexlibrarymember{operator<<}{stacktrace_entry}% +\begin{itemdecl} +template +basic_ostream& + operator<<(basic_ostream& os, const stacktrace_entry& f); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return os << to_string(f);} +\end{itemdescr} + +\indexlibrarymember{operator<<}{basic_stacktrace}% +\begin{itemdecl} +template +basic_ostream& + operator<<(basic_ostream& os, const basic_stacktrace& st); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return os << to_string(st);} +\end{itemdescr} + +\rSec3[stacktrace.basic.hash]{Hash support} + +\begin{itemdecl} +template<> struct hash; +template struct hash>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The specializations are enabled\iref{unord.hash}. +\end{itemdescr} diff --git a/source/exceptions.tex b/source/exceptions.tex index ddabdcc06f..a436edfc57 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -257,12 +257,9 @@ \pnum Throwing an exception -copy-initializes~(\ref{dcl.init}, \ref{class.copy.ctor}) a temporary object, +copy-initializes\iref{dcl.init,class.copy.ctor} a temporary object, called the \defnx{exception object}{exception handling!exception object}. -An lvalue denoting the temporary is used to initialize the -variable declared in the matching -\grammarterm{handler}\iref{except.handle}. If the type of the exception object would be an incomplete type, an abstract class type\iref{class.abstract}, @@ -655,11 +652,12 @@ of type \tcode{E}, as follows: \begin{itemize} \item -if \tcode{T} is a base class of \tcode{E}, the variable is -copy-initialized\iref{dcl.init} from the corresponding base class subobject +if \tcode{T} is a base class of \tcode{E}, +the variable is copy-initialized\iref{dcl.init} +from an lvalue of type \tcode{T} designating the corresponding base class subobject of the exception object; \item otherwise, the variable is copy-initialized\iref{dcl.init} -from the exception object. +from an lvalue of type \tcode{E} designating the exception object. \end{itemize} The lifetime of the variable ends @@ -870,7 +868,7 @@ to the exception specification of the constructor, because an exception thrown from such a destructor would call the function \tcode{std::terminate} -rather than escape the constructor~(\ref{except.throw}, \ref{except.terminate}). +rather than escape the constructor\iref{except.throw,except.terminate}. \end{note} \pnum @@ -941,7 +939,7 @@ An exception specification is considered to be \defnx{needed}{needed!exception specification} when: \begin{itemize} \item in an expression, the function is selected by -overload resolution~(\ref{over.match}, \ref{over.over}); +overload resolution\iref{over.match,over.over}; \item the function is odr-used\iref{term.odr.use} or, if it appears in an unevaluated operand, would be odr-used if the expression were @@ -1044,18 +1042,18 @@ \item% for a parallel algorithm whose \tcode{ExecutionPolicy} specifies such -behavior~(\ref{execpol.seq}, \ref{execpol.par}, \ref{execpol.parunseq}), +behavior\iref{execpol.seq,execpol.par,execpol.parunseq}, when execution of an element access function\iref{algorithms.parallel.defns} of the parallel algorithm exits via an exception\iref{algorithms.parallel.exceptions}, or \item% when the destructor or the move assignment operator is invoked on an object -of type \tcode{std::thread} that refers to a joinable thread -(\ref{thread.thread.destr}, \ref{thread.thread.assign}), or +of type \tcode{std::thread} that refers to +a joinable thread\iref{thread.thread.destr,thread.thread.assign}, or \item% when a call to a \tcode{wait()}, \tcode{wait_until()}, or \tcode{wait_for()} -function on a condition variable~(\ref{thread.condition.condvar}, \ref{thread.condition.condvarany}) +function on a condition variable\iref{thread.condition.condvar,thread.condition.condvarany} fails to meet a postcondition. \end{itemize} @@ -1096,7 +1094,7 @@ As a consequence, an exception is considered uncaught during any stack unwinding resulting from it being thrown. \end{note} -If an exception is rethrown~(\ref{expr.throw}, \ref{propagation}), +If an exception is rethrown\iref{expr.throw,propagation}, it is considered uncaught from the point of rethrow until the rethrown exception is caught. The function \tcode{std::uncaught_exceptions}\iref{uncaught.exceptions} diff --git a/source/expressions.tex b/source/expressions.tex index 75a4f5bde0..6710c39aeb 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -189,9 +189,9 @@ \item the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type\iref{expr.call}, -\item a cast to an rvalue reference to object type -(\ref{expr.type.conv}, \ref{expr.dynamic.cast}, \ref{expr.static.cast} -\ref{expr.reinterpret.cast}, \ref{expr.const.cast}, \ref{expr.cast}), +\item a cast to an rvalue reference to +object type\iref{expr.type.conv,expr.dynamic.cast,expr.static.cast, +expr.reinterpret.cast,expr.const.cast,expr.cast}, \item a subscripting operation with an xvalue array operand\iref{expr.sub}, @@ -292,7 +292,7 @@ \begin{note} A program that attempts to modify an object through a nonmodifiable lvalue or through an rvalue -is ill-formed~(\ref{expr.ass}, \ref{expr.post.incr}, \ref{expr.pre.incr}). +is ill-formed\iref{expr.ass,expr.post.incr,expr.pre.incr}. \end{note} \pnum @@ -319,7 +319,9 @@ that does not denote an object of type \cv{}~\keyword{U} within its lifetime, the behavior is undefined. \begin{note} -Unlike in C, \Cpp{} has no accesses of class type. +In C, an entire object of structure type can be accessed, e.g. using assignment. +By contrast, \Cpp{} has no notion of accessing an object of class type +through an lvalue of class type. \end{note} \rSec2[expr.type]{Type} @@ -327,7 +329,7 @@ \pnum \indextext{expression!reference}% If an expression initially has the type ``reference to -\tcode{T}''~(\ref{dcl.ref}, \ref{dcl.init.ref}), the type is adjusted to +\tcode{T}''\iref{dcl.ref,dcl.init.ref}, the type is adjusted to \tcode{T} prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression. @@ -426,13 +428,13 @@ \pnum \label{term.unevaluated.operand}% In some contexts, \defnx{unevaluated operands}{unevaluated operand} -appear~(\ref{expr.prim.req}, -\ref{expr.typeid}, -\ref{expr.sizeof}, -\ref{expr.unary.noexcept}, -\ref{dcl.type.decltype}, -\ref{temp.pre}, -\ref{temp.concept}). +appear\iref{expr.prim.req, +expr.typeid, +expr.sizeof, +expr.unary.noexcept, +dcl.type.decltype, +temp.pre, +temp.concept}. An unevaluated operand is not evaluated. \begin{note} In an unevaluated operand, a non-static class member can be @@ -469,15 +471,14 @@ Using an overloaded operator causes a function call; the above covers only operators with built-in meaning. \end{note} -If the (possibly converted) expression is a prvalue, -the temporary materialization conversion\iref{conv.rval} is applied. +The temporary materialization conversion\iref{conv.rval} is applied +if the (possibly converted) expression is a prvalue of object type. \begin{note} -If the expression is an lvalue of -class type, it must have a volatile copy constructor to initialize the -temporary object that is the result object of the lvalue-to-rvalue -conversion. +If the original expression is an lvalue of class type, +it must have a volatile copy constructor to initialize the temporary object +that is the result object of the temporary materialization conversion. \end{note} -The glvalue expression is evaluated and its value is discarded. +The expression is evaluated and its result (if any) is discarded. \rSec1[conv]{Standard conversions} @@ -1056,7 +1057,7 @@ The rule for conversion of pointers to members (from pointer to member of base to pointer to member of derived) appears inverted compared to the rule for pointers to objects (from pointer to derived to pointer to -base)~(\ref{conv.ptr}, \ref{class.derived}). This inversion is +base)\iref{conv.ptr,class.derived}. This inversion is necessary to ensure type safety. Note that a pointer to member is not an object pointer or a function pointer and the rules for conversions @@ -1196,7 +1197,7 @@ \pnum \indextext{\idxcode{this}}% The keyword \keyword{this} names a pointer to the object for which an implicit object member -function\iref{class.mfct.non-static} is invoked or a non-static data member's +function\iref{class.mfct.non.static} is invoked or a non-static data member's initializer\iref{class.mem} is evaluated. \pnum @@ -1254,7 +1255,7 @@ \begin{codeblock} class Outer { int a[sizeof(*this)]; // error: not inside a member function - unsigned int sz = sizeof(*this); // OK: in default member initializer + unsigned int sz = sizeof(*this); // OK, in default member initializer void f() { int b[sizeof(*this)]; // OK @@ -1304,7 +1305,7 @@ \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}). +a class member access expression\iref{class.mfct.non.static}). \begin{example} \tcode{o.x} is interpreted as \tcode{o.$u$.x}, where $u$ names the anonymous union member. @@ -1331,7 +1332,7 @@ refers to the member's class \begin{footnote} This also applies when the object expression -is an implicit \tcode{(*\keyword{this})}~(\ref{class.mfct.non-static}). +is an implicit \tcode{(*\keyword{this})}\iref{class.mfct.non.static}. \end{footnote} or a class derived from that class, or @@ -1363,7 +1364,7 @@ \pnum For an \grammarterm{id-expression} that denotes an overload set, overload resolution is performed -to select a unique function~(\ref{over.match}, \ref{over.over}). +to select a unique function\iref{over.match,over.over}. \begin{note} A program cannot refer to a function with a trailing \grammarterm{requires-clause} @@ -1420,7 +1421,7 @@ 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~(\ref{class.mfct.non-static}). +class member access expression\iref{class.mfct.non.static}. \end{note} \pnum @@ -1433,10 +1434,9 @@ the \grammarterm{template-id} or \grammarterm{type-name} of $U$, if any. \end{itemize} \begin{note} -Other constructs that contain names to look up can have several component names -(\ref{expr.prim.id.qual}, \ref{dcl.type.simple}, \ref{dcl.type.elab}, -\ref{dcl.mptr}, \ref{namespace.udecl}, \ref{temp.param}, \ref{temp.names}, -\ref{temp.res}). +Other constructs that contain names to look up can have several +component names\iref{expr.prim.id.qual,dcl.type.simple,dcl.type.elab, +dcl.mptr,namespace.udecl,temp.param,temp.names,temp.res}. \end{note} The \defnadj{terminal}{name} of a construct is the component name of that construct that appears lexically last. @@ -1448,7 +1448,7 @@ in a \grammarterm{lambda-expression} at program point $P$ and the entity is a local entity\iref{basic.pre} or a variable declared by an \grammarterm{init-capture}\iref{expr.prim.lambda.capture}, -then let $S$ be the \grammarterm{compound-expression} of +then let $S$ be the \grammarterm{compound-statement} of the innermost enclosing \grammarterm{lambda-expression} of $P$. If naming the entity from outside of an unevaluated operand within $S$ would refer to an entity @@ -1645,7 +1645,7 @@ as the right operand of a class member access\iref{expr.ref} that forms the \grammarterm{postfix-expression} of a function call\iref{expr.call}. \begin{note} -Such a call ends the lifetime of the object (\ref{expr.call}, \ref{basic.life}). +Such a call ends the lifetime of the object\iref{expr.call,basic.life}. \end{note} \pnum @@ -1671,8 +1671,9 @@ \begin{bnf} \nontermdef{lambda-expression}\br - lambda-introducer lambda-declarator compound-statement\br - lambda-introducer \terminal{<} template-parameter-list \terminal{>} \opt{requires-clause} lambda-declarator compound-statement + lambda-introducer \opt{attribute-specifier-seq} lambda-declarator compound-statement\br + lambda-introducer \terminal{<} template-parameter-list \terminal{>} \opt{requires-clause} \opt{attribute-specifier-seq}\br + \bnfindent lambda-declarator compound-statement \end{bnf} \begin{bnf} @@ -1682,13 +1683,24 @@ \begin{bnf} \nontermdef{lambda-declarator}\br - lambda-specifiers\br - \terminal{(} parameter-declaration-clause \terminal{)} lambda-specifiers \opt{requires-clause} + lambda-specifier-seq \opt{noexcept-specifier} \opt{attribute-specifier-seq} \opt{trailing-return-type}\br + noexcept-specifier \opt{attribute-specifier-seq} \opt{trailing-return-type}\br + \opt{trailing-return-type}\br + \terminal{(} parameter-declaration-clause \terminal{)} \opt{lambda-specifier-seq} \opt{noexcept-specifier} \opt{attribute-specifier-seq}\br + \bnfindent \opt{trailing-return-type} \opt{requires-clause} +\end{bnf} + +\begin{bnf} +\nontermdef{lambda-specifier}\br + \keyword{consteval}\br + \keyword{constexpr}\br + \keyword{mutable} \end{bnf} \begin{bnf} -\nontermdef{lambda-specifiers}\br - \opt{decl-specifier-seq} \opt{noexcept-specifier} \opt{attribute-specifier-seq} \opt{trailing-return-type} +\nontermdef{lambda-specifier-seq}\br + lambda-specifier\br + lambda-specifier lambda-specifier-seq \end{bnf} \pnum @@ -1713,31 +1725,47 @@ \end{note} \pnum -In the \grammarterm{decl-specifier-seq} of the \grammarterm{lambda-declarator}, -each \grammarterm{decl-specifier} -shall be one of \keyword{mutable}, \keyword{constexpr}, or \keyword{consteval}. +An ambiguity can arise +because a \grammarterm{requires-clause} can end in +an \grammarterm{attribute-specifier-seq}, +which collides with +the \grammarterm{attribute-specifier-seq} in \grammarterm{lambda-expression}. +In such cases, +any attributes are treated as +\grammarterm{attribute-specifier-seq} in \grammarterm{lambda-expression}. +\begin{note} +Such ambiguous cases cannot have valid semantics +because the constraint expression would not have type \keyword{bool}. +\end{note} + +\pnum +A \grammarterm{lambda-specifier-seq} +shall contain at most one of each \grammarterm{lambda-specifier} and +shall not contain both \keyword{constexpr} and \keyword{consteval}. If the \grammarterm{lambda-declarator} contains an explicit object parameter\iref{dcl.fct}, -then no \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq} +then no \grammarterm{lambda-specifier} in the \grammarterm{lambda-specifier-seq} shall be \keyword{mutable}. \begin{note} The trailing \grammarterm{requires-clause} is described in \ref{dcl.decl}. \end{note} \pnum -If a \grammarterm{lambda-expression} includes an empty -\grammarterm{lambda-declarator}, it is as if the \grammarterm{lambda-declarator} were -\tcode{()}. -The lambda return type is \keyword{auto}, which is replaced by the -type specified by the -\grammarterm{trailing-return-type} if provided and/or deduced from -\tcode{return} statements as described in~\ref{dcl.spec.auto}. +If a \grammarterm{lambda-declarator} does not include +a \grammarterm{parameter-declaration-clause}, +it is as if \tcode{()} were inserted +at the start of the \grammarterm{lambda-declarator}. +If the \grammarterm{lambda-declarator} +does not include a \grammarterm{trailing-return-type}, +the lambda return type is \keyword{auto}, +which is deduced from \keyword{return} statements +as described in \ref{dcl.spec.auto}. \begin{example} \begin{codeblock} -auto x1 = [](int i) { return i; }; // OK: return type is \tcode{int} +auto x1 = [](int i) { return i; }; // OK, return type is \tcode{int} auto x2 = []{ return { 1, 2 }; }; // error: deducing return type from \grammarterm{braced-init-list} int j; -auto x3 = []()->auto&& { return j; }; // OK: return type is \tcode{int\&} +auto x3 = []()->auto&& { return j; }; // OK, return type is \tcode{int\&} \end{codeblock} \end{example} @@ -1748,8 +1776,8 @@ if the lambda has a \grammarterm{template-parameter-list}. \begin{example} \begin{codeblock} -int i = [](int i, auto a) { return i; }(3, 4); // OK: a generic lambda -int j = [](T t, int i) { return i; }(3, 4); // OK: a generic lambda +int i = [](int i, auto a) { return i; }(3, 4); // OK, a generic lambda +int j = [](T t, int i) { return i; }(3, 4); // OK, a generic lambda \end{codeblock} \end{example} @@ -1812,7 +1840,7 @@ bool b = glambda(3, 3.14); // OK auto vglambda = [](auto printer) { - return [=](auto&& ... ts) { // OK: \tcode{ts} is a function parameter pack + return [=](auto&& ... ts) { // OK, \tcode{ts} is a function parameter pack printer(std::forward(ts)...); return [=]() { @@ -1822,13 +1850,13 @@ }; auto p = vglambda( [](auto v1, auto v2, auto v3) { std::cout << v1 << v2 << v3; } ); -auto q = p(1, 'a', 3.14); // OK: outputs \tcode{1a3.14} -q(); // OK: outputs \tcode{1a3.14} +auto q = p(1, 'a', 3.14); // OK, outputs \tcode{1a3.14} +q(); // OK, outputs \tcode{1a3.14} -auto fact = [](this auto self, int n) -> int { // OK: explicit object parameter +auto fact = [](this auto self, int n) -> int { // OK, explicit object parameter return (n <= 1) ? 1 : n * self(n-1); }; -std::cout << fact(5); // OK: outputs 120 +std::cout << fact(5); // OK, outputs 120 \end{codeblock} \end{example} @@ -1863,7 +1891,7 @@ \pnum The function call operator or operator template is declared -\keyword{const}~(\ref{class.mfct.non-static}) if and only if the +\keyword{const}\iref{class.mfct.non.static} if and only if the \grammarterm{lambda-expression}'s \grammarterm{parameter-declaration-clause} is not followed by \keyword{mutable} and the \grammarterm{lambda-declarator} does not contain @@ -1873,6 +1901,9 @@ applies to the corresponding function call operator or operator template. An \grammarterm{attribute-specifier-seq} in a \grammarterm{lambda-declarator} appertains to the type of the corresponding function call operator or operator template. +An \grammarterm{attribute-specifier-seq} in a \grammarterm{lambda-expression} +preceding a \grammarterm{lambda-declarator} +appertains to the corresponding function call operator or operator template. The function call operator or any given operator template specialization is a constexpr function if either the corresponding \grammarterm{lambda-expression}{'s} @@ -2020,7 +2051,7 @@ f1(glambda); // OK f2(glambda); // error: ID is not convertible g(glambda); // error: ambiguous -h(glambda); // OK: calls \#3 since it is convertible from ID +h(glambda); // OK, calls \#3 since it is convertible from ID int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK \end{codeblock} \end{example} @@ -2042,8 +2073,8 @@ \begin{example} \begin{codeblock} auto GL = [](auto a) { std::cout << a; return a; }; -int (*GL_int)(int) = GL; // OK: through conversion function template -GL_int(3); // OK: same as \tcode{GL(3)} +int (*GL_int)(int) = GL; // OK, through conversion function template +GL_int(3); // OK, same as \tcode{GL(3)} \end{codeblock} \end{example} @@ -2201,7 +2232,7 @@ \pnum The \grammarterm{identifier} in a \grammarterm{simple-capture} -shall denote a local entity (\ref{basic.lookup.unqual}, \ref{basic.pre}). +shall denote a local entity\iref{basic.lookup.unqual,basic.pre}. The \grammarterm{simple-capture}{s} \keyword{this} and \tcode{* \keyword{this}} denote the local entity \tcode{*\keyword{this}}. An entity that is designated by a @@ -2297,16 +2328,16 @@ void test() { const int x = 17; auto g = [](auto a) { - f(x); // OK: calls \#1, does not capture \tcode{x} + f(x); // OK, calls \#1, does not capture \tcode{x} }; auto g1 = [=](auto a) { - f(x); // OK: calls \#1, captures \tcode{x} + f(x); // OK, calls \#1, captures \tcode{x} }; auto g2 = [=](auto a) { int selector[sizeof(a) == 1 ? 1 : 2]{}; - f(x, selector); // OK: captures \tcode{x}, can call \#1 or \#2 + f(x, selector); // OK, captures \tcode{x}, can call \#1 or \#2 }; auto g3 = [=](auto a) { @@ -2353,8 +2384,8 @@ auto m1 = [=]{ int const M = 30; auto m2 = [i]{ - int x[N][M]; // OK: \tcode{N} and \tcode{M} are not odr-used - x[0][0] = i; // OK: \tcode{i} is explicitly captured by \tcode{m2} and implicitly captured by \tcode{m1} + int x[N][M]; // OK, \tcode{N} and \tcode{M} are not odr-used + x[0][0] = i; // OK, \tcode{i} is explicitly captured by \tcode{m2} and implicitly captured by \tcode{m1} }; }; struct s1 { @@ -2365,10 +2396,10 @@ auto m3 = [this,m] { auto m4 = [&,j] { // error: \tcode{j} not odr-usable due to intervening lambda \tcode{m3} int x = n; // error: \tcode{n} is odr-used but not odr-usable due to intervening lambda \tcode{m3} - x += m; // OK: \tcode{m} implicitly captured by \tcode{m4} and explicitly captured by \tcode{m3} + x += m; // OK, \tcode{m} implicitly captured by \tcode{m4} and explicitly captured by \tcode{m3} x += i; // error: \tcode{i} is odr-used but not odr-usable // due to intervening function and class scopes - x += f; // OK: \keyword{this} captured implicitly by \tcode{m4} and explicitly by \tcode{m3} + x += f; // OK, \keyword{this} captured implicitly by \tcode{m4} and explicitly by \tcode{m3} }; }; } @@ -2461,8 +2492,8 @@ void g() { const int N = 10; [=] { - int arr[N]; // OK: not an odr-use, refers to automatic variable - f(&N); // OK: causes \tcode{N} to be captured; \tcode{\&N} points to + int arr[N]; // OK, not an odr-use, refers to automatic variable + f(&N); // OK, causes \tcode{N} to be captured; \tcode{\&N} points to // the corresponding member of the closure type }; } @@ -2515,7 +2546,7 @@ \item If \tcode{m1} captures the entity by copy, \tcode{m2} captures the corresponding non-static data member of \tcode{m1}'s closure type; -if \tcode{m1} is not mutable, the non-static data member is considered to be const-qualified. +if \tcode{m1} is not \keyword{mutable}, the non-static data member is considered to be const-qualified. \item If \tcode{m1} captures the entity by reference, \tcode{m2} captures the same entity captured by \tcode{m1}. @@ -2680,7 +2711,7 @@ \begin{bnf} \nontermdef{requirement-seq}\br requirement\br - requirement-seq requirement + requirement requirement-seq \end{bnf} \begin{bnf} @@ -2831,7 +2862,7 @@ \pnum A \grammarterm{type-requirement} that names a class template specialization -does not require that type to be complete\iref{basic.types}. +does not require that type to be complete\iref{term.incomplete.type}. \rSec3[expr.prim.req.compound]{Compound requirements} \indextext{requirement!compound}% @@ -3082,7 +3113,7 @@ \pnum For a call to a non-static member function, the postfix expression shall be an -implicit~(\ref{class.mfct.non-static}, \ref{class.static}) or explicit +implicit\iref{class.mfct.non.static,class.static} or explicit class member access\iref{expr.ref} whose \grammarterm{id-expression} is a function member name, or a pointer-to-member expression\iref{expr.mptr.oper} selecting a function member; the call is as a member of @@ -3091,7 +3122,7 @@ member access, the implied object is the one pointed to by \keyword{this}. \begin{note} A member function call of the form \tcode{f()} is interpreted as -\tcode{(*\keyword{this}).f()} (see~\ref{class.mfct.non-static}). +\tcode{(*\keyword{this}).f()} (see~\ref{class.mfct.non.static}). \end{note} \pnum @@ -3131,7 +3162,7 @@ the function call destroys the object of scalar type denoted by the object expression -of the class member access (\ref{expr.ref}, \ref{basic.life}). +of the class member access\iref{expr.ref,basic.life}. \pnum Calling a function through an @@ -3152,7 +3183,7 @@ \indextext{function parameter|see{parameter}}% \indextext{initialization!parameter}% When a function is called, each parameter\iref{dcl.fct} is -initialized~(\ref{dcl.init}, \ref{class.copy.ctor}) with +initialized\iref{dcl.init,class.copy.ctor} with its corresponding argument. If the function is an explicit object member function and there is an implied object argument\iref{over.call.func}, @@ -3270,7 +3301,7 @@ 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 -needed~(\ref{dcl.type}, \ref{lex.literal}, \ref{lex.string}, \ref{dcl.array}, \ref{class.temporary}). +needed\iref{dcl.type,lex.literal,lex.string,dcl.array,class.temporary}. In addition, it is possible to modify the values of non-constant objects through pointer parameters. \end{note} @@ -3871,7 +3902,7 @@ the result refers to the object or the specified base class subobject thereof; otherwise, the lvalue-to-rvalue conversion\iref{conv.lval} is applied to the bit-field and the resulting prvalue is used as the -\grammarterm{expression} of the \keyword{static_cast} for the remainder of this subclause. +operand of the \keyword{static_cast} for the remainder of this subclause. If \tcode{T2} is an inaccessible\iref{class.access} or ambiguous\iref{class.member.lookup} base class of \tcode{T1}, a program that necessitates such a cast is ill-formed. @@ -3911,8 +3942,11 @@ \pnum Any expression can be explicitly converted to type \cv{}~\keyword{void}, -in which case it becomes a discarded-value -expression\iref{expr.prop}. +in which case the operand is a discarded-value expression\iref{expr.prop}. +\begin{note} +Such a \keyword{static_cast} has no result +as it is a prvalue of type \keyword{void}; see~\ref{basic.lval}. +\end{note} \begin{note} However, if the value is in a temporary object\iref{class.temporary}, the destructor for that @@ -4791,7 +4825,7 @@ \end{note} \begin{note} See~\ref{intro.memory} for the definition of byte -and~\ref{basic.types} for the definition of object representation. +and~\ref{term.object.representation} for the definition of object representation. \end{note} \pnum @@ -4848,7 +4882,7 @@ A \keyword{sizeof} expression is an integral constant expression\iref{expr.const}. The type \tcode{std::size_t} is defined in the standard header -\libheader{cstddef}~(\ref{cstddef.syn}, \ref{support.types.layout}). +\libheader{cstddef}\iref{cstddef.syn,support.types.layout}. \end{note} \rSec3[expr.alignof]{Alignof} @@ -4867,7 +4901,7 @@ An \keyword{alignof} expression is an integral constant expression\iref{expr.const}. The type \tcode{std::size_t} is defined in the standard header -\libheader{cstddef}~(\ref{cstddef.syn}, \ref{support.types.layout}). +\libheader{cstddef}\iref{cstddef.syn,support.types.layout}. \end{note} \pnum @@ -4917,9 +4951,9 @@ \grammarterm{type-id}\iref{dcl.name} or \grammarterm{new-type-id} to which it is applied. The type of that object is the \defnadj{allocated}{type}. \indextext{type!incomplete}% -This type shall be a complete object type, but not an abstract class -type or array -thereof~(\ref{intro.object}, \ref{basic.types}, \ref{class.abstract}). +This type shall be a complete object type\iref{term.incomplete.type}, +but not an abstract class type\iref{class.abstract} or array +thereof\iref{intro.object}. \begin{note} Because references are not objects, references cannot be created by \grammarterm{new-expression}{s}. @@ -5057,7 +5091,7 @@ the allocated object is an array with \tcode{n} elements, where \tcode{n} is determined from the number of initial elements supplied in -the \grammarterm{new-initializer}~(\ref{dcl.init.aggr}, \ref{dcl.init.string}). +the \grammarterm{new-initializer}\iref{dcl.init.aggr,dcl.init.string}. \pnum \indextext{\idxcode{new}}% @@ -5160,7 +5194,7 @@ \begin{note} An implementation is required to provide default definitions for the global allocation -functions~(\ref{basic.stc.dynamic}, \ref{new.delete.single}, \ref{new.delete.array}). +functions\iref{basic.stc.dynamic,new.delete.single,new.delete.array}. A \Cpp{} program can provide alternative definitions of these functions\iref{replacement.functions} and/or class-specific versions\iref{class.free}. @@ -5183,7 +5217,7 @@ \pnum An implementation is allowed to omit a call to a replaceable global allocation -function~(\ref{new.delete.single}, \ref{new.delete.array}). When it does so, +function\iref{new.delete.single,new.delete.array}. When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another \grammarterm{new-expression}. @@ -5356,8 +5390,8 @@ it indicates failure to allocate storage by throwing a \indextext{\idxcode{bad_alloc}}% \indexlibraryglobal{bad_alloc}% -\tcode{std::bad_alloc} exception~(\ref{basic.stc.dynamic.allocation}, -\ref{except}, \ref{bad.alloc}); +\tcode{std::bad_alloc} +exception\iref{basic.stc.dynamic.allocation,except,bad.alloc}; it returns a non-null pointer otherwise. If the allocation function has a non-throwing exception specification, it returns null to indicate failure to allocate storage @@ -5643,7 +5677,7 @@ \begin{note} \indextext{\idxcode{operator delete}}% An implementation provides default definitions of the global -deallocation functions (\ref{new.delete.single}, \ref{new.delete.array}). +deallocation functions\iref{new.delete.single,new.delete.array}. A \Cpp{} program can provide alternative definitions of these functions\iref{replacement.functions}, and/or class-specific versions\iref{class.free}. @@ -5758,12 +5792,12 @@ the first argument was not the result of a prior call to a replaceable allocation function or the second or third argument was not the corresponding argument in said call, -the behavior is undefined~(\ref{new.delete.single}, \ref{new.delete.array}). +the behavior is undefined\iref{new.delete.single,new.delete.array}. \end{note} \pnum Access and ambiguity control are done for both the deallocation function -and the destructor~(\ref{class.dtor}, \ref{class.free}). +and the destructor\iref{class.dtor,class.free}. \rSec2[expr.cast]{Explicit type conversion (cast notation)}% \indextext{expression!cast|(} @@ -6785,7 +6819,7 @@ Otherwise, the result is a prvalue. If the second and third operands do not have the same type, and either has (possibly cv-qualified) class type, overload resolution is used to determine the conversions (if any) -to be applied to the operands~(\ref{over.match.oper}, \ref{over.built}). +to be applied to the operands\iref{over.match.oper,over.built}. If the overload resolution fails, the program is ill-formed. Otherwise, the conversions thus determined are applied, and the converted operands are used in place of the original operands for the remainder of this @@ -7041,7 +7075,7 @@ \item an assignment to an object of class type, in which case the initializer list is passed as the argument to the assignment operator function selected by -overload resolution~(\ref{over.ass}, \ref{over.match}). +overload resolution\iref{over.ass,over.match}. \end{itemize} \begin{example} \begin{codeblock} @@ -7265,7 +7299,7 @@ a reference to \keyword{this} or to a variable with automatic storage duration defined outside that \grammarterm{lambda-expression}, where -the reference would be an odr-use~(\ref{term.odr.use}, \ref{expr.prim.lambda}); +the reference would be an odr-use\iref{term.odr.use,expr.prim.lambda}; \begin{example} \begin{codeblock} void g() { @@ -7304,8 +7338,7 @@ a \keyword{reinterpret_cast}\iref{expr.reinterpret.cast}; \item -a modification of an object~(\ref{expr.ass}, \ref{expr.post.incr}, -\ref{expr.pre.incr}) +a modification of an object\iref{expr.ass,expr.post.incr,expr.pre.incr} unless it is applied to a non-volatile lvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of $E$; @@ -7318,8 +7351,7 @@ \item a \grammarterm{new-expression}\iref{expr.new}, unless the selected allocation function is -a replaceable global allocation function~(\ref{new.delete.single}, -\ref{new.delete.array}) and +a replaceable global allocation function\iref{new.delete.single,new.delete.array} and the allocated storage is deallocated within the evaluation of $E$; \item @@ -7360,7 +7392,11 @@ an \grammarterm{asm-declaration}\iref{dcl.asm}; \item -an invocation of the \tcode{va_arg} macro\iref{cstdarg.syn}; or +an invocation of the \tcode{va_arg} macro\iref{cstdarg.syn}; + +\item +a non-constant library call\iref{defns.nonconst.libcall}; +or \item a \keyword{goto} statement\iref{stmt.goto}. @@ -7379,7 +7415,7 @@ constexpr A(bool b) : m(b?42:x) { } int m; }; -constexpr int v = A(true).m; // OK: constructor call initializes \tcode{m} with the value \tcode{42} +constexpr int v = A(true).m; // OK, constructor call initializes \tcode{m} with the value \tcode{42} constexpr int w = A(false).m; // error: initializer for \tcode{m} is \tcode{x}, which is non-constant @@ -7389,7 +7425,7 @@ return x; } constexpr int f2(int k) { - int x = k; // OK: not required to be a constant expression + int x = k; // OK, not required to be a constant expression // because \tcode{x} is not \keyword{constexpr} return x; } @@ -7403,10 +7439,10 @@ return x; } constexpr int h(int k) { - int x = incr(k); // OK: \tcode{incr(k)} is not required to be a core constant expression + int x = incr(k); // OK, \tcode{incr(k)} is not required to be a core constant expression return x; } -constexpr int y = h(1); // OK: initializes \tcode{y} with the value \tcode{2} +constexpr int y = h(1); // OK, initializes \tcode{y} with the value \tcode{2} // \tcode{h(1)} is a core constant expression because // the lifetime of \tcode{k} begins inside \tcode{h(1)} \end{codeblock} @@ -7421,7 +7457,8 @@ even if the actual evaluation of such a call would otherwise fail the requirements for a core constant expression. Similarly, the evaluation of a call to -\tcode{std::construct_at} or \tcode{std::ranges::construct_at} +\tcode{std::construct_at} or +\tcode{std::ranges::construct_at}\iref{specialized.construct} does not disqualify $E$ from being a core constant expression unless the first argument, of type \tcode{T*}, does not point diff --git a/source/front.tex b/source/front.tex index 1961ad74cf..ef9189eb80 100644 --- a/source/front.tex +++ b/source/front.tex @@ -12,6 +12,11 @@ \renewcommand\@pnumwidth{2.5em} \makeatother +% Disable indexing within the table of contents +\newcommand{\indexoff}[2][generalindex]{} +\let\oindex\index +\let\index\indexoff + %% Include table of contents. Do not list "Contents" %% within it (per ISO request) but do include a %% bookmark for it in the PDF. @@ -19,4 +24,7 @@ \pdfbookmark{\contentsname}{toctarget} \hypertarget{toctarget}{\tableofcontents*} +% Restore indexing +\let\index\oindex + \setcounter{tocdepth}{5} diff --git a/source/future.tex b/source/future.tex index ee0a3f2443..17bd08d0ea 100644 --- a/source/future.tex +++ b/source/future.tex @@ -61,7 +61,7 @@ \rSec1[depr.array.comp]{Array comparisons} \pnum -Equality and relational comparisons (\ref{expr.eq}, \ref{expr.rel}) +Equality and relational comparisons\iref{expr.eq,expr.rel} between two operands of array type are deprecated. \begin{note} @@ -565,7 +565,8 @@ 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.) +\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} @@ -1319,6 +1320,7 @@ The following member is defined in addition to those specified in \ref{default.allocator}: +\indexlibrarymember{is_always_equal}{allocator}% \begin{codeblock} namespace std { template class allocator { @@ -1368,6 +1370,14 @@ namespace std { template struct is_pod; template inline constexpr bool is_pod_v = is_pod::value; + template // \seebelow + struct aligned_storage; + template // \seebelow + using @\libglobal{aligned_storage_t}@ = typename aligned_storage::type; + template + struct aligned_union; + template + using @\libglobal{aligned_union_t}@ = typename aligned_union::type; } \end{codeblock} @@ -1376,6 +1386,7 @@ any of the templates defined in this subclause is undefined, unless explicitly permitted by the specification of the corresponding template. +\indexlibraryglobal{is_pod}% \begin{itemdecl} template struct is_pod; \end{itemdecl} @@ -1402,6 +1413,74 @@ \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} is 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} is 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 diff --git a/source/grammar.tex b/source/grammar.tex index affc8ca89b..8501d39453 100644 --- a/source/grammar.tex +++ b/source/grammar.tex @@ -9,7 +9,7 @@ It is not an exact statement of the language. In particular, the grammar described here accepts a superset of valid \Cpp{} constructs. -Disambiguation rules~(\ref{stmt.ambig}, \ref{dcl.spec}, \ref{class.member.lookup}) +Disambiguation rules\iref{stmt.ambig,dcl.spec,class.member.lookup} are applied to distinguish expressions from declarations. Further, access control, ambiguity, and type rules are used to weed out syntactically valid but meaningless constructs. diff --git a/source/intro.tex b/source/intro.tex index 97433869f5..9200f81357 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -92,7 +92,7 @@ \end{footnote} \pnum -The operating system interface described in ISO/IEC 9945:2003 is +The operating system interface described in ISO/IEC 9945:2009 is hereinafter called \defn{POSIX}. \pnum @@ -118,12 +118,12 @@ and the following apply. \pnum -ISO and IEC maintain terminological databases +ISO and IEC maintain terminology databases for use in standardization at the following addresses: \begin{itemize} \item ISO Online browsing platform: available at \url{https://www.iso.org/obp} -\item IEC Electropedia: available at \url{http://www.electropedia.org/} +\item IEC Electropedia: available at \url{http://www.electropedia.org} \end{itemize} \pnum @@ -137,9 +137,9 @@ read or modify the value of an object \begin{defnote} -Only objects of scalar type can be accessed. +Only glvalues of scalar type can be used to access objects. Reads of scalar objects are described in \ref{conv.lval} and -modifications of scalar objects are describred in +modifications of scalar objects are described in \ref{expr.ass}, \ref{expr.post.incr}, and \ref{expr.pre.incr}. Attempts to read or modify an object of class type typically invoke a constructor\iref{class.ctor} @@ -283,7 +283,7 @@ message belonging to an \impldef{diagnostic message} subset of the implementation's output messages -\definition{direct-non-list-initialization}{defns.direct-non-list-init} +\definition{direct-non-list-initialization}{defns.direct.non.list.init} \indexdefn{direct-non-list-initialization}% direct-initialization that is not list-initialization @@ -305,7 +305,7 @@ \definition{dynamic type}{defns.dynamic.type.prvalue} \defncontext{prvalue} static type of the prvalue expression -\definition{expression-equivalent}{defns.expression-equivalent} +\definition{expression-equivalent}{defns.expression.equivalent} \defncontext{library} \indexdefn{expression-equivalent}% expressions that all have the same effects, @@ -423,6 +423,12 @@ sequence of one or more bytes representing the code unit sequence for an encoded character of the execution character set +\indexdefn{library call!non-constant}% +\definition{non-constant library call}{defns.nonconst.libcall} +invocation of a library function that, +as part of evaluating any expression \tcode{E}, +prevents \tcode{E} from being a core constant expression + \definition{NTCTS}{defns.ntcts} \defncontext{library} \indexdefn{NTCTS}% diff --git a/source/iostreams.tex b/source/iostreams.tex index 2ea745316f..bb586b70d6 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -135,7 +135,7 @@ \rSec2[iostreams.threadsafety]{Thread safety} \pnum -Concurrent access to a stream object~(\ref{string.streams}, \ref{file.streams}), stream buffer +Concurrent access to a stream object\iref{string.streams,file.streams}, stream buffer object\iref{stream.buffers}, or C Library stream\iref{c.files} by multiple threads may result in a data race\iref{intro.multithread} unless otherwise specified\iref{iostream.objects}. \begin{note} @@ -3593,8 +3593,7 @@ Influences stream buffering in a way that is defined separately for each class derived from \tcode{basic_streambuf} -in this Clause~(\ref{stringbuf.virtuals}, -\ref{filebuf.virtuals}). +in this Clause\iref{stringbuf.virtuals,filebuf.virtuals}. \pnum \default @@ -3617,8 +3616,7 @@ the controlled sequences in a way that is defined separately for each class derived from \tcode{basic_streambuf} -in this Clause~(\ref{stringbuf.virtuals}, -\ref{filebuf.virtuals}). +in this Clause\iref{stringbuf.virtuals,filebuf.virtuals}. \pnum \default @@ -3640,8 +3638,7 @@ the controlled sequences in a way that is defined separately for each class derived from \tcode{basic_streambuf} -in this Clause~(\ref{stringbuf}, -\ref{filebuf}). +in this Clause\iref{stringbuf,filebuf}. \pnum \default @@ -4030,8 +4027,7 @@ \begin{footnote} That is, for each class derived from a specialization of \tcode{basic_streambuf} -in this Clause~(\ref{stringbuf}, -\ref{filebuf}), +in this Clause\iref{stringbuf,filebuf}, a specification of how consuming a character effects the associated output sequence is given. There is no requirement on a program-defined class. \end{footnote} @@ -4291,7 +4287,7 @@ basic_istream(const basic_istream&) = delete; basic_istream(basic_istream&& rhs); - // \ref{istream.assign}, assign and swap + // \ref{istream.assign}, assignment and swap basic_istream& operator=(const basic_istream&) = delete; basic_istream& operator=(basic_istream&& rhs); void swap(basic_istream& rhs); @@ -5714,7 +5710,7 @@ basic_iostream(const basic_iostream&) = delete; basic_iostream(basic_iostream&& rhs); - // \ref{iostream.assign}, assign and swap + // \ref{iostream.assign}, assignment and swap basic_iostream& operator=(const basic_iostream&) = delete; basic_iostream& operator=(basic_iostream&& rhs); void swap(basic_iostream& rhs); @@ -5874,7 +5870,7 @@ basic_ostream(const basic_ostream&) = delete; basic_ostream(basic_ostream&& rhs); - // \ref{ostream.assign}, assign and swap + // \ref{ostream.assign}, assignment and swap basic_ostream& operator=(const basic_ostream&) = delete; basic_ostream& operator=(basic_ostream&& rhs); void swap(basic_ostream& rhs); @@ -7587,7 +7583,7 @@ basic_stringbuf(basic_stringbuf&& rhs); basic_stringbuf(basic_stringbuf&& rhs, const Allocator& a); - // \ref{stringbuf.assign}, assign and swap + // \ref{stringbuf.assign}, assignment and swap basic_stringbuf& operator=(const basic_stringbuf&) = delete; basic_stringbuf& operator=(basic_stringbuf&& rhs); void swap(basic_stringbuf& rhs) noexcept(@\seebelow@); @@ -8383,9 +8379,10 @@ basic_istringstream(const basic_istringstream&) = delete; basic_istringstream(basic_istringstream&& rhs); - // \ref{istringstream.assign}, assign and swap basic_istringstream& operator=(const basic_istringstream&) = delete; basic_istringstream& operator=(basic_istringstream&& rhs); + + // \ref{istringstream.swap}, swap void swap(basic_istringstream& rhs); // \ref{istringstream.members}, members @@ -8450,7 +8447,7 @@ Initializes the base class with \tcode{basic_istream(addressof(sb))}\iref{istream} and \tcode{sb} with -\tcode{basic_stringbuf(s, which | ios_base::in)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(s, which | ios_base::in)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_istringstream}% @@ -8497,7 +8494,7 @@ Initializes the base class with \tcode{basic_istream(addressof(sb))}\iref{istream} and \tcode{sb} with -\tcode{basic_stringbuf(s, which | ios_base::in, a)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(s, which | ios_base::in, a)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_istringstream}% @@ -8532,7 +8529,7 @@ to install the contained \tcode{basic_stringbuf}. \end{itemdescr} -\rSec3[istringstream.assign]{Assignment and swap} +\rSec3[istringstream.swap]{Swap} \indexlibrarymember{swap}{basic_istringstream}% \begin{itemdecl} @@ -8697,9 +8694,10 @@ basic_ostringstream(const basic_ostringstream&) = delete; basic_ostringstream(basic_ostringstream&& rhs); - // \ref{ostringstream.assign}, assign and swap basic_ostringstream& operator=(const basic_ostringstream&) = delete; basic_ostringstream& operator=(basic_ostringstream&& rhs); + + // \ref{ostringstream.swap}, swap void swap(basic_ostringstream& rhs); // \ref{ostringstream.members}, members @@ -8765,7 +8763,7 @@ Initializes the base class with \tcode{basic_ostream(addressof(sb))}\iref{ostream} and \tcode{sb} with -\tcode{basic_stringbuf(s, which | ios_base::out)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(s, which | ios_base::out)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_ostringstream}% @@ -8779,7 +8777,7 @@ Initializes the base class with \tcode{basic_ostream(addressof(sb))}\iref{ostream} and \tcode{sb} with -\tcode{basic_stringbuf(which | ios_base::out, a)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(which | ios_base::out, a)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_ostringstream}% @@ -8812,7 +8810,7 @@ Initializes the base class with \tcode{basic_ostream(addressof(sb))}\iref{ostream} and \tcode{sb} with -\tcode{basic_stringbuf(s, which | ios_base::out, a)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(s, which | ios_base::out, a)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_ostringstream}% @@ -8833,7 +8831,7 @@ Initializes the base class with \tcode{basic_ostream(addressof(sb))}\iref{ostream} and \tcode{sb} with -\tcode{basic_stringbuf(s, which | ios_base::out)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(s, which | ios_base::out)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_ostringstream}% @@ -8851,7 +8849,7 @@ to install the contained \tcode{basic_stringbuf}. \end{itemdescr} -\rSec3[ostringstream.assign]{Assignment and swap} +\rSec3[ostringstream.swap]{Swap} \indexlibrarymember{swap}{basic_ostringstream}% \begin{itemdecl} @@ -9016,9 +9014,10 @@ basic_stringstream(const basic_stringstream&) = delete; basic_stringstream(basic_stringstream&& rhs); - // \ref{stringstream.assign}, assign and swap basic_stringstream& operator=(const basic_stringstream&) = delete; basic_stringstream& operator=(basic_stringstream&& rhs); + + // \ref{stringstream.swap}, swap void swap(basic_stringstream& rhs); // \ref{stringstream.members}, members @@ -9175,7 +9174,7 @@ to install the contained \tcode{basic_stringbuf}. \end{itemdescr} -\rSec3[stringstream.assign]{Assignment and swap} +\rSec3[stringstream.swap]{Swap} \indexlibrarymember{swap}{basic_stringstream}% \begin{itemdecl} @@ -9707,9 +9706,10 @@ basic_ispanstream(basic_ispanstream&& rhs); template explicit basic_ispanstream(ROS&& s); - // \ref{ispanstream.assign}, assignment and swap basic_ispanstream& operator=(const basic_ispanstream&) = delete; basic_ispanstream& operator=(basic_ispanstream&& rhs); + + // \ref{ispanstream.swap}, swap void swap(basic_ispanstream& rhs); // \ref{ispanstream.members}, member functions @@ -9786,7 +9786,7 @@ \end{codeblock} \end{itemdescr} -\rSec3[ispanstream.assign]{Assignment and swap} +\rSec3[ispanstream.swap]{Swap} \indexlibrarymember{swap}{basic_ispanstream}% \begin{itemdecl} @@ -9896,9 +9896,10 @@ basic_ospanstream(const basic_ospanstream&) = delete; basic_ospanstream(basic_ospanstream&& rhs); - // \ref{ospanstream.assign}, assignment and swap basic_ospanstream& operator=(const basic_ospanstream&) = delete; basic_ospanstream& operator=(basic_ospanstream&& rhs); + + // \ref{ospanstream.swap}, swap void swap(basic_ospanstream& rhs); // \ref{ospanstream.members}, member functions @@ -9946,7 +9947,7 @@ is called to install the contained \tcode{basic_spanbuf}. \end{itemdescr} -\rSec3[ospanstream.assign]{Assignment and swap} +\rSec3[ospanstream.swap]{Swap} \indexlibrarymember{swap}{basic_ospanstream}% \begin{itemdecl} @@ -10036,9 +10037,10 @@ basic_spanstream(const basic_spanstream&) = delete; basic_spanstream(basic_spanstream&& rhs); - // \ref{spanstream.assign}, assignment and swap basic_spanstream& operator=(const basic_spanstream&) = delete; basic_spanstream& operator=(basic_spanstream&& rhs); + + // \ref{spanstream.swap}, swap void swap(basic_spanstream& rhs); // \ref{spanstream.members}, members @@ -10067,7 +10069,7 @@ \pnum \effects Initializes the base class with -\tcode{basic_ostream(addressof(sb))} +\tcode{basic_iostream(addressof(sb))} and \tcode{sb} with \tcode{basic_spanbuf(s, which)}\iref{spanbuf.ctor}. \end{itemdescr} @@ -10086,7 +10088,7 @@ is called to install the contained \tcode{basic_spanbuf}. \end{itemdescr} -\rSec3[spanstream.assign]{Assignment and swap} +\rSec3[spanstream.swap]{Swap} \indexlibrarymember{swap}{basic_spanstream}% \begin{itemdecl} @@ -10257,7 +10259,7 @@ basic_filebuf(basic_filebuf&& rhs); virtual ~basic_filebuf(); - // \ref{filebuf.assign}, assign and swap + // \ref{filebuf.assign}, assignment and swap basic_filebuf& operator=(const basic_filebuf&) = delete; basic_filebuf& operator=(basic_filebuf&& rhs); void swap(basic_filebuf& rhs); @@ -10447,8 +10449,7 @@ \indexlibrarymember{swap}{basic_filebuf}% \begin{itemdecl} template - void swap(basic_filebuf& x, - basic_filebuf& y); + void swap(basic_filebuf& x, basic_filebuf& y); \end{itemdecl} \begin{itemdescr} @@ -11031,9 +11032,10 @@ basic_ifstream(const basic_ifstream&) = delete; basic_ifstream(basic_ifstream&& rhs); - // \ref{ifstream.assign}, assign and swap basic_ifstream& operator=(const basic_ifstream&) = delete; basic_ifstream& operator=(basic_ifstream&& rhs); + + // \ref{ifstream.swap}, swap void swap(basic_ifstream& rhs); // \ref{ifstream.members}, members @@ -11144,7 +11146,7 @@ to install the contained \tcode{basic_filebuf}. \end{itemdescr} -\rSec3[ifstream.assign]{Assignment and swap} +\rSec3[ifstream.swap]{Swap} \indexlibrarymember{swap}{basic_ifstream}% \begin{itemdecl} @@ -11163,8 +11165,7 @@ \indexlibrarymember{swap}{basic_ifstream}% \begin{itemdecl} template - void swap(basic_ifstream& x, - basic_ifstream& y); + void swap(basic_ifstream& x, basic_ifstream& y); \end{itemdecl} \begin{itemdescr} @@ -11276,9 +11277,10 @@ basic_ofstream(const basic_ofstream&) = delete; basic_ofstream(basic_ofstream&& rhs); - // \ref{ofstream.assign}, assign and swap basic_ofstream& operator=(const basic_ofstream&) = delete; basic_ofstream& operator=(basic_ofstream&& rhs); + + // \ref{ofstream.swap}, swap void swap(basic_ofstream& rhs); // \ref{ofstream.members}, members @@ -11389,7 +11391,7 @@ to install the contained \tcode{basic_filebuf}. \end{itemdescr} -\rSec3[ofstream.assign]{Assignment and swap} +\rSec3[ofstream.swap]{Swap} \indexlibrarymember{swap}{basic_ofstream}% \begin{itemdecl} @@ -11408,8 +11410,7 @@ \indexlibrarymember{swap}{basic_ofstream}% \begin{itemdecl} template - void swap(basic_ofstream& x, - basic_ofstream& y); + void swap(basic_ofstream& x, basic_ofstream& y); \end{itemdecl} \begin{itemdescr} @@ -11522,9 +11523,10 @@ basic_fstream(const basic_fstream&) = delete; basic_fstream(basic_fstream&& rhs); - // \ref{fstream.assign}, assign and swap basic_fstream& operator=(const basic_fstream&) = delete; basic_fstream& operator=(basic_fstream&& rhs); + + // \ref{fstream.swap}, swap void swap(basic_fstream& rhs); // \ref{fstream.members}, members @@ -11645,7 +11647,7 @@ to install the contained \tcode{basic_filebuf}. \end{itemdescr} -\rSec3[fstream.assign]{Assignment and swap} +\rSec3[fstream.swap]{Swap} \indexlibrarymember{swap}{basic_fstream}% \begin{itemdecl} @@ -12149,8 +12151,8 @@ \end{codeblock} \pnum -\tcode{Allocator} shall meet the \oldconcept{Allocator} requirements -(\tref{cpp17.allocator}). +\tcode{Allocator} shall meet +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \pnum \begin{example} @@ -12456,8 +12458,8 @@ \end{note} \pnum -Template parameters named \tcode{Allocator} shall meet the -\oldconcept{Allocator} requirements (\tref{cpp17.allocator}). +Template parameters named \tcode{Allocator} shall meet +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \rSec2[fs.filesystem.syn]{Header \tcode{} synopsis} @@ -12662,6 +12664,12 @@ path weakly_canonical(const path& p, error_code& ec); } +// \ref{fs.path.hash}, hash support +namespace std { + template struct hash; + template<> struct hash; +} + namespace std::ranges { template<> inline constexpr bool enable_borrowed_range = true; @@ -14612,6 +14620,19 @@ Equivalent to: \tcode{return path(lhs) /= rhs;} \end{itemdescr} +\rSec3[fs.path.hash]{Hash support} + +\begin{itemdecl} +template<> struct hash; +\end{itemdecl} + +\begin{itemdescr} +\pnum +For an object \tcode{p} of type \tcode{filesystem::path}, +\tcode{hash()(p)} evaluates to the same result as +\tcode{filesystem::hash_value(p)}. +\end{itemdescr} + \rSec2[fs.class.filesystem.error]{Class \tcode{filesystem_error}} \rSec3[fs.class.filesystem.error.general]{General} @@ -15265,6 +15286,7 @@ then \tcode{refresh()} or \tcode{refresh(ec)}, respectively. If an error occurs, the values of any cached attributes are unspecified. +\pnum \throws As specified in~\ref{fs.err.report}. \end{itemdescr} @@ -15650,7 +15672,7 @@ \pnum The result of calling the \tcode{path()} member of the \tcode{directory_entry} object obtained by dereferencing a \tcode{directory_iterator} is a reference to a \tcode{path} object composed of the directory argument from which the iterator was -constructed with filename of the directory entry appended as if by \tcode{operator/=}. +constructed with the filename of the directory entry appended as if by \tcode{operator/=}. \pnum Directory iteration shall not yield directory entries for the current (dot) diff --git a/source/iterators.tex b/source/iterators.tex index ce9786e65a..14e44f0150 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -1472,14 +1472,6 @@ If both \tcode{I1} and \tcode{I2} are signed-integer-like types, then \tcode{common_type_t} is also a signed-integer-like type. -\pnum -For any two integer-like types \tcode{I1} and \tcode{I2}, -at least one of which is an integer-class type, -\tcode{common_type_t} denotes an integer-like type -whose width is not less than that of \tcode{I1} or \tcode{I2}. -If both \tcode{I1} and \tcode{I2} are signed-integer-like types, -then \tcode{common_type_t} is also a signed-integer-like type. - \pnum \tcode{\exposid{is-integer-like}} is \tcode{true} if and only if \tcode{I} is an integer-like type. @@ -1562,8 +1554,8 @@ an iterator. Most algorithms will require additional operations to compare iterators with sentinels\iref{iterator.concept.sentinel}, to read\iref{iterator.concept.input} or write\iref{iterator.concept.output} values, or -to provide a richer set of iterator movements (\ref{iterator.concept.forward}, -\ref{iterator.concept.bidir}, \ref{iterator.concept.random.access}). +to provide a richer set of iterator movements\iref{iterator.concept.forward, +iterator.concept.bidir,iterator.concept.random.access}. \begin{codeblock} template @@ -1911,8 +1903,12 @@ The type \tcode{I} models \libconcept{contiguous_iterator} only if \begin{itemize} \item \tcode{to_address(a) == addressof(*a)}, -\item \tcode{to_address(b) == to_address(a) + D(b - a)}, and -\item \tcode{to_address(c) == to_address(a) + D(c - a)}. +\item \tcode{to_address(b) == to_address(a) + D(b - a)}, +\item \tcode{to_address(c) == to_address(a) + D(c - a)}, +\item \tcode{ranges::iter_move(a)} has +the same type, value category, and effects as \tcode{std::move(*a)}, and +\item if \tcode{ranges::iter_swap(a, b)} is well-formed, +it has effects equivalent to \tcode{ranges::swap(*a, *b)}. \end{itemize} \rSec2[iterator.cpp17]{\Cpp{}17 iterator requirements} @@ -1958,8 +1954,8 @@ set of requirements specifies operations for dereferencing and incrementing an iterator. Most algorithms will require additional operations to read\iref{input.iterators} or write\iref{output.iterators} values, or -to provide a richer set of iterator movements~(\ref{forward.iterators}, -\ref{bidirectional.iterators}, \ref{random.access.iterators}). +to provide a richer set of iterator movements\iref{forward.iterators, +bidirectional.iterators,random.access.iterators}. \pnum A type \tcode{X} meets the \defnoldconcept{Iterator} requirements if: @@ -2088,6 +2084,9 @@ The implementation of an algorithm on input iterators should never attempt to pass through the same iterator twice; such an algorithm should be a single pass algorithm. + +\newpage + \begin{note} For input iterators, \tcode{a == b} does not imply \tcode{++a == ++b}. (Equality does not guarantee the substitution property or referential transparency.) @@ -2107,8 +2106,6 @@ and the expressions in \tref{outputiterator} are valid and have the indicated semantics. -\newpage - \begin{libreqtab4b}[floattable] {\defnoldconcept{OutputIterator} requirements (in addition to \oldconcept{Iterator})} {outputiterator} @@ -4867,9 +4864,9 @@ otherwise it denotes \tcode{input_iterator_tag}. \item +Let \tcode{a} denote an lvalue of type \tcode{const common_iterator}. If the expression \tcode{a.operator->()} is well-formed, -where \tcode{a} is an lvalue of type \tcode{const common_iterator}, -then \tcode{pointer} denotes the type of that expression. +then \tcode{pointer} denotes \tcode{decltype(a.operator->())}. Otherwise, \tcode{pointer} denotes \keyword{void}. \end{itemize} @@ -5060,8 +5057,11 @@ Otherwise, if \tcode{requires(I\& i) \{ \{ *i++ \} -> \exposconceptnc{can-reference}; \}} is \tcode{true} or -\tcode{\libconceptx{constructible_\newline{}from}{constructible_from}, iter_reference_t> \&\& \libconcept{move_constructible}>} -is \linebreak \tcode{false}, +\begin{codeblock} +@\libconcept{indirectly_readable}@ && @\libconcept{constructible_from}@, iter_reference_t> && +@\libconcept{move_constructible}@> +\end{codeblock} +is \tcode{false}, equivalent to: \begin{codeblock} return get(v_)++; @@ -5273,7 +5273,7 @@ requires @\libconcept{contiguous_iterator}@; constexpr counted_iterator& operator++(); - decltype(auto) operator++(int); + constexpr decltype(auto) operator++(int); constexpr counted_iterator operator++(int) requires @\libconcept{forward_iterator}@; constexpr counted_iterator& operator--() @@ -5491,7 +5491,7 @@ \indexlibrarymember{operator++}{counted_iterator}% \begin{itemdecl} -decltype(auto) operator++(int); +constexpr decltype(auto) operator++(int); \end{itemdecl} \begin{itemdescr} diff --git a/source/lex.tex b/source/lex.tex index 19b93a0a18..77e09e142a 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -159,7 +159,7 @@ whether the sources for module units and header units on which the current translation unit has an interface -dependency (\ref{module.unit}, \ref{module.import}) +dependency\iref{module.unit,module.import} are required to be available. \begin{note} Source files, translation @@ -243,45 +243,45 @@ \begin{floattable}{Basic character set}{lex.charset.basic}{lll} \topline \lhdrx{2}{character} & \rhdr{glyph} \\ \capsep -U+0009 & CHARACTER TABULATION & \\ -U+000B & LINE TABULATION & \\ -U+000C & FORM FEED (FF) & \\ -U+0020 & SPACE & \\ -U+000A & LINE FEED (LF) & new-line \\ -U+0021 & EXCLAMATION MARK & \tcode{!} \\ -U+0022 & QUOTATION MARK & \tcode{"} \\ -U+0023 & NUMBER SIGN & \tcode{\#} \\ -U+0025 & PERCENT SIGN & \tcode{\%} \\ -U+0026 & AMPERSAND & \tcode{\&} \\ -U+0027 & APOSTROPHE & \tcode{'} \\ -U+0028 & LEFT PARENTHESIS & \tcode{(} \\ -U+0029 & RIGHT PARENTHESIS & \tcode{)} \\ -U+002A & ASTERISK & \tcode{*} \\ -U+002B & PLUS SIGN & \tcode{+} \\ -U+002C & COMMA & \tcode{,} \\ -U+002D & HYPHEN-MINUS & \tcode{-} \\ -U+002E & FULL STOP & \tcode{.} \\ -U+002F & SOLIDUS & \tcode{/} \\ -U+0030 .. U+0039 & DIGIT ZERO .. NINE & \tcode{0 1 2 3 4 5 6 7 8 9} \\ -U+003A & COLON & \tcode{:} \\ -U+003B & SEMICOLON & \tcode{;} \\ -U+003C & LESS-THAN SIGN & \tcode{<} \\ -U+003D & EQUALS SIGN & \tcode{=} \\ -U+003E & GREATER-THAN SIGN & \tcode{>} \\ -U+003F & QUESTION MARK & \tcode{?} \\ -U+0041 .. U+005A & LATIN CAPITAL LETTER A .. Z & \tcode{A B C D E F G H I J K L M} \\ -& & \tcode{N O P Q R S T U V W X Y Z} \\ -U+005B & LEFT SQUARE BRACKET & \tcode{[} \\ -U+005C & REVERSE SOLIDUS & \tcode{\textbackslash} \\ -U+005D & RIGHT SQUARE BRACKET & \tcode{]} \\ -U+005E & CIRCUMFLEX ACCENT & \tcode{\caret} \\ -U+005F & LOW LINE & \tcode{_} \\ -U+0061 .. U+007A & LATIN SMALL LETTER A .. Z & \tcode{a b c d e f g h i j k l m} \\ +\ucode{0009} & \uname{character tabulation} & \\ +\ucode{000b} & \uname{line tabulation} & \\ +\ucode{000c} & \uname{form feed} & \\ +\ucode{0020} & \uname{space} & \\ +\ucode{000a} & \uname{line feed} & new-line \\ +\ucode{0021} & \uname{exclamation mark} & \tcode{!} \\ +\ucode{0022} & \uname{quotation mark} & \tcode{"} \\ +\ucode{0023} & \uname{number sign} & \tcode{\#} \\ +\ucode{0025} & \uname{percent sign} & \tcode{\%} \\ +\ucode{0026} & \uname{ampersand} & \tcode{\&} \\ +\ucode{0027} & \uname{apostrophe} & \tcode{'} \\ +\ucode{0028} & \uname{left parenthesis} & \tcode{(} \\ +\ucode{0029} & \uname{right parenthesis} & \tcode{)} \\ +\ucode{002a} & \uname{asterisk} & \tcode{*} \\ +\ucode{002b} & \uname{plus sign} & \tcode{+} \\ +\ucode{002c} & \uname{comma} & \tcode{,} \\ +\ucode{002d} & \uname{hyphen-minus} & \tcode{-} \\ +\ucode{002e} & \uname{full stop} & \tcode{.} \\ +\ucode{002f} & \uname{solidus} & \tcode{/} \\ +\ucode{0030} .. \ucode{0039} & \uname{digit zero .. nine} & \tcode{0 1 2 3 4 5 6 7 8 9} \\ +\ucode{003a} & \uname{colon} & \tcode{:} \\ +\ucode{003b} & \uname{semicolon} & \tcode{;} \\ +\ucode{003c} & \uname{less-than sign} & \tcode{<} \\ +\ucode{003d} & \uname{equals sign} & \tcode{=} \\ +\ucode{003e} & \uname{greater-than sign} & \tcode{>} \\ +\ucode{003f} & \uname{question mark} & \tcode{?} \\ +\ucode{0041} .. \ucode{005a} & \uname{latin capital letter a .. z} & \tcode{A B C D E F G H I J K L M} \\ + & & \tcode{N O P Q R S T U V W X Y Z} \\ +\ucode{005b} & \uname{left square bracket} & \tcode{[} \\ +\ucode{005c} & \uname{reverse solidus} & \tcode{\textbackslash} \\ +\ucode{005d} & \uname{right square bracket} & \tcode{]} \\ +\ucode{005e} & \uname{circumflex accent} & \tcode{\caret} \\ +\ucode{005f} & \uname{low line} & \tcode{_} \\ +\ucode{0061} .. \ucode{007a} & \uname{latin small letter a .. z} & \tcode{a b c d e f g h i j k l m} \\ & & \tcode{n o p q r s t u v w x y z} \\ -U+007B & LEFT CURLY BRACKET & \tcode{\{} \\ -U+007C & VERTICAL LINE & \tcode{|} \\ -U+007D & RIGHT CURLY BRACKET & \tcode{\}} \\ -U+007E & TILDE & \tcode{\textasciitilde} \\ +\ucode{007b} & \uname{left curly bracket} & \tcode{\{} \\ +\ucode{007c} & \uname{vertical line} & \tcode{|} \\ +\ucode{007d} & \uname{right curly bracket} & \tcode{\}} \\ +\ucode{007e} & \uname{tilde} & \tcode{\textasciitilde} \\ \end{floattable} \pnum @@ -322,13 +322,18 @@ The \defnadj{basic literal}{character set} consists of all characters of the basic character set, plus the control characters specified in \tref{lex.charset.literal}. +\begin{note} +The alias \uname{bell} for \ucode{0007} shown in ISO 10646 +is ambiguous with \unicode{1f514}{bell}. +\end{note} + \begin{floattable}{Additional control characters in the basic literal character set}{lex.charset.literal}{ll} \topline \ohdrx{2}{character} \\ \capsep -U+0000 & NULL \\ -U+0007 & BELL \\ -U+0008 & BACKSPACE \\ -U+000D & CARRIAGE RETURN (CR) \\ +\ucode{0000} & \uname{null} \\ +\ucode{0007} & \uname{alert} \\ +\ucode{0008} & \uname{backspace} \\ +\ucode{000d} & \uname{carriage return} \\ \end{floattable} \pnum @@ -338,7 +343,7 @@ other than a multicharacter or non-encodable character literal or in a \grammarterm{string-literal} are encoded as a sequence of one or more code units, as determined -by the \grammarterm{encoding-prefix} (\ref{lex.ccon}, \ref{lex.string}); +by the \grammarterm{encoding-prefix}\iref{lex.ccon,lex.string}; this is termed the respective \defnadj{literal}{encoding}. The \defnadj{ordinary literal}{encoding} is the encoding applied to an ordinary character or string literal. @@ -357,10 +362,12 @@ the value of such a code unit can be the same as that of a code unit for an element of the basic literal character set. \end{note} -The U+0000 NULL character is encoded as the value \tcode{0}. +\indextext{character!null}% +\indextext{wide-character!null}% +The \unicode{0000}{null} character is encoded as the value \tcode{0}. No other element of the translation character set is encoded with a code unit of value \tcode{0}. -The code unit value of each decimal digit character after the digit \tcode{0} (U+0030) +The code unit value of each decimal digit character after the digit \tcode{0} (\ucode{0030}) shall be one greater than the value of the previous. The ordinary and wide literal encodings are otherwise \impldef{ordinary and wide literal encodings}. @@ -410,7 +417,7 @@ literals), string literals (including user-defined string literals), preprocessing operators and punctuators, and single non-whitespace characters that do not lexically match the other preprocessing token categories. -If a U+0027 APOSTROPHE or a U+0022 QUOTATION MARK character +If a \unicode{0027}{apostrophe} or a \unicode{0022}{quotation mark} character matches the last category, the behavior is undefined. If any character not in the basic character set matches the last category, the program is ill-formed. @@ -418,8 +425,13 @@ \indextext{whitespace}% whitespace; \indextext{comment}% -this consists of comments\iref{lex.comment}, or whitespace -characters (U+0020 SPACE, U+0009 CHARACTER TABULATION, new-line, U+000B LINE TABULATION, and U+000C FORM FEED), or both. As described in \ref{cpp}, in certain +this consists of comments\iref{lex.comment}, or whitespace characters +(\unicode{0020}{space}, +\unicode{0009}{character tabulation}, +new-line, +\unicode{000b}{line tabulation}, and +\unicode{000c}{form feed}), or both. +As described in \ref{cpp}, in certain circumstances during translation phase 4, whitespace (or the absence thereof) serves as more than preprocessing token separation. Whitespace can appear within a preprocessing token only as part of a header name or @@ -623,7 +635,7 @@ \begin{bnf} \nontermdef{h-char}\br - \textnormal{any member of the translation character set except new-line and \terminal{U+003E GREATER-THAN SIGN}} + \textnormal{any member of the translation character set except new-line and \unicode{003e}{greater-than sign}} \end{bnf} \begin{bnf} @@ -634,7 +646,7 @@ \begin{bnf} \nontermdef{q-char}\br - \textnormal{any member of the translation character set except new-line and \terminal{U+0022 QUOTATION MARK}} + \textnormal{any member of the translation character set except new-line and \unicode{0022}{quotation mark}} \end{bnf} \pnum @@ -748,7 +760,7 @@ if an \grammarterm{identifier} does not conform to Normalization Form C as specified in ISO/IEC 10646. \begin{note} -Upper- and lower-case letters are considered different for all identifiers. +Identifiers are case-sensitive. \end{note} \begin{note} In translation phase 4, @@ -1271,8 +1283,8 @@ \begin{bnf} \nontermdef{basic-c-char}\br - \textnormal{any member of the translation character set except the U+0027 APOSTROPHE,}\br - \bnfindent\textnormal{U+005C REVERSE SOLIDUS, or new-line character} + \textnormal{any member of the translation character set except the \unicode{0027}{apostrophe},}\br + \bnfindent\textnormal{\unicode{005c}{reverse solidus}, or new-line character} \end{bnf} \begin{bnf} @@ -1483,24 +1495,24 @@ is specified in \tref{lex.ccon.esc}. \begin{note} Using an escape sequence for a question mark -is supported for compatibility with ISO C++ 2014 and ISO C. +is supported for compatibility with ISO \CppXIV{} and ISO C. \end{note} \begin{floattable}{Simple escape sequences}{lex.ccon.esc} {lll} \topline \lhdrx{2}{character} & \rhdr{\grammarterm{simple-escape-sequence}} \\ \capsep -U+000A & LINE FEED (LF) & \tcode{\textbackslash n} \\ -U+0009 & CHARACTER TABULATION & \tcode{\textbackslash t} \\ -U+000B & LINE TABULATION & \tcode{\textbackslash v} \\ -U+0008 & BACKSPACE & \tcode{\textbackslash b} \\ -U+000D & CARRIAGE RETURN (CR) & \tcode{\textbackslash r} \\ -U+000C & FORM FEED (FF) & \tcode{\textbackslash f} \\ -U+0007 & BELL & \tcode{\textbackslash a} \\ -U+005C & REVERSE SOLIDUS & \tcode{\textbackslash\textbackslash} \\ -U+003F & QUESTION MARK & \tcode{\textbackslash ?} \\ -U+0027 & APOSTROPHE & \tcode{\textbackslash '} \\ -U+0022 & QUOTATION MARK & \tcode{\textbackslash "} \\ +\ucode{000a} & \uname{line feed} & \tcode{\textbackslash n} \\ +\ucode{0009} & \uname{character tabulation} & \tcode{\textbackslash t} \\ +\ucode{000b} & \uname{line tabulation} & \tcode{\textbackslash v} \\ +\ucode{0008} & \uname{backspace} & \tcode{\textbackslash b} \\ +\ucode{000d} & \uname{carriage return} & \tcode{\textbackslash r} \\ +\ucode{000c} & \uname{form feed} & \tcode{\textbackslash f} \\ +\ucode{0007} & \uname{alert} & \tcode{\textbackslash a} \\ +\ucode{005c} & \uname{reverse solidus} & \tcode{\textbackslash\textbackslash} \\ +\ucode{003f} & \uname{question mark} & \tcode{\textbackslash ?} \\ +\ucode{0027} & \uname{apostrohpe} & \tcode{\textbackslash '} \\ +\ucode{0022} & \uname{quotation mark} & \tcode{\textbackslash "} \\ \end{floattable} \rSec2[lex.fcon]{Floating-point literals} @@ -1652,8 +1664,8 @@ \begin{bnf} \nontermdef{basic-s-char}\br - \textnormal{any member of the translation character set except the U+0022 QUOTATION MARK,}\br - \bnfindent\textnormal{U+005C REVERSE SOLIDUS, or new-line character} + \textnormal{any member of the translation character set except the \unicode{0022}{quotation mark},}\br + \bnfindent\textnormal{\unicode{005c}{reverse solidus}, or new-line character} \end{bnf} \begin{bnf} @@ -1669,8 +1681,8 @@ \begin{bnf} \nontermdef{r-char}\br - \textnormal{any member of the translation character set, except a U+0029 RIGHT PARENTHESIS followed by}\br - \bnfindent\textnormal{the initial \grammarterm{d-char-sequence} (which may be empty) followed by a U+0022 QUOTATION MARK} + \textnormal{any member of the translation character set, except a \unicode{0029}{right parenthesis} followed by}\br + \bnfindent\textnormal{the initial \grammarterm{d-char-sequence} (which may be empty) followed by a \unicode{0022}{quotation mark}} \end{bnf} \begin{bnf} @@ -1682,9 +1694,8 @@ \begin{bnf} \nontermdef{d-char}\br \textnormal{any member of the basic character set except:}\br - \bnfindent\textnormal{U+0020 SPACE, U+0028 LEFT PARENTHESIS, U+0029 RIGHT PARENTHESIS,}\br - \bnfindent\textnormal{U+005C REVERSE SOLIDUS, U+0009 CHARACTER TABULATION,}\br - \bnfindent\textnormal{U+000B LINE TABULATION, U+000C FORM FEED (FF), and new-line} + \bnfindent\textnormal{\unicode{0020}{space}, \unicode{0028}{left parenthesis}, \unicode{0029}{right parenthesis}, \unicode{005c}{reverse solidus},}\br + \bnfindent\textnormal{\unicode{0009}{character tabulation}, \unicode{000b}{line tabulation}, \unicode{000c}{form feed}, and new-line} \end{bnf} \pnum @@ -1880,7 +1891,7 @@ corresponding to the \grammarterm{string-literal}'s sequence of \grammarterm{s-char}s (originally from non-raw string literals) and \grammarterm{r-char}s (originally from raw string literals), -plus a terminating U+0000 NULL character, +plus a terminating \unicode{0000}{null} character, in order as follows: \begin{itemize} \item @@ -2150,7 +2161,7 @@ \begin{example} \begin{codeblock} int main() { - L"A" "B" "C"_x; // OK: same as \tcode{L"ABC"_x} + L"A" "B" "C"_x; // OK, same as \tcode{L"ABC"_x} "P"_x "Q" "R"_y; // error: two different \grammarterm{ud-suffix}{es} } \end{codeblock} diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 87bf68e065..04ada51d52 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -29,6 +29,8 @@ \ref{support} & Language support library \\ \ref{concepts} & Concepts library \\ \ref{diagnostics} & Diagnostics library \\ +\ref{mem} & Memory management library \\ +\ref{meta} & Metaprogramming library \\ \ref{utilities} & General utilities library \\ \ref{strings} & Strings library \\ \ref{containers} & Containers library \\ @@ -40,14 +42,14 @@ \ref{localization} & Localization library \\ \ref{input.output} & Input/output library \\ \ref{re} & Regular expressions library \\ -\ref{atomics} & Atomic operations library \\ -\ref{thread} & Thread support library \\ +\ref{thread} & Concurrency support library \\ \end{floattable} \pnum The language support library\iref{support} provides components that are -required by certain parts of the \Cpp{} language, such as memory allocation~(\ref{expr.new}, -\ref{expr.delete}) and exception processing\iref{except}. +required by certain parts of the \Cpp{} language, +such as memory allocation\iref{expr.new,expr.delete} and +exception processing\iref{except}. \pnum The concepts library\iref{concepts} describes library components that \Cpp{} @@ -58,6 +60,15 @@ The diagnostics library\iref{diagnostics} provides a consistent framework for reporting errors in a \Cpp{} program, including predefined exception classes. +\pnum +The memory management library\iref{mem} provides components for +memory management, including smart pointers and scoped allocators. + +\pnum +The metaprogramming library\iref{meta} describes facilities +for use in templates and during constant evaluation, +including type traits, integer sequences, and rational arithmetic. + \pnum The general utilities library\iref{utilities} includes components used by other library elements, such as a predefined storage allocator for dynamic @@ -109,13 +120,10 @@ \pnum The regular expressions library\iref{re} provides regular expression matching and searching. -\pnum -The atomic operations library\iref{atomics} allows more fine-grained -concurrent access to shared data than is possible with locks. - \pnum The thread support library\iref{thread} provides components to create -and manage threads, including mutual exclusion and interthread communication. +and manage threads, +including atomic operations, mutual exclusion, and interthread communication. \rSec1[library.c]{The C standard library} @@ -136,6 +144,30 @@ ISO C \tcode{restrict} qualifier) are the same unless otherwise stated. +\pnum +A call to a C standard library function is +a non-constant library call\iref{defns.nonconst.libcall} +if it raises a floating-point exception other than \tcode{FE_INEXACT}. +The semantics of a call to a C standard library function +evaluated as a core constant expression +are those specified in Annex F of the C standard +\begin{footnote} +See also ISO/IEC 9899:2018 section 7.6. +\end{footnote} +to the extent applicable to the floating-point types\iref{basic.fundamental} +that are parameter types of the called function. +\begin{note} +Annex F specifies +the conditions under which floating-point exceptions are raised and +the behavior when NaNs and/or infinities are passed as arguments. +\end{note} +\begin{note} +Equivalently, a call to a C standard library function is +a non-constant library call +if \tcode{errno} is set +when \tcode{math_errhandling \& MATH_ERRNO} is \tcode{true}. +\end{note} + \rSec1[description]{Method of description} \rSec2[description.general]{General} @@ -349,6 +381,15 @@ the conditions (sometimes termed observable results) established by the function. +\item +\result +for a \grammarterm{typename-specifier}, a description of the named type; +for an \grammarterm{expression}, +a description of the type of the expression; +the expression is an lvalue if the type is an lvalue reference type, +an xvalue if the type is an rvalue reference type, and +a prvalue otherwise. + \item \returns a description of the value(s) returned by the function. @@ -831,7 +872,7 @@ and \ref{depr} do not describe copy/move constructors, assignment operators, or (non-virtual) destructors with the same apparent semantics as those that can be generated -by default~(\ref{class.copy.ctor}, \ref{class.copy.assign}, \ref{class.dtor}). +by default\iref{class.copy.ctor,class.copy.assign,class.dtor}. \indextext{constructor!copy}% \indextext{operator!assignment}% \indextext{destructor}% @@ -927,7 +968,7 @@ \end{footnote} \pnum -Whenever an unqualified name is used +Whenever an unqualified name other than \tcode{swap} is used in the specification of a declaration \tcode{D} in \ref{\firstlibchapter} through \ref{\lastlibchapter} or \ref{depr}, its meaning is established @@ -946,6 +987,9 @@ Operators in expressions\iref{over.match.oper} are not so constrained; see \ref{global.functions}. \end{note} +The meaning of the unqualified name \tcode{swap} is established +in an overload resolution context +for swappable values\iref{swappable.requirements}. \rSec3[headers]{Headers} @@ -983,9 +1027,10 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ -\tcode{} \\ \columnbreak +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1005,8 +1050,8 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \columnbreak +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1026,8 +1071,8 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \columnbreak +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1295,7 +1340,7 @@ \ref{support.coroutine} & Coroutines support & \tcode{} \\ \rowsep \ref{support.runtime} & Other runtime support & \tcode{} \\ \rowsep \ref{concepts} & Concepts library & \tcode{} \\ \rowsep -\ref{meta} & Type traits & \tcode{} \\ \rowsep +\ref{type.traits} & Type traits & \tcode{} \\ \rowsep \ref{bit} & Bit manipulation & \tcode{} \\ \rowsep \ref{atomics} & Atomics & \tcode{} \\ \end{libsumtab} @@ -1625,7 +1670,7 @@ template void value_swap(T&& t, U&& u) { using std::swap; - swap(std::forward(t), std::forward(u)); // OK: uses ``swappable with'' conditions + swap(std::forward(t), std::forward(u)); // OK, uses ``swappable with'' conditions // for rvalues and lvalues } @@ -1633,7 +1678,7 @@ template void lv_swap(T& t1, T& t2) { using std::swap; - swap(t1, t2); // OK: uses swappable conditions for lvalues of type \tcode{T} + swap(t1, t2); // OK, uses swappable conditions for lvalues of type \tcode{T} } namespace N { @@ -1642,7 +1687,7 @@ Proxy proxy(A& a) { return Proxy{ &a }; } void swap(A& x, Proxy p) { - std::swap(x.m, p.a->m); // OK: uses context equivalent to swappable + std::swap(x.m, p.a->m); // OK, uses context equivalent to swappable // conditions for fundamental types } void swap(Proxy p, A& x) { swap(x, p); } // satisfy symmetry constraint @@ -1795,137 +1840,323 @@ \tcode{match_results}\iref{re} are parameterized in terms of allocators. -\begin{shortlibreqtab2} -{Descriptive variable definitions} -{allocator.req.var} -\topline -\lhdr{Variable} & \rhdr{Definition} \\ \capsep -\tcode{T, U, C} & any \cv-unqualified object type\iref{basic.types} \\ \rowsep -\tcode{X} & an allocator class for type \tcode{T} \\ \rowsep -\tcode{Y} & the corresponding allocator class for type \tcode{U} \\ \rowsep -\tcode{XX} & the type \tcode{allocator_traits} \\ \rowsep -\tcode{YY} & the type \tcode{allocator_traits} \\ \rowsep -\tcode{a, a1, a2} & lvalues of type \tcode{X} \\ \rowsep -\tcode{u} & the name of a variable being declared \\ \rowsep -\tcode{b} & a value of type \tcode{Y} \\ \rowsep -\tcode{c} & a pointer of type \tcode{C*} through which indirection is valid \\ \rowsep -\tcode{p} & a value of type \tcode{XX::pointer}, obtained -by calling \tcode{a1.allocate}, where \tcode{a1 == a} \\ \rowsep -\tcode{q} & a value of type \tcode{XX::const_pointer} -obtained by conversion from a value \tcode{p} \\ \rowsep -\tcode{r} & a value of type \tcode{T\&} -obtained by the expression \tcode{*p} \\ \rowsep -\tcode{w} & a value of type \tcode{XX::void_pointer} obtained by - conversion from a value \tcode{p} \\ \rowsep -\tcode{x} & a value of type \tcode{XX::const_void_pointer} obtained by - conversion from a value \tcode{q} or a value \tcode{w} \\ \rowsep -\tcode{y} & a value of type \tcode{XX::const_void_pointer} obtained by -conversion from a result value of \tcode{YY::allocate}, or else a value of -type (possibly \keyword{const}) \tcode{std::nullptr_t} \\ \rowsep -\tcode{n} & a value of type \tcode{XX::size_type} \\ \rowsep -\tcode{Args} & a template parameter pack \\ \rowsep -\tcode{args} & a function parameter pack with the pattern \tcode{Args\&\&} \\ -\end{shortlibreqtab2} +\pnum +In subclause \ref{allocator.requirements}, +\begin{itemize} +\item +\tcode{T}, \tcode{U}, \tcode{C} denote +any \cv-unqualified object type\iref{term.object.type}, +\item +\tcode{X} denotes an allocator class for type \tcode{T}, +\item +\tcode{Y} denotes the corresponding allocator class for type \tcode{U}, +\item +\tcode{XX} denotes the type \tcode{allocator_traits}, +\item +\tcode{YY} denotes the type \tcode{allocator_traits}, +\item +\tcode{a}, \tcode{a1}, \tcode{a2} denote lvalues of type \tcode{X}, +\item +\tcode{u} denotes the name of a variable being declared, +\item +\tcode{b} denotes a value of type \tcode{Y}, +\item +\tcode{c} denotes a pointer of type \tcode{C*} +through which indirection is valid, +\item +\tcode{p} denotes a value of type \tcode{XX::pointer} +obtained by calling \tcode{a1.allocate}, where \tcode{a1 == a}, +\item +\tcode{q} denotes a value of type \tcode{XX::const_pointer} +obtained by conversion from a value \tcode{p}, +\item +\tcode{r} denotes a value of type \tcode{T\&} +obtained by the expression \tcode{*p}, +\item +\tcode{w} denotes a value of type \tcode{XX::void_pointer} +obtained by conversion from a value \tcode{p}, +\item +\tcode{x} denotes a value of type \tcode{XX::const_void_pointer} +obtained by conversion from a value \tcode{q} or a value \tcode{w}, +\item +\tcode{y} denotes a value of type \tcode{XX::const_void_pointer} +obtained by conversion from a result value of \tcode{YY::allocate}, or else +a value of type (possibly \tcode{const}) \tcode{std::nullptr_t}, +\item +\tcode{n} denotes a value of type \tcode{XX::size_type}, +\item +\tcode{Args} denotes a template parameter pack, and +\item +\tcode{args} denotes +a function parameter pack with the pattern \tcode{Args\&\&}. +\end{itemize} \pnum The class template \tcode{allocator_traits}\iref{allocator.traits} supplies a uniform interface to all allocator types. -\tref{allocator.req.var} describes the types manipulated -through allocators. \tref{cpp17.allocator} +This subclause describes the requirements on allocator types -and thus on types used to instantiate \tcode{allocator_traits}. A requirement -is optional if the last column of -\tref{cpp17.allocator} specifies a default for a -given expression. Within the standard library \tcode{allocator_traits} +and thus on types used to instantiate \tcode{allocator_traits}. +A requirement is optional if a default for a +given type or expression is specified. +Within the standard library \tcode{allocator_traits} template, an optional requirement that is not supplied by an allocator is -replaced by the specified default expression. A user specialization of +replaced by the specified default type or expression. A user specialization of \tcode{allocator_traits} may provide different defaults and may provide -defaults for different requirements than the primary template. Within -Tables~\ref{tab:allocator.req.var} and~\ref{tab:cpp17.allocator}, -the use of \tcode{move} and \tcode{forward} always refers to \tcode{std::move} -and \tcode{std::forward}, respectively. - -\begin{libreqtab4d} -{\oldconcept{Allocator} requirements} -{cpp17.allocator} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Default} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Default} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endhead -\tcode{X::pointer} & & & \tcode{T*} \\ \rowsep - -\tcode{X::const_pointer} & - & - \tcode{X::pointer} is convertible to \tcode{X::const_pointer} & - \tcode{pointer_traits::\brk{}rebind} \\ \rowsep - -\tcode{X::void_pointer}\br\tcode{Y::void_pointer} & - & - \tcode{X::pointer} is convertible to \tcode{X::void_pointer}. - \tcode{X::void_pointer} and \tcode{Y::void_pointer} are the same type. & - \tcode{pointer_traits::\brk{}rebind} \\ \rowsep - -\tcode{X::const_void_pointer}\br\tcode{Y::const_void_pointer} & - & - \tcode{X::pointer}, \tcode{X::const_pointer}, and \tcode{X::void_pointer} are convertible to \tcode{X::const_void_pointer}. - \tcode{X::const_void_pointer} and \tcode{Y::const_void_pointer} are the same type. & - \tcode{pointer_traits::\brk{}rebind} \\ \rowsep - -\tcode{X::value_type} & - Identical to \tcode{T} & & \\ \rowsep - -\tcode{X::size_type} & - unsigned integer type & - a type that can represent the size of the largest object in the allocation model & - \tcode{make_unsigned_t} \\ \rowsep - -\tcode{X::difference_type} & - signed integer type & - a type that can represent the difference between any two pointers - in the allocation model & - \tcode{pointer_traits::\brk{}difference_type} \\ \rowsep - -\tcode{typename X::template rebind::other} & - \tcode{Y} & - For all \tcode{U} (including \tcode{T}), \tcode{Y::template rebind::other} - is \tcode{X}. & - See Note A, below. \\ \rowsep - -\tcode{*p} & - \tcode{T\&} && \\ \rowsep - -\tcode{*q} & - \tcode{const T\&} & - \tcode{*q} refers to the same object as \tcode{*p}. & \\ \rowsep - -\tcode{p->m} & - type of \tcode{T::m} & - \expects \tcode{(*p).m} is well-defined.\br - equivalent to \tcode{(*p).m} & \\ \rowsep - -\tcode{q->m} & - type of \tcode{T::m} & - \expects \tcode{(*q).m} is well-defined.\br - equivalent to \tcode{(*q).m} & \\ \rowsep - -\tcode{static_cast<\brk{}X::pointer\brk{}>(w)} & - \tcode{X::pointer} & - \tcode{static_cast(w) == p} & \\ \rowsep - -\tcode{static_cast<\brk{}X::const_pointer\brk{}>(x)} & - \tcode{X::const_pointer} & - \tcode{static_cast<} \tcode{X::const_pointer\brk{}>(x) == q} & \\ \rowsep - -\tcode{pointer_traits<\brk{}X::pointer\brk{}>::pointer_to(r)} & - \tcode{X::pointer} & - same as \tcode{p} & \\ \rowsep - -\tcode{a.allocate(n)} & \tcode{X::pointer} & +defaults for different requirements than the primary template. + +\begin{itemdecl} +typename X::pointer +\end{itemdecl} + +\begin{itemdescr} +\pnum +\remarks +Default: \tcode{T*} +\end{itemdescr} + +\begin{itemdecl} +typename X::const_pointer +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{X::pointer} is convertible to \tcode{X::const_pointer}. + +\pnum +\remarks +Default: \tcode{pointer_traits::rebind} +\end{itemdescr} + +\begin{itemdecl} +typename X::void_pointer +typename Y::void_pointer +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{X::pointer} is convertible to \tcode{X::void_pointer}. +\tcode{X::void_pointer} and \tcode{Y::void_pointer} are the same type. + +\pnum +\remarks +Default: +\tcode{pointer_traits::rebind} +\end{itemdescr} + +\begin{itemdecl} +typename X::const_void_pointer +typename Y::const_void_pointer +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{X::pointer}, \tcode{X::const_pointer}, and \tcode{X::void_pointer} +are convertible to \tcode{X::const_void_pointer}. +\tcode{X::const_void_pointer} and \tcode{Y::const_void_pointer} +are the same type. + +\pnum +\remarks +Default: +\tcode{pointer_traits::rebind} +\end{itemdescr} + +\begin{itemdecl} +typename X::value_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Identical to \tcode{T}. +\end{itemdescr} + +\begin{itemdecl} +typename X::size_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +An unsigned integer type +that can represent the size of the largest object in the allocation model. + +\pnum +\remarks +Default: +\tcode{make_unsigned_t} +\end{itemdescr} + +\begin{itemdecl} +typename X::difference_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A signed integer type that can represent +the difference between any two pointers in the allocation model. + +\pnum +\remarks +Default: +\tcode{pointer_traits::difference_type} +\end{itemdescr} + +\begin{itemdecl} +typename X::template rebind::other +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Y} + +\pnum +\ensures +For all \tcode{U} (including \tcode{T}), +\tcode{Y::template rebind::other} is \tcode{X}. + +\pnum +\remarks +If \tcode{Allocator} is a class template instantiation of the form +\tcode{SomeAllocator}, where \tcode{Args} is zero or more type +arguments, and \tcode{Allocator} does not supply a \tcode{rebind} member +template, the standard \tcode{allocator_traits} template uses +\tcode{SomeAllocator} in place of \tcode{Allocator::re\-bind::other} +by default. For allocator types that are not template instantiations of the +above form, no default is provided. + +\pnum +\begin{note} +The member class template \tcode{rebind} of \tcode{X} is +effectively a typedef template. +In general, if +the name \tcode{Allocator} is bound to \tcode{SomeAllocator}, then +\tcode{Allocator::rebind::other} is the same type as +\tcode{SomeAllocator}, where +\tcode{SomeAllocator::value_type} is \tcode{T} and +\tcode{SomeAllocator::value_type} is \tcode{U}. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +*p +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{T\&} +\end{itemdescr} + +\begin{itemdecl} +*q +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{const T\&} + +\pnum +\ensures +\tcode{*q} refers to the same object as \tcode{*p}. +\end{itemdescr} + +\begin{itemdecl} +p->m +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Type of \tcode{T::m}. + +\pnum +\expects +\tcode{(*p).m} is well-defined. + +\pnum +\effects +Equivalent to \tcode{(*p).m}. +\end{itemdescr} + +\begin{itemdecl} +q->m +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Type of \tcode{T::m}. + +\pnum +\expects +\tcode{(*q).m} is well-defined. + +\pnum +\effects +Equivalent to \tcode{(*q).m}. +\end{itemdescr} + +\begin{itemdecl} +static_cast(w) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::pointer} + +\pnum +\ensures +\tcode{static_cast(w) == p}. +\end{itemdescr} + +\begin{itemdecl} +static_cast(x) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::const_pointer} + +\pnum +\ensures +\tcode{static_cast(x) == q}. +\end{itemdescr} + +\begin{itemdecl} +pointer_traits::pointer_to(r) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::pointer} + +\pnum +\ensures +Same as \tcode{p}. +\end{itemdescr} + +\begin{itemdecl} +a.allocate(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::pointer} + +\pnum +\effects Memory is allocated for an array of \tcode{n} \tcode{T} and such an object is created but array elements are not constructed. @@ -1935,189 +2166,388 @@ can be used to implicitly create a suitable array object and obtain a pointer to it. \end{example} + +\pnum +\throws \tcode{allocate} may throw an appropriate exception. -\begin{footnote} + +\pnum +\begin{note} It is intended that \tcode{a.allocate} be an efficient means of allocating a single object of type \tcode{T}, even when \tcode{sizeof(T)} is small. That is, there is no need for a container to maintain its own free list. -\end{footnote} -See Note C, below. -& \\ \rowsep - -\tcode{a.allocate(n, y)} & - \tcode{X::pointer} & - Same as \tcode{a.allocate(n)}. The use of \tcode{y} is unspecified, but - it is intended as an aid to locality. & - \tcode{a.allocate(n)} \\ \rowsep - -\tcode{a.allocate_at_least(n)} & - \tcode{allocation_result} & - \returns - \tcode{allocation_result\{ptr, count\}} - where \tcode{ptr} is memory allocated for an array of \tcode{count} \tcode{T} - and such an object is created but array elements are not constructed, - such that $\tcode{count} \geq \tcode{n}$. - \tcode{allocate_at_least} may throw an appropriate exception. - See Note C, below. & - See Note D, below. \\ \rowsep - -\tcode{a.deallocate(p,n)} & - (not used) & - \expects - \begin{itemize} - \item - If \tcode{p} is memory - that was obtained by a call to \tcode{a.allocate_at_least}, - let \tcode{ret} be the value returned and - \tcode{req} be the value passed as the first argument of that call. - \tcode{p} is equal to \tcode{ret.ptr} and - \tcode{n} is a value such that - $\tcode{req} \leq \tcode{n} \leq \tcode{ret.count}$. - \item - Otherwise, \tcode{p} is a pointer value obtained from \tcode{allocate}. - \tcode{n} equals the value passed as the first argument - to the invocation of \tcode{allocate} which returned \tcode{p}. - \end{itemize} - \tcode{p} has not been invalidated by - an intervening call to \tcode{deallocate}.\br - \throws Nothing. & \\ \rowsep - -\tcode{a.max_size()} & - \tcode{X::size_type} & - the largest value that can meaningfully be passed to \tcode{X::allocate()} & - \tcode{numeric_limits::max() / sizeof\brk{}(value_type)} \\ \rowsep - -\tcode{a1 == a2} & - \tcode{bool} & - Returns \tcode{true} only if storage allocated from each can - be deallocated via the other. \tcode{operator==} shall be reflexive, symmetric, - and transitive, and shall not exit via an exception. & \\ \rowsep - -\tcode{a1 != a2} & - \tcode{bool} & - same as \tcode{!(a1 == a2)} & \\ \rowsep - -\tcode{a == b} & - \tcode{bool} & - same as \tcode{a ==} \tcode{Y::rebind::other(b)} & \\ \rowsep - -\tcode{a != b} & - \tcode{bool} & - same as \tcode{!(a == b)} & \\ \rowsep - -\tcode{X u(a)}; \br -\tcode{X u = a;} & - & - Shall not exit via an exception.\br - \ensures \tcode{u == a} & \\ \rowsep - -\tcode{X u(b);} & - & - Shall not exit via an exception.\br - \ensures \tcode{Y(u) == b}, \tcode{u == X(b)} & \\ \rowsep - -\tcode{X u(std::move(a));} \br -\tcode{X u = std::move(a);} & - & - Shall not exit via an exception.\br - \ensures The value of \tcode{a} is unchanged and is equal to \tcode{u}. & \\ \rowsep - -\tcode{X u(std::move(b));} & - & - Shall not exit via an exception.\br - \ensures \tcode{u} is equal to the prior value of \tcode{X(b)}. & \\ \rowsep - -\tcode{a.construct(c, args)}& - (not used) & - \effects Constructs an object of type \tcode{C} at - \tcode{c}. & - \tcode{construct_at(c,~std::\brk{}forward\brk{}(args)...)} \\ \rowsep - -\tcode{a.destroy(c)} & - (not used) & - \effects Destroys the object at \tcode{c} & - \tcode{destroy_at(c)} \\ \rowsep - -\tcode{a.select_on_container_copy_construction()} & - \tcode{X} & - Typically returns either \tcode{a} or \tcode{X()}. & - \tcode{return a;} \\ \rowsep - -\tcode{X::propagate_on_container_copy_assignment} & - Identical to or derived from \tcode{true_type} or \tcode{false_type} & - \tcode{true_type} only if an allocator of type \tcode{X} should be copied - when the client container is copy-assigned. - See Note B, below. & - \tcode{false_type} \\ \rowsep - -\tcode{X::propagate_on_container_move_assignment} & - Identical to or derived from \tcode{true_type} or \tcode{false_type} & - \tcode{true_type} only if an allocator of type \tcode{X} should be moved - when the client container is move-assigned. - See Note B, below. & - \tcode{false_type} \\ \rowsep - -\tcode{X::propagate_on_-} \tcode{container_swap} & - Identical to or derived from \tcode{true_type} or \tcode{false_type} & - \tcode{true_type} only if an allocator of type \tcode{X} should be swapped - when the client container is swapped. - See Note B, below. & - \tcode{false_type} \\ \rowsep - -\tcode{X::is_always_equal} & - Identical to or derived from \tcode{true_type} or \tcode{false_type} & - \tcode{true_type} only if the expression \tcode{a1 == a2} is guaranteed - to be \tcode{true} for any two (possibly \keyword{const}) values - \tcode{a1}, \tcode{a2} of type \tcode{X}. & - \tcode{is_empty::\brk{}type} \\ - -\end{libreqtab4d} - -\pnum -Note A: The member class template \tcode{rebind} in the table above is -effectively a typedef template. -\begin{note} -In general, if -the name \tcode{Allocator} is bound to \tcode{SomeAllocator}, then -\tcode{Allocator::rebind::other} is the same type as -\tcode{SomeAllocator}, where -\tcode{SomeAllocator::value_type} is \tcode{T} and -\tcode{SomeAllocator::\brk{}value_type} is \tcode{U}. \end{note} -If -\tcode{Allocator} is a class template instantiation of the form -\tcode{SomeAllocator}, where \tcode{Args} is zero or more type -arguments, and \tcode{Allocator} does not supply a \tcode{rebind} member -template, the standard \tcode{allocator_traits} template uses -\tcode{SomeAllocator} in place of \tcode{Allocator::\brk{}rebind::other} -by default. For allocator types that are not template instantiations of the -above form, no default is provided. \pnum -Note B: -If \tcode{X::propagate_on_container_copy_assignment::value} is \tcode{true}, -\tcode{X} shall meet the -\oldconcept{\-Copy\-Assign\-able} requirements (\tref{cpp17.copyassignable}) -and the copy operation shall not throw exceptions. -If \tcode{X::propagate_on_container_move_assignment::value} is \tcode{true}, -\tcode{X} shall meet the -\oldconcept{\-Move\-Assign\-able} requirements (\tref{cpp17.moveassignable}) -and the move operation shall not throw exceptions. -If \tcode{X::propagate_on_container_swap::value} is \tcode{true}, -lvalues of type \tcode{X} shall be swappable\iref{swappable.requirements} -and the \tcode{swap} operation shall not throw exceptions. +\remarks +If \tcode{n == 0}, the return value is unspecified. +\end{itemdescr} + +\begin{itemdecl} +a.allocate(n, y) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::pointer} \pnum -Note C: +\effects +Same as \tcode{a.allocate(n)}. +The use of \tcode{y} is unspecified, but it is intended as an aid to locality. + +\pnum +\remarks +Default: \tcode{a.allocate(n)} +\end{itemdescr} + +\begin{itemdecl} +a.allocate_at_least(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{allocation_result} + +\pnum +\returns +\tcode{allocation_result\{ptr, count\}} +where \tcode{ptr} is memory allocated for an array of \tcode{count} \tcode{T} +and such an object is created but array elements are not constructed, +such that $\tcode{count} \geq \tcode{n}$. If \tcode{n == 0}, the return value is unspecified. \pnum -Note D: +\throws +\tcode{allocate_at_least} may throw an appropriate exception. + +\pnum +\remarks An allocator need not support \tcode{allocate_at_least}, but no default is provided in \tcode{allocator_traits}. If an allocator has an \tcode{allocate_at_least} member, it shall satisfy the requirements. +\end{itemdescr} + +\begin{itemdecl} +a.deallocate(p, n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +(not used) + +\pnum +\expects +\begin{itemize} +\item +If \tcode{p} is memory +that was obtained by a call to \tcode{a.allocate_at_least}, +let \tcode{ret} be the value returned and +\tcode{req} be the value passed as the first argument of that call. +\tcode{p} is equal to \tcode{ret.ptr} and +\tcode{n} is a value such that +$\tcode{req} \leq \tcode{n} \leq \tcode{ret.count}$. +\item +Otherwise, \tcode{p} is a pointer value obtained from \tcode{allocate}. +\tcode{n} equals the value passed as the first argument +to the invocation of \tcode{allocate} which returned \tcode{p}. +\end{itemize} +\tcode{p} has not been invalidated by +an intervening call to \tcode{deallocate}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +a.max_size() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::size_type} + +\pnum +\returns +The largest value that can meaningfully be passed to \tcode{X::allocate()}. + +\pnum +\remarks +Default: +\tcode{numeric_limits::max() / sizeof(value_type)} +\end{itemdescr} + +\begin{itemdecl} +a1 == a2 +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\returns +\tcode{true} only if storage allocated from each can +be deallocated via the other. + +\pnum +\throws +Nothing. + +\pnum +\remarks +\tcode{operator==} shall be reflexive, symmetric, +and transitive. +\end{itemdescr} + +\begin{itemdecl} +a1 != a2 +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\returns +\tcode{!(a1 == a2)}. +\end{itemdescr} + +\begin{itemdecl} +a == b +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\returns +\tcode{a == Y::rebind::other(b)}. +\end{itemdescr} + +\begin{itemdecl} +a != b +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\returns +\tcode{!(a == b)}. +\end{itemdescr} + +\begin{itemdecl} +X u(a); +X u = a; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{u == a} + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +X u(b); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{Y(u) == b} and \tcode{u == X(b)}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +X u(std::move(a)); +X u = std::move(a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +The value of \tcode{a} is unchanged and is equal to \tcode{u}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +X u(std::move(b)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{u} is equal to the prior value of \tcode{X(b)}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +a.construct(c, args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +(not used) + +\pnum +\effects +Constructs an object of type \tcode{C} at \tcode{c}. + +\pnum +\remarks +Default: +\tcode{construct_at(c, std::forward(args)...)} +\end{itemdescr} + +\begin{itemdecl} +a.destroy(c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +(not used) + +\pnum +\effects +Destroys the object at \tcode{c}. + +\pnum +\remarks +Default: \tcode{destroy_at(c)} +\end{itemdescr} + +\begin{itemdecl} +a.select_on_container_copy_construction() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X} + +\pnum +\returns +Typically returns either \tcode{a} or \tcode{X()}. + +\pnum +\remarks +Default: \tcode{return a;} +\end{itemdescr} + +\begin{itemdecl} +X::propagate_on_container_copy_assignment +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Identical to or derived from \tcode{true_type} or \tcode{false_type}. + +\pnum +\returns +\tcode{true_type} only if an allocator of type \tcode{X} should be copied +when the client container is copy-assigned; +if so, \tcode{X} shall meet +the \oldconcept{CopyAssignable} requirements (\tref{cpp17.copyassignable}) and +the copy operation shall not throw exceptions. + +\pnum +\remarks +Default: \tcode{false_type} +\end{itemdescr} + +\begin{itemdecl} +X::propagate_on_container_move_assignment +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Identical to or derived from \tcode{true_type} or \tcode{false_type}. + +\pnum +\returns +\tcode{true_type} only if an allocator of type \tcode{X} should be moved +when the client container is move-assigned; +if so, \tcode{X} shall meet +the \oldconcept{MoveAssignable} requirements (\tref{cpp17.moveassignable}) and +the move operation shall not throw exceptions. + +\pnum +\remarks +Default: \tcode{false_type} +\end{itemdescr} + +\begin{itemdecl} +X::propagate_on_container_swap +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Identical to or derived from \tcode{true_type} or \tcode{false_type}. + +\pnum +\returns +\tcode{true_type} only if an allocator of type \tcode{X} should be swapped +when the client container is swapped; +if so, +lvalues of type \tcode{X} shall be swappable\iref{swappable.requirements} and +the \tcode{swap} operation shall not throw exceptions. + +\pnum +\remarks +Default: \tcode{false_type} +\end{itemdescr} + +\begin{itemdecl} +X::is_always_equal +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Identical to or derived from \tcode{true_type} or \tcode{false_type}. + +\pnum +\returns +\tcode{true_type} only if the expression \tcode{a1 == a2} is guaranteed +to be \tcode{true} for any two (possibly \tcode{const}) values +\tcode{a1}, \tcode{a2} of type \tcode{X}. + +\pnum +\remarks +Default: \tcode{is_empty::type} +\end{itemdescr} \pnum An allocator type \tcode{X} shall meet the @@ -2191,8 +2621,7 @@ \pnum \begin{example} The following is an allocator class template supporting the minimal -interface that meets the requirements of -\tref{cpp17.allocator}: +interface that meets the requirements of \ref{allocator.requirements.general}: \begin{codeblock} template @@ -2468,7 +2897,6 @@ \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} \tcode{unexpected}, and \item \indexlibraryzombie{unexpected_handler} \tcode{unexpected_handler}. \end{itemize} @@ -2645,7 +3073,7 @@ \pnum A \Cpp{} program may provide the definition for any of the following dynamic memory allocation function signatures declared in header -\tcode{}~(\ref{basic.stc.dynamic}, \ref{new.syn}): +\tcode{}\iref{basic.stc.dynamic,new.syn}: \indextext{\idxcode{new}!\idxcode{operator}!replaceable}% \indexlibrarymember{new}{operator}% @@ -2687,7 +3115,7 @@ \pnum The program's definitions are used instead of the default versions supplied by the implementation\iref{new.delete}. -Such replacement occurs prior to program startup~(\ref{basic.def.odr}, \ref{basic.start}). +Such replacement occurs prior to program startup\iref{basic.def.odr,basic.start}. \indextext{startup!program}% The program's declarations shall not be specified as \keyword{inline}. @@ -2753,7 +3181,7 @@ \required paragraph. \item -For handler functions~(\ref{new.handler}, \ref{terminate.handler}), +For handler functions\iref{new.handler,terminate.handler}, if the installed handler function does not implement the semantics of the applicable \required paragraph. @@ -2761,8 +3189,8 @@ For types used as template arguments when instantiating a template component, if the operations on the type do not implement the semantics of the applicable \emph{Requirements} -subclause~(\ref{allocator.requirements}, \ref{container.requirements}, \ref{iterator.requirements}, -\ref{algorithms.requirements}, \ref{numeric.requirements}). +subclause\iref{allocator.requirements,container.requirements,iterator.requirements, +algorithms.requirements,numeric.requirements}. Operations on such types can report a failure by throwing an exception unless otherwise specified. \item @@ -2772,7 +3200,7 @@ \required paragraph. \item -If an incomplete type\iref{basic.types} is used as a template +If an incomplete type\iref{term.incomplete.type} is used as a template argument when instantiating a template component or evaluating a concept, unless specifically allowed for that component. \end{itemize} @@ -3140,12 +3568,12 @@ \item Unless explicitly stated otherwise, types with distinct names shall be distinct types. -\begin{footnote} +\begin{note} There is an implicit exception to this rule for types that are -described as synonyms for basic integral types, such as +described as synonyms\iref{dcl.typedef,namespace.udecl}, such as \tcode{size_t}\iref{support.types} and \tcode{streamoff}\iref{stream.types}. -\end{footnote} +\end{note} \end{itemize} \pnum @@ -3206,8 +3634,8 @@ \end{footnote} Implementations should report errors by throwing exceptions of or derived -from the standard exception classes~(\ref{bad.alloc}, -\ref{support.exception}, \ref{std.exceptions}). +from the standard +exception classes\iref{bad.alloc,support.exception,std.exceptions}. \pnum An implementation may strengthen the diff --git a/source/limits.tex b/source/limits.tex index 4a9d97c2e5..e3b86f6ca1 100644 --- a/source/limits.tex +++ b/source/limits.tex @@ -37,7 +37,7 @@ or macro name\iref{cpp.replace} [1\,024]. \item% Number of -characters in an external identifier (\ref{lex.name}, \ref{basic.link}) [1\,024]. +characters in an external identifier\iref{lex.name,basic.link} [1\,024]. \item% External identifiers\iref{basic.link} in one translation unit [65\,536]. \item% diff --git a/source/locales.tex b/source/locales.tex index 328ed5c7ed..e0533f7d71 100644 --- a/source/locales.tex +++ b/source/locales.tex @@ -725,7 +725,7 @@ \begin{example} A vector of strings \tcode{v} can be collated according to collation rules in locale \tcode{loc} -simply by~(\ref{alg.sort}, \ref{vector}): +simply by\iref{alg.sort,vector}: \begin{codeblock} std::sort(v.begin(), v.end(), loc); @@ -1227,7 +1227,7 @@ from a \tcode{char} value or sequence of \tcode{char} values to the corresponding \tcode{charT} value or values. \begin{footnote} -The char argument of \tcode{do_widen} is intended to +The parameter \tcode{c} of \tcode{do_widen} is intended to accept values derived from \grammarterm{character-literal}s for conversion to the locale's encoding. \end{footnote} @@ -2044,7 +2044,7 @@ Extractor and inserter members of the standard iostreams use \tcode{num_get<>} and \tcode{num_put<>} member functions for formatting and parsing -numeric values~(\ref{istream.formatted.reqmts}, \ref{ostream.formatted.reqmts}). +numeric values\iref{istream.formatted.reqmts,ostream.formatted.reqmts}. \rSec3[locale.num.get]{Class template \tcode{num_get}} @@ -3345,7 +3345,7 @@ optionally followed by a modifier character, followed by a conversion specifier character, \tcode{format}, together forming a conversion specification -valid for the ISO/IEC 9945 function \tcode{strptime}. +valid for the POSIX function \tcode{strptime}. If the number of elements in the range \range{fmt}{fmtend} is not sufficient to unambiguously determine whether the conversion specification is complete and valid, @@ -3534,8 +3534,8 @@ It then reads characters starting at \tcode{s} until it encounters an error, or until it has extracted and assigned those \tcode{tm} members, and any remaining format characters, -corresponding to a conversion directive appropriate for -the ISO/IEC 9945 function \tcode{strptime}, +corresponding to a conversion specification appropriate for +the POSIX function \tcode{strptime}, formed by concatenating \tcode{'\%'}, the \tcode{modifier} character, when non-NUL, and the \tcode{format} character. @@ -3546,9 +3546,9 @@ the function evaluates \tcode{err |= ios_base::eofbit}. \pnum -For complex conversion directives +For complex conversion specifications such as \tcode{\%c}, \tcode{\%x}, or \tcode{\%X}, or -directives that involve the optional modifiers \tcode{E} or \tcode{O}, +conversion specifications that involve the optional modifiers \tcode{E} or \tcode{O}, when the function is unable to unambiguously determine some or all \tcode{tm} members from the input sequence \range{s}{end}, it evaluates \tcode{err |= ios_base::eofbit}. diff --git a/source/macros.tex b/source/macros.tex index b012059397..84f6ecbf71 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -188,13 +188,15 @@ \newcommand{\idxxname}[1]{__#1@\xname{#1}} % library index entries +\newcommand{\indexlibrarymisc}[2]{\indexlibrary{\idxcode{#1}!#2}} \newcommand{\indexlibraryglobal}[1]{\indexlibrary{\idxcode{#1}}} -\newcommand{\indexlibraryctor}[1]{\indexlibrary{\idxcode{#1}!constructor}} -\newcommand{\indexlibrarydtor}[1]{\indexlibrary{\idxcode{#1}!destructor}} +\newcommand{\indexlibraryctor}[1]{\indexlibrarymisc{#1}{constructor}} +\newcommand{\indexlibrarydtor}[1]{\indexlibrarymisc{#1}{destructor}} % class member library index -\newcommand{\indexlibrarymember}[2]{\indexlibrary{\idxcode{#1}!\idxcode{#2}}\indexlibrary{\idxcode{#2}!\idxcode{#1}}} -\newcommand{\indexlibraryzombie}[1]{\indexlibrary{\idxcode{#1}!zombie}} +\newcommand{\indexlibrarymemberx}[2]{\indexlibrarymisc{#1}{\idxcode{#2}}} +\newcommand{\indexlibrarymember}[2]{\indexlibrarymemberx{#1}{#2}\indexlibrarymemberx{#2}{#1}} +\newcommand{\indexlibraryzombie}[1]{\indexlibrarymisc{#1}{zombie}} \newcommand{\libglobal}[1]{\indexlibraryglobal{#1}#1} \newcommand{\libmember}[2]{\indexlibrarymember{#1}{#2}#1} @@ -224,8 +226,8 @@ \newcommand{\term}[1]{\textit{#1}} \newcommand{\gterm}[1]{\GrammarStylex{#1}} \newcommand{\fakegrammarterm}[1]{\gterm{#1}} -\newcommand{\keyword}[1]{\tcode{#1}\indextext{\idxcode{#1}}} % macro length: 8 -\newcommand{\grammarterm}[1]{\indexgram{\idxgram{#1}}\gterm{#1}} +\newcommand{\keyword}[1]{\texorpdfstring{\tcode{#1}\protect\indextext{\idxcode{#1}!keyword}}{#1}} % macro length: 8 +\newcommand{\grammarterm}[1]{\texorpdfstring{\protect\indexgram{\idxgram{#1}}\gterm{#1}}{#1}} \newcommand{\grammartermnc}[1]{\indexgram{\idxgram{#1}}\gterm{#1\nocorr}} \newcommand{\regrammarterm}[1]{\textit{#1}} \newcommand{\placeholder}[1]{\textit{#1}} % macro length: 12 @@ -337,20 +339,28 @@ \newcommand{\sync}{\Fundesc{Synchronization}} \newcommand{\implimits}{\Fundesc{Implementation limits}} \newcommand{\replaceable}{\Fundesc{Replaceable}} +\newcommand{\result}{\Fundesc{Result}} \newcommand{\returntype}{\Fundesc{Return type}} -\newcommand{\cvalue}{\Fundesc{Value}} \newcommand{\ctype}{\Fundesc{Type}} -\newcommand{\ctypes}{\Fundesc{Types}} -\newcommand{\dtype}{\Fundesc{Default type}} -\newcommand{\ctemplate}{\Fundesc{Class template}} \newcommand{\templalias}{\Fundesc{Alias template}} %% Cross reference \newcommand{\xref}{\textsc{See also:}\space} \newcommand{\xrefc}[1]{\xref{} ISO C #1} -%% Inline parenthesized reference -\newcommand{\iref}[1]{\nolinebreak[3] (\ref{#1})} +%% Inline comma-separated parenthesized references +\ExplSyntaxOn +\NewDocumentCommand \iref { m } { + \clist_set:Nx \l_tmpa_clist { #1 } + \nolinebreak[3] ~ ( + \clist_map_inline:Nn \l_tmpa_clist { + \clist_put_right:Nn \g_tmpa_clist { \ref{##1} } + } + \clist_use:Nn \g_tmpa_clist { ,~ } + ) + \clist_clear:N \g_tmpa_clist +} +\ExplSyntaxOff %% Inline non-parenthesized table reference (override memoir's \tref) \renewcommand{\tref}[1]{\hyperref[tab:#1]{\tablerefname \nolinebreak[3] \ref*{tab:#1}}} @@ -358,6 +368,39 @@ \renewcommand{\fref}[1]{\hyperref[fig:#1]{\figurerefname \nolinebreak[3] \ref*{fig:#1}}} %% NTBS, etc. +\verbtocs{\StrTextsmaller}|\textsmaller[1]{| +\verbtocs{\StrTextsc}|\textsc{| +\verbtocs{\StrClosingbrace}|}| +\newcommand{\ucode}[1]{% + \textsc{u}% + \textsmaller[2]{\kern-0.05em\protect\raisebox{.25ex}{+}}% + \begingroup% + \def\temp{#1}% + \StrSubstitute{\temp}{0}{X0Z}[\temp]% + \StrSubstitute{\temp}{1}{X1Z}[\temp]% + \StrSubstitute{\temp}{2}{X2Z}[\temp]% + \StrSubstitute{\temp}{3}{X3Z}[\temp]% + \StrSubstitute{\temp}{4}{X4Z}[\temp]% + \StrSubstitute{\temp}{5}{X5Z}[\temp]% + \StrSubstitute{\temp}{6}{X6Z}[\temp]% + \StrSubstitute{\temp}{7}{X7Z}[\temp]% + \StrSubstitute{\temp}{8}{X8Z}[\temp]% + \StrSubstitute{\temp}{9}{X9Z}[\temp]% + \StrSubstitute{\temp}{a}{YaZ}[\temp]% + \StrSubstitute{\temp}{b}{YbZ}[\temp]% + \StrSubstitute{\temp}{c}{YcZ}[\temp]% + \StrSubstitute{\temp}{d}{YdZ}[\temp]% + \StrSubstitute{\temp}{e}{YeZ}[\temp]% + \StrSubstitute{\temp}{f}{YfZ}[\temp]% + \StrSubstitute{\temp}{X}{\StrTextsmaller}[\temp]% + \StrSubstitute{\temp}{Y}{\StrTextsc}[\temp]% + \StrSubstitute{\temp}{Z}{\StrClosingbrace}[\temp]% + \tokenize\temp{\temp}% + \temp% + \endgroup% +} +\newcommand{\uname}[1]{\textsc{#1}} +\newcommand{\unicode}[2]{\ucode{#1} \uname{#2}} \newcommand{\NTS}[1]{\textsc{#1}} \newcommand{\ntbs}{\NTS{ntbs}} \newcommand{\ntmbs}{\NTS{ntmbs}} @@ -429,7 +472,7 @@ \newcommand{\defexposconceptnc}[1]{\ecname{#1}\indexconcept{\idxexposconcept{#1}|idxbfpage}\itcorr[-1]} % macro length: 18 %% Ranges -\newcommand{\Range}[4]{\tcode{#1#3,\penalty2000{} #4#2}} +\newcommand{\Range}[4]{\ensuremath{#1}\tcode{#3}\ensuremath{,}\,\penalty2000{}\tcode{#4}\ensuremath{#2}} \newcommand{\crange}[2]{\Range{[}{]}{#1}{#2}} \newcommand{\brange}[2]{\Range{(}{]}{#1}{#2}} \newcommand{\orange}[2]{\Range{(}{)}{#1}{#2}} @@ -594,7 +637,7 @@ { \newcommand{\nontermdef}[1]{{\BnfNontermshape##1\itcorr}\indexgrammar{\idxgram{##1}}\textnormal{:}} \newcommand{\terminal}[1]{{\BnfTermshape ##1}} - \renewcommand{\keyword}[1]{\terminal{##1}\indextext{\idxcode{##1}}} + \renewcommand{\keyword}[1]{\terminal{##1}\indextext{\idxcode{##1}!keyword}} \renewcommand{\exposid}[1]{\terminal{\textit{##1}}} \renewcommand{\placeholder}[1]{\textrm{\textit{##1}}} \newcommand{\descr}[1]{\textnormal{##1}} diff --git a/source/memory.tex b/source/memory.tex new file mode 100644 index 0000000000..576a28b9fc --- /dev/null +++ b/source/memory.tex @@ -0,0 +1,6756 @@ +%!TEX root = std.tex +\rSec0[mem]{Memory management library} + +\rSec1[mem.general]{General} + +\pnum +This Clause describes components for memory management. + +\pnum +The following subclauses describe general memory management facilities, +smart pointers, memory resources, and scoped allocators, +as summarized in \tref{mem.summary}. + +\begin{libsumtab}{Memory management library summary}{mem.summary} +\ref{memory} & Memory & \tcode{}, \tcode{} \\ \rowsep +\ref{smartptr} & Smart pointers & \tcode{} \\ \rowsep +\ref{mem.res} & Memory resources & \tcode{} \\ \rowsep +\ref{allocator.adaptor} & Scoped allocators & \tcode{} \\ +\end{libsumtab} + +\rSec1[memory]{Memory} + +\rSec2[memory.general]{In general} + +\pnum +Subclause~\ref{memory} describes the contents of the header +\libheaderref{memory} and some +of the contents of the header \libheaderref{cstdlib}. + +\rSec2[memory.syn]{Header \tcode{} synopsis} + +\pnum +The header \libheaderdef{memory} defines several types and function templates that +describe properties of pointers and pointer-like types, manage memory +for containers and other template types, destroy objects, and +construct objects in +uninitialized memory +buffers~(\ref{pointer.traits}--\ref{specialized.addressof} and \ref{specialized.algorithms}). +The header also defines the templates +\tcode{unique_ptr}, \tcode{shared_ptr}, \tcode{weak_ptr}, +\tcode{out_ptr_t}, \tcode{inout_ptr_t}, and various function +templates that operate on objects of these types\iref{smartptr}. + +\pnum +Let \tcode{\exposid{POINTER_OF}(T)} denote a type that is +\begin{itemize} +\item +\tcode{T::pointer} if the \grammarterm{qualified-id} \tcode{T::pointer} +is valid and denotes a type, +\item +otherwise, \tcode{T::element_type*} +if the \grammarterm{qualified-id} \tcode{T::element_type} +is valid and denotes a type, +\item +otherwise, \tcode{pointer_traits::element_type*}. +\end{itemize} + +\pnum +Let \tcode{\exposid{POINTER_OF_OR}(T, U)} denote a type that is: +\begin{itemize} +\item +\tcode{\exposid{POINTER_OF}(T)} +if \tcode{\exposid{POINTER_OF}(T)} is valid and denotes a type, +\item +otherwise, \tcode{U}. +\end{itemize} + +\begin{codeblock} +#include // see \ref{compare.syn} + +namespace std { + // \ref{pointer.traits}, pointer traits + template struct pointer_traits; + template struct pointer_traits; + + // \ref{pointer.conversion}, pointer conversion + template + constexpr T* to_address(T* p) noexcept; + template + constexpr auto to_address(const Ptr& p) noexcept; + + // \ref{ptr.align}, pointer alignment + void* align(size_t alignment, size_t size, void*& ptr, size_t& space); + template + [[nodiscard]] constexpr T* assume_aligned(T* ptr); + + // \ref{allocator.tag}, allocator argument tag + struct allocator_arg_t { explicit allocator_arg_t() = default; }; + inline constexpr allocator_arg_t allocator_arg{}; + + // \ref{allocator.uses}, \tcode{uses_allocator} + template struct uses_allocator; + + // \ref{allocator.uses.trait}, \tcode{uses_allocator} + template + inline constexpr bool @\libglobal{uses_allocator_v}@ = uses_allocator::value; + + // \ref{allocator.uses.construction}, uses-allocator construction + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + Args&&... args) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, + Tuple1&& x, Tuple2&& y) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + U&& u, V&& v) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + pair& pr) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + const pair& pr) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + pair&& pr) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + const pair&& pr) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept; + template + constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); + template + constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, + Args&&... args); + + // \ref{allocator.traits}, allocator traits + template struct allocator_traits; + + template + struct allocation_result { + Pointer ptr; + size_t count; + }; + + template + [[nodiscard] constexpr allocation_result::pointer> + allocate_at_least(Allocator& a, size_t n); + + // \ref{default.allocator}, the default allocator + template class allocator; + template + constexpr bool operator==(const allocator&, const allocator&) noexcept; + + // \ref{specialized.addressof}, addressof + template + constexpr T* addressof(T& r) noexcept; + template + const T* addressof(const T&&) = delete; + + // \ref{specialized.algorithms}, specialized algorithms + // \ref{special.mem.concepts}, special memory concepts + template + concept @\exposconcept{nothrow-input-iterator}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-forward-iterator}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-sentinel-for}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-input-range}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-forward-range}@ = @\seebelow@; // \expos + + template + void uninitialized_default_construct(NoThrowForwardIterator first, + NoThrowForwardIterator last); + template + void uninitialized_default_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, + NoThrowForwardIterator last); + template + NoThrowForwardIterator + uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); + template + NoThrowForwardIterator + uninitialized_default_construct_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, Size n); + + namespace ranges { + template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> + requires @\libconcept{default_initializable}@> + I uninitialized_default_construct(I first, S last); + template<@\exposconcept{nothrow-forward-range}@ R> + requires @\libconcept{default_initializable}@> + borrowed_iterator_t uninitialized_default_construct(R&& r); + + template<@\exposconcept{nothrow-forward-iterator}@ I> + requires @\libconcept{default_initializable}@> + I uninitialized_default_construct_n(I first, iter_difference_t n); + } + + template + void uninitialized_value_construct(NoThrowForwardIterator first, + NoThrowForwardIterator last); + template + void uninitialized_value_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, + NoThrowForwardIterator last); + template + NoThrowForwardIterator + uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); + template + NoThrowForwardIterator + uninitialized_value_construct_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, Size n); + + namespace ranges { + template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> + requires @\libconcept{default_initializable}@> + I uninitialized_value_construct(I first, S last); + template<@\exposconcept{nothrow-forward-range}@ R> + requires @\libconcept{default_initializable}@> + borrowed_iterator_t uninitialized_value_construct(R&& r); + + template<@\exposconcept{nothrow-forward-iterator}@ I> + requires @\libconcept{default_initializable}@> + I uninitialized_value_construct_n(I first, iter_difference_t n); + } + + template + NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last, + NoThrowForwardIterator result); + template + NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator first, ForwardIterator last, + NoThrowForwardIterator result); + template + NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, + NoThrowForwardIterator result); + template + NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator first, Size n, + NoThrowForwardIterator result); + + namespace ranges { + template + using uninitialized_copy_result = in_out_result; + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S1, + @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> + requires @\libconcept{constructible_from}@, iter_reference_t> + uninitialized_copy_result + uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast); + template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> + requires @\libconcept{constructible_from}@, range_reference_t> + uninitialized_copy_result, borrowed_iterator_t> + uninitialized_copy(IR&& in_range, OR&& out_range); + + template + using uninitialized_copy_n_result = in_out_result; + template<@\libconcept{input_iterator}@ I, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> + requires @\libconcept{constructible_from}@, iter_reference_t> + uninitialized_copy_n_result + uninitialized_copy_n(I ifirst, iter_difference_t n, O ofirst, S olast); + } + + template + NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last, + NoThrowForwardIterator result); + template + NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator first, ForwardIterator last, + NoThrowForwardIterator result); + template + pair + uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result); + template + pair + uninitialized_move_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator first, Size n, NoThrowForwardIterator result); + + namespace ranges { + template + using uninitialized_move_result = in_out_result; + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S1, + @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> + requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> + uninitialized_move_result + uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast); + template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> + requires @\libconcept{constructible_from}@, range_rvalue_reference_t> + uninitialized_move_result, borrowed_iterator_t> + uninitialized_move(IR&& in_range, OR&& out_range); + + template + using uninitialized_move_n_result = in_out_result; + template<@\libconcept{input_iterator}@ I, + @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> + requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> + uninitialized_move_n_result + uninitialized_move_n(I ifirst, iter_difference_t n, O ofirst, S olast); + } + + template + void uninitialized_fill(NoThrowForwardIterator first, NoThrowForwardIterator last, + const T& x); + template + void uninitialized_fill(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, NoThrowForwardIterator last, + const T& x); + template + NoThrowForwardIterator + uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); + template + NoThrowForwardIterator + uninitialized_fill_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, Size n, const T& x); + + namespace ranges { + template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S, class T> + requires @\libconcept{constructible_from}@, const T&> + I uninitialized_fill(I first, S last, const T& x); + template<@\exposconcept{nothrow-forward-range}@ R, class T> + requires @\libconcept{constructible_from}@, const T&> + borrowed_iterator_t uninitialized_fill(R&& r, const T& x); + + template<@\exposconcept{nothrow-forward-iterator}@ I, class T> + requires @\libconcept{constructible_from}@, const T&> + I uninitialized_fill_n(I first, iter_difference_t n, const T& x); + } + + // \ref{specialized.construct}, \tcode{construct_at} + template + constexpr T* construct_at(T* location, Args&&... args); + + namespace ranges { + template + constexpr T* construct_at(T* location, Args&&... args); + } + + // \ref{specialized.destroy}, \tcode{destroy} + template + constexpr void destroy_at(T* location); + template + constexpr void destroy(NoThrowForwardIterator first, NoThrowForwardIterator last); + template + void destroy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, NoThrowForwardIterator last); + template + constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, Size n); + template + NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, Size n); + + namespace ranges { + template<@\libconcept{destructible}@ T> + constexpr void destroy_at(T* location) noexcept; + + template<@\exposconcept{nothrow-input-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> + requires @\libconcept{destructible}@> + constexpr I destroy(I first, S last) noexcept; + template<@\exposconcept{nothrow-input-range}@ R> + requires @\libconcept{destructible}@> + constexpr borrowed_iterator_t destroy(R&& r) noexcept; + + template<@\exposconcept{nothrow-input-iterator}@ I> + requires @\libconcept{destructible}@> + constexpr I destroy_n(I first, iter_difference_t n) noexcept; + } + + // \ref{unique.ptr}, class template \tcode{unique_ptr} + template struct default_delete; + template struct default_delete; + template> class unique_ptr; + template class unique_ptr; + + template + constexpr unique_ptr make_unique(Args&&... args); // \tcode{T} is not array + template + constexpr unique_ptr make_unique(size_t n); // \tcode{T} is \tcode{U[]} + template + @\unspecnc@ make_unique(Args&&...) = delete; // \tcode{T} is \tcode{U[N]} + + template + constexpr unique_ptr make_unique_for_overwrite(); // \tcode{T} is not array + template + constexpr unique_ptr make_unique_for_overwrite(size_t n); // \tcode{T} is \tcode{U[]} + template + @\unspecnc@ make_unique_for_overwrite(Args&&...) = delete; // \tcode{T} is \tcode{U[N]} + + template + constexpr void swap(unique_ptr& x, unique_ptr& y) noexcept; + + template + constexpr bool operator==(const unique_ptr& x, const unique_ptr& y); + template + bool operator<(const unique_ptr& x, const unique_ptr& y); + template + bool operator>(const unique_ptr& x, const unique_ptr& y); + template + bool operator<=(const unique_ptr& x, const unique_ptr& y); + template + bool operator>=(const unique_ptr& x, const unique_ptr& y); + template + requires @\libconcept{three_way_comparable_with}@::pointer, + typename unique_ptr::pointer> + compare_three_way_result_t::pointer, + typename unique_ptr::pointer> + operator<=>(const unique_ptr& x, const unique_ptr& y); + + template + constexpr bool operator==(const unique_ptr& x, nullptr_t) noexcept; + template + constexpr bool operator<(const unique_ptr& x, nullptr_t); + template + constexpr bool operator<(nullptr_t, const unique_ptr& y); + template + constexpr bool operator>(const unique_ptr& x, nullptr_t); + template + constexpr bool operator>(nullptr_t, const unique_ptr& y); + template + constexpr bool operator<=(const unique_ptr& x, nullptr_t); + template + constexpr bool operator<=(nullptr_t, const unique_ptr& y); + template + constexpr bool operator>=(const unique_ptr& x, nullptr_t); + template + constexpr bool operator>=(nullptr_t, const unique_ptr& y); + template + requires @\libconcept{three_way_comparable}@::pointer> + constexpr compare_three_way_result_t::pointer> + operator<=>(const unique_ptr& x, nullptr_t); + + template + basic_ostream& operator<<(basic_ostream& os, const unique_ptr& p); + + // \ref{util.smartptr.weak.bad}, class \tcode{bad_weak_ptr} + class bad_weak_ptr; + + // \ref{util.smartptr.shared}, class template \tcode{shared_ptr} + template class shared_ptr; + + // \ref{util.smartptr.shared.create}, \tcode{shared_ptr} creation + template + shared_ptr make_shared(Args&&... args); // \tcode{T} is not array + template + shared_ptr allocate_shared(const A& a, Args&&... args); // \tcode{T} is not array + + template + shared_ptr make_shared(size_t N); // \tcode{T} is \tcode{U[]} + template + shared_ptr allocate_shared(const A& a, size_t N); // \tcode{T} is \tcode{U[]} + + template + shared_ptr make_shared(); // \tcode{T} is \tcode{U[N]} + template + shared_ptr allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]} + + template + shared_ptr make_shared(size_t N, const remove_extent_t& u); // \tcode{T} is \tcode{U[]} + template + shared_ptr allocate_shared(const A& a, size_t N, + const remove_extent_t& u); // \tcode{T} is \tcode{U[]} + + template + shared_ptr make_shared(const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} + template + shared_ptr allocate_shared(const A& a, const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} + + template + shared_ptr make_shared_for_overwrite(); // \tcode{T} is not \tcode{U[]} + template + shared_ptr allocate_shared_for_overwrite(const A& a); // \tcode{T} is not \tcode{U[]} + + template + shared_ptr make_shared_for_overwrite(size_t N); // \tcode{T} is \tcode{U[]} + template + shared_ptr allocate_shared_for_overwrite(const A& a, size_t N); // \tcode{T} is \tcode{U[]} + + // \ref{util.smartptr.shared.cmp}, \tcode{shared_ptr} comparisons + template + bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; + template + strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; + + template + bool operator==(const shared_ptr& x, nullptr_t) noexcept; + template + strong_ordering operator<=>(const shared_ptr& x, nullptr_t) noexcept; + + // \ref{util.smartptr.shared.spec}, \tcode{shared_ptr} specialized algorithms + template + void swap(shared_ptr& a, shared_ptr& b) noexcept; + + // \ref{util.smartptr.shared.cast}, \tcode{shared_ptr} casts + template + shared_ptr static_pointer_cast(const shared_ptr& r) noexcept; + template + shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; + template + shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; + template + shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; + template + shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; + template + shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; + template + shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept; + template + shared_ptr reinterpret_pointer_cast(shared_ptr&& r) noexcept; + + // \ref{util.smartptr.getdeleter}, \tcode{shared_ptr} \tcode{get_deleter} + template + D* get_deleter(const shared_ptr& p) noexcept; + + // \ref{util.smartptr.shared.io}, \tcode{shared_ptr} I/O + template + basic_ostream& operator<<(basic_ostream& os, const shared_ptr& p); + + // \ref{util.smartptr.weak}, class template \tcode{weak_ptr} + template class weak_ptr; + + // \ref{util.smartptr.weak.spec}, \tcode{weak_ptr} specialized algorithms + template void swap(weak_ptr& a, weak_ptr& b) noexcept; + + // \ref{util.smartptr.ownerless}, class template \tcode{owner_less} + template struct owner_less; + + // \ref{util.smartptr.enab}, class template \tcode{enable_shared_from_this} + template class enable_shared_from_this; + + // \ref{util.smartptr.hash}, hash support + template struct hash; + template struct hash>; + template struct hash>; + + // \ref{util.smartptr.atomic}, atomic smart pointers + template struct atomic; + template struct atomic>; + template struct atomic>; + + // \ref{out.ptr.t}, class template \tcode{out_ptr_t} + template + class out_ptr_t; + + // \ref{out.ptr}, function template \tcode{out_ptr} + template + auto out_ptr(Smart& s, Args&&... args); + + // \ref{inout.ptr.t}, class template \tcode{inout_ptr_t} + template + class inout_ptr_t; + + // \ref{inout.ptr}, function template \tcode{inout_ptr} + template + auto inout_ptr(Smart& s, Args&&... args); +} +\end{codeblock} + +\rSec2[pointer.traits]{Pointer traits} + +\rSec3[pointer.traits.general]{General} + +\pnum +The class template \tcode{pointer_traits} supplies a uniform interface to certain +attributes of pointer-like types. + +\indexlibraryglobal{pointer_traits}% +\begin{codeblock} +namespace std { + template struct pointer_traits { + using pointer = Ptr; + using element_type = @\seebelow@; + using difference_type = @\seebelow@; + + template using rebind = @\seebelow@; + + static pointer pointer_to(@\seebelow@ r); + }; + + template struct pointer_traits { + using pointer = T*; + using element_type = T; + using difference_type = ptrdiff_t; + + template using rebind = U*; + + static constexpr pointer pointer_to(@\seebelow@ r) noexcept; + }; +} +\end{codeblock} + +\rSec3[pointer.traits.types]{Member types} + +\indexlibrarymember{element_type}{pointer_traits}% +\begin{itemdecl} +using element_type = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Ptr::element_type} if +the \grammarterm{qualified-id} \tcode{Ptr::element_type} is valid and denotes a +type\iref{temp.deduct}; otherwise, \tcode{T} if +\tcode{Ptr} is a class template instantiation of the form \tcode{SomePointer}, +where \tcode{Args} is zero or more type arguments; otherwise, the specialization is +ill-formed. +\end{itemdescr} + +\indexlibrarymember{difference_type}{pointer_traits}% +\begin{itemdecl} +using difference_type = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Ptr::difference_type} if +the \grammarterm{qualified-id} \tcode{Ptr::difference_type} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{ptrdiff_t}. +\end{itemdescr} + +\indexlibrarymember{rebind}{pointer_traits}% +\begin{itemdecl} +template using rebind = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\templalias \tcode{Ptr::rebind} if +the \grammarterm{qualified-id} \tcode{Ptr::rebind} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{SomePointer} if +\tcode{Ptr} is a class template instantiation of the form \tcode{SomePointer}, +where \tcode{Args} is zero or more type arguments; otherwise, the instantiation of +\tcode{rebind} is ill-formed. +\end{itemdescr} + +\rSec3[pointer.traits.functions]{Member functions} + +\indexlibrarymember{pointer_to}{pointer_traits}% +\begin{itemdecl} +static pointer pointer_traits::pointer_to(@\seebelow@ r); +static constexpr pointer pointer_traits::pointer_to(@\seebelow@ r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +For the first member function, +\tcode{Ptr::pointer_to(r)} is well-formed. + +\pnum +\expects +For the first member function, +\tcode{Ptr::pointer_to(r)} returns a pointer to \tcode{r} +through which indirection is valid. + +\pnum +\returns +The first member function returns \tcode{Ptr::pointer_to(r)}. +The second member function returns \tcode{addressof(r)}. + +\pnum +\remarks +If \tcode{element_type} is \cv{}~\keyword{void}, the type of +\tcode{r} is unspecified; otherwise, it is \tcode{element_type\&}. +\end{itemdescr} + +\rSec3[pointer.traits.optmem]{Optional members} + +\pnum +Specializations of \tcode{pointer_traits} may define the member declared +in this subclause to customize the behavior of the standard library. + +\indexlibrarymember{to_address}{pointer_traits}% +\begin{itemdecl} +static element_type* to_address(pointer p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A pointer of type \tcode{element_type*} that references +the same location as the argument \tcode{p}. + +\pnum +\begin{note} +This function is intended to be the inverse of \tcode{pointer_to}. +If defined, it customizes the behavior of +the non-member function +\tcode{to_address}\iref{pointer.conversion}. +\end{note} +\end{itemdescr} + +\rSec2[pointer.conversion]{Pointer conversion} + +\indexlibraryglobal{to_address}% +\begin{itemdecl} +template constexpr T* to_address(T* p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is not a function type. + +\pnum +\returns +\tcode{p}. +\end{itemdescr} + +\indexlibraryglobal{to_address}% +\begin{itemdecl} +template constexpr auto to_address(const Ptr& p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{pointer_traits::to_address(p)} if that expression is well-formed +(see \ref{pointer.traits.optmem}), +otherwise \tcode{to_address(p.operator->())}. +\end{itemdescr} + +\rSec2[ptr.align]{Pointer alignment} + +\indexlibraryglobal{align}% +\begin{itemdecl} +void* align(size_t alignment, size_t size, void*& ptr, size_t& space); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +\tcode{alignment} is a power of two + +\item +\tcode{ptr} represents the address of contiguous storage of at least +\tcode{space} bytes +\end{itemize} + +\pnum +\effects +If it is possible to fit \tcode{size} bytes +of storage aligned by \tcode{alignment} into the buffer pointed to by +\tcode{ptr} with length \tcode{space}, the function updates +\tcode{ptr} to represent the first possible address of such storage +and decreases \tcode{space} by the number of bytes used for alignment. +Otherwise, the function does nothing. + +\pnum +\returns +A null pointer if the requested aligned buffer +would not fit into the available space, otherwise the adjusted value +of \tcode{ptr}. + +\pnum +\begin{note} +The function updates its \tcode{ptr} +and \tcode{space} arguments so that it can be called repeatedly +with possibly different \tcode{alignment} and \tcode{size} +arguments for the same buffer. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{assume_aligned}% +\begin{itemdecl} +template + [[nodiscard]] constexpr T* assume_aligned(T* ptr); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{N} is a power of two. + +\pnum +\expects +\tcode{ptr} points to an object \tcode{X} of +a type similar\iref{conv.qual} to \tcode{T}, +where \tcode{X} has alignment \tcode{N}\iref{basic.align}. + +\pnum +\returns +\tcode{ptr}. + +\pnum +\throws +Nothing. + +\pnum +\begin{note} +The alignment assumption on an object \tcode{X} +expressed by a call to \tcode{assume_aligned} +might result in generation of more efficient code. +It is up to the program to ensure that the assumption actually holds. +The call does not cause the implementation to verify or enforce this. +An implementation might only make the assumption +for those operations on \tcode{X} that access \tcode{X} +through the pointer returned by \tcode{assume_aligned}. +\end{note} +\end{itemdescr} + +\rSec2[allocator.tag]{Allocator argument tag} + +\indexlibraryglobal{allocator_arg_t}% +\indexlibraryglobal{allocator_arg}% +\begin{itemdecl} +namespace std { + struct allocator_arg_t { explicit allocator_arg_t() = default; }; + inline constexpr allocator_arg_t allocator_arg{}; +} +\end{itemdecl} + +\pnum +The \tcode{allocator_arg_t} struct is an empty class type used as a unique type to +disambiguate constructor and function overloading. Specifically, several types (see +\tcode{tuple}~\ref{tuple}) have constructors with \tcode{allocator_arg_t} as the first +argument, immediately followed by an argument of a type that meets the +\oldconcept{Allocator} requirements\iref{allocator.requirements.general}. + +\rSec2[allocator.uses]{\tcode{uses_allocator}} + +\rSec3[allocator.uses.trait]{\tcode{uses_allocator} trait} + +\indexlibraryglobal{uses_allocator}% +\begin{itemdecl} +template struct uses_allocator; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\remarks +Automatically detects whether \tcode{T} has a nested \tcode{allocator_type} that +is convertible from \tcode{Alloc}. Meets the \oldconcept{BinaryTypeTrait} +requirements\iref{meta.rqmts}. The implementation shall provide a definition that is +derived from \tcode{true_type} if the \grammarterm{qualified-id} \tcode{T::allocator_type} +is valid and denotes a type\iref{temp.deduct} and +\tcode{is_convertible_v != false}, otherwise it shall be +derived from \tcode{false_type}. A program may specialize this template to derive from +\tcode{true_type} for a program-defined type \tcode{T} that does not have a nested +\tcode{allocator_type} but nonetheless can be constructed with an allocator where +either: +\begin{itemize} +\item the first argument of a constructor has type \tcode{allocator_arg_t} and the +second argument has type \tcode{Alloc} or + +\item the last argument of a constructor has type \tcode{Alloc}. +\end{itemize} +\end{itemdescr} + +\rSec3[allocator.uses.construction]{Uses-allocator construction} + +\pnum +\defnx{Uses-allocator construction}{uses-allocator construction} +with allocator \tcode{alloc} and constructor arguments \tcode{args...} +refers to the construction of an object of type \tcode{T} +such that \tcode{alloc} is passed to the constructor of \tcode{T} +if \tcode{T} uses an allocator type compatible with \tcode{alloc}. +When applied to the construction of an object of type \tcode{T}, +it is equivalent to initializing it with the value of the expression +\tcode{make_obj_using_allocator(alloc, args...)}, described below. + +\pnum +The following utility functions support +three conventions for passing \tcode{alloc} to a constructor: +\begin{itemize} +\item + If \tcode{T} does not use an allocator compatible with \tcode{alloc}, + then \tcode{alloc} is ignored. +\item + Otherwise, if \tcode{T} has a constructor invocable as + \tcode{T(allocator_arg, alloc, args...)} (leading-allocator convention), + then uses-allocator construction chooses this constructor form. +\item + Otherwise, if \tcode{T} has a constructor invocable as + \tcode{T(args..., alloc)} (trailing-allocator convention), + then uses-allocator construction chooses this constructor form. +\end{itemize} + +\pnum +The \tcode{uses_allocator_construction_args} function template +takes an allocator and argument list and +produces (as a tuple) a new argument list matching one of the above conventions. +Additionally, overloads are provided +that treat specializations of \tcode{pair} +such that uses-allocator construction is applied individually +to the \tcode{first} and \tcode{second} data members. +The \tcode{make_obj_using_allocator} and +\tcode{uninitialized_construct_using_allocator} function templates +apply the modified constructor arguments +to construct an object of type \tcode{T} +as a return value or in-place, respectively. +\begin{note} +For \tcode{uses_allocator_construction_args} and +\tcode{make_obj_using_allocator}, type \tcode{T} +is not deduced and must therefore be specified explicitly by the caller. +\end{note} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + Args&&... args) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is not a specialization of \tcode{pair}. + +\pnum +\returns +A \tcode{tuple} value determined as follows: +\begin{itemize} +\item + If \tcode{uses_allocator_v} is \tcode{false} and + \tcode{is_constructible_v} is \tcode{true}, + return \tcode{forward_as_tuple(std::forward(args)...)}. +\item + Otherwise, if \tcode{uses_allocator_v} is \tcode{true} and + \tcode{is_constructible_v} + is \tcode{true}, + return +\begin{codeblock} +tuple( + allocator_arg, alloc, std::forward(args)...) +\end{codeblock} +\item + Otherwise, if \tcode{uses_allocator_v} is \tcode{true} and + \tcode{is_constructible_v} is \tcode{true}, + return \tcode{forward_as_tuple(std::forward(args)..., alloc)}. +\item + Otherwise, the program is ill-formed. +\end{itemize} +\begin{note} +This definition prevents a silent failure +to pass the allocator to a constructor of a type for which +\tcode{uses_allocator_v} is \tcode{true}. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, + Tuple1&& x, Tuple2&& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}. + +\pnum +\effects +For \tcode{T} specified as \tcode{pair}, equivalent to: +\begin{codeblock} +return make_tuple( + piecewise_construct, + apply([&alloc](auto&&... args1) { + return uses_allocator_construction_args( + alloc, std::forward(args1)...); + }, std::forward(x)), + apply([&alloc](auto&&... args2) { + return uses_allocator_construction_args( + alloc, std::forward(args2)...); + }, std::forward(y))); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return uses_allocator_construction_args(alloc, piecewise_construct, + tuple<>{}, tuple<>{}); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + U&& u, V&& v) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return uses_allocator_construction_args(alloc, piecewise_construct, + forward_as_tuple(std::forward(u)), + forward_as_tuple(std::forward(v))); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + pair& pr) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + const pair& pr) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return uses_allocator_construction_args(alloc, piecewise_construct, + forward_as_tuple(pr.first), + forward_as_tuple(pr.second)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + pair&& pr) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + const pair&& pr) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return uses_allocator_construction_args(alloc, piecewise_construct, + forward_as_tuple(get<0>(std::move(pr))), + forward_as_tuple(get<1>(std::move(pr)))); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \exposid{FUN} be the function template: +\begin{codeblock} +template + void @\exposid{FUN}@(const pair&); +\end{codeblock} + +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}, and +the expression \tcode{\exposid{FUN}(u)} is not well-formed +when considered as an unevaluated operand. + +\pnum +Let \exposid{pair-constructor} be an exposition-only class defined as follows: + +\begin{codeblock} +class @\exposid{pair-constructor}@ { + using @\exposid{pair-type}@ = remove_cv_t; // \expos + + constexpr auto @\exposid{do-construct}@(const @\exposid{pair-type}@& p) const { // \expos + return make_obj_using_allocator<@\exposid{pair-type}@>(@\exposid{alloc_}@, p); + } + constexpr auto @\exposid{do-construct}@(@\exposid{pair-type}@&& p) const { // \expos + return make_obj_using_allocator<@\exposid{pair-type}@>(@\exposid{alloc_}@, std::move(p)); + } + + const Alloc& @\exposid{alloc_}@; // \expos + U& @\exposid{u_}@; // \expos + +public: + constexpr operator @\exposid{pair-type}@() const { + return @\exposid{do-construct}@(std::forward(@\exposid{u_}@)); + } +}; +\end{codeblock} + +\pnum +\returns +\tcode{make_tuple(pc)}, +where \tcode{pc} is a \exposid{pair-constructor} object +whose \exposid{alloc_} member is initialized with \tcode{alloc} and +whose \exposid{u_} member is initialized with \tcode{u}. +\end{itemdescr} + +\indexlibraryglobal{make_obj_using_allocator}% +\begin{itemdecl} +template + constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return make_from_tuple(uses_allocator_construction_args( + alloc, std::forward(args)...)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uninitialized_construct_using_allocator}% +\begin{itemdecl} +template + constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply([&](U&&... xs) { + return construct_at(p, std::forward(xs)...); + }, uses_allocator_construction_args(alloc, std::forward(args)...)); +\end{codeblock} +\end{itemdescr} + +\rSec2[allocator.traits]{Allocator traits} + +\rSec3[allocator.traits.general]{General} + +\pnum +The class template \tcode{allocator_traits} supplies a uniform interface to all +allocator types. +An allocator cannot be a non-class type, however, even if \tcode{allocator_traits} +supplies the entire required interface. +\begin{note} +Thus, it is always possible to create +a derived class from an allocator. +\end{note} + +\indexlibraryglobal{allocator_traits}% +\begin{codeblock} +namespace std { + template struct allocator_traits { + using allocator_type = Alloc; + + using value_type = typename Alloc::value_type; + + using pointer = @\seebelow@; + using const_pointer = @\seebelow@; + using void_pointer = @\seebelow@; + using const_void_pointer = @\seebelow@; + + using difference_type = @\seebelow@; + using size_type = @\seebelow@; + + using propagate_on_container_copy_assignment = @\seebelow@; + using propagate_on_container_move_assignment = @\seebelow@; + using propagate_on_container_swap = @\seebelow@; + using is_always_equal = @\seebelow@; + + template using rebind_alloc = @\seebelow@; + template using rebind_traits = allocator_traits>; + + [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n); + [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n, + const_void_pointer hint); + + static constexpr void deallocate(Alloc& a, pointer p, size_type n); + + template + static constexpr void construct(Alloc& a, T* p, Args&&... args); + + template + static constexpr void destroy(Alloc& a, T* p); + + static constexpr size_type max_size(const Alloc& a) noexcept; + + static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs); + }; +} +\end{codeblock} + +\rSec3[allocator.traits.types]{Member types} + +\indexlibrarymember{pointer}{allocator_traits}% +\begin{itemdecl} +using pointer = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::pointer} if +the \grammarterm{qualified-id} \tcode{Alloc::pointer} is valid and denotes a +type\iref{temp.deduct}; otherwise, \tcode{value_type*}. +\end{itemdescr} + +\indexlibrarymember{const_pointer}{allocator_traits}% +\begin{itemdecl} +using const_pointer = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::const_pointer} if +the \grammarterm{qualified-id} \tcode{Alloc::const_pointer} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{pointer_traits::rebind<\brk{}const value_type>}. +\end{itemdescr} + +\indexlibrarymember{void_pointer}{allocator_traits}% +\begin{itemdecl} +using void_pointer = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::void_pointer} if +the \grammarterm{qualified-id} \tcode{Alloc::void_pointer} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{pointer_traits::rebind<\brk{}void>}. +\end{itemdescr} + +\indexlibrarymember{const_void_pointer}{allocator_traits}% +\begin{itemdecl} +using const_void_pointer = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::const_void_pointer} if +the \grammarterm{qualified-id} \tcode{Alloc::const_void_pointer} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{pointer_traits::\brk{}rebind}. +\end{itemdescr} + +\indexlibrarymember{difference_type}{allocator_traits}% +\begin{itemdecl} +using difference_type = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::difference_type} if +the \grammarterm{qualified-id} \tcode{Alloc::difference_type} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{pointer_traits::dif\-ference_type}. +\end{itemdescr} + +\indexlibrarymember{size_type}{allocator_traits}% +\begin{itemdecl} +using size_type = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::size_type} if +the \grammarterm{qualified-id} \tcode{Alloc::size_type} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{make_unsigned_t}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_copy_assignment}{allocator_traits}% +\begin{itemdecl} +using propagate_on_container_copy_assignment = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::propagate_on_container_copy_assignment} if +the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_copy_assignment} is valid and denotes a +type\iref{temp.deduct}; otherwise +\tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_move_assignment}{allocator_traits}% +\begin{itemdecl} +using propagate_on_container_move_assignment = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::propagate_on_container_move_assignment} if +the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_move_assignment} is valid and denotes a +type\iref{temp.deduct}; otherwise +\tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_swap}{allocator_traits}% +\begin{itemdecl} +using propagate_on_container_swap = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::propagate_on_container_swap} if +the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_swap} is valid and denotes a +type\iref{temp.deduct}; otherwise +\tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{is_always_equal}{allocator_traits}% +\begin{itemdecl} +using is_always_equal = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::is_always_equal} if +the \grammarterm{qualified-id} \tcode{Alloc::is_always_equal} +is valid and denotes a type\iref{temp.deduct}; +otherwise \tcode{is_empty::type}. +\end{itemdescr} + +\indexlibrarymember{rebind_alloc}{allocator_traits}% +\begin{itemdecl} +template using rebind_alloc = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\templalias \tcode{Alloc::rebind::other} if +the \grammarterm{qualified-id} \tcode{Alloc::rebind::other} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{Alloc} if \tcode{Alloc} is a class template instantiation +of the form \tcode{Alloc}, where \tcode{Args} is zero or more type arguments; +otherwise, the instantiation of \tcode{rebind_alloc} is ill-formed. +\end{itemdescr} + +\rSec3[allocator.traits.members]{Static member functions} + +\indexlibrarymember{allocate}{allocator_traits}% +\begin{itemdecl} +[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{a.allocate(n)}. +\end{itemdescr} + +\indexlibrarymember{allocate}{allocator_traits}% +\begin{itemdecl} +[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{a.allocate(n, hint)} if that expression is well-formed; otherwise, \tcode{a.allocate(n)}. +\end{itemdescr} + +\indexlibrarymember{deallocate}{allocator_traits}% +\begin{itemdecl} +static constexpr void deallocate(Alloc& a, pointer p, size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{a.deallocate(p, n)}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{construct}{allocator_traits}% +\begin{itemdecl} +template + static constexpr void construct(Alloc& a, T* p, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{a.construct(p, std::forward(args)...)} +if that call is well-formed; +otherwise, invokes \tcode{construct_at(p, std::forward(args)...)}. +\end{itemdescr} + +\indexlibrarymember{destroy}{allocator_traits}% +\begin{itemdecl} +template + static constexpr void destroy(Alloc& a, T* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{a.destroy(p)} if that call is well-formed; otherwise, invokes +\tcode{destroy_at(p)}. +\end{itemdescr} + +\indexlibrarymember{max_size}{allocator_traits}% +\begin{itemdecl} +static constexpr size_type max_size(const Alloc& a) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{a.max_size()} if that expression is well-formed; otherwise, +\tcode{numeric_limits::\brk{}max()/sizeof(value_type)}. +\end{itemdescr} + +\indexlibrarymember{select_on_container_copy_construction}{allocator_traits}% +\begin{itemdecl} +static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{rhs.select_on_container_copy_construction()} if that expression is +well-formed; otherwise, \tcode{rhs}. +\end{itemdescr} + +\rSec3[allocator.traits.other]{Other} + +\pnum +The class template \tcode{allocation_result} has +the template parameters, data members, and special members specified above. +It has no base classes or members other than those specified. + +\begin{itemdecl} +template +[[nodiscard]] constexpr allocation_result::pointer> + allocate_at_least(Allocator& a, size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{a.allocate_at_least(n)} if that expression is well-formed; +otherwise, \tcode{\{a.allocate(n), n\}}. +\end{itemdescr} + +\rSec2[default.allocator]{The default allocator} + +\rSec3[default.allocator.general]{General} + +\pnum +All specializations of the default allocator meet the +allocator completeness requirements\iref{allocator.requirements.completeness}. + +\indexlibraryglobal{allocator}% +\indexlibrarymember{value_type}{allocator}% +\indexlibrarymember{size_type}{allocator}% +\indexlibrarymember{difference_type}{allocator}% +\indexlibrarymember{propagate_on_container_move_assignment}{allocator}% +\indexlibrarymember{operator=}{allocator}% +\begin{codeblock} +namespace std { + template class allocator { + public: + using value_type = T; + using size_type = size_t; + using difference_type = ptrdiff_t; + using propagate_on_container_move_assignment = true_type; + + constexpr allocator() noexcept; + constexpr allocator(const allocator&) noexcept; + template constexpr allocator(const allocator&) noexcept; + constexpr ~allocator(); + constexpr allocator& operator=(const allocator&) = default; + + [[nodiscard]] constexpr T* allocate(size_t n); + [[nodiscard]] constexpr allocation_result allocate_at_least(size_t n); + constexpr void deallocate(T* p, size_t n); + }; +} +\end{codeblock} + +\pnum +\tcode{allocator_traits>::is_always_equal::value} +is \tcode{true} for any \tcode{T}. + +\rSec3[allocator.members]{Members} + +\pnum +Except for the destructor, member functions of the default allocator shall not introduce +data races\iref{intro.multithread} as a result of concurrent calls to those member +functions from different threads. Calls to these functions that allocate or deallocate a +particular unit of storage shall occur in a single total order, and each such +deallocation call shall happen before the next allocation (if any) in this order. + +\indexlibrarymember{allocate}{allocator}% +\begin{itemdecl} +[[nodiscard]] constexpr T* allocate(size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is not an incomplete type\iref{term.incomplete.type}. + +\pnum +\returns +A pointer to the initial element of an array of \tcode{n} \tcode{T}. + +\pnum +\throws +\tcode{bad_array_new_length} if +\tcode{numeric_limits::max() / sizeof(T) < n}, or +\tcode{bad_alloc} if the storage cannot be obtained. + +\pnum +\remarks +The storage for the array +is obtained by calling \tcode{::operator new}\iref{new.delete}, +but it is unspecified when or how often this +function is called. +This function starts the lifetime of the array object, +but not that of any of the array elements. +\end{itemdescr} + +\indexlibrarymember{allocate_at_least}{allocator}% +\begin{itemdecl} +[[nodiscard]] constexpr allocation_result allocate_at_least(size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is not an incomplete type\iref{term.incomplete.type}. + +\pnum +\returns +\tcode{allocation_result\{ptr, count\}}, +where \tcode{ptr} is a pointer to +the initial element of an array of \tcode{count} \tcode{T} and +$\tcode{count} \geq \tcode{n}$. + +\pnum +\throws +\tcode{bad_array_new_length} +if $\tcode{numeric_limits::max() / sizeof(T)} < \tcode{n}$, +or \tcode{bad_alloc} if the storage cannot be obtained. + +\pnum +\remarks +The storage for the array is obtained by calling \tcode{::operator new}, +but it is unspecified when or how often this function is called. +This function starts the lifetime of the array object, +but not that of any of the array elements. +\end{itemdescr} + +\indexlibrarymember{deallocate}{allocator}% +\begin{itemdecl} +constexpr void deallocate(T* p, size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +If \tcode{p} is memory that was obtained by a call to \tcode{allocate_at_least}, +let \tcode{ret} be the value returned and +\tcode{req} be the value passed as the first argument to that call. +\tcode{p} is equal to \tcode{ret.ptr} and +\tcode{n} is a value such that $\tcode{req} \leq \tcode{n} \leq \tcode{ret.count}$. +\item +Otherwise, \tcode{p} is a pointer value obtained from \tcode{allocate}. +\tcode{n} equals the value passed as the first argument +to the invocation of \tcode{allocate} which returned \tcode{p}. +\end{itemize} + +\pnum +\effects +Deallocates the storage referenced by \tcode{p}. + +\pnum +\remarks +Uses +\tcode{::operator delete}\iref{new.delete}, +but it is unspecified +when this function is called. +\end{itemdescr} + +\rSec3[allocator.globals]{Operators} + +\indexlibrarymember{operator==}{allocator}% +\begin{itemdecl} +template + constexpr bool operator==(const allocator&, const allocator&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true}. +\end{itemdescr} + +\rSec2[specialized.addressof]{\tcode{addressof}} + +\indexlibraryglobal{addressof}% +\begin{itemdecl} +template constexpr T* addressof(T& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The actual address of the object or function referenced by \tcode{r}, even in the +presence of an overloaded \tcode{operator\&}. + +\pnum +\remarks +An expression \tcode{addressof(E)} +is a constant subexpression\iref{defns.const.subexpr} +if \tcode{E} is an lvalue constant subexpression. +\end{itemdescr} + +\rSec2[c.malloc]{C library memory allocation} + +\pnum +\begin{note} +The header \libheaderref{cstdlib} +declares the functions described in this subclause. +\end{note} + +\indexlibraryglobal{aligned_alloc}% +\indexlibraryglobal{calloc}% +\indexlibraryglobal{malloc}% +\indexlibraryglobal{realloc}% +\begin{itemdecl} +void* aligned_alloc(size_t alignment, size_t size); +void* calloc(size_t nmemb, size_t size); +void* malloc(size_t size); +void* realloc(void* ptr, size_t size); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +These functions have the semantics specified in the C standard library. + +\pnum +\remarks +These functions do not attempt to allocate +storage by calling \tcode{::operator new()}\iref{new.delete}. +\indexlibrarymember{new}{operator}% + +\pnum +These functions implicitly create objects\iref{intro.object} +in the returned region of storage and +return a pointer to a suitable created object. +In the case of \tcode{calloc} and \tcode{realloc}, +the objects are created before the storage is zeroed or copied, respectively. +\end{itemdescr} + +\indexlibraryglobal{free}% +\begin{itemdecl} +void free(void* ptr); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +This function has the semantics specified in the C standard library. + +\pnum +\remarks +This function does not attempt to +deallocate storage by calling +\tcode{::operator delete()}\indexlibrarymember{delete}{operator}. +\end{itemdescr} + +\xrefc{7.22.3} + +\rSec1[smartptr]{Smart pointers} + +\rSec2[unique.ptr]{Unique-ownership pointers} + +\rSec3[unique.ptr.general]{General} + +\pnum +A \defn{unique pointer} is an object that owns another object and +manages that other object through a pointer. More precisely, a unique pointer +is an object \textit{u} that stores a pointer to a second object \textit{p} and +will dispose of \textit{p} when \textit{u} is itself destroyed (e.g., when +leaving block scope\iref{stmt.dcl}). In this context, \textit{u} is said +to \defn{own} \tcode{p}. + +\pnum +The mechanism by which \textit{u} disposes of \textit{p} is known as +\textit{p}'s associated \defn{deleter}, a function object whose correct +invocation results in \textit{p}'s appropriate disposition (typically its deletion). + +\pnum +Let the notation \textit{u.p} denote the pointer stored by \textit{u}, and +let \textit{u.d} denote the associated deleter. Upon request, \textit{u} can +\defn{reset} (replace) \textit{u.p} and \textit{u.d} with another pointer and +deleter, but properly disposes of its owned object via the associated +deleter before such replacement is considered completed. + +\pnum +Each object of a type \tcode{U} instantiated from the \tcode{unique_ptr} template +specified in \ref{unique.ptr} has the strict ownership semantics, specified above, +of a unique pointer. In partial satisfaction of these semantics, each such \tcode{U} +is \oldconcept{MoveConstructible} and \oldconcept{MoveAssignable}, but is not +\oldconcept{CopyConstructible} nor \oldconcept{CopyAssignable}. +The template parameter \tcode{T} of \tcode{unique_ptr} may be an incomplete type. + +\pnum +\begin{note} +The uses +of \tcode{unique_ptr} include providing exception safety for +dynamically allocated memory, passing ownership of dynamically allocated +memory to a function, and returning dynamically allocated memory from a +function. +\end{note} + +\rSec3[unique.ptr.dltr]{Default deleters} + +\rSec4[unique.ptr.dltr.general]{In general} + +\pnum +The class template \tcode{default_delete} serves as the default deleter (destruction policy) +for the class template \tcode{unique_ptr}. + +\pnum +The template parameter \tcode{T} of \tcode{default_delete} may be +an incomplete type. + +\rSec4[unique.ptr.dltr.dflt]{\tcode{default_delete}} + +\begin{codeblock} +namespace std { + template struct default_delete { + constexpr default_delete() noexcept = default; + template constexpr default_delete(const default_delete&) noexcept; + constexpr void operator()(T*) const; + }; +} +\end{codeblock} + +\indexlibraryctor{default_delete}% +\begin{itemdecl} +template constexpr default_delete(const default_delete& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{U*} is implicitly convertible to \tcode{T*}. + +\pnum +\effects +Constructs a \tcode{default_delete} object +from another \tcode{default_delete} object. +\end{itemdescr} + +\indexlibrarymember{operator()}{default_delete}% +\begin{itemdecl} +constexpr void operator()(T* ptr) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is a complete type. + +\pnum +\effects +Calls \keyword{delete} on \tcode{ptr}. +\end{itemdescr} + +\rSec4[unique.ptr.dltr.dflt1]{\tcode{default_delete}} + +\begin{codeblock} +namespace std { + template struct default_delete { + constexpr default_delete() noexcept = default; + template constexpr default_delete(const default_delete&) noexcept; + template constexpr void operator()(U* ptr) const; + }; +} +\end{codeblock} + +\indexlibraryctor{default_delete} +\begin{itemdecl} +template constexpr default_delete(const default_delete& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{U(*)[]} is convertible to \tcode{T(*)[]}. + +\pnum +\effects +Constructs a \tcode{default_delete} object from another \tcode{default_delete} object. +\end{itemdescr} + +\indexlibrarymember{operator()}{default_delete}% +\begin{itemdecl} +template constexpr void operator()(U* ptr) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{U(*)[]} is convertible to \tcode{T(*)[]}. + +\pnum +\mandates +\tcode{U} is a complete type. + +\pnum +\effects +Calls \tcode{delete[]} on \tcode{ptr}. +\end{itemdescr} + +\rSec3[unique.ptr.single]{\tcode{unique_ptr} for single objects} + +\rSec4[unique.ptr.single.general]{General} + +\indexlibraryglobal{unique_ptr}% +\begin{codeblock} +namespace std { + template> class unique_ptr { + public: + using pointer = @\seebelow@; + using element_type = T; + using deleter_type = D; + + // \ref{unique.ptr.single.ctor}, constructors + constexpr unique_ptr() noexcept; + constexpr explicit unique_ptr(type_identity_t p) noexcept; + constexpr unique_ptr(type_identity_t p, @\seebelow@ d1) noexcept; + constexpr unique_ptr(type_identity_t p, @\seebelow@ d2) noexcept; + constexpr unique_ptr(unique_ptr&& u) noexcept; + constexpr unique_ptr(nullptr_t) noexcept; + template + constexpr unique_ptr(unique_ptr&& u) noexcept; + + // \ref{unique.ptr.single.dtor}, destructor + constexpr ~unique_ptr(); + + // \ref{unique.ptr.single.asgn}, assignment + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; + template + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; + constexpr unique_ptr& operator=(nullptr_t) noexcept; + + // \ref{unique.ptr.single.observers}, observers + constexpr add_lvalue_reference_t operator*() const noexcept(@\seebelow@); + constexpr pointer operator->() const noexcept; + constexpr pointer get() const noexcept; + constexpr deleter_type& get_deleter() noexcept; + constexpr const deleter_type& get_deleter() const noexcept; + constexpr explicit operator bool() const noexcept; + + // \ref{unique.ptr.single.modifiers}, modifiers + constexpr pointer release() noexcept; + constexpr void reset(pointer p = pointer()) noexcept; + constexpr void swap(unique_ptr& u) noexcept; + + // disable copy from lvalue + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + }; +} +\end{codeblock} + +\pnum +The default type for the template parameter \tcode{D} is +\tcode{default_delete}. A client-supplied template argument +\tcode{D} shall be a function +object type\iref{function.objects}, lvalue reference to function, or +lvalue reference to function object type +for which, given +a value \tcode{d} of type \tcode{D} and a value +\tcode{ptr} of type \tcode{unique_ptr::pointer}, the expression +\tcode{d(ptr)} is valid and has the effect of disposing of the +pointer as appropriate for that deleter. + +\pnum +If the deleter's type \tcode{D} is not a reference type, \tcode{D} shall meet +the \oldconcept{Destructible} requirements (\tref{cpp17.destructible}). + +\pnum +If the \grammarterm{qualified-id} \tcode{remove_reference_t::pointer} is valid and denotes a +type\iref{temp.deduct}, then \tcode{unique_ptr::pointer} shall be a synonym for \tcode{remove_reference_t::pointer}. Otherwise +\tcode{unique_ptr::pointer} shall be a synonym for \tcode{element_type*}. The type \tcode{unique_ptr::pointer} shall +meet the \oldconcept{NullablePointer} requirements (\tref{cpp17.nullablepointer}). + +\pnum +\begin{example} +Given an allocator type \tcode{X}\iref{allocator.requirements.general} and +letting \tcode{A} be a synonym for \tcode{allocator_traits}, the types \tcode{A::pointer}, +\tcode{A::const_pointer}, \tcode{A::void_pointer}, and \tcode{A::const_void_pointer} +may be used as \tcode{unique_ptr::pointer}. +\end{example} + +\rSec4[unique.ptr.single.ctor]{Constructors} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +constexpr unique_ptr() noexcept; +constexpr unique_ptr(nullptr_t) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_pointer_v} is \tcode{false} and +\tcode{is_default_constructible_v} is \tcode{true}. + +\pnum +\expects +\tcode{D} meets the \oldconcept{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}), +and that construction does not throw an exception. + +\pnum +\effects +Constructs a \tcode{unique_ptr} object that owns +nothing, value-initializing the stored pointer and the stored deleter. + +\pnum +\ensures +\tcode{get() == nullptr}. \tcode{get_deleter()} +returns a reference to the stored deleter. +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +constexpr explicit unique_ptr(type_identity_t p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_pointer_v} is \tcode{false} and +\tcode{is_default_constructible_v} is \tcode{true}. + +\pnum +\expects +\tcode{D} meets the \oldconcept{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}), +and that construction does not throw an exception. + +\pnum +\effects +Constructs a \tcode{unique_ptr} which owns +\tcode{p}, initializing the stored pointer with \tcode{p} and +value-initializing the stored deleter. + +\pnum +\ensures +\tcode{get() == p}. \tcode{get_deleter()} +returns a reference to the stored deleter. +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +constexpr unique_ptr(type_identity_t p, const D& d) noexcept; +constexpr unique_ptr(type_identity_t p, remove_reference_t&& d) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\expects +For the first constructor, if \tcode{D} is not a reference type, +\tcode{D} meets the \oldconcept{CopyConstructible} requirements and +such construction does not exit via an exception. +For the second constructor, if \tcode{D} is not a reference type, +\tcode{D} meets the \oldconcept{MoveConstructible} requirements and +such construction does not exit via an exception. + +\pnum +\effects +Constructs a \tcode{unique_ptr} object which owns \tcode{p}, initializing +the stored pointer with \tcode{p} and initializing the deleter +from \tcode{std::forward(d)}. + +\pnum +\ensures +\tcode{get() == p}. +\tcode{get_deleter()} returns a reference to the stored +deleter. If \tcode{D} is a reference type then \tcode{get_deleter()} +returns a reference to the lvalue \tcode{d}. + +\pnum +\remarks +If \tcode{D} is a reference type, +the second constructor is defined as deleted. + +\pnum +\begin{example} +\begin{codeblock} +D d; +unique_ptr p1(new int, D()); // \tcode{D} must be \oldconcept{MoveConstructible} +unique_ptr p2(new int, d); // \tcode{D} must be \oldconcept{CopyConstructible} +unique_ptr p3(new int, d); // \tcode{p3} holds a reference to \tcode{d} +unique_ptr p4(new int, D()); // error: rvalue deleter object combined + // with reference deleter type +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +constexpr unique_ptr(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_move_constructible_v} is \tcode{true}. + +\pnum +\expects +If \tcode{D} is not a reference type, +\tcode{D} meets the \oldconcept{MoveConstructible} +requirements (\tref{cpp17.moveconstructible}). +Construction +of the deleter from an rvalue of type \tcode{D} does not +throw an exception. + +\pnum +\effects +Constructs a \tcode{unique_ptr} from +\tcode{u}. If \tcode{D} is a reference type, this +deleter is copy constructed from \tcode{u}'s deleter; otherwise, this +deleter is move constructed from \tcode{u}'s deleter. +\begin{note} +The +construction of the deleter can be implemented with \tcode{std::forward}. +\end{note} + +\pnum +\ensures +\tcode{get()} yields the value \tcode{u.get()} +yielded before the construction. \tcode{u.get() == nullptr}. +\tcode{get_deleter()} returns a reference +to the stored deleter that was constructed from +\tcode{u.get_deleter()}. If \tcode{D} is a reference type then +\tcode{get_deleter()} and \tcode{u.get_deleter()} both reference +the same lvalue deleter. +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +template constexpr unique_ptr(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{pointer}, +\item \tcode{U} is not an array type, and +\item either \tcode{D} is a reference type and \tcode{E} is the same type as \tcode{D}, or +\tcode{D} is not a reference type and \tcode{E} is implicitly convertible to \tcode{D}. +\end{itemize} + +\pnum +\expects +If \tcode{E} is not a reference type, +construction of the deleter from an rvalue of type \tcode{E} +is well-formed and does not throw an exception. +Otherwise, \tcode{E} is a reference type and +construction of the deleter from an lvalue of type \tcode{E} +is well-formed and does not throw an exception. + +\pnum +\effects +Constructs a \tcode{unique_ptr} from \tcode{u}. +If \tcode{E} is a reference type, this deleter is copy constructed from +\tcode{u}'s deleter; otherwise, this deleter is move constructed from \tcode{u}'s +deleter. +\begin{note} +The deleter constructor can be implemented with +\tcode{std::forward}. +\end{note} + +\pnum +\ensures +\tcode{get()} yields the value \tcode{u.get()} +yielded before the construction. \tcode{u.get() == nullptr}. +\tcode{get_deleter()} returns a reference +to the stored deleter that was constructed from +\tcode{u.get_deleter()}. +\end{itemdescr} + +\rSec4[unique.ptr.single.dtor]{Destructor} + +\indexlibrarydtor{unique_ptr}% +\begin{itemdecl} +constexpr ~unique_ptr(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{if (get()) get_deleter()(get());} +\begin{note} +The use of \tcode{default_delete} requires \tcode{T} to be a complete type. +\end{note} + +\pnum +\remarks +The behavior is undefined +if the evaluation of \tcode{get_deleter()(get())} throws an exception. +\end{itemdescr} + +\rSec4[unique.ptr.single.asgn]{Assignment} + +\indexlibrarymember{operator=}{unique_ptr}% +\begin{itemdecl} +constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_move_assignable_v} is \tcode{true}. + +\pnum +\expects +If \tcode{D} is not a reference type, \tcode{D} meets the +\oldconcept{MoveAssignable} requirements (\tref{cpp17.moveassignable}) and assignment +of the deleter from an rvalue of type \tcode{D} does not throw an exception. +Otherwise, \tcode{D} is a reference type; +\tcode{remove_reference_t} meets the \oldconcept{CopyAssignable} +requirements and assignment of the deleter from an +lvalue of type \tcode{D} does not throw an exception. + +\pnum +\effects +Calls \tcode{reset(u.release())} followed by +\tcode{get_deleter() = std::forward(u.get_dele\-ter())}. + +\pnum +\ensures +If \tcode{this != addressof(u)}, +\tcode{u.get() == nullptr}, +otherwise \tcode{u.get()} is unchanged. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{operator=}{unique_ptr}% +\begin{itemdecl} +template constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{pointer}, and +\item \tcode{U} is not an array type, and +\item \tcode{is_assignable_v} is \tcode{true}. +\end{itemize} + +\pnum +\expects +If \tcode{E} is not a reference type, +assignment of the deleter from an rvalue of type \tcode{E} +is well-formed and does not throw an exception. +Otherwise, \tcode{E} is a reference type and +assignment of the deleter from an lvalue of type \tcode{E} +is well-formed and does not throw an exception. + +\pnum +\effects +Calls \tcode{reset(u.release())} followed by +\tcode{get_deleter() = std::forward(u.get_dele\-ter())}. + +\pnum +\ensures +\tcode{u.get() == nullptr}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{operator=}{unique_ptr}% +\begin{itemdecl} +constexpr unique_ptr& operator=(nullptr_t) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +As if by \tcode{reset()}. + +\pnum +\ensures +\tcode{get() == nullptr}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\rSec4[unique.ptr.single.observers]{Observers} + +\indexlibrarymember{operator*}{unique_ptr}% +\begin{itemdecl} +constexpr add_lvalue_reference_t operator*() const noexcept(noexcept(*declval())); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get() != nullptr}. + +\pnum +\returns +\tcode{*get()}. + +\end{itemdescr} + +\indexlibrarymember{operator->}{unique_ptr}% +\begin{itemdecl} +constexpr pointer operator->() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get() != nullptr}. + +\pnum +\returns +\tcode{get()}. + +\pnum +\begin{note} +The use of this function typically requires that \tcode{T} be a complete type. +\end{note} +\end{itemdescr} + +\indexlibrarymember{get}{unique_ptr}% +\begin{itemdecl} +constexpr pointer get() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The stored pointer. +\end{itemdescr} + +\indexlibrarymember{get_deleter}{unique_ptr}% +\begin{itemdecl} +constexpr deleter_type& get_deleter() noexcept; +constexpr const deleter_type& get_deleter() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A reference to the stored deleter. +\end{itemdescr} + +\indexlibrarymember{operator bool}{unique_ptr}% +\begin{itemdecl} +constexpr explicit operator bool() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{get() != nullptr}. +\end{itemdescr} + +\rSec4[unique.ptr.single.modifiers]{Modifiers} + +\indexlibrarymember{release}{unique_ptr}% +\begin{itemdecl} +constexpr pointer release() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{get() == nullptr}. + +\pnum +\returns +The value \tcode{get()} had at the start of +the call to \tcode{release}. +\end{itemdescr} + +\indexlibrarymember{reset}{unique_ptr}% +\begin{itemdecl} +constexpr void reset(pointer p = pointer()) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Assigns \tcode{p} to the stored pointer, and then, +with the old value of the stored pointer, \tcode{old_p}, +evaluates \tcode{if (old_p) get_deleter()(old_p);} +\begin{note} +The order of these operations is significant +because the call to \tcode{get_deleter()} might destroy \tcode{*this}. +\end{note} + +\pnum +\ensures +\tcode{get() == p}. +\begin{note} +The postcondition does not hold if the call to \tcode{get_deleter()} +destroys \tcode{*this} since \tcode{this->get()} is no longer a valid expression. +\end{note} + +\pnum +\remarks +The behavior is undefined +if the evaluation of \tcode{get_deleter()(old_p)} throws an exception. +\end{itemdescr} + +\indexlibrarymember{swap}{unique_ptr}% +\begin{itemdecl} +constexpr void swap(unique_ptr& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get_deleter()} is swappable\iref{swappable.requirements} and +does not throw an exception under \tcode{swap}. + +\pnum +\effects +Invokes \tcode{swap} on the stored pointers and on the stored +deleters of \tcode{*this} and \tcode{u}. +\end{itemdescr} + +\rSec3[unique.ptr.runtime]{\tcode{unique_ptr} for array objects with a runtime length} + +\rSec4[unique.ptr.runtime.general]{General} + +\indexlibraryglobal{unique_ptr}% +\begin{codeblock} +namespace std { + template class unique_ptr { + public: + using pointer = @\seebelow@; + using element_type = T; + using deleter_type = D; + + // \ref{unique.ptr.runtime.ctor}, constructors + constexpr unique_ptr() noexcept; + template constexpr explicit unique_ptr(U p) noexcept; + template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; + template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; + constexpr unique_ptr(unique_ptr&& u) noexcept; + template + constexpr unique_ptr(unique_ptr&& u) noexcept; + constexpr unique_ptr(nullptr_t) noexcept; + + // destructor + constexpr ~unique_ptr(); + + // assignment + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; + template + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; + constexpr unique_ptr& operator=(nullptr_t) noexcept; + + // \ref{unique.ptr.runtime.observers}, observers + constexpr T& operator[](size_t i) const; + constexpr pointer get() const noexcept; + constexpr deleter_type& get_deleter() noexcept; + constexpr const deleter_type& get_deleter() const noexcept; + constexpr explicit operator bool() const noexcept; + + // \ref{unique.ptr.runtime.modifiers}, modifiers + constexpr pointer release() noexcept; + template constexpr void reset(U p) noexcept; + constexpr void reset(nullptr_t = nullptr) noexcept; + constexpr void swap(unique_ptr& u) noexcept; + + // disable copy from lvalue + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + }; +} +\end{codeblock} + +\pnum +A specialization for array types is provided with a slightly altered +interface. + +\begin{itemize} +\item Conversions between different types of +\tcode{unique_ptr} +that would be disallowed for the corresponding pointer-to-array types, +and conversions to or from the non-array forms of +\tcode{unique_ptr}, produce an ill-formed program. + +\item Pointers to types derived from \tcode{T} are +rejected by the constructors, and by \tcode{reset}. + +\item The observers \tcode{operator*} and +\tcode{operator->} are not provided. + +\item The indexing observer \tcode{operator[]} is provided. + +\item The default deleter will call \tcode{delete[]}. +\end{itemize} + +\pnum +Descriptions are provided below only for members that +differ from the primary template. + +\pnum +The template argument \tcode{T} shall be a complete type. + +\rSec4[unique.ptr.runtime.ctor]{Constructors} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +template constexpr explicit unique_ptr(U p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +This constructor behaves the same as +the constructor in the primary template that +takes a single parameter of type \tcode{pointer}. + +\pnum +\constraints +\begin{itemize} +\item \tcode{U} is the same type as \tcode{pointer}, or +\item \tcode{pointer} is the same type as \tcode{element_type*}, +\tcode{U} is a pointer type \tcode{V*}, and +\tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; +template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +These constructors behave the same as +the constructors in the primary template that +take a parameter of type \tcode{pointer} and a second parameter. + +\pnum +\constraints +\begin{itemize} +\item \tcode{U} is the same type as \tcode{pointer}, +\item \tcode{U} is \tcode{nullptr_t}, or +\item \tcode{pointer} is the same type as \tcode{element_type*}, + \tcode{U} is a pointer type \tcode{V*}, and + \tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +template constexpr unique_ptr(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +This constructor behaves the same as in the primary template. + +\pnum +\constraints +Where \tcode{UP} is \tcode{unique_ptr}: +\begin{itemize} +\item \tcode{U} is an array type, and +\item \tcode{pointer} is the same type as \tcode{element_type*}, and +\item \tcode{UP::pointer} is the same type as \tcode{UP::element_type*}, and +\item \tcode{UP::element_type(*)[]} is convertible to \tcode{element_type(*)[]}, and +\item either \tcode{D} is a reference type and \tcode{E} is the same type as \tcode{D}, + or \tcode{D} is not a reference type and \tcode{E} is implicitly convertible to \tcode{D}. +\end{itemize} + +\begin{note} +This replaces the \constraints specification of the primary template. +\end{note} +\end{itemdescr} + +\rSec4[unique.ptr.runtime.asgn]{Assignment} + +\indexlibrarymember{operator=}{unique_ptr}% +\begin{itemdecl} +template constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +This operator behaves the same as in the primary template. + +\pnum +\constraints +Where \tcode{UP} is \tcode{unique_ptr}: +\begin{itemize} +\item \tcode{U} is an array type, and +\item \tcode{pointer} is the same type as \tcode{element_type*}, and +\item \tcode{UP::pointer} is the same type as \tcode{UP::element_type*}, and +\item \tcode{UP::element_type(*)[]} is convertible to \tcode{element_type(*)[]}, and +\item \tcode{is_assignable_v} is \tcode{true}. +\end{itemize} + +\begin{note} +This replaces the \constraints specification of the primary template. +\end{note} +\end{itemdescr} + +\rSec4[unique.ptr.runtime.observers]{Observers} + +\indexlibrarymember{operator[]}{unique_ptr}% +\begin{itemdecl} +constexpr T& operator[](size_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +$\tcode{i} <$ the +number of elements in the array to which +the stored pointer points. + +\pnum +\returns +\tcode{get()[i]}. +\end{itemdescr} + +\rSec4[unique.ptr.runtime.modifiers]{Modifiers} + +\indexlibrarymember{reset}{unique_ptr}% +\begin{itemdecl} +constexpr void reset(nullptr_t p = nullptr) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{reset(pointer())}. +\end{itemdescr} + +\indexlibrarymember{reset}{unique_ptr}% +\begin{itemdecl} +constexpr template void reset(U p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +This function behaves the same as +the \tcode{reset} member of the primary template. + +\pnum +\constraints +\begin{itemize} +\item \tcode{U} is the same type as \tcode{pointer}, or +\item \tcode{pointer} is the same type as \tcode{element_type*}, + \tcode{U} is a pointer type \tcode{V*}, and + \tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. +\end{itemize} +\end{itemdescr} + +\rSec3[unique.ptr.create]{Creation} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template constexpr unique_ptr make_unique(Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is not an array type. + +\pnum +\returns +\tcode{unique_ptr(new T(std::forward(args)...))}. + +\end{itemdescr} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template constexpr unique_ptr make_unique(size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an array of unknown bound. + +\pnum +\returns +\tcode{unique_ptr(new remove_extent_t[n]())}. + +\end{itemdescr} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template @\unspec@ make_unique(Args&&...) = delete; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an array of known bound. + +\end{itemdescr} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template constexpr unique_ptr make_unique_for_overwrite(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is not an array type. + +\pnum +\returns +\tcode{unique_ptr(new T)}. +\end{itemdescr} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template constexpr unique_ptr make_unique_for_overwrite(size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an array of unknown bound. + +\pnum +\returns +\tcode{unique_ptr(new remove_extent_t[n])}. +\end{itemdescr} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template @\unspec@ make_unique_for_overwrite(Args&&...) = delete; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an array of known bound. +\end{itemdescr} + +\rSec3[unique.ptr.special]{Specialized algorithms} + +\indexlibrary{\idxcode{swap(unique_ptr\&, unique_ptr\&)}}% +\begin{itemdecl} +template constexpr void swap(unique_ptr& x, unique_ptr& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_swappable_v} is \tcode{true}. + +\pnum +\effects +Calls \tcode{x.swap(y)}. +\end{itemdescr} + +\indexlibrarymember{operator==}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator==(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.get() == y.get()}. +\end{itemdescr} + +\indexlibrarymember{operator<}{unique_ptr}% +\begin{itemdecl} +template + bool operator<(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{CT} denote +\begin{codeblock} +common_type_t::pointer, + typename unique_ptr::pointer> +\end{codeblock} + +\pnum +\mandates +\begin{itemize} +\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{CT} and +\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{CT}. +\end{itemize} + +\pnum +\expects +The specialization +\tcode{less} is a function object type\iref{function.objects} that +induces a strict weak ordering\iref{alg.sorting} on the pointer values. + +\pnum +\returns +\tcode{less()(x.get(), y.get())}. +\end{itemdescr} + +\indexlibrarymember{operator>}{unique_ptr}% +\begin{itemdecl} +template + bool operator>(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{y < x}. +\end{itemdescr} + +\indexlibrarymember{operator<=}{unique_ptr}% +\begin{itemdecl} +template + bool operator<=(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!(y < x)}. +\end{itemdescr} + +\indexlibrarymember{operator>=}{unique_ptr}% +\begin{itemdecl} +template + bool operator>=(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!(x < y)}. +\end{itemdescr} + +\indexlibrarymember{operator<=>}{unique_ptr}% +\begin{itemdecl} +template + requires @\libconcept{three_way_comparable_with}@::pointer, + typename unique_ptr::pointer> + compare_three_way_result_t::pointer, + typename unique_ptr::pointer> + operator<=>(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{compare_three_way()(x.get(), y.get())}. +\end{itemdescr} + +\indexlibrarymember{operator==}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator==(const unique_ptr& x, nullptr_t) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!x}. +\end{itemdescr} + +\indexlibrarymember{operator<}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator<(const unique_ptr& x, nullptr_t); +template + constexpr bool operator<(nullptr_t, const unique_ptr& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The specialization \tcode{less::pointer>} is +a function object type\iref{function.objects} that induces a strict weak +ordering\iref{alg.sorting} on the pointer values. + +\pnum +\returns +The first function template returns +\begin{codeblock} +less::pointer>()(x.get(), nullptr) +\end{codeblock} +The second function template returns +\begin{codeblock} +less::pointer>()(nullptr, x.get()) +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator>}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator>(const unique_ptr& x, nullptr_t); +template + constexpr bool operator>(nullptr_t, const unique_ptr& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The first function template returns \tcode{nullptr < x}. +The second function template returns \tcode{x < nullptr}. +\end{itemdescr} + +\indexlibrarymember{operator<=}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator<=(const unique_ptr& x, nullptr_t); +template + constexpr bool operator<=(nullptr_t, const unique_ptr& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The first function template returns \tcode{!(nullptr < x)}. +The second function template returns \tcode{!(x < nullptr)}. +\end{itemdescr} + +\indexlibrarymember{operator>=}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator>=(const unique_ptr& x, nullptr_t); +template + constexpr bool operator>=(nullptr_t, const unique_ptr& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The first function template returns \tcode{!(x < nullptr)}. +The second function template returns \tcode{!(nullptr < x)}. +\end{itemdescr} + +\indexlibrarymember{operator<=>}{unique_ptr}% +\begin{itemdecl} +template + requires @\libconcept{three_way_comparable}@::pointer> + constexpr compare_three_way_result_t::pointer> + operator<=>(const unique_ptr& x, nullptr_t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +compare_three_way()(x.get(), static_cast::pointer>(nullptr)). +\end{codeblock} +\end{itemdescr} + +\rSec3[unique.ptr.io]{I/O} + +\indexlibrarymember{operator<<}{unique_ptr}% +\begin{itemdecl} +template + basic_ostream& operator<<(basic_ostream& os, const unique_ptr& p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{os << p.get()} is a valid expression. + +\pnum +\effects +Equivalent to: \tcode{os << p.get();} + +\pnum +\returns +\tcode{os}. +\end{itemdescr} + +\rSec2[util.sharedptr]{Shared-ownership pointers} + +\rSec3[util.smartptr.weak.bad]{Class \tcode{bad_weak_ptr}}% +\indextext{smart pointers|(}% + +\indexlibraryglobal{bad_weak_ptr}% +\begin{codeblock} +namespace std { + class bad_weak_ptr : public exception { + public: + // see \ref{exception} for the specification of the special member functions + const char* what() const noexcept override; + }; +} +\end{codeblock} + +\pnum +An exception of type \tcode{bad_weak_ptr} is thrown by the \tcode{shared_ptr} +constructor taking a \tcode{weak_ptr}. + +\indexlibrarymember{what}{bad_weak_ptr}% +\begin{itemdecl} +const char* what() const noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An \impldef{return value of \tcode{bad_weak_ptr::what}} \ntbs{}. +\end{itemdescr} + +\rSec3[util.smartptr.shared]{Class template \tcode{shared_ptr}} + +\rSec4[util.smartptr.shared.general]{General} + +\pnum +\indexlibraryglobal{shared_ptr}% +The \tcode{shared_ptr} class template stores a pointer, usually obtained +via \keyword{new}. \tcode{shared_ptr} implements semantics of shared ownership; +the last remaining owner of the pointer is responsible for destroying +the object, or otherwise releasing the resources associated with the stored pointer. A +\tcode{shared_ptr} is said to be empty if it does not own a pointer. + +\begin{codeblock} +namespace std { + template class shared_ptr { + public: + using element_type = remove_extent_t; + using weak_type = weak_ptr; + + // \ref{util.smartptr.shared.const}, constructors + constexpr shared_ptr() noexcept; + constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { } + template + explicit shared_ptr(Y* p); + template + shared_ptr(Y* p, D d); + template + shared_ptr(Y* p, D d, A a); + template + shared_ptr(nullptr_t p, D d); + template + shared_ptr(nullptr_t p, D d, A a); + template + shared_ptr(const shared_ptr& r, element_type* p) noexcept; + template + shared_ptr(shared_ptr&& r, element_type* p) noexcept; + shared_ptr(const shared_ptr& r) noexcept; + template + shared_ptr(const shared_ptr& r) noexcept; + shared_ptr(shared_ptr&& r) noexcept; + template + shared_ptr(shared_ptr&& r) noexcept; + template + explicit shared_ptr(const weak_ptr& r); + template + shared_ptr(unique_ptr&& r); + + // \ref{util.smartptr.shared.dest}, destructor + ~shared_ptr(); + + // \ref{util.smartptr.shared.assign}, assignment + shared_ptr& operator=(const shared_ptr& r) noexcept; + template + shared_ptr& operator=(const shared_ptr& r) noexcept; + shared_ptr& operator=(shared_ptr&& r) noexcept; + template + shared_ptr& operator=(shared_ptr&& r) noexcept; + template + shared_ptr& operator=(unique_ptr&& r); + + // \ref{util.smartptr.shared.mod}, modifiers + void swap(shared_ptr& r) noexcept; + void reset() noexcept; + template + void reset(Y* p); + template + void reset(Y* p, D d); + template + void reset(Y* p, D d, A a); + + // \ref{util.smartptr.shared.obs}, observers + element_type* get() const noexcept; + T& operator*() const noexcept; + T* operator->() const noexcept; + element_type& operator[](ptrdiff_t i) const; + long use_count() const noexcept; + explicit operator bool() const noexcept; + template + bool owner_before(const shared_ptr& b) const noexcept; + template + bool owner_before(const weak_ptr& b) const noexcept; + }; + + template + shared_ptr(weak_ptr) -> shared_ptr; + template + shared_ptr(unique_ptr) -> shared_ptr; +} +\end{codeblock} + +\pnum +Specializations of \tcode{shared_ptr} shall be \oldconcept{CopyConstructible}, +\oldconcept{CopyAssignable}, and \oldconcept{\-Less\-Than\-Comparable}, allowing their use in standard +containers. Specializations of \tcode{shared_ptr} shall be +contextually convertible to \tcode{bool}, +allowing their use in boolean expressions and declarations in conditions. + +\pnum +The template parameter \tcode{T} of \tcode{shared_ptr} +may be an incomplete type. +\begin{note} +\tcode{T} can be a function type. +\end{note} + +\pnum +\begin{example} +\begin{codeblock} +if (shared_ptr px = dynamic_pointer_cast(py)) { + // do something with \tcode{px} +} +\end{codeblock} +\end{example} + +\pnum +For purposes of determining the presence of a data race, member functions shall +access and modify only the \tcode{shared_ptr} and \tcode{weak_ptr} objects +themselves and not objects they refer to. Changes in \tcode{use_count()} do not +reflect modifications that can introduce data races. + +\pnum +For the purposes of subclause \ref{smartptr}, +a pointer type \tcode{Y*} is said to be +\defnx{compatible with}{compatible with!\idxcode{shared_ptr}} +a pointer type \tcode{T*} when either +\tcode{Y*} is convertible to \tcode{T*} or +\tcode{Y} is \tcode{U[N]} and \tcode{T} is \cv{}~\tcode{U[]}. + +\rSec4[util.smartptr.shared.const]{Constructors} + +\pnum +In the constructor definitions below, +enables \tcode{shared_from_this} with \tcode{p}, +for a pointer \tcode{p} of type \tcode{Y*}, +means that if \tcode{Y} has an unambiguous and accessible base class +that is a specialization of \tcode{enable_shared_from_this}\iref{util.smartptr.enab}, +then \tcode{remove_cv_t*} shall be implicitly convertible to \tcode{T*} and +the constructor evaluates the statement: +\begin{codeblock} +if (p != nullptr && p->weak_this.expired()) + p->weak_this = shared_ptr>(*this, const_cast*>(p)); +\end{codeblock} +The assignment to the \tcode{weak_this} member is not atomic and +conflicts with any potentially concurrent access to the same object\iref{intro.multithread}. + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +constexpr shared_ptr() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{use_count() == 0 \&\& get() == nullptr}. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +template explicit shared_ptr(Y* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +When \tcode{T} is an array type, +the expression \tcode{delete[] p} is well-formed and either +\tcode{T} is \tcode{U[N]} and \tcode{Y(*)[N]} is convertible to \tcode{T*}, or +\tcode{T} is \tcode{U[]} and \tcode{Y(*)[]} is convertible to \tcode{T*}. +When \tcode{T} is not an array type, +the expression \tcode{delete p} is well-formed and +\tcode{Y*} is convertible to \tcode{T*}. + +\pnum +\mandates +\tcode{Y} is a complete type. + +\pnum +\expects +The expression +\tcode{delete[] p}, when \tcode{T} is an array type, or +\tcode{delete p}, when \tcode{T} is not an array type, +has well-defined behavior, and +does not throw exceptions. + +\pnum +\effects +When \tcode{T} is not an array type, +constructs a \tcode{shared_ptr} object +that owns the pointer \tcode{p}. +Otherwise, constructs a \tcode{shared_ptr} +that owns \tcode{p} and a deleter of an +unspecified type that calls \tcode{delete[] p}. +When \tcode{T} is not an array type, +enables \tcode{shared_from_this} with \tcode{p}. +If an exception is thrown, \tcode{delete p} is called +when \tcode{T} is not an array type, \tcode{delete[] p} otherwise. + +\pnum +\ensures +\tcode{use_count() == 1 \&\& get() == p}. + +\pnum +\throws +\tcode{bad_alloc}, or an \impldef{exception type when \tcode{shared_ptr} +constructor fails} exception when a resource other than memory cannot be obtained. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +template shared_ptr(Y* p, D d); +template shared_ptr(Y* p, D d, A a); +template shared_ptr(nullptr_t p, D d); +template shared_ptr(nullptr_t p, D d, A a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_move_constructible_v} is \tcode{true}, and +\tcode{d(p)} is a well-formed expression. +For the first two overloads: + +\begin{itemize} +\item +If \tcode{T} is an array type, then either +\tcode{T} is \tcode{U[N]} and \tcode{Y(*)[N]} is convertible to \tcode{T*}, or +\tcode{T} is \tcode{U[]} and \tcode{Y(*)[]} is convertible to \tcode{T*}. + +\item +If \tcode{T} is not an array type, then \tcode{Y*} is convertible to \tcode{T*}. +\end{itemize} + +\pnum +\expects +Construction of \tcode{d} and a deleter of type \tcode{D} +initialized with \tcode{std::move(d)} do not throw exceptions. +The expression \tcode{d(p)} +has well-defined behavior and does not throw exceptions. +\tcode{A} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. + +\pnum +\effects +Constructs a \tcode{shared_ptr} object that owns the +object \tcode{p} and the deleter \tcode{d}. +When \tcode{T} is not an array type, +the first and second constructors enable \tcode{shared_from_this} with \tcode{p}. +The second and fourth constructors shall use a copy of \tcode{a} to +allocate memory for internal use. +If an exception is thrown, \tcode{d(p)} is called. + +\pnum +\ensures +\tcode{use_count() == 1 \&\& get() == p}. + +\pnum +\throws +\tcode{bad_alloc}, or an \impldef{exception type when \tcode{shared_ptr} +constructor fails} exception +when a resource other than memory cannot be obtained. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +template shared_ptr(const shared_ptr& r, element_type* p) noexcept; +template shared_ptr(shared_ptr&& r, element_type* p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{shared_ptr} instance that +stores \tcode{p} and shares ownership with +the initial value of \tcode{r}. + +\pnum +\ensures +\tcode{get() == p}. +For the second overload, +\tcode{r} is empty and \tcode{r.get() == nullptr}. + +\pnum +\begin{note} +Use of this constructor leads to a dangling pointer +unless \tcode{p} remains valid +at least until the ownership group of \tcode{r} is destroyed. +\end{note} + +\pnum +\begin{note} +This constructor allows creation of an empty +\tcode{shared_ptr} instance with a non-null stored pointer. +\end{note} +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +shared_ptr(const shared_ptr& r) noexcept; +template shared_ptr(const shared_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. + +\pnum +\effects +If \tcode{r} is empty, constructs +an empty \tcode{shared_ptr} object; otherwise, constructs +a \tcode{shared_ptr} object that shares ownership with \tcode{r}. + +\pnum +\ensures +\tcode{get() == r.get() \&\& use_count() == r.use_count()}. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +shared_ptr(shared_ptr&& r) noexcept; +template shared_ptr(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. + +\pnum +\effects +Move constructs a \tcode{shared_ptr} instance from \tcode{r}. + +\pnum +\ensures +\tcode{*this} contains the old value of +\tcode{r}. \tcode{r} is empty, and \tcode{r.get() == nullptr}. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\indexlibraryglobal{weak_ptr}% +\begin{itemdecl} +template explicit shared_ptr(const weak_ptr& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{Y*} is compatible with \tcode{T*}. + +\pnum +\effects +Constructs a \tcode{shared_ptr} object that shares ownership with +\tcode{r} and stores a copy of the pointer stored in \tcode{r}. +If an exception is thrown, the constructor has no effect. + +\pnum +\ensures +\tcode{use_count() == r.use_count()}. + +\pnum +\throws +\tcode{bad_weak_ptr} when \tcode{r.expired()}. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\indexlibraryglobal{unique_ptr}% +\begin{itemdecl} +template shared_ptr(unique_ptr&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{Y*} is compatible with \tcode{T*} and +\tcode{unique_ptr::pointer} is convertible to \tcode{element_type*}. + +\pnum +\effects +If \tcode{r.get() == nullptr}, equivalent to \tcode{shared_ptr()}. +Otherwise, if \tcode{D} is not a reference type, +equivalent to \tcode{shared_ptr(r.release(), std::move(r.get_deleter()))}. +Otherwise, equivalent to \tcode{shared_ptr(r.release(), ref(r.get_deleter()))}. +If an exception is thrown, the constructor has no effect. +\end{itemdescr} + +\rSec4[util.smartptr.shared.dest]{Destructor} + +\indexlibrarydtor{shared_ptr}% +\begin{itemdecl} +~shared_ptr(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item If \tcode{*this} is empty or shares ownership with another +\tcode{shared_ptr} instance (\tcode{use_count() > 1}), there are no side effects. + +\item +Otherwise, if \tcode{*this} owns an object +\tcode{p} and a deleter \tcode{d}, \tcode{d(p)} is called. + +\item Otherwise, \tcode{*this} owns a pointer \tcode{p}, +and \tcode{delete p} is called. +\end{itemize} +\end{itemdescr} + +\pnum +\begin{note} +Since the destruction of \tcode{*this} +decreases the number of instances that share ownership with \tcode{*this} +by one, +after \tcode{*this} has been destroyed +all \tcode{shared_ptr} instances that shared ownership with +\tcode{*this} will report a \tcode{use_count()} that is one less +than its previous value. +\end{note} + +\rSec4[util.smartptr.shared.assign]{Assignment} + +\indexlibrarymember{operator=}{shared_ptr}% +\begin{itemdecl} +shared_ptr& operator=(const shared_ptr& r) noexcept; +template shared_ptr& operator=(const shared_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(r).swap(*this)}. + +\pnum +\returns +\tcode{*this}. + +\pnum +\begin{note} +The use count updates caused by the temporary object +construction and destruction are not observable side +effects, so the implementation can meet the effects (and the +implied guarantees) via different means, without creating a +temporary. In particular, in the example: +\begin{codeblock} +shared_ptr p(new int); +shared_ptr q(p); +p = p; +q = p; +\end{codeblock} +both assignments can be no-ops. +\end{note} +\end{itemdescr} + +\indexlibrarymember{operator=}{shared_ptr}% +\begin{itemdecl} +shared_ptr& operator=(shared_ptr&& r) noexcept; +template shared_ptr& operator=(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(std::move(r)).swap(*this)}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{operator=}{shared_ptr}% +\begin{itemdecl} +template shared_ptr& operator=(unique_ptr&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(std::move(r)).swap(*this)}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\rSec4[util.smartptr.shared.mod]{Modifiers} + +\indexlibrarymember{swap}{shared_ptr}% +\begin{itemdecl} +void swap(shared_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} + +\pnum +\effects +Exchanges the contents of \tcode{*this} and \tcode{r}. +\end{itemdescr} + +\indexlibrarymember{reset}{shared_ptr}% +\begin{itemdecl} +void reset() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr().swap(*this)}. +\end{itemdescr} + +\indexlibrarymember{reset}{shared_ptr}% +\begin{itemdecl} +template void reset(Y* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(p).swap(*this)}. +\end{itemdescr} + +\indexlibrarymember{reset}{shared_ptr}% +\begin{itemdecl} +template void reset(Y* p, D d); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(p, d).swap(*this)}. +\end{itemdescr} + +\indexlibrarymember{reset}{shared_ptr}% +\begin{itemdecl} +template void reset(Y* p, D d, A a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(p, d, a).swap(*this)}. +\end{itemdescr} + +\rSec4[util.smartptr.shared.obs]{Observers} +\indexlibrarymember{get}{shared_ptr}% +\begin{itemdecl} +element_type* get() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The stored pointer. +\end{itemdescr} + +\indexlibrarymember{operator*}{shared_ptr}% +\begin{itemdecl} +T& operator*() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get() != 0}. + +\pnum +\returns +\tcode{*get()}. + +\pnum +\remarks +When \tcode{T} is an array type or \cv{}~\keyword{void}, +it is unspecified whether this +member function is declared. If it is declared, it is unspecified what its +return type is, except that the declaration (although not necessarily the +definition) of the function shall be well-formed. +\end{itemdescr} + +\indexlibrarymember{operator->}{shared_ptr}% +\begin{itemdecl} +T* operator->() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get() != 0}. + +\pnum +\returns +\tcode{get()}. + +\pnum +\remarks +When \tcode{T} is an array type, +it is unspecified whether this member function is declared. +If it is declared, it is unspecified what its return type is, +except that the declaration (although not necessarily the definition) +of the function shall be well-formed. +\end{itemdescr} + +\indexlibrarymember{operator[]}{shared_ptr}% +\begin{itemdecl} +element_type& operator[](ptrdiff_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get() != 0 \&\& i >= 0}. +If \tcode{T} is \tcode{U[N]}, \tcode{i < N}. + +\pnum +\returns +\tcode{get()[i]}. + +\pnum +\throws +Nothing. + +\pnum +\remarks +When \tcode{T} is not an array type, +it is unspecified whether this member function is declared. +If it is declared, it is unspecified what its return type is, +except that the declaration (although not necessarily the definition) +of the function shall be well-formed. +\end{itemdescr} + +\indexlibrarymember{use_count}{shared_ptr}% +\begin{itemdecl} +long use_count() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\sync +None. + +\pnum +\returns +The number of \tcode{shared_ptr} objects, \tcode{*this} included, +that share ownership with \tcode{*this}, or \tcode{0} when \tcode{*this} is +empty. + +\pnum +\begin{note} +\tcode{get() == nullptr} +does not imply a specific return value of \tcode{use_count()}. +\end{note} + +\pnum +\begin{note} +\tcode{weak_ptr::lock()} +can affect the return value of \tcode{use_count()}. +\end{note} + +\pnum +\begin{note} +When multiple threads +might affect the return value of \tcode{use_count()}, +the result is approximate. +In particular, \tcode{use_count() == 1} does not imply that accesses through +a previously destroyed \tcode{shared_ptr} have in any sense completed. +\end{note} +\end{itemdescr} + +\indexlibrarymember{operator bool}{shared_ptr}% +\begin{itemdecl} +explicit operator bool() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{get() != 0}. +\end{itemdescr} + +\indexlibrarymember{owner_before}{shared_ptr}% +\begin{itemdecl} +template bool owner_before(const shared_ptr& b) const noexcept; +template bool owner_before(const weak_ptr& b) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An unspecified value such that +\begin{itemize} +\item \tcode{x.owner_before(y)} defines a strict weak ordering as defined in~\ref{alg.sorting}; + +\item under the equivalence relation defined by \tcode{owner_before}, +\tcode{!a.owner_before(b) \&\& !b.owner_before(a)}, two \tcode{shared_ptr} or +\tcode{weak_ptr} instances are equivalent if and only if they share ownership or +are both empty. +\end{itemize} + +\end{itemdescr} + +\rSec4[util.smartptr.shared.create]{Creation} + +\pnum +The common requirements that apply to all +\tcode{make_shared}, +\tcode{allocate_shared}, +\tcode{make_shared_for_overwrite}, and +\tcode{allocate_shared_for_overwrite} overloads, +unless specified otherwise, are described below. + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared(@\placeholdernc{args}@); +template + shared_ptr allocate_shared(const A& a, @\placeholdernc{args}@); +template + shared_ptr make_shared_for_overwrite(@\placeholdernc{args}@); +template + shared_ptr allocate_shared_for_overwrite(const A& a, @\placeholdernc{args}@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{A} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. + +\pnum +\effects +Allocates memory for an object of type \tcode{T} +(or \tcode{U[N]} when \tcode{T} is \tcode{U[]}, +where \tcode{N} is determined from \placeholder{args} as specified by the concrete overload). +The object is initialized from \placeholder{args} as specified by the concrete overload. +The \tcode{allocate_shared} and \tcode{allocate_shared_for_overwrite} templates +use a copy of \tcode{a} +(rebound for an unspecified \tcode{value_type}) to allocate memory. +If an exception is thrown, the functions have no effect. + +\pnum +\ensures +\tcode{r.get() != 0 \&\& r.use_count() == 1}, +where \tcode{r} is the return value. + +\pnum +\returns +A \tcode{shared_ptr} instance that stores and owns the address of +the newly constructed object. + +\pnum +\throws +\tcode{bad_alloc}, or +an exception thrown from \tcode{allocate} or from the initialization of the object. + +\pnum +\remarks +\begin{itemize} +\item + Implementations should perform no more than one memory allocation. + \begin{note} + This provides efficiency equivalent to an intrusive smart pointer. + \end{note} +\item + When an object of an array type \tcode{U} is specified to have + an initial value of \tcode{u} (of the same type), + this shall be interpreted to mean that + each array element of the object has as its initial value + the corresponding element from \tcode{u}. +\item + When an object of an array type is specified to have + a default initial value, + this shall be interpreted to mean that each array element of the object + has a default initial value. +\item + When a (sub)object of a non-array type \tcode{U} is specified to have + an initial value of \tcode{v}, or \tcode{U(l...)}, + where \tcode{l...} is a list of constructor arguments, + \tcode{make_shared} shall initialize this (sub)object + via the expression \tcode{::new(pv) U(v)} or \tcode{::new(pv) U(l...)} respectively, + where \tcode{pv} has type \tcode{void*} and points to storage + suitable to hold an object of type \tcode{U}. +\item + When a (sub)object of a non-array type \tcode{U} is specified to have + an initial value of \tcode{v}, or \tcode{U(l...)}, + where \tcode{l...} is a list of constructor arguments, + \tcode{allocate_shared} shall initialize this (sub)object + via the expression + \begin{itemize} + \item \tcode{allocator_traits::construct(a2, pv, v)} or + \item \tcode{allocator_traits::construct(a2, pv, l...)} + \end{itemize} + respectively, + where \tcode{pv} points to storage + suitable to hold an object of type \tcode{U} and + \tcode{a2} of type \tcode{A2} is a rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared} + such that its \tcode{value_type} is \tcode{remove_cv_t}. +\item + When a (sub)object of non-array type \tcode{U} is specified to have + a default initial value, + \tcode{make_shared} shall initialize this (sub)object + via the expression \tcode{::new(pv) U()}, + where \tcode{pv} has type \tcode{void*} and points to storage + suitable to hold an object of type \tcode{U}. +\item + When a (sub)object of non-array type \tcode{U} is specified to have + a default initial value, + \tcode{allocate_shared} shall initialize this (sub)object + via the expression \tcode{allocator_traits::construct(a2, pv)}, + where \tcode{pv} points to storage + suitable to hold an object of type \tcode{U} and + \tcode{a2} of type \tcode{A2} is a rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared} + such that its \tcode{value_type} is \tcode{remove_cv_t}. +\item + When a (sub)object of non-array type \tcode{U} is initialized by + \tcode{make_shared_for_overwrite} or\linebreak % avoid Overfull + \tcode{allocate_shared_for_overwrite}, + it is initialized via the expression \tcode{::new(pv) U}, + where \tcode{pv} has type \tcode{void*} and + points to storage suitable to hold an object of type \tcode{U}. +\item + Array elements are initialized in ascending order of their addresses. +\item + When the lifetime of the object managed by the return value ends, or + when the initialization of an array element throws an exception, + the initialized elements are destroyed in the reverse order + of their original construction. +\item + When a (sub)object of non-array type \tcode{U} + that was initialized by \tcode{make_shared} is to be destroyed, + it is destroyed via the expression \tcode{pv->\~{}U()} where + \tcode{pv} points to that object of type \tcode{U}. +\item + When a (sub)object of non-array type \tcode{U} + that was initialized by \tcode{allocate_shared} is to be destroyed, + it is destroyed via the expression + \tcode{allocator_traits::destroy(a2, pv)} where + \tcode{pv} points to that object of type \tcode{remove_cv_t} and + \tcode{a2} of type \tcode{A2} is a rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared} + such that its \tcode{value_type} is \tcode{remove_cv_t}. +\end{itemize} +\begin{note} +These functions will typically allocate more memory than \tcode{sizeof(T)} to +allow for internal bookkeeping structures such as reference counts. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared(Args&&... args); // \tcode{T} is not array +template + shared_ptr allocate_shared(const A& a, Args&&... args); // \tcode{T} is not array +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is not an array type. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{T} +with an initial value \tcode{T(forward(args)...)}. + +\pnum +\remarks +The \tcode{shared_ptr} constructors called by these functions +enable \tcode{shared_from_this} +with the address of the newly constructed object of type \tcode{T}. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared(); // \tcode{shared_ptr} to \tcode{int()} +shared_ptr> q = make_shared>(16, 1); + // \tcode{shared_ptr} to vector of \tcode{16} elements with value \tcode{1} +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template shared_ptr + make_shared(size_t N); // \tcode{T} is \tcode{U[]} +template + shared_ptr allocate_shared(const A& a, size_t N); // \tcode{T} is \tcode{U[]} +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is of the form \tcode{U[]}. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{U[N]} +with a default initial value, +where \tcode{U} is \tcode{remove_extent_t}. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared(1024); + // \tcode{shared_ptr} to a value-initialized \tcode{double[1024]} +shared_ptr q = make_shared(6); + // \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]} +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared(); // \tcode{T} is \tcode{U[N]} +template + shared_ptr allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]} +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is of the form \tcode{U[N]}. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{T} +with a default initial value. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared(); + // \tcode{shared_ptr} to a value-initialized \tcode{double[1024]} +shared_ptr q = make_shared(); + // \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]} +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared(size_t N, + const remove_extent_t& u); // \tcode{T} is \tcode{U[]} +template + shared_ptr allocate_shared(const A& a, size_t N, + const remove_extent_t& u); // \tcode{T} is \tcode{U[]} +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is of the form \tcode{U[]}. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{U[N]}, +where \tcode{U} is \tcode{remove_extent_t} and +each array element has an initial value of \tcode{u}. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared(1024, 1.0); + // \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0} +shared_ptr q = make_shared(6, {1.0, 0.0}); + // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each \tcode{double[2]} element is \tcode{\{1.0, 0.0\}} +shared_ptr[]> r = make_shared[]>(4, {1, 2}); + // \tcode{shared_ptr} to a \tcode{vector[4]}, where each vector has contents \tcode{\{1, 2\}} +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared(const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} +template + shared_ptr allocate_shared(const A& a, + const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is of the form \tcode{U[N]}. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{T}, +where each array element of type \tcode{remove_extent_t} +has an initial value of \tcode{u}. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared(1.0); + // \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0} +shared_ptr q = make_shared({1.0, 0.0}); + // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each double[2] element is \tcode{\{1.0, 0.0\}} +shared_ptr[4]> r = make_shared[4]>({1, 2}); + // \tcode{shared_ptr} to a \tcode{vector[4]}, where each vector has contents \tcode{\{1, 2\}} +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared_for_overwrite(); +template + shared_ptr allocate_shared_for_overwrite(const A& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is not an array of unknown bound. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{T}. + +\pnum +\begin{example} +\begin{codeblock} +struct X { double data[1024]; }; +shared_ptr p = make_shared_for_overwrite(); + // \tcode{shared_ptr} to a default-initialized \tcode{X}, where each element in \tcode{X::data} has an indeterminate value + +shared_ptr q = make_shared_for_overwrite(); + // \tcode{shared_ptr} to a default-initialized \tcode{double[1024]}, where each element has an indeterminate value +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared_for_overwrite(size_t N); +template + shared_ptr allocate_shared_for_overwrite(const A& a, size_t N); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an array of unknown bound. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{U[N]}, +where \tcode{U} is \tcode{remove_extent_t}. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared_for_overwrite(1024); + // \tcode{shared_ptr} to a default-initialized \tcode{double[1024]}, where each element has an indeterminate value +\end{codeblock} +\end{example} +\end{itemdescr} + +\rSec4[util.smartptr.shared.cmp]{Comparison} + +\indexlibrarymember{operator==}{shared_ptr}% +\begin{itemdecl} +template + bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{a.get() == b.get()}. +\end{itemdescr} + +\indexlibrarymember{operator==}{shared_ptr}% +\begin{itemdecl} +template + bool operator==(const shared_ptr& a, nullptr_t) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!a}. +\end{itemdescr} + +\indexlibrarymember{operator<=>}{shared_ptr}% +\begin{itemdecl} +template + strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{compare_three_way()(a.get(), b.get())}. + +\pnum +\begin{note} +Defining a comparison operator function allows \tcode{shared_ptr} objects +to be used as keys in associative containers. +\end{note} +\end{itemdescr} + +\indexlibrarymember{operator<=>}{shared_ptr}% +\begin{itemdecl} +template + strong_ordering operator<=>(const shared_ptr& a, nullptr_t) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +compare_three_way()(a.get(), static_cast::element_type*>(nullptr). +\end{codeblock} +\end{itemdescr} + +\rSec4[util.smartptr.shared.spec]{Specialized algorithms} + +\indexlibrarymember{swap}{shared_ptr}% +\begin{itemdecl} +template + void swap(shared_ptr& a, shared_ptr& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a.swap(b)}. +\end{itemdescr} + +\rSec4[util.smartptr.shared.cast]{Casts} + +\indexlibrarymember{static_pointer_cast}{shared_ptr}% +\begin{itemdecl} +template + shared_ptr static_pointer_cast(const shared_ptr& r) noexcept; +template + shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{static_cast((U*)nullptr)} is well-formed. + +\pnum +\returns +\begin{codeblock} +shared_ptr(@\placeholder{R}@, static_cast::element_type*>(r.get())) +\end{codeblock} +where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and +\tcode{std::move(r)} for the second. + +\pnum +\begin{note} +The seemingly equivalent expression +\tcode{shared_ptr(static_cast(r.get()))} +will eventually result in undefined behavior, attempting to delete the +same object twice. +\end{note} +\end{itemdescr} + +\indexlibrarymember{dynamic_pointer_cast}{shared_ptr}% +\begin{itemdecl} +template + shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; +template + shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{dynamic_cast((U*)nullptr)} is well-formed. +The expression \tcode{dynamic_cast::element_type*>(r.get())} is well-formed. + +\pnum +\expects +The expression \tcode{dynamic_cast::element_type*>(r.get())} has well-defined behavior. + +\pnum +\returns +\begin{itemize} +\item When \tcode{dynamic_cast::element_type*>(r.get())} + returns a non-null value \tcode{p}, + \tcode{shared_ptr(\placeholder{R}, p)}, + where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and + \tcode{std::move(r)} for the second. +\item Otherwise, \tcode{shared_ptr()}. +\end{itemize} + +\pnum +\begin{note} +The seemingly equivalent expression +\tcode{shared_ptr(dynamic_cast(r.get()))} will eventually result in +undefined behavior, attempting to delete the same object twice. +\end{note} +\end{itemdescr} + +\indexlibrarymember{const_pointer_cast}{shared_ptr}% +\begin{itemdecl} +template + shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; +template + shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{const_cast((U*)nullptr)} is well-formed. + +\pnum +\returns +\begin{codeblock} +shared_ptr(@\placeholder{R}@, const_cast::element_type*>(r.get())) +\end{codeblock} +where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and +\tcode{std::move(r)} for the second. + +\pnum +\begin{note} +The seemingly equivalent expression +\tcode{shared_ptr(const_cast(r.get()))} will eventually result in +undefined behavior, attempting to delete the same object twice. +\end{note} +\end{itemdescr} + +\indexlibrarymember{reinterpret_pointer_cast}{shared_ptr}% +\begin{itemdecl} +template + shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept; +template + shared_ptr reinterpret_pointer_cast(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{reinterpret_cast((U*)nullptr)} is well-formed. + +\pnum +\returns +\begin{codeblock} +shared_ptr(@\placeholder{R}@, reinterpret_cast::element_type*>(r.get())) +\end{codeblock} +where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and +\tcode{std::move(r)} for the second. + +\pnum +\begin{note} +The seemingly equivalent expression +\tcode{shared_ptr(reinterpret_cast(r.get()))} will eventually result in +undefined behavior, attempting to delete the same object twice. +\end{note} +\end{itemdescr} + +\rSec4[util.smartptr.getdeleter]{\tcode{get_deleter}} + +\indexlibrarymember{get_deleter}{shared_ptr}% +\begin{itemdecl} +template + D* get_deleter(const shared_ptr& p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{p} owns a deleter \tcode{d} of type cv-unqualified +\tcode{D}, returns \tcode{addressof(d)}; otherwise returns \keyword{nullptr}. +The returned +pointer remains valid as long as there exists a \tcode{shared_ptr} instance +that owns \tcode{d}. +\begin{note} +It is unspecified whether the pointer +remains valid longer than that. This can happen if the implementation doesn't destroy +the deleter until all \tcode{weak_ptr} instances that share ownership with +\tcode{p} have been destroyed. +\end{note} +\end{itemdescr} + +\rSec4[util.smartptr.shared.io]{I/O} + +\indexlibrarymember{operator<<}{shared_ptr}% +\begin{itemdecl} +template + basic_ostream& operator<<(basic_ostream& os, const shared_ptr& p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +As if by: \tcode{os <{}< p.get();} + +\pnum +\returns +\tcode{os}. +\end{itemdescr} + +\rSec3[util.smartptr.weak]{Class template \tcode{weak_ptr}} + +\rSec4[util.smartptr.weak.general]{General} + +\pnum +\indexlibraryglobal{weak_ptr}% +The \tcode{weak_ptr} class template stores a weak reference to an object +that is already managed by a \tcode{shared_ptr}. To access the object, a +\tcode{weak_ptr} can be converted to a \tcode{shared_ptr} using the member +function \tcode{lock}. + +\begin{codeblock} +namespace std { + template class weak_ptr { + public: + using element_type = remove_extent_t; + + // \ref{util.smartptr.weak.const}, constructors + constexpr weak_ptr() noexcept; + template + weak_ptr(const shared_ptr& r) noexcept; + weak_ptr(const weak_ptr& r) noexcept; + template + weak_ptr(const weak_ptr& r) noexcept; + weak_ptr(weak_ptr&& r) noexcept; + template + weak_ptr(weak_ptr&& r) noexcept; + + // \ref{util.smartptr.weak.dest}, destructor + ~weak_ptr(); + + // \ref{util.smartptr.weak.assign}, assignment + weak_ptr& operator=(const weak_ptr& r) noexcept; + template + weak_ptr& operator=(const weak_ptr& r) noexcept; + template + weak_ptr& operator=(const shared_ptr& r) noexcept; + weak_ptr& operator=(weak_ptr&& r) noexcept; + template + weak_ptr& operator=(weak_ptr&& r) noexcept; + + // \ref{util.smartptr.weak.mod}, modifiers + void swap(weak_ptr& r) noexcept; + void reset() noexcept; + + // \ref{util.smartptr.weak.obs}, observers + long use_count() const noexcept; + bool expired() const noexcept; + shared_ptr lock() const noexcept; + template + bool owner_before(const shared_ptr& b) const noexcept; + template + bool owner_before(const weak_ptr& b) const noexcept; + }; + + template + weak_ptr(shared_ptr) -> weak_ptr; +} +\end{codeblock} + +\pnum +Specializations of \tcode{weak_ptr} shall be \oldconcept{CopyConstructible} and +\oldconcept{CopyAssignable}, allowing their use in standard +containers. The template parameter \tcode{T} of \tcode{weak_ptr} may be an +incomplete type. + +\rSec4[util.smartptr.weak.const]{Constructors} + +\indexlibraryctor{weak_ptr}% +\begin{itemdecl} +constexpr weak_ptr() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{weak_ptr} object that stores a null pointer value. + +\pnum +\ensures +\tcode{use_count() == 0}. +\end{itemdescr} + +\indexlibraryctor{weak_ptr}% +\begin{itemdecl} +weak_ptr(const weak_ptr& r) noexcept; +template weak_ptr(const weak_ptr& r) noexcept; +template weak_ptr(const shared_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the second and third constructors, \tcode{Y*} is compatible with \tcode{T*}. + +\pnum +\effects +If \tcode{r} is empty, constructs +an empty \tcode{weak_ptr} object that stores a null pointer value; +otherwise, constructs +a \tcode{weak_ptr} object that shares ownership +with \tcode{r} and stores a copy of the pointer stored in \tcode{r}. + +\pnum +\ensures +\tcode{use_count() == r.use_count()}. +\end{itemdescr} + +\indexlibraryctor{weak_ptr}% +\begin{itemdecl} +weak_ptr(weak_ptr&& r) noexcept; +template weak_ptr(weak_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. + +\pnum +\effects +Move constructs a \tcode{weak_ptr} instance from \tcode{r}. + +\pnum +\ensures +\tcode{*this} contains the old value of \tcode{r}. +\tcode{r} is empty, stores a null pointer value, and \tcode{r.use_count() == 0}. +\end{itemdescr} + +\rSec4[util.smartptr.weak.dest]{Destructor} + +\indexlibrarydtor{weak_ptr}% +\begin{itemdecl} +~weak_ptr(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Destroys this \tcode{weak_ptr} object but has no +effect on the object its stored pointer points to. +\end{itemdescr} + +\rSec4[util.smartptr.weak.assign]{Assignment} + +\indexlibrarymember{operator=}{weak_ptr}% +\begin{itemdecl} +weak_ptr& operator=(const weak_ptr& r) noexcept; +template weak_ptr& operator=(const weak_ptr& r) noexcept; +template weak_ptr& operator=(const shared_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{weak_ptr(r).swap(*this)}. + +\pnum +\returns +\tcode{*this}. + +\pnum +\remarks +The implementation may meet the effects (and the +implied guarantees) via different means, without creating a temporary object. +\end{itemdescr} + +\indexlibrarymember{operator=}{weak_ptr}% +\begin{itemdecl} +weak_ptr& operator=(weak_ptr&& r) noexcept; +template weak_ptr& operator=(weak_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{weak_ptr(std::move(r)).swap(*this)}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\rSec4[util.smartptr.weak.mod]{Modifiers} +\indexlibrarymember{swap}{weak_ptr}% +\begin{itemdecl} +void swap(weak_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Exchanges the contents of \tcode{*this} and \tcode{r}. +\end{itemdescr} + +\indexlibrarymember{reset}{weak_ptr}% +\begin{itemdecl} +void reset() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{weak_ptr().swap(*this)}. +\end{itemdescr} + +\rSec4[util.smartptr.weak.obs]{Observers} +\indexlibrarymember{use_count}{weak_ptr}% +\begin{itemdecl} +long use_count() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{0} if \tcode{*this} is empty; +otherwise, the number of \tcode{shared_ptr} instances +that share ownership with \tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{expired}{weak_ptr}% +\begin{itemdecl} +bool expired() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{use_count() == 0}. +\end{itemdescr} + +\indexlibrarymember{lock}{weak_ptr}% +\begin{itemdecl} +shared_ptr lock() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{expired() ?\ shared_ptr() :\ shared_ptr(*this)}, executed atomically. +\end{itemdescr} + +\indexlibrarymember{owner_before}{weak_ptr}% +\begin{itemdecl} +template bool owner_before(const shared_ptr& b) const noexcept; +template bool owner_before(const weak_ptr& b) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An unspecified value such that +\begin{itemize} +\item \tcode{x.owner_before(y)} defines a strict weak ordering as defined in~\ref{alg.sorting}; + +\item under the equivalence relation defined by \tcode{owner_before}, +\tcode{!a.owner_before(b) \&\& !b.owner_before(a)}, two \tcode{shared_ptr} or +\tcode{weak_ptr} instances are equivalent if and only if they share ownership or are +both empty. +\end{itemize} +\end{itemdescr} + + +\rSec4[util.smartptr.weak.spec]{Specialized algorithms} + +\indexlibrarymember{swap}{weak_ptr}% +\begin{itemdecl} +template + void swap(weak_ptr& a, weak_ptr& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a.swap(b)}. +\end{itemdescr} + +\rSec3[util.smartptr.ownerless]{Class template \tcode{owner_less}} + +\pnum +The class template \tcode{owner_less} allows ownership-based mixed comparisons of shared +and weak pointers. + +\indexlibraryglobal{owner_less}% +\begin{codeblock} +namespace std { + template struct owner_less; + + template struct owner_less> { + bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; + bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + }; + + template struct owner_less> { + bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + }; + + template<> struct owner_less { + template + bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; + template + bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + template + bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + template + bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + + using is_transparent = @\unspec@; + }; +} +\end{codeblock} + +\indexlibrarymember{operator()}{owner_less}% +\pnum +\tcode{operator()(x, y)} returns \tcode{x.owner_before(y)}. +\begin{note} +Note that +\begin{itemize} +\item \tcode{operator()} defines a strict weak ordering as defined in~\ref{alg.sorting}; + +\item +two \tcode{shared_ptr} or \tcode{weak_ptr} instances are equivalent +under the equivalence relation defined by \tcode{operator()}, +\tcode{!operator()(a, b) \&\& !operator()(b, a)}, +if and only if they share ownership or are both empty. +\end{itemize} +\end{note} + +\rSec3[util.smartptr.enab]{Class template \tcode{enable_shared_from_this}} + +\pnum +\indexlibraryglobal{enable_shared_from_this}% +A class \tcode{T} can inherit from \tcode{enable_shared_from_this} +to inherit the \tcode{shared_from_this} member functions that obtain +a \tcode{shared_ptr} instance pointing to \tcode{*this}. + +\pnum +\begin{example} +\begin{codeblock} +struct X: public enable_shared_from_this { }; + +int main() { + shared_ptr p(new X); + shared_ptr q = p->shared_from_this(); + assert(p == q); + assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership +} +\end{codeblock} +\end{example} + +\begin{codeblock} +namespace std { + template class enable_shared_from_this { + protected: + constexpr enable_shared_from_this() noexcept; + enable_shared_from_this(const enable_shared_from_this&) noexcept; + enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; + ~enable_shared_from_this(); + + public: + shared_ptr shared_from_this(); + shared_ptr shared_from_this() const; + weak_ptr weak_from_this() noexcept; + weak_ptr weak_from_this() const noexcept; + + private: + mutable weak_ptr weak_this; // \expos + }; +} +\end{codeblock} + +\pnum +The template parameter \tcode{T} of \tcode{enable_shared_from_this} +may be an incomplete type. + +\indexlibraryctor{enable_shared_from_this}% +\begin{itemdecl} +constexpr enable_shared_from_this() noexcept; +enable_shared_from_this(const enable_shared_from_this&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Value-initializes \tcode{weak_this}. +\end{itemdescr} + +\indexlibrarymember{operator=}{enable_shared_from_this}% +\begin{itemdecl} +enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{*this}. + +\pnum +\begin{note} +\tcode{weak_this} is not changed. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{shared_ptr}% +\indexlibrarymember{shared_from_this}{enable_shared_from_this}% +\begin{itemdecl} +shared_ptr shared_from_this(); +shared_ptr shared_from_this() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{shared_ptr(weak_this)}. +\end{itemdescr} + +\indexlibraryglobal{weak_ptr}% +\indexlibrarymember{weak_from_this}{enable_shared_from_this}% +\begin{itemdecl} +weak_ptr weak_from_this() noexcept; +weak_ptr weak_from_this() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{weak_this}. +\end{itemdescr} + +\rSec2[util.smartptr.hash]{Smart pointer hash support} + +\indexlibrarymember{hash}{unique_ptr}% +\begin{itemdecl} +template struct hash>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Letting \tcode{UP} be \tcode{unique_ptr}, +the specialization \tcode{hash} is enabled\iref{unord.hash} +if and only if \tcode{hash} is enabled. +When enabled, for an object \tcode{p} of type \tcode{UP}, +\tcode{hash()(p)} evaluates to +the same value as \tcode{hash()(p.get())}. +The member functions are not guaranteed to be \keyword{noexcept}. +\end{itemdescr} + +\indexlibrarymember{hash}{shared_ptr}% +\begin{itemdecl} +template struct hash>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +For an object \tcode{p} of type \tcode{shared_ptr}, +\tcode{hash>()(p)} evaluates to +the same value as \tcode{hash::element_type*>()(p.get())}. +\end{itemdescr}% +\indextext{smart pointers|)} + +\rSec2[smartptr.adapt]{Smart pointer adaptors} + +\rSec3[out.ptr.t]{Class template \tcode{out_ptr_t}} + +\pnum +\tcode{out_ptr_t} is a class template used to adapt types +such as smart pointers\iref{smartptr} +for functions that use output pointer parameters. + +\pnum +\begin{example} +\begin{codeblock} +#include +#include + +int fopen_s(std::FILE** f, const char* name, const char* mode); + +struct fclose_deleter { + void operator()(std::FILE* f) const noexcept { + std::fclose(f); + } +}; + +int main(int, char*[]) { + constexpr const char* file_name = "ow.o"; + std::unique_ptr file_ptr; + int err = fopen_s(std::out_ptr(file_ptr), file_name, "r+b"); + if (err != 0) + return 1; + // \tcode{*file_ptr} is valid + return 0; +} +\end{codeblock} +\tcode{unique_ptr} can be used with \tcode{out_ptr} +to be passed into an output pointer-style function, +without needing to hold onto an intermediate pointer value and +manually delete it on error or failure. +\end{example} + +\indexlibraryglobal{out_ptr_t}% +\begin{codeblock} +namespace std { + template + class out_ptr_t { + public: + explicit out_ptr_t(Smart&, Args...); + out_ptr_t(const out_ptr_t&) = delete; + + ~out_ptr_t(); + + operator Pointer*() const noexcept; + operator void**() const noexcept; + + private: + Smart& s; // \expos + tuple a; // \expos + Pointer p; // \expos + }; +} +\end{codeblock} + +\pnum +\tcode{Pointer} shall meet the \oldconcept{NullablePointer} requirements. +If \tcode{Smart} is a specialization of \tcode{shared_ptr} and +\tcode{sizeof...(Args) == 0}, +the program is ill-formed. +\begin{note} +It is typically a user error to reset a \tcode{shared_ptr} +without specifying a deleter, +as \tcode{shared_ptr} will replace a custom deleter upon usage of \tcode{reset}, +as specified in \ref{util.smartptr.shared.mod}. +\end{note} + +\pnum +Program-defined specializations of \tcode{out_ptr_t} +that depend on at least one program-defined type +need not meet the requirements for the primary template. + +\pnum +Evaluations of the conversion functions +on the same object may conflict\iref{intro.races}. + +\indexlibraryctor{out_ptr_t}% +\begin{itemdecl} +explicit out_ptr_t(Smart& smart, Args... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{s} with \tcode{smart}, +\tcode{a} with \tcode{std::forward(args)...}, and +value-initializes \tcode{p}. + +\pnum +\begin{note} +The constructor is not \tcode{noexcept} +to allow for a variety of non-terminating and safe implementation strategies. +For example, an implementation can allocate +a \tcode{shared_ptr}'s internal node in the constructor and +let implementation-defined exceptions escape safely. +The destructor can then move the allocated control block in directly and +avoid any other exceptions. +\end{note} +\end{itemdescr} + +\indexlibrarydtor{out_ptr_t}% +\begin{itemdecl} +~out_ptr_t(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{SP} be +\tcode{\exposid{POINTER_OF_OR}(Smart, Pointer)}\iref{memory.general}. + +\pnum +\effects +Equivalent to: +\begin{itemize} +\item +% pretend to \item that there is real text here, but undo the vertical spacing +\mbox{}\vspace{-\baselineskip}\vspace{-\parskip} +\begin{codeblock} +if (p) { + apply([&](auto&&... args) { + s.reset(static_cast(p), std::forward(args)...); }, std::move(a)); +} +\end{codeblock} +if the expression +\tcode{s.reset(static_cast(p), std::forward(args)...)} +is well-\linebreak formed; +\item +otherwise, +\begin{codeblock} +if (p) { + apply([&](auto&&... args) { + s = Smart(static_cast(p), std::forward(args)...); }, std::move(a)); +} +\end{codeblock} +if \tcode{is_constructible_v} is \tcode{true}; +\item +otherwise, the program is ill-formed. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +operator Pointer*() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{operator void**()} has not been called on \tcode{*this}. + +\pnum +\returns +\tcode{addressof(const_cast(p))}. +\end{itemdescr} + +\begin{itemdecl} +operator void**() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_same_v} is \tcode{false}. + +\pnum +\mandates +\tcode{is_pointer_v} is \tcode{true}. + +\pnum +\expects +\tcode{operator Pointer*()} has not been called on \tcode{*this}. + +\pnum +\returns +A pointer value \tcode{v} such that: +\begin{itemize} +\item +the initial value \tcode{*v} is equivalent to \tcode{static_cast(p)} and +\item +any modification of \tcode{*v} +that is not followed by a subsequent modification of \tcode{*this} +affects the value of \tcode{p} during the destruction of \tcode{*this}, +such that \tcode{static_cast(p) == *v}. +\end{itemize} + +\pnum +\remarks +Accessing \tcode{*v} outside the lifetime of \tcode{*this} +has undefined behavior. + +\pnum +\begin{note} +\tcode{reinterpret_cast(static_cast(*this))} +can be a viable implementation strategy for some implementations. +\end{note} +\end{itemdescr} + +\rSec3[out.ptr]{Function template \tcode{out_ptr}} + +\indexlibraryglobal{out_ptr}% +\begin{itemdecl} +template + auto out_ptr(Smart& s, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{P} be \tcode{Pointer} +if \tcode{is_void_v} is \tcode{false}, +otherwise \tcode{\exposid{POINTER_OF}(Smart)}. + +\pnum +\returns +\tcode{out_ptr_t(s, std::forward(args)...)} +\end{itemdescr} + +\rSec3[inout.ptr.t]{Class template \tcode{inout_ptr_t}} + +\pnum +\tcode{inout_ptr_t} is a class template used to adapt types +such as smart pointers\iref{smartptr} +for functions that use output pointer parameters +whose dereferenced values may first be deleted +before being set to another allocated value. + +\pnum +\begin{example} +\begin{codeblock} +#include + +struct star_fish* star_fish_alloc(); +int star_fish_populate(struct star_fish** ps, const char* description); + +struct star_fish_deleter { + void operator() (struct star_fish* c) const noexcept; +}; + +using star_fish_ptr = std::unique_ptr; + +int main(int, char*[]) { + star_fish_ptr peach(star_fish_alloc()); + // ... + // used, need to re-make + int err = star_fish_populate(std::inout_ptr(peach), "caring clown-fish liker"); + return err; +} +\end{codeblock} +A \tcode{unique_ptr} can be used with \tcode{inout_ptr} +to be passed into an output pointer-style function. +The original value will be properly deleted +according to the function it is used with and +a new value reset in its place. +\end{example} + +\indexlibraryglobal{inout_ptr_t}% +\begin{codeblock} +namespace std { + template + class inout_ptr_t { + public: + explicit inout_ptr_t(Smart&, Args...); + inout_ptr_t(const inout_ptr_t&) = delete; + + ~inout_ptr_t(); + + operator Pointer*() const noexcept; + operator void**() const noexcept; + + private: + Smart& s; // \expos + tuple a; // \expos + Pointer p; // \expos + }; +} +\end{codeblock} + +\pnum +\tcode{Pointer} shall meet the \oldconcept{NullablePointer} requirements. +If \tcode{Smart} is a specialization of \tcode{shared_ptr}, +the program is ill-formed. +\begin{note} +It is impossible to properly acquire unique ownership of the managed resource +from a \tcode{shared_ptr} given its shared ownership model. +\end{note} + +\pnum +Program-defined specializations of \tcode{inout_ptr_t} +that depend on at least one program-defined type +need not meet the requirements for the primary template. + +\pnum +Evaluations of the conversion functions on the same object +may conflict\iref{intro.races}. + +\indexlibraryctor{inout_ptr_t}% +\begin{itemdecl} +explicit inout_ptr_t(Smart& smart, Args... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{s} with \tcode{smart}, +\tcode{a} with \tcode{std::forward(args)...}, and +\tcode{p} to either +\begin{itemize} +\item \tcode{smart} if \tcode{is_pointer_v} is \tcode{true}, +\item otherwise, \tcode{smart.get()}. +\end{itemize} + +\pnum +\remarks +An implementation can call \tcode{s.release()}. + +\pnum +\begin{note} +The constructor is not \tcode{noexcept} +to allow for a variety of non-terminating and safe implementation strategies. +For example, an intrusive pointer implementation with a control block +can allocate in the constructor and safely fail with an exception. +\end{note} +\end{itemdescr} + +\indexlibrarydtor{inout_ptr_t}% +\begin{itemdecl} +~inout_ptr_t(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{SP} be +\tcode{\exposid{POINTER_OF_OR}(Smart, Pointer)}\iref{memory.general}. + +\pnum +Let \exposid{release-statement} be \tcode{s.release();} +if an implementation does not call \tcode{s.release()} in the constructor. +Otherwise, it is empty. + +\pnum +\effects +Equivalent to: +\begin{itemize} +\item +% pretend to \item that there is real text here, but undo the vertical spacing +\mbox{}\vspace{-\baselineskip}\vspace{-\parskip} +\begin{codeblock} +if (p) { + apply([&](auto&&... args) { + s = Smart( static_cast(p), std::forward(args)...); }, std::move(a)); +} +\end{codeblock} +if \tcode{is_pointer_v} is \tcode{true}; +\item +otherwise, +\begin{codeblock} +if (p) { + apply([&](auto&&... args) { + @\exposid{release-statement}@; + s.reset(static_cast(p), std::forward(args)...); }, std::move(a)); +} +\end{codeblock} +if the expression +\tcode{s.reset(static_cast(p), std::forward(args)...)} +is well-\newline formed; +\item +otherwise, +\begin{codeblock} +if (p) { + apply([&](auto&&... args) { + @\exposid{release-statement}@; + s = Smart(static_cast(p), std::forward(args)...); }, std::move(a)); +} +\end{codeblock} +if \tcode{is_constructible_v} is \tcode{true}; +\item +otherwise, the program is ill-formed. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +operator Pointer*() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{operator void**()} has not been called on \tcode{*this}. + +\pnum +\returns +\tcode{addressof(const_cast(p))}. +\end{itemdescr} + +\begin{itemdecl} +operator void**() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_same_v} is \tcode{false}. + +\pnum +\mandates +\tcode{is_pointer_v} is \tcode{true}. + +\pnum +\expects +\tcode{operator Pointer*()} has not been called on \tcode{*this}. + +\pnum +\returns +A pointer value \tcode{v} such that: +\begin{itemize} +\item +the initial value \tcode{*v} is equivalent to \tcode{static_cast(p)} and +\item +any modification of \tcode{*v} +that is not followed by subsequent modification of \tcode{*this} +affects the value of \tcode{p} during the destruction of \tcode{*this}, +such that \tcode{static_cast(p) == *v}. +\end{itemize} + +\pnum +\remarks +Accessing \tcode{*v} outside the lifetime of \tcode{*this} +has undefined behavior. + +\pnum +\begin{note} +\tcode{reinterpret_cast(static_cast(*this))} +can be a viable implementation strategy for some implementations. +\end{note} +\end{itemdescr} + +\rSec3[inout.ptr]{Function template \tcode{inout_ptr}} + +\indexlibraryglobal{inout_ptr}% +\begin{itemdecl} +template + auto inout_ptr(Smart& s, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{P} be \tcode{Pointer} if \tcode{is_void_v} is \tcode{false}, +otherwise \tcode{\exposid{POINTER_OF}(Smart)}. + +\pnum +\returns +\tcode{inout_ptr_t(s, std::forward(args)...)}. +\end{itemdescr} + +\rSec1[mem.res]{Memory resources} + +\rSec2[mem.res.syn]{Header \tcode{} synopsis} + +\indexheader{memory_resource}% +\begin{codeblock} +namespace std::pmr { + // \ref{mem.res.class}, class \tcode{memory_resource} + class memory_resource; + + bool operator==(const memory_resource& a, const memory_resource& b) noexcept; + + // \ref{mem.poly.allocator.class}, class template \tcode{polymorphic_allocator} + template class polymorphic_allocator; + + template + bool operator==(const polymorphic_allocator& a, + const polymorphic_allocator& b) noexcept; + + // \ref{mem.res.global}, global memory resources + memory_resource* new_delete_resource() noexcept; + memory_resource* null_memory_resource() noexcept; + memory_resource* set_default_resource(memory_resource* r) noexcept; + memory_resource* get_default_resource() noexcept; + + // \ref{mem.res.pool}, pool resource classes + struct pool_options; + class synchronized_pool_resource; + class unsynchronized_pool_resource; + class monotonic_buffer_resource; +} +\end{codeblock} + +\rSec2[mem.res.class]{Class \tcode{memory_resource}} + +\rSec3[mem.res.class.general]{General} + +\pnum +The \tcode{memory_resource} class is an abstract interface to an unbounded set of classes encapsulating memory resources. + +\indexlibraryglobal{memory_resource}% +\indexlibrarymember{operator=}{memory_resource}% +\begin{codeblock} +namespace std::pmr { + class memory_resource { + static constexpr size_t max_align = alignof(max_align_t); // \expos + + public: + memory_resource() = default; + memory_resource(const memory_resource&) = default; + virtual ~memory_resource(); + + memory_resource& operator=(const memory_resource&) = default; + + [[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align); + void deallocate(void* p, size_t bytes, size_t alignment = max_align); + + bool is_equal(const memory_resource& other) const noexcept; + + private: + virtual void* do_allocate(size_t bytes, size_t alignment) = 0; + virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; + + virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; + }; +} +\end{codeblock} + + +\rSec3[mem.res.public]{Public member functions} + +\indexlibrarydtor{memory_resource}% +\begin{itemdecl} +~memory_resource(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Destroys this \tcode{memory_resource}. +\end{itemdescr} + +\indexlibrarymember{allocate}{memory_resource}% +\begin{itemdecl} +[[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Allocates storage by calling \tcode{do_allocate(bytes, alignment)} and +implicitly creates objects within the allocated region of storage. + +\pnum +\returns +A pointer to a suitable created object\iref{intro.object} +in the allocated region of storage. + +\pnum +\throws +What and when the call to \tcode{do_allocate} throws. +\end{itemdescr} + +\indexlibrarymember{deallocate}{memory_resource}% +\begin{itemdecl} +void deallocate(void* p, size_t bytes, size_t alignment = max_align); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{do_deallocate(p, bytes, alignment)}. +\end{itemdescr} + +\indexlibrarymember{is_equal}{memory_resource}% +\begin{itemdecl} +bool is_equal(const memory_resource& other) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return do_is_equal(other);} +\end{itemdescr} + + +\rSec3[mem.res.private]{Private virtual member functions} + +\indexlibrarymember{do_allocate}{memory_resource}% +\begin{itemdecl} +virtual void* do_allocate(size_t bytes, size_t alignment) = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{alignment} is a power of two. + +\pnum +\returns +A derived class shall implement this function to +return a pointer to allocated storage\iref{basic.stc.dynamic.allocation} +with a size of at least \tcode{bytes}, +aligned to the specified \tcode{alignment}. + +\pnum +\throws +A derived class implementation shall throw an appropriate exception if it is unable to allocate memory with the requested size and alignment. +\end{itemdescr} + +\indexlibrarymember{do_deallocate}{memory_resource}% +\begin{itemdecl} +virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{p} was returned from a prior call to \tcode{allocate(bytes, alignment)} +on a memory resource equal to \tcode{*this}, +and the storage at \tcode{p} has not yet been deallocated. + +\pnum +\effects +A derived class shall implement this function to dispose of allocated storage. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{do_is_equal}{memory_resource}% +\begin{itemdecl} +virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A derived class shall implement this function to return \tcode{true} if memory allocated from \keyword{this} can be deallocated from \tcode{other} and vice-versa, +otherwise \tcode{false}. +\begin{note} +It is possible that the most-derived type of \tcode{other} does not match the type of \keyword{this}. +For a derived class \tcode{D}, an implementation of this function +can immediately return \tcode{false} +if \tcode{dynamic_cast(\&other) == nullptr}. +\end{note} +\end{itemdescr} + +\rSec3[mem.res.eq]{Equality} + +\indexlibrarymember{operator==}{memory_resource}% +\begin{itemdecl} +bool operator==(const memory_resource& a, const memory_resource& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\&a == \&b || a.is_equal(b)}. +\end{itemdescr} + +\rSec2[mem.poly.allocator.class]{Class template \tcode{polymorphic_allocator}} + +\rSec3[mem.poly.allocator.class.general]{General} + +\pnum +A specialization of class template \tcode{pmr::polymorphic_allocator} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. +Constructed with different memory resources, +different instances of the same specialization of \tcode{pmr::polymorphic_allocator} +can exhibit entirely different allocation behavior. +This runtime polymorphism allows objects that use \tcode{polymorphic_allocator} +to behave as if they used different allocator types at run time +even though they use the same static allocator type. + +\pnum +All specializations of class template \tcode{pmr::polymorphic_allocator} +meet the allocator completeness requirements\iref{allocator.requirements.completeness}. + +\indexlibraryglobal{polymorphic_allocator}% +\indexlibrarymember{value_type}{polymorphic_allocator}% +\begin{codeblock} +namespace std::pmr { + template class polymorphic_allocator { + memory_resource* memory_rsrc; // \expos + + public: + using value_type = Tp; + + // \ref{mem.poly.allocator.ctor}, constructors + polymorphic_allocator() noexcept; + polymorphic_allocator(memory_resource* r); + + polymorphic_allocator(const polymorphic_allocator& other) = default; + + template + polymorphic_allocator(const polymorphic_allocator& other) noexcept; + + polymorphic_allocator& operator=(const polymorphic_allocator&) = delete; + + // \ref{mem.poly.allocator.mem}, member functions + [[nodiscard]] Tp* allocate(size_t n); + void deallocate(Tp* p, size_t n); + + [[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); + void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t)); + template [[nodiscard]] T* allocate_object(size_t n = 1); + template void deallocate_object(T* p, size_t n = 1); + template [[nodiscard]] T* new_object(CtorArgs&&... ctor_args); + template void delete_object(T* p); + + template + void construct(T* p, Args&&... args); + + polymorphic_allocator select_on_container_copy_construction() const; + + memory_resource* resource() const; + }; +} +\end{codeblock} + +\rSec3[mem.poly.allocator.ctor]{Constructors} + +\indexlibraryctor{polymorphic_allocator}% +\begin{itemdecl} +polymorphic_allocator() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Sets \tcode{memory_rsrc} to \tcode{get_default_resource()}. +\end{itemdescr} + +\indexlibraryctor{polymorphic_allocator}% +\begin{itemdecl} +polymorphic_allocator(memory_resource* r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{r} is non-null. + +\pnum +\effects +Sets \tcode{memory_rsrc} to \tcode{r}. + +\pnum +\throws +Nothing. + +\pnum +\begin{note} +This constructor provides an implicit conversion from \tcode{memory_resource*}. +\end{note} +\end{itemdescr} + +\indexlibraryctor{polymorphic_allocator}% +\begin{itemdecl} +template polymorphic_allocator(const polymorphic_allocator& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Sets \tcode{memory_rsrc} to \tcode{other.resource()}. +\end{itemdescr} + + +\rSec3[mem.poly.allocator.mem]{Member functions} + +\indexlibrarymember{allocate}{polymorphic_allocator}% +\begin{itemdecl} +[[nodiscard]] Tp* allocate(size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{numeric_limits::max() / sizeof(Tp) < n}, +throws \tcode{bad_array_new_length}. +Otherwise equivalent to: +\begin{codeblock} +return static_cast(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp))); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{deallocate}{polymorphic_allocator}% +\begin{itemdecl} +void deallocate(Tp* p, size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{p} was allocated from a memory resource \tcode{x}, +equal to \tcode{*memory_rsrc}, +using \tcode{x.allocate(n * sizeof(Tp), alignof(Tp))}. + +\pnum +\effects +Equivalent to \tcode{memory_rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp))}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{allocate_bytes}{polymorphic_allocator}% +\begin{itemdecl} +[[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return memory_rsrc->allocate(nbytes, alignment);} + +\pnum +\begin{note} +The return type is \tcode{void*} (rather than, e.g., \tcode{byte*}) +to support conversion to an arbitrary pointer type \tcode{U*} +by \tcode{static_cast}, thus facilitating construction of a \tcode{U} +object in the allocated memory. +\end{note} +\end{itemdescr} + +\indexlibrarymember{deallocate_bytes}{polymorphic_allocator}% +\begin{itemdecl} +void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{memory_rsrc->deallocate(p, nbytes, alignment)}. +\end{itemdescr} + +\indexlibrarymember{allocate_object}{polymorphic_allocator}% +\begin{itemdecl} +template + [[nodiscard]] T* allocate_object(size_t n = 1); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Allocates memory suitable for holding +an array of \tcode{n} objects of type \tcode{T}, as follows: +\begin{itemize} +\item + if \tcode{numeric_limits::max() / sizeof(T) < n}, + throws \tcode{bad_array_new_length}, +\item + otherwise equivalent to: +\begin{codeblock} +return static_cast(allocate_bytes(n*sizeof(T), alignof(T))); +\end{codeblock} +\end{itemize} + +\pnum +\begin{note} +\tcode{T} is not deduced and must therefore be provided as a template argument. +\end{note} +\end{itemdescr} + +\indexlibrarymember{deallocate_object}{polymorphic_allocator}% +\begin{itemdecl} +template + void deallocate_object(T* p, size_t n = 1); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{deallocate_bytes(p, n*sizeof(T), alignof(T))}. +\end{itemdescr} + +\indexlibrarymember{new_object}{polymorphic_allocator}% +\begin{itemdecl} +template + [[nodiscard]] T* new_object(CtorArgs&&... ctor_args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Allocates and constructs an object of type \tcode{T}, as follows.\newline +Equivalent to: +\begin{codeblock} +T* p = allocate_object(); +try { + construct(p, std::forward(ctor_args)...); +} catch (...) { + deallocate_object(p); + throw; +} +return p; +\end{codeblock} + +\pnum +\begin{note} +\tcode{T} is not deduced and must therefore be provided as a template argument. +\end{note} +\end{itemdescr} + +\indexlibrarymember{new_object}{polymorphic_allocator}% +\begin{itemdecl} +template + void delete_object(T* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +allocator_traits::destroy(*this, p); +deallocate_object(p); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{construct}{polymorphic_allocator}% +\begin{itemdecl} +template + void construct(T* p, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +Uses-allocator construction of \tcode{T} +with allocator \tcode{*this} (see~\ref{allocator.uses.construction}) +and constructor arguments \tcode{std::forward(args)...} is well-formed. + +\pnum +\effects +Construct a \tcode{T} object in the storage +whose address is represented by \tcode{p} +by uses-allocator construction with allocator \tcode{*this} +and constructor arguments \tcode{std::forward(args)...}. + +\pnum +\throws +Nothing unless the constructor for \tcode{T} throws. +\end{itemdescr} + +\indexlibrarymember{select_on_container_copy_construction}{polymorphic_allocator}% +\begin{itemdecl} +polymorphic_allocator select_on_container_copy_construction() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{polymorphic_allocator()}. + +\pnum +\begin{note} +The memory resource is not propagated. +\end{note} +\end{itemdescr} + +\indexlibrarymember{resource}{polymorphic_allocator}% +\begin{itemdecl} +memory_resource* resource() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{memory_rsrc}. +\end{itemdescr} + +\rSec3[mem.poly.allocator.eq]{Equality} + +\indexlibrarymember{operator==}{polymorphic_allocator}% +\begin{itemdecl} +template + bool operator==(const polymorphic_allocator& a, + const polymorphic_allocator& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{*a.resource() == *b.resource()}. +\end{itemdescr} + +\rSec2[mem.res.global]{Access to program-wide \tcode{memory_resource} objects} + +\indexlibraryglobal{new_delete_resource}% +\begin{itemdecl} +memory_resource* new_delete_resource() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A pointer to a static-duration object of a type derived from \tcode{memory_resource} +that can serve as a resource for allocating memory +using \tcode{::operator new} and \tcode{::operator delete}. +The same value is returned every time this function is called. +For a return value \tcode{p} and a memory resource \tcode{r}, +\tcode{p->is_equal(r)} returns \tcode{\&r == p}. +\end{itemdescr} + +\indexlibraryglobal{null_memory_resource}% +\begin{itemdecl} +memory_resource* null_memory_resource() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A pointer to a static-duration object of a type derived from \tcode{memory_resource} +for which \tcode{allocate()} always throws \tcode{bad_alloc} and +for which \tcode{deallocate()} has no effect. +The same value is returned every time this function is called. +For a return value \tcode{p} and a memory resource \tcode{r}, +\tcode{p->is_equal(r)} returns \tcode{\&r == p}. +\end{itemdescr} + +\pnum +The \defn{default memory resource pointer} is a pointer to a memory resource +that is used by certain facilities when an explicit memory resource +is not supplied through the interface. +Its initial value is the return value of \tcode{new_delete_resource()}. + +\indexlibraryglobal{set_default_resource}% +\begin{itemdecl} +memory_resource* set_default_resource(memory_resource* r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{r} is non-null, +sets the value of the default memory resource pointer to \tcode{r}, +otherwise sets the default memory resource pointer to \tcode{new_delete_resource()}. + +\pnum +\returns +The previous value of the default memory resource pointer. + +\pnum +\remarks +Calling the \tcode{set_default_resource} and +\tcode{get_default_resource} functions shall not incur a data race. +A call to the \tcode{set_default_resource} function +shall synchronize with subsequent calls to +the \tcode{set_default_resource} and \tcode{get_default_resource} functions. +\end{itemdescr} + +\indexlibraryglobal{get_default_resource}% +\begin{itemdecl} +memory_resource* get_default_resource() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The current value of the default memory resource pointer. +\end{itemdescr} + +\rSec2[mem.res.pool]{Pool resource classes} + +\rSec3[mem.res.pool.overview]{Classes \tcode{synchronized_pool_resource} and \tcode{unsynchronized_pool_resource}} + +\pnum +The \tcode{synchronized_pool_resource} and +\tcode{unsynchronized_pool_resource} classes +(collectively called \defn{pool resource classes}) +are general-purpose memory resources having the following qualities: +\begin{itemize} +\item +Each resource frees its allocated memory on destruction, +even if \tcode{deallocate} has not been called for some of the allocated blocks. +\item +A pool resource consists of a collection of \defn{pools}, +serving requests for different block sizes. +Each individual pool manages a collection of \defn{chunks} +that are in turn divided into blocks of uniform size, +returned via calls to \tcode{do_allocate}. +Each call to \tcode{do_allocate(size, alignment)} is dispatched +to the pool serving the smallest blocks accommodating at least \tcode{size} bytes. +\item +When a particular pool is exhausted, +allocating a block from that pool results in the allocation +of an additional chunk of memory from the \defn{upstream allocator} +(supplied at construction), thus replenishing the pool. +With each successive replenishment, +the chunk size obtained increases geometrically. +\begin{note} +By allocating memory in chunks, +the pooling strategy increases the chance that consecutive allocations +will be close together in memory. +\end{note} +\item +Allocation requests that exceed the largest block size of any pool +are fulfilled directly from the upstream allocator. +\item +A \tcode{pool_options} struct may be passed to the pool resource constructors +to tune the largest block size and the maximum chunk size. +\end{itemize} + +\pnum +A \tcode{synchronized_pool_resource} may be accessed from multiple threads +without external synchronization +and may have thread-specific pools to reduce synchronization costs. +An \tcode{unsynchronized_pool_resource} class may not be accessed +from multiple threads simultaneously +and thus avoids the cost of synchronization entirely +in single-threaded applications. + +\indexlibraryglobal{pool_options}% +\indexlibraryglobal{synchronized_pool_resource}% +\indexlibraryglobal{unsynchronized_pool_resource}% +\begin{codeblock} +namespace std::pmr { + struct pool_options { + size_t max_blocks_per_chunk = 0; + size_t largest_required_pool_block = 0; + }; + + class synchronized_pool_resource : public memory_resource { + public: + synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); + + synchronized_pool_resource() + : synchronized_pool_resource(pool_options(), get_default_resource()) {} + explicit synchronized_pool_resource(memory_resource* upstream) + : synchronized_pool_resource(pool_options(), upstream) {} + explicit synchronized_pool_resource(const pool_options& opts) + : synchronized_pool_resource(opts, get_default_resource()) {} + + synchronized_pool_resource(const synchronized_pool_resource&) = delete; + virtual ~synchronized_pool_resource(); + + synchronized_pool_resource& operator=(const synchronized_pool_resource&) = delete; + + void release(); + memory_resource* upstream_resource() const; + pool_options options() const; + + protected: + void* do_allocate(size_t bytes, size_t alignment) override; + void do_deallocate(void* p, size_t bytes, size_t alignment) override; + + bool do_is_equal(const memory_resource& other) const noexcept override; + }; + + class unsynchronized_pool_resource : public memory_resource { + public: + unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); + + unsynchronized_pool_resource() + : unsynchronized_pool_resource(pool_options(), get_default_resource()) {} + explicit unsynchronized_pool_resource(memory_resource* upstream) + : unsynchronized_pool_resource(pool_options(), upstream) {} + explicit unsynchronized_pool_resource(const pool_options& opts) + : unsynchronized_pool_resource(opts, get_default_resource()) {} + + unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete; + virtual ~unsynchronized_pool_resource(); + + unsynchronized_pool_resource& operator=(const unsynchronized_pool_resource&) = delete; + + void release(); + memory_resource* upstream_resource() const; + pool_options options() const; + + protected: + void* do_allocate(size_t bytes, size_t alignment) override; + void do_deallocate(void* p, size_t bytes, size_t alignment) override; + + bool do_is_equal(const memory_resource& other) const noexcept override; + }; +} +\end{codeblock} + +\rSec3[mem.res.pool.options]{\tcode{pool_options} data members} + +\pnum +The members of \tcode{pool_options} +comprise a set of constructor options for pool resources. +The effect of each option on the pool resource behavior is described below: + +\indexlibrarymember{pool_options}{max_blocks_per_chunk}% +\begin{itemdecl} +size_t max_blocks_per_chunk; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The maximum number of blocks that will be allocated at once +from the upstream memory resource\iref{mem.res.monotonic.buffer} +to replenish a pool. +If the value of \tcode{max_blocks_per_chunk} is zero or +is greater than an \impldef{largest supported value to configure the maximum number of blocks to replenish a pool} +limit, that limit is used instead. +The implementation +may choose to use a smaller value than is specified in this field and +may use different values for different pools. +\end{itemdescr} + +\indexlibrarymember{pool_options}{largest_required_pool_block}% +\begin{itemdecl} +size_t largest_required_pool_block; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The largest allocation size that is required to be fulfilled +using the pooling mechanism. +Attempts to allocate a single block larger than this threshold +will be allocated directly from the upstream memory resource. +If \tcode{largest_required_pool_block} is zero or +is greater than an \impldef{largest supported value to configure the largest allocation satisfied directly by a pool} +limit, that limit is used instead. +The implementation may choose a pass-through threshold +larger than specified in this field. +\end{itemdescr} + +\rSec3[mem.res.pool.ctor]{Constructors and destructors} + +\indexlibraryctor{synchronized_pool_resource}% +\indexlibraryctor{unsynchronized_pool_resource}% +\begin{itemdecl} +synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); +unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{upstream} is the address of a valid memory resource. + +\pnum +\effects +Constructs a pool resource object that will obtain memory from \tcode{upstream} +whenever the pool resource is unable to satisfy a memory request +from its own internal data structures. +The resulting object will hold a copy of \tcode{upstream}, +but will not own the resource to which \tcode{upstream} points. +\begin{note} +The intention is that calls to \tcode{upstream->allocate()} +will be substantially fewer than calls to \tcode{this->allocate()} +in most cases. +\end{note} +The behavior of the pooling mechanism is tuned +according to the value of the \tcode{opts} argument. + +\pnum +\throws +Nothing unless \tcode{upstream->allocate()} throws. +It is unspecified if, or under what conditions, +this constructor calls \tcode{upstream->allocate()}. +\end{itemdescr} + +\indexlibrarydtor{synchronized_pool_resource}% +\indexlibrarydtor{unsynchronized_pool_resource}% +\begin{itemdecl} +virtual ~synchronized_pool_resource(); +virtual ~unsynchronized_pool_resource(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{release()}. +\end{itemdescr} + +\rSec3[mem.res.pool.mem]{Members} + +\indexlibrarymember{release}{synchronized_pool_resource}% +\indexlibrarymember{release}{unsynchronized_pool_resource}% +\begin{itemdecl} +void release(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{upstream_resource()->deallocate()} as necessary +to release all allocated memory. +\begin{note} +The memory is released back to \tcode{upstream_resource()} +even if \tcode{deallocate} has not been called +for some of the allocated blocks. +\end{note} +\end{itemdescr} + +\indexlibrarymember{upstream_resource}{synchronized_pool_resource}% +\indexlibrarymember{upstream_resource}{unsynchronized_pool_resource}% +\begin{itemdecl} +memory_resource* upstream_resource() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The value of the \tcode{upstream} argument +provided to the constructor of this object. +\end{itemdescr} + +\indexlibrarymember{options}{synchronized_pool_resource}% +\indexlibrarymember{options}{unsynchronized_pool_resource}% +\begin{itemdecl} +pool_options options() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The options that control the pooling behavior of this resource. +The values in the returned struct may differ +from those supplied to the pool resource constructor in that +values of zero will be replaced with \impldef{default configuration of a pool} +defaults, and sizes may be rounded to unspecified granularity. +\end{itemdescr} + +\indexlibrarymember{do_allocate}{synchronized_pool_resource}% +\indexlibrarymember{do_allocate}{unsynchronized_pool_resource}% +\begin{itemdecl} +void* do_allocate(size_t bytes, size_t alignment) override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If the pool selected for a block of size \tcode{bytes} +is unable to satisfy the memory request from its own internal data structures, +it will call \tcode{upstream_resource()->allocate()} to obtain more memory. +If \tcode{bytes} is larger than that which the largest pool can handle, +then memory will be allocated using \tcode{upstream_resource()->allocate()}. + +\pnum +\returns +A pointer to allocated storage\iref{basic.stc.dynamic.allocation} +with a size of at least \tcode{bytes}. +The size and alignment of the allocated memory shall meet the requirements +for a class derived from \tcode{memory_resource}\iref{mem.res.class}. + +\pnum +\throws +Nothing unless \tcode{upstream_resource()->allocate()} throws. +\end{itemdescr} + +\indexlibrarymember{do_deallocate}{synchronized_pool_resource}% +\indexlibrarymember{do_deallocate}{unsynchronized_pool_resource}% +\begin{itemdecl} +void do_deallocate(void* p, size_t bytes, size_t alignment) override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Returns the memory at \tcode{p} to the pool. +It is unspecified if, or under what circumstances, +this operation will result in a call to \tcode{upstream_resource()->deallocate()}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{do_is_equal}{synchronized_pool_resource}% +\indexlibrarymember{do_is_equal}{unsynchronized_pool_resource}% +\begin{itemdecl} +bool do_is_equal(const memory_resource& other) const noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{this == \&other}. +\end{itemdescr} + +\rSec2[mem.res.monotonic.buffer]{Class \tcode{monotonic_buffer_resource}} + +\rSec3[mem.res.monotonic.buffer.general]{General} + +\pnum +A \tcode{monotonic_buffer_resource} is a special-purpose memory resource +intended for very fast memory allocations in situations +where memory is used to build up a few objects +and then is released all at once when the memory resource object is destroyed. + +\indexlibraryglobal{monotonic_buffer_resource}% +\begin{codeblock} +namespace std::pmr { + class monotonic_buffer_resource : public memory_resource { + memory_resource* upstream_rsrc; // \expos + void* current_buffer; // \expos + size_t next_buffer_size; // \expos + + public: + explicit monotonic_buffer_resource(memory_resource* upstream); + monotonic_buffer_resource(size_t initial_size, memory_resource* upstream); + monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream); + + monotonic_buffer_resource() + : monotonic_buffer_resource(get_default_resource()) {} + explicit monotonic_buffer_resource(size_t initial_size) + : monotonic_buffer_resource(initial_size, get_default_resource()) {} + monotonic_buffer_resource(void* buffer, size_t buffer_size) + : monotonic_buffer_resource(buffer, buffer_size, get_default_resource()) {} + + monotonic_buffer_resource(const monotonic_buffer_resource&) = delete; + + virtual ~monotonic_buffer_resource(); + + monotonic_buffer_resource& operator=(const monotonic_buffer_resource&) = delete; + + void release(); + memory_resource* upstream_resource() const; + + protected: + void* do_allocate(size_t bytes, size_t alignment) override; + void do_deallocate(void* p, size_t bytes, size_t alignment) override; + + bool do_is_equal(const memory_resource& other) const noexcept override; + }; +} +\end{codeblock} + +\rSec3[mem.res.monotonic.buffer.ctor]{Constructors and destructor} + +\indexlibraryctor{monotonic_buffer_resource}% +\begin{itemdecl} +explicit monotonic_buffer_resource(memory_resource* upstream); +monotonic_buffer_resource(size_t initial_size, memory_resource* upstream); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{upstream} is the address of a valid memory resource. +\tcode{initial_size}, if specified, is greater than zero. + +\pnum +\effects +Sets \tcode{upstream_rsrc} to \tcode{upstream} and +\tcode{current_buffer} to \keyword{nullptr}. +If \tcode{initial_size} is specified, +sets \tcode{next_buffer_size} to at least \tcode{initial_size}; +otherwise sets \tcode{next_buffer_size} to an +\impldef{default \tcode{next_buffer_size} for a \tcode{monotonic_buffer_resource}} size. +\end{itemdescr} + +\indexlibraryctor{monotonic_buffer_resource}% +\begin{itemdecl} +monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{upstream} is the address of a valid memory resource. +\tcode{buffer_size} is no larger than the number of bytes in \tcode{buffer}. + +\pnum +\effects +Sets \tcode{upstream_rsrc} to \tcode{upstream}, +\tcode{current_buffer} to \tcode{buffer}, and +\tcode{next_buffer_size} to \tcode{buffer_size} (but not less than 1), +then increases \tcode{next_buffer_size} +by an \impldef{growth factor for \tcode{monotonic_buffer_resource}} growth factor (which need not be integral). +\end{itemdescr} + +\indexlibrarydtor{monotonic_buffer_resource}% +\begin{itemdecl} +~monotonic_buffer_resource(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{release()}. +\end{itemdescr} + + +\rSec3[mem.res.monotonic.buffer.mem]{Members} + +\indexlibrarymember{release}{monotonic_buffer_resource}% +\begin{itemdecl} +void release(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{upstream_rsrc->deallocate()} as necessary +to release all allocated memory. +Resets \tcode{current_buffer} and \tcode{next_buffer_size} +to their initial values at construction. + +\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}. +\end{note} +\end{itemdescr} + +\indexlibrarymember{upstream_resource}{monotonic_buffer_resource}% +\begin{itemdecl} +memory_resource* upstream_resource() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The value of \tcode{upstream_rsrc}. +\end{itemdescr} + +\indexlibrarymember{do_allocate}{monotonic_buffer_resource}% +\begin{itemdecl} +void* do_allocate(size_t bytes, size_t alignment) override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If the unused space in \tcode{current_buffer} +can fit a block with the specified \tcode{bytes} and \tcode{alignment}, +then allocate the return block from \tcode{current_buffer}; +otherwise set \tcode{current_buffer} to \tcode{upstream_rsrc->allocate(n, m)}, +where \tcode{n} is not less than \tcode{max(bytes, next_buffer_size)} and +\tcode{m} is not less than \tcode{alignment}, +and increase \tcode{next_buffer_size} +by an \impldef{growth factor for \tcode{monotonic_buffer_resource}} growth factor (which need not be integral), +then allocate the return block from the newly-allocated \tcode{current_buffer}. + +\pnum +\returns +A pointer to allocated storage\iref{basic.stc.dynamic.allocation} +with a size of at least \tcode{bytes}. +The size and alignment of the allocated memory shall meet the requirements +for a class derived from \tcode{memory_resource}\iref{mem.res.class}. + +\pnum +\throws +Nothing unless \tcode{upstream_rsrc->allocate()} throws. +\end{itemdescr} + +\indexlibrarymember{do_deallocate}{monotonic_buffer_resource}% +\begin{itemdecl} +void do_deallocate(void* p, size_t bytes, size_t alignment) override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +None. + +\pnum +\throws +Nothing. + +\pnum +\remarks +Memory used by this resource increases monotonically until its destruction. +\end{itemdescr} + +\indexlibrarymember{do_is_equal}{monotonic_buffer_resource}% +\begin{itemdecl} +bool do_is_equal(const memory_resource& other) const noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{this == \&other}. +\end{itemdescr} + + +\rSec1[allocator.adaptor]{Class template \tcode{scoped_allocator_adaptor}} + +\rSec2[allocator.adaptor.syn]{Header \tcode{} synopsis} + +\indexheader{scoped_allocator}% +\begin{codeblock} +namespace std { + // class template \tcode{scoped allocator adaptor} + template + class scoped_allocator_adaptor; + + // \ref{scoped.adaptor.operators}, scoped allocator operators + template + bool operator==(const scoped_allocator_adaptor& a, + const scoped_allocator_adaptor& b) noexcept; +} +\end{codeblock} + +\pnum +The class template \tcode{scoped_allocator_adaptor} is an allocator template that +specifies an allocator resource (the outer allocator) to be used by a container (as any +other allocator does) and also specifies an inner allocator resource to be passed to the +constructor of every element within the container. This adaptor is instantiated with one +outer and zero or more inner allocator types. If instantiated with only one allocator +type, the inner allocator becomes the \tcode{scoped_allocator_adaptor} itself, thus +using the same allocator resource for the container and every element within the +container and, if the elements themselves are containers, each of their elements +recursively. If instantiated with more than one allocator, the first allocator is the +outer allocator for use by the container, the second allocator is passed to the +constructors of the container's elements, and, if the elements themselves are +containers, the third allocator is passed to the elements' elements, and so on. If +containers are nested to a depth greater than the number of allocators, the last +allocator is used repeatedly, as in the single-allocator case, for any remaining +recursions. +\begin{note} +The \tcode{scoped_allocator_adaptor} is derived from the outer +allocator type so it can be substituted for the outer allocator type in most +expressions. +\end{note} + +\indexlibraryglobal{scoped_allocator_adaptor}% +\indexlibrarymember{outer_allocator_type}{scoped_allocator_adaptor}% +\indexlibrarymember{value_type}{scoped_allocator_adaptor}% +\indexlibrarymember{size_type}{scoped_allocator_adaptor}% +\indexlibrarymember{difference_type}{scoped_allocator_adaptor}% +\indexlibrarymember{pointer}{scoped_allocator_adaptor}% +\indexlibrarymember{const_pointer}{scoped_allocator_adaptor}% +\indexlibrarymember{void_pointer}{scoped_allocator_adaptor}% +\indexlibrarymember{const_void_pointer}{scoped_allocator_adaptor}% +\begin{codeblock} +namespace std { + template + class scoped_allocator_adaptor : public OuterAlloc { + private: + using OuterTraits = allocator_traits; // \expos + scoped_allocator_adaptor inner; // \expos + + public: + using outer_allocator_type = OuterAlloc; + using inner_allocator_type = @\seebelow@; + + using value_type = typename OuterTraits::value_type; + using size_type = typename OuterTraits::size_type; + using difference_type = typename OuterTraits::difference_type; + using pointer = typename OuterTraits::pointer; + using const_pointer = typename OuterTraits::const_pointer; + using void_pointer = typename OuterTraits::void_pointer; + using const_void_pointer = typename OuterTraits::const_void_pointer; + + using propagate_on_container_copy_assignment = @\seebelow@; + using propagate_on_container_move_assignment = @\seebelow@; + using propagate_on_container_swap = @\seebelow@; + using is_always_equal = @\seebelow@; + + template struct rebind { + using other = scoped_allocator_adaptor< + OuterTraits::template rebind_alloc, InnerAllocs...>; + }; + + scoped_allocator_adaptor(); + template + scoped_allocator_adaptor(OuterA2&& outerAlloc, + const InnerAllocs&... innerAllocs) noexcept; + + scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept; + scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; + + template + scoped_allocator_adaptor( + const scoped_allocator_adaptor& other) noexcept; + template + scoped_allocator_adaptor( + scoped_allocator_adaptor&& other) noexcept; + + scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default; + scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default; + + ~scoped_allocator_adaptor(); + + inner_allocator_type& inner_allocator() noexcept; + const inner_allocator_type& inner_allocator() const noexcept; + outer_allocator_type& outer_allocator() noexcept; + const outer_allocator_type& outer_allocator() const noexcept; + + [[nodiscard]] pointer allocate(size_type n); + [[nodiscard]] pointer allocate(size_type n, const_void_pointer hint); + void deallocate(pointer p, size_type n); + size_type max_size() const; + + template + void construct(T* p, Args&&... args); + + template + void destroy(T* p); + + scoped_allocator_adaptor select_on_container_copy_construction() const; + }; + + template + scoped_allocator_adaptor(OuterAlloc, InnerAllocs...) + -> scoped_allocator_adaptor; +} +\end{codeblock} + +\rSec2[allocator.adaptor.types]{Member types} + +\indexlibrarymember{inner_allocator_type}{scoped_allocator_adaptor}% +\begin{itemdecl} +using inner_allocator_type = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{scoped_allocator_adaptor} if \tcode{sizeof...(InnerAllocs)} is +zero; otherwise,\\ \tcode{scoped_allocator_adaptor}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_copy_assignment}{scoped_allocator_adaptor}% +\begin{itemdecl} +using propagate_on_container_copy_assignment = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{true_type} if +\tcode{allocator_traits::propagate_on_container_copy_assignment::value} is +\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and +\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_move_assignment}{scoped_allocator_adaptor}% +\begin{itemdecl} +using propagate_on_container_move_assignment = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{true_type} if +\tcode{allocator_traits::propagate_on_container_move_assignment::value} is +\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and +\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_swap}{scoped_allocator_adaptor}% +\begin{itemdecl} +using propagate_on_container_swap = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{true_type} if +\tcode{allocator_traits::propagate_on_container_swap::value} is +\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and +\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{is_always_equal}{scoped_allocator_adaptor}% +\begin{itemdecl} +using is_always_equal = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{true_type} if +\tcode{allocator_traits::is_always_equal::value} is +\tcode{true} for every \tcode{A} in the set of \tcode{OuterAlloc} and +\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\end{itemdescr} + +\rSec2[allocator.adaptor.cnstr]{Constructors} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +scoped_allocator_adaptor(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Value-initializes the \tcode{OuterAlloc} base class and the \tcode{inner} allocator +object. +\end{itemdescr} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +template + scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Initializes the \tcode{OuterAlloc} base class with +\tcode{std::forward(outerAlloc)} and \tcode{inner} with \tcode{innerAllocs...} +(hence recursively initializing each allocator within the adaptor with the corresponding +allocator from the argument list). +\end{itemdescr} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes each allocator within the adaptor with the corresponding allocator +from \tcode{other}. +\end{itemdescr} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Move constructs each allocator within the adaptor with the corresponding allocator +from \tcode{other}. +\end{itemdescr} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +template + scoped_allocator_adaptor( + const scoped_allocator_adaptor& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Initializes each allocator within the adaptor with the corresponding allocator +from \tcode{other}. +\end{itemdescr} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +template + scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Initializes each allocator within the adaptor with the corresponding allocator rvalue +from \tcode{other}. +\end{itemdescr} + +\rSec2[allocator.adaptor.members]{Members} + +\pnum +In the \tcode{construct} member functions, +\tcode{\placeholdernc{OUTERMOST}(x)} is +\tcode{\placeholdernc{OUTERMOST}(x.outer_allocator())} if +the expression \tcode{x.outer_allocator()} is +valid~\iref{temp.deduct} and +\tcode{x} otherwise; +\tcode{\placeholdernc{OUTERMOST_ALLOC_TRAITS}(x)} is +\tcode{allocator_traits>}. +\begin{note} +\tcode{\placeholdernc{OUTERMOST}(x)} and +\tcode{\placeholdernc{OUTERMOST_ALL\-OC_TRAITS}(x)} are recursive operations. It +is incumbent upon the definition of \tcode{outer_allocator()} to ensure that the +recursion terminates. It will terminate for all instantiations of +\tcode{scoped_allocator_adaptor}. +\end{note} + +\indexlibrarymember{inner_allocator}{scoped_allocator_adaptor}% +\begin{itemdecl} +inner_allocator_type& inner_allocator() noexcept; +const inner_allocator_type& inner_allocator() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{*this} if \tcode{sizeof...(InnerAllocs)} is zero; otherwise, +\tcode{inner}. +\end{itemdescr} + +\indexlibrarymember{outer_allocator}{scoped_allocator_adaptor}% +\begin{itemdecl} +outer_allocator_type& outer_allocator() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{static_cast(*this)}. +\end{itemdescr} + +\indexlibrarymember{outer_allocator}{scoped_allocator_adaptor}% +\begin{itemdecl} +const outer_allocator_type& outer_allocator() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{static_cast(*this)}. +\end{itemdescr} + +\indexlibrarymember{allocate}{scoped_allocator_adaptor}% +\begin{itemdecl} +[[nodiscard]] pointer allocate(size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{allocator_traits::allocate(outer_allocator(), n)}. +\end{itemdescr} + +\indexlibrarymember{allocate}{scoped_allocator_adaptor}% +\begin{itemdecl} +[[nodiscard]] pointer allocate(size_type n, const_void_pointer hint); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{allocator_traits::allocate(outer_allocator(), n, hint)}. +\end{itemdescr} + +\indexlibrarymember{deallocate}{scoped_allocator_adaptor}% +\begin{itemdecl} +void deallocate(pointer p, size_type n) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +As if by: +\tcode{allocator_traits::deallocate(outer_allocator(), p, n);} +\end{itemdescr} + +\indexlibrarymember{max_size}{scoped_allocator_adaptor}% +\begin{itemdecl} +size_type max_size() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{allocator_traits::max_size(outer_allocator())}. +\end{itemdescr} + +\indexlibrarymember{construct}{scoped_allocator_adaptor}% +\begin{itemdecl} +template + void construct(T* p, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +apply([p, this](auto&&... newargs) { + @\placeholdernc{OUTERMOST_ALLOC_TRAITS}@(*this)::construct( + @\placeholdernc{OUTERMOST}@(*this), p, + std::forward(newargs)...); + }, + uses_allocator_construction_args(inner_allocator(), + std::forward(args)...)); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{destroy}{scoped_allocator_adaptor}% +\begin{itemdecl} +template + void destroy(T* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{\placeholdernc{OUTERMOST_ALLOC_TRAITS}(*this)::destroy(\placeholdernc{OUTERMOST}(*this), p)}. +\end{itemdescr} + +\indexlibrarymember{select_on_container_copy_construction}{scoped_allocator_adaptor}% +\begin{itemdecl} +scoped_allocator_adaptor select_on_container_copy_construction() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A new \tcode{scoped_allocator_adaptor} object +where each allocator \tcode{a1} within the adaptor +is initialized with +\tcode{allocator_traits::select_on_container_copy_construction(a2)}, +where \tcode{A1} is the type of \tcode{a1} and +\tcode{a2} is the corresponding allocator in \tcode{*this}. +\end{itemdescr} + +\rSec2[scoped.adaptor.operators]{Operators} + +\indexlibrarymember{operator==}{scoped_allocator_adaptor}% +\begin{itemdecl} +template + bool operator==(const scoped_allocator_adaptor& a, + const scoped_allocator_adaptor& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{sizeof...(InnerAllocs)} is zero, +\begin{codeblock} +a.outer_allocator() == b.outer_allocator() +\end{codeblock} +otherwise +\begin{codeblock} +a.outer_allocator() == b.outer_allocator() && a.inner_allocator() == b.inner_allocator() +\end{codeblock} +\end{itemdescr} diff --git a/source/meta.tex b/source/meta.tex new file mode 100644 index 0000000000..6c6d7914fd --- /dev/null +++ b/source/meta.tex @@ -0,0 +1,2629 @@ +%!TEX root = std.tex +\rSec0[meta]{Metaprogramming library} + +\rSec1[meta.general]{General} + +\pnum +This Clause describes metaprogramming facilities. +These facilities are summarized in \tref{meta.summary}. + +\begin{libsumtab}{Metaprogramming library summary}{meta.summary} +\ref{intseq} & Integer sequences & \tcode{} \\ \rowsep +\ref{type.traits} & Type traits & \tcode{} \\ \rowsep +\ref{ratio} & Rational arithmetic & \tcode{} \\ +\end{libsumtab} + +\rSec1[intseq]{Compile-time integer sequences} + +\rSec2[intseq.general]{In general} + +\pnum +The library provides a class template that can represent an integer sequence. +When used as an argument to a function template the template parameter pack defining the +sequence can be deduced and used in a pack expansion. +\begin{note} +The \tcode{index_sequence} alias template is provided for the common case of +an integer sequence of type \tcode{size_t}; see also \ref{tuple.apply}. +\end{note} + +\rSec2[intseq.intseq]{Class template \tcode{integer_sequence}} + +\indexlibraryglobal{integer_sequence}% +\indexlibrarymember{value_type}{integer_sequence}% +\begin{codeblock} +namespace std { + template struct integer_sequence { + using value_type = T; + static constexpr size_t size() noexcept { return sizeof...(I); } + }; +} +\end{codeblock} + +\pnum +\mandates +\tcode{T} is an integer type. + +\rSec2[intseq.make]{Alias template \tcode{make_integer_sequence}} + +\indexlibraryglobal{make_integer_sequence}% +\begin{itemdecl} +template + using make_integer_sequence = integer_sequence; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +$\tcode{N} \geq 0$. + +\pnum +The alias template +\tcode{make_integer_sequence} denotes a specialization of +\tcode{integer_sequence} with \tcode{N} non-type template arguments. +The type \tcode{make_integer_sequence} is an alias for the type +\tcode{integer_sequence}. +\begin{note} +\tcode{make_integer_sequence} is an alias for the type +\tcode{integer_sequence}. +\end{note} +\end{itemdescr} + +\rSec1[type.traits]{Metaprogramming and type traits} + +\rSec2[type.traits.general]{General} + +\pnum +Subclause \ref{type.traits} describes components used by \Cpp{} programs, particularly in +templates, to support the widest possible range of types, optimize +template code usage, detect type related user errors, and perform +type inference and transformation at compile time. It includes type +classification traits, type property inspection traits, and type +transformations. The type classification traits describe a complete taxonomy +of all possible \Cpp{} types, and state where in that taxonomy a given +type belongs. The type property inspection traits allow important +characteristics of types or of combinations of types to be inspected. The +type transformations allow certain properties of types to be manipulated. + +\pnum +\indextext{signal-safe!type traits}% +All functions specified in \ref{type.traits} are signal-safe\iref{support.signal}. + +\rSec2[meta.rqmts]{Requirements} + +\pnum +A \defnoldconcept{UnaryTypeTrait} describes a property +of a type. It shall be a class template that takes one template type +argument and, optionally, additional arguments that help define the +property being described. It shall be \oldconcept{DefaultConstructible}, +\oldconcept{CopyConstructible}, +and publicly and unambiguously derived, directly or indirectly, from +its \defn{base characteristic}, which is +a specialization of the template +\tcode{integral_constant}\iref{meta.help}, with +the arguments to the template \tcode{integral_constant} determined by the +requirements for the particular property being described. +The member names of the base characteristic shall not be hidden and shall be +unambiguously available in the \oldconcept{UnaryTypeTrait}. + +\pnum +A \defnoldconcept{BinaryTypeTrait} describes a +relationship between two types. It shall be a class template that +takes two template type arguments and, optionally, additional +arguments that help define the relationship being described. It shall +be \oldconcept{DefaultConstructible}, \oldconcept{CopyConstructible}, +and publicly and unambiguously derived, directly or +indirectly, from +its \term{base characteristic}, which is a specialization +of the template +\tcode{integral_constant}\iref{meta.help}, with +the arguments to the template \tcode{integral_constant} determined by the +requirements for the particular relationship being described. +The member names of the base characteristic shall not be hidden and shall be +unambiguously available in the \oldconcept{BinaryTypeTrait}. + +\pnum +A \defnoldconcept{TransformationTrait} +modifies a property +of a type. It shall be a class template that takes one +template type argument and, optionally, additional arguments that help +define the modification. It shall define a publicly accessible nested type +named \tcode{type}, which shall be a synonym for the modified type. + +\pnum +Unless otherwise specified, +the behavior of a program that adds specializations +for any of the templates specified in \ref{type.traits} +is undefined. + +\pnum +Unless otherwise specified, an incomplete type may be used +to instantiate a template specified in \ref{type.traits}. +The behavior of a program is undefined if: +\begin{itemize} +\item + an instantiation of a template specified in \ref{type.traits} + directly or indirectly depends on + an incompletely-defined object type \tcode{T}, and +\item + that instantiation could yield a different result + were \tcode{T} hypothetically completed. +\end{itemize} + +\rSec2[meta.type.synop]{Header \tcode{} synopsis} + +\indexheader{type_traits}% +% FIXME: Many index entries missing. +\begin{codeblock} +namespace std { + // \ref{meta.help}, helper class + template struct integral_constant; + + template + using bool_constant = integral_constant; + using true_type = bool_constant; + using false_type = bool_constant; + + // \ref{meta.unary.cat}, primary type categories + template struct is_void; + template struct is_null_pointer; + template struct is_integral; + template struct is_floating_point; + template struct is_array; + template struct is_pointer; + template struct is_lvalue_reference; + template struct is_rvalue_reference; + template struct is_member_object_pointer; + template struct is_member_function_pointer; + template struct is_enum; + template struct is_union; + template struct is_class; + template struct is_function; + + // \ref{meta.unary.comp}, composite type categories + template struct is_reference; + template struct is_arithmetic; + template struct is_fundamental; + template struct is_object; + template struct is_scalar; + template struct is_compound; + template struct is_member_pointer; + + // \ref{meta.unary.prop}, type properties + template struct is_const; + template struct is_volatile; + template struct is_trivial; + template struct is_trivially_copyable; + template struct is_standard_layout; + template struct is_empty; + template struct is_polymorphic; + template struct is_abstract; + template struct is_final; + template struct is_aggregate; + + template struct is_signed; + template struct is_unsigned; + template struct is_bounded_array; + template struct is_unbounded_array; + template struct is_scoped_enum; + + template struct is_constructible; + template struct is_default_constructible; + template struct is_copy_constructible; + template struct is_move_constructible; + + template struct is_assignable; + template struct is_copy_assignable; + template struct is_move_assignable; + + template struct is_swappable_with; + template struct is_swappable; + + template struct is_destructible; + + template struct is_trivially_constructible; + template struct is_trivially_default_constructible; + template struct is_trivially_copy_constructible; + template struct is_trivially_move_constructible; + + template struct is_trivially_assignable; + template struct is_trivially_copy_assignable; + template struct is_trivially_move_assignable; + template struct is_trivially_destructible; + + template struct is_nothrow_constructible; + template struct is_nothrow_default_constructible; + template struct is_nothrow_copy_constructible; + template struct is_nothrow_move_constructible; + + template struct is_nothrow_assignable; + template struct is_nothrow_copy_assignable; + template struct is_nothrow_move_assignable; + + template struct is_nothrow_swappable_with; + template struct is_nothrow_swappable; + + template struct is_nothrow_destructible; + + template struct has_virtual_destructor; + + template struct has_unique_object_representations; + + template struct reference_constructs_from_temporary; + template struct reference_converts_from_temporary; + + // \ref{meta.unary.prop.query}, type property queries + template struct alignment_of; + template struct rank; + template struct extent; + + // \ref{meta.rel}, type relations + template struct is_same; + template struct is_base_of; + template struct is_convertible; + template struct is_nothrow_convertible; + template struct is_layout_compatible; + template struct is_pointer_interconvertible_base_of; + + template struct is_invocable; + template struct is_invocable_r; + + template struct is_nothrow_invocable; + template struct is_nothrow_invocable_r; + + // \ref{meta.trans.cv}, const-volatile modifications + template struct remove_const; + template struct remove_volatile; + template struct remove_cv; + template struct add_const; + template struct add_volatile; + template struct add_cv; + + template + using @\libglobal{remove_const_t}@ = typename remove_const::type; + template + using @\libglobal{remove_volatile_t}@ = typename remove_volatile::type; + template + using @\libglobal{remove_cv_t}@ = typename remove_cv::type; + template + using @\libglobal{add_const_t}@ = typename add_const::type; + template + using @\libglobal{add_volatile_t}@ = typename add_volatile::type; + template + using @\libglobal{add_cv_t}@ = typename add_cv::type; + + // \ref{meta.trans.ref}, reference modifications + template struct remove_reference; + template struct add_lvalue_reference; + template struct add_rvalue_reference; + + template + using @\libglobal{remove_reference_t}@ = typename remove_reference::type; + template + using @\libglobal{add_lvalue_reference_t}@ = typename add_lvalue_reference::type; + template + using @\libglobal{add_rvalue_reference_t}@ = typename add_rvalue_reference::type; + + // \ref{meta.trans.sign}, sign modifications + template struct make_signed; + template struct make_unsigned; + + template + using @\libglobal{make_signed_t}@ = typename make_signed::type; + template + using @\libglobal{make_unsigned_t}@ = typename make_unsigned::type; + + // \ref{meta.trans.arr}, array modifications + template struct remove_extent; + template struct remove_all_extents; + + template + using @\libglobal{remove_extent_t}@ = typename remove_extent::type; + template + using @\libglobal{remove_all_extents_t}@ = typename remove_all_extents::type; + + // \ref{meta.trans.ptr}, pointer modifications + template struct remove_pointer; + template struct add_pointer; + + template + using @\libglobal{remove_pointer_t}@ = typename remove_pointer::type; + template + using @\libglobal{add_pointer_t}@ = typename add_pointer::type; + + // \ref{meta.trans.other}, other transformations + template struct type_identity; + template struct remove_cvref; + template struct decay; + template struct enable_if; + template struct conditional; + template struct common_type; + template class TQual, template class UQual> + struct basic_common_reference { }; + template struct common_reference; + template struct underlying_type; + template struct invoke_result; + template struct unwrap_reference; + template struct unwrap_ref_decay; + + template + using @\libglobal{type_identity_t}@ = typename type_identity::type; + template + using @\libglobal{remove_cvref_t}@ = typename remove_cvref::type; + template + using @\libglobal{decay_t}@ = typename decay::type; + template + using @\libglobal{enable_if_t}@ = typename enable_if::type; + template + using @\libglobal{conditional_t}@ = typename conditional::type; + template + using @\libglobal{common_type_t}@ = typename common_type::type; + template + using @\libglobal{common_reference_t}@ = typename common_reference::type; + template + using @\libglobal{underlying_type_t}@ = typename underlying_type::type; + template + using @\libglobal{invoke_result_t}@ = typename invoke_result::type; + template + using unwrap_reference_t = typename unwrap_reference::type; + template + using unwrap_ref_decay_t = typename unwrap_ref_decay::type; + template + using @\libglobal{void_t}@ = void; + + // \ref{meta.logical}, logical operator traits + template struct conjunction; + template struct disjunction; + template struct negation; + + // \ref{meta.unary.cat}, primary type categories + template + inline constexpr bool @\libglobal{is_void_v}@ = is_void::value; + template + inline constexpr bool @\libglobal{is_null_pointer_v}@ = is_null_pointer::value; + template + inline constexpr bool @\libglobal{is_integral_v}@ = is_integral::value; + template + inline constexpr bool @\libglobal{is_floating_point_v}@ = is_floating_point::value; + template + inline constexpr bool @\libglobal{is_array_v}@ = is_array::value; + template + inline constexpr bool @\libglobal{is_pointer_v}@ = is_pointer::value; + template + inline constexpr bool @\libglobal{is_lvalue_reference_v}@ = is_lvalue_reference::value; + template + inline constexpr bool @\libglobal{is_rvalue_reference_v}@ = is_rvalue_reference::value; + template + inline constexpr bool @\libglobal{is_member_object_pointer_v}@ = is_member_object_pointer::value; + template + inline constexpr bool @\libglobal{is_member_function_pointer_v}@ = is_member_function_pointer::value; + template + inline constexpr bool @\libglobal{is_enum_v}@ = is_enum::value; + template + inline constexpr bool @\libglobal{is_union_v}@ = is_union::value; + template + inline constexpr bool @\libglobal{is_class_v}@ = is_class::value; + template + inline constexpr bool @\libglobal{is_function_v}@ = is_function::value; + + // \ref{meta.unary.comp}, composite type categories + template + inline constexpr bool @\libglobal{is_reference_v}@ = is_reference::value; + template + inline constexpr bool @\libglobal{is_arithmetic_v}@ = is_arithmetic::value; + template + inline constexpr bool @\libglobal{is_fundamental_v}@ = is_fundamental::value; + template + inline constexpr bool @\libglobal{is_object_v}@ = is_object::value; + template + inline constexpr bool @\libglobal{is_scalar_v}@ = is_scalar::value; + template + inline constexpr bool @\libglobal{is_compound_v}@ = is_compound::value; + template + inline constexpr bool @\libglobal{is_member_pointer_v}@ = is_member_pointer::value; + + // \ref{meta.unary.prop}, type properties + template + inline constexpr bool @\libglobal{is_const_v}@ = is_const::value; + template + inline constexpr bool @\libglobal{is_volatile_v}@ = is_volatile::value; + template + inline constexpr bool @\libglobal{is_trivial_v}@ = is_trivial::value; + template + inline constexpr bool @\libglobal{is_trivially_copyable_v}@ = is_trivially_copyable::value; + template + inline constexpr bool @\libglobal{is_standard_layout_v}@ = is_standard_layout::value; + template + inline constexpr bool @\libglobal{is_empty_v}@ = is_empty::value; + template + inline constexpr bool @\libglobal{is_polymorphic_v}@ = is_polymorphic::value; + template + inline constexpr bool @\libglobal{is_abstract_v}@ = is_abstract::value; + template + inline constexpr bool @\libglobal{is_final_v}@ = is_final::value; + template + inline constexpr bool @\libglobal{is_aggregate_v}@ = is_aggregate::value; + template + inline constexpr bool @\libglobal{is_signed_v}@ = is_signed::value; + template + inline constexpr bool @\libglobal{is_unsigned_v}@ = is_unsigned::value; + template + inline constexpr bool @\libglobal{is_bounded_array_v}@ = is_bounded_array::value; + template + inline constexpr bool @\libglobal{is_unbounded_array_v}@ = is_unbounded_array::value; + template + inline constexpr bool @\libglobal{is_scoped_enum_v}@ = is_scoped_enum::value; + template + inline constexpr bool @\libglobal{is_constructible_v}@ = is_constructible::value; + template + inline constexpr bool @\libglobal{is_default_constructible_v}@ = is_default_constructible::value; + template + inline constexpr bool @\libglobal{is_copy_constructible_v}@ = is_copy_constructible::value; + template + inline constexpr bool @\libglobal{is_move_constructible_v}@ = is_move_constructible::value; + template + inline constexpr bool @\libglobal{is_assignable_v}@ = is_assignable::value; + template + inline constexpr bool @\libglobal{is_copy_assignable_v}@ = is_copy_assignable::value; + template + inline constexpr bool @\libglobal{is_move_assignable_v}@ = is_move_assignable::value; + template + inline constexpr bool @\libglobal{is_swappable_with_v}@ = is_swappable_with::value; + template + inline constexpr bool @\libglobal{is_swappable_v}@ = is_swappable::value; + template + inline constexpr bool @\libglobal{is_destructible_v}@ = is_destructible::value; + template + inline constexpr bool is_trivially_constructible_v + = is_trivially_constructible::value; + template + inline constexpr bool is_trivially_default_constructible_v + = is_trivially_default_constructible::value; + template + inline constexpr bool is_trivially_copy_constructible_v + = is_trivially_copy_constructible::value; + template + inline constexpr bool is_trivially_move_constructible_v + = is_trivially_move_constructible::value; + template + inline constexpr bool @\libglobal{is_trivially_assignable_v}@ = is_trivially_assignable::value; + template + inline constexpr bool is_trivially_copy_assignable_v + = is_trivially_copy_assignable::value; + template + inline constexpr bool is_trivially_move_assignable_v + = is_trivially_move_assignable::value; + template + inline constexpr bool @\libglobal{is_trivially_destructible_v}@ = is_trivially_destructible::value; + template + inline constexpr bool is_nothrow_constructible_v + = is_nothrow_constructible::value; + template + inline constexpr bool is_nothrow_default_constructible_v + = is_nothrow_default_constructible::value; + template + inline constexpr bool is_nothrow_copy_constructible_v + = is_nothrow_copy_constructible::value; + template + inline constexpr bool is_nothrow_move_constructible_v + = is_nothrow_move_constructible::value; + template + inline constexpr bool @\libglobal{is_nothrow_assignable_v}@ = is_nothrow_assignable::value; + template + inline constexpr bool @\libglobal{is_nothrow_copy_assignable_v}@ = is_nothrow_copy_assignable::value; + template + inline constexpr bool @\libglobal{is_nothrow_move_assignable_v}@ = is_nothrow_move_assignable::value; + template + inline constexpr bool @\libglobal{is_nothrow_swappable_with_v}@ = is_nothrow_swappable_with::value; + template + inline constexpr bool @\libglobal{is_nothrow_swappable_v}@ = is_nothrow_swappable::value; + template + inline constexpr bool @\libglobal{is_nothrow_destructible_v}@ = is_nothrow_destructible::value; + template + inline constexpr bool @\libglobal{has_virtual_destructor_v}@ = has_virtual_destructor::value; + template + inline constexpr bool has_unique_object_representations_v + = has_unique_object_representations::value; + template + inline constexpr bool @\libglobal{reference_constructs_from_temporary_v}@ + = reference_constructs_from_temporary::value; + template + inline constexpr bool @\libglobal{reference_converts_from_temporary_v}@ + = reference_converts_from_temporary::value; + + // \ref{meta.unary.prop.query}, type property queries + template + inline constexpr size_t @\libglobal{alignment_of_v}@ = alignment_of::value; + template + inline constexpr size_t @\libglobal{rank_v}@ = rank::value; + template + inline constexpr size_t @\libglobal{extent_v}@ = extent::value; + + // \ref{meta.rel}, type relations + template + inline constexpr bool @\libglobal{is_same_v}@ = is_same::value; + template + inline constexpr bool @\libglobal{is_base_of_v}@ = is_base_of::value; + template + inline constexpr bool @\libglobal{is_convertible_v}@ = is_convertible::value; + template + inline constexpr bool @\libglobal{is_nothrow_convertible_v}@ = is_nothrow_convertible::value; + template + inline constexpr bool @\libglobal{is_layout_compatible_v}@ = is_layout_compatible::value; + template + inline constexpr bool is_pointer_interconvertible_base_of_v + = is_pointer_interconvertible_base_of::value; + template + inline constexpr bool @\libglobal{is_invocable_v}@ = is_invocable::value; + template + inline constexpr bool @\libglobal{is_invocable_r_v}@ = is_invocable_r::value; + template + inline constexpr bool @\libglobal{is_nothrow_invocable_v}@ = is_nothrow_invocable::value; + template + inline constexpr bool is_nothrow_invocable_r_v + = is_nothrow_invocable_r::value; + + // \ref{meta.logical}, logical operator traits + template + inline constexpr bool @\libglobal{conjunction_v}@ = conjunction::value; + template + inline constexpr bool @\libglobal{disjunction_v}@ = disjunction::value; + template + inline constexpr bool @\libglobal{negation_v}@ = negation::value; + + // \ref{meta.member}, member relationships + template + constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept; + template + constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept; + + // \ref{meta.const.eval}, constant evaluation context + constexpr bool is_constant_evaluated() noexcept; +} +\end{codeblock} + +\rSec2[meta.help]{Helper classes} + +\indexlibrarymember{value_type}{integral_constant}% +\begin{codeblock} +namespace std { + template struct integral_constant { + static constexpr T value = v; + + using value_type = T; + using type = integral_constant; + + constexpr operator value_type() const noexcept { return value; } + constexpr value_type operator()() const noexcept { return value; } + }; +} +\end{codeblock} + +\indexlibraryglobal{integral_constant}% +\indexlibraryglobal{bool_constant}% +\indexlibraryglobal{true_type}% +\indexlibraryglobal{false_type}% +\pnum +The class template \tcode{integral_constant}, +alias template \tcode{bool_constant}, and +its associated \grammarterm{typedef-name}{s} +\tcode{true_type} and \tcode{false_type} +are used as base classes to define +the interface for various type traits. + +\rSec2[meta.unary]{Unary type traits} + +\rSec3[meta.unary.general]{General} + +\pnum +Subclause \ref{meta.unary} contains templates that may be used to query the +properties of a type at compile time. + +\pnum +Each of these templates shall be a +\oldconcept{UnaryTypeTrait}\iref{meta.rqmts} +with a base characteristic of +\tcode{true_type} if the corresponding condition is \tcode{true}, otherwise +\tcode{false_type}. + +\rSec3[meta.unary.cat]{Primary type categories} + +\pnum +The primary type categories correspond to the descriptions given in +subclause~\ref{basic.types} of the \Cpp{} standard. + +\pnum +For any given type \tcode{T}, the result of applying one of these templates to +\tcode{T} and to \cv{}~\tcode{T} shall yield the same result. + +\pnum +\begin{note} +For any given type \tcode{T}, exactly one of the primary type categories +has a \tcode{value} member that evaluates to \tcode{true}. +\end{note} + +\begin{libreqtab3e}{Primary type category predicates}{meta.unary.cat} +\\ \topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\\capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep +\endhead +\indexlibraryglobal{is_void}% +\tcode{template}\br + \tcode{struct is_void;} & +\tcode{T} is \keyword{void} & \\ \rowsep +\indexlibraryglobal{is_null_pointer}% +\tcode{template}\br + \tcode{struct is_null_pointer;} & +\tcode{T} is \tcode{nullptr_t}\iref{basic.fundamental} & \\ \rowsep +\indexlibraryglobal{is_integral}% +\tcode{template}\br + \tcode{struct is_integral;} & +\tcode{T} is an integral type\iref{basic.fundamental} & \\ \rowsep +\indexlibraryglobal{is_floating_point}% +\tcode{template}\br + \tcode{struct is_floating_point;} & +\tcode{T} is a floating-point type\iref{basic.fundamental} & \\ \rowsep +\indexlibraryglobal{is_array}% +\tcode{template}\br + \tcode{struct is_array;} & +\tcode{T} is an array type\iref{basic.compound} of known or unknown extent & +Class template \tcode{array}\iref{array} +is not an array type. \\ \rowsep +\indexlibraryglobal{is_pointer}% +\tcode{template}\br + \tcode{struct is_pointer;} & +\tcode{T} is a pointer type\iref{basic.compound} & +Includes pointers to functions +but not pointers to non-static members. \\ \rowsep +\indexlibraryglobal{is_lvalue_reference}% +\tcode{template}\br + \tcode{struct is_lvalue_reference;} & + \tcode{T} is an lvalue reference type\iref{dcl.ref} & \\ \rowsep +\indexlibraryglobal{is_rvalue_reference}% +\tcode{template}\br + \tcode{struct is_rvalue_reference;} & + \tcode{T} is an rvalue reference type\iref{dcl.ref} & \\ \rowsep +\indexlibraryglobal{is_member_object_pointer}% +\tcode{template}\br + \tcode{struct is_member_object_pointer;}& + \tcode{T} is a pointer to data member & \\ \rowsep +\indexlibraryglobal{is_member_function_pointer}% +\tcode{template}\br + \tcode{struct is_member_function_pointer;}& +\tcode{T} is a pointer to member function & \\ \rowsep +\indexlibraryglobal{is_enum}% +\tcode{template}\br + \tcode{struct is_enum;} & +\tcode{T} is an enumeration type\iref{basic.compound} & \\ \rowsep +\indexlibraryglobal{is_union}% +\tcode{template}\br + \tcode{struct is_union;} & +\tcode{T} is a union type\iref{basic.compound} & \\ \rowsep +\indexlibraryglobal{is_class}% +\tcode{template}\br + \tcode{struct is_class;} & +\tcode{T} is a non-union class type\iref{basic.compound} & \\ \rowsep +\indexlibraryglobal{is_function}% +\tcode{template}\br + \tcode{struct is_function;} & +\tcode{T} is a function type\iref{basic.compound} & \\ +\end{libreqtab3e} + +\rSec3[meta.unary.comp]{Composite type traits} + +\pnum +These templates provide convenient compositions of the primary type +categories, corresponding to the descriptions given in subclause~\ref{basic.types}. + +\pnum +For any given type \tcode{T}, the result of applying one of these templates to +\tcode{T} and to \cv{}~\tcode{T} shall yield the same result. + +\begin{libreqtab3b}{Composite type category predicates}{meta.unary.comp} +\\ \topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep +\endhead +\indexlibraryglobal{is_reference}% +\tcode{template}\br + \tcode{struct is_reference;} & + \tcode{T} is an lvalue reference or an rvalue reference & \\ \rowsep +\indexlibraryglobal{is_arithmetic}% +\tcode{template}\br + \tcode{struct is_arithmetic;} & + \tcode{T} is an arithmetic type\iref{basic.fundamental} & \\ \rowsep +\indexlibraryglobal{is_fundamental}% +\tcode{template}\br + \tcode{struct is_fundamental;} & + \tcode{T} is a fundamental type\iref{basic.fundamental} & \\ \rowsep +\indexlibraryglobal{is_object}% +\tcode{template}\br + \tcode{struct is_object;} & + \tcode{T} is an object type\iref{term.object.type} & \\ \rowsep +\indexlibraryglobal{is_scalar}% +\tcode{template}\br + \tcode{struct is_scalar;} & + \tcode{T} is a scalar type\iref{term.scalar.type} & \\ \rowsep +\indexlibraryglobal{is_compound}% +\tcode{template}\br + \tcode{struct is_compound;} & + \tcode{T} is a compound type\iref{basic.compound} & \\ \rowsep +\indexlibraryglobal{is_member_pointer}% +\tcode{template}\br + \tcode{struct is_member_pointer;} & + \tcode{T} is a pointer-to-member type\iref{basic.compound} & \\ +\end{libreqtab3b} + +\rSec3[meta.unary.prop]{Type properties} + +\pnum +These templates provide access to some of the more important +properties of types. + +\pnum +It is unspecified whether the library defines any full or partial +specializations of any of these templates. + +\pnum +For all of the class templates \tcode{X} declared in this subclause, +instantiating that template with a template-argument that is a class +template specialization may result in the implicit instantiation of +the template argument if and only if the semantics of \tcode{X} require that +the argument is a complete type. + +\pnum +For the purpose of defining the templates in this subclause, +a function call expression \tcode{declval()} for any type \tcode{T} +is considered to be a trivial\iref{term.trivial.type,special} function call +that is not an odr-use\iref{term.odr.use} of \tcode{declval} +in the context of the corresponding definition +notwithstanding the restrictions of~\ref{declval}. + +\pnum +For the purpose of defining the templates in this subclause, +let \tcode{\placeholdernc{VAL}} for some type \tcode{T} be +an expression defined as follows: +\begin{itemize} +\item +If \tcode{T} is a reference or function type, +\tcode{\placeholdernc{VAL}} is an expression +with the same type and value category as \tcode{declval()}. +\item +Otherwise, \tcode{\placeholdernc{VAL}} is a prvalue +that initially has type \tcode{T}. +\begin{note} +If \tcode{T} is cv-qualified, +the cv-qualification is subject to adjustment\iref{expr.type}. +\end{note} +\end{itemize} + +\begin{libreqtab3b}{Type property predicates}{meta.unary.prop} +\\ \topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Preconditions} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Preconditions} \\ \capsep +\endhead + +\indexlibraryglobal{is_const}% +\tcode{template}\br + \tcode{struct is_const;} & + \tcode{T} is const-qualified\iref{basic.type.qualifier} & \\ \rowsep + +\indexlibraryglobal{is_volatile}% +\tcode{template}\br + \tcode{struct is_volatile;} & + \tcode{T} is volatile-qualified\iref{basic.type.qualifier} & \\ \rowsep + + +\indexlibraryglobal{is_trivial}% +\tcode{template}\br + \tcode{struct is_trivial;} & + \tcode{T} is a trivial type\iref{term.trivial.type} & + \tcode{remove_all_extents_t} shall be a complete + type or \cv{}~\keyword{void}. \\ \rowsep + +\indexlibraryglobal{is_trivially_copyable}% +\tcode{template}\br + \tcode{struct is_trivially_copyable;} & + \tcode{T} is a trivially copyable type\iref{term.trivially.copyable.type} & + \tcode{remove_all_extents_t} shall be a complete type or + \cv{}~\keyword{void}. \\ \rowsep + +\indexlibraryglobal{is_standard_layout}% +\tcode{template}\br + \tcode{struct is_standard_layout;} & + \tcode{T} is a standard-layout type\iref{term.standard.layout.type} & + \tcode{remove_all_extents_t} shall be a complete + type or \cv{}~\keyword{void}. \\ \rowsep + +\indexlibrary{\idxcode{is_empty}!class}% +\tcode{template}\br + \tcode{struct is_empty;} & + \tcode{T} is a class type, but not a union type, with no non-static data + members other than subobjects of zero size, no virtual member functions, + no virtual base classes, and no base class \tcode{B} for + which \tcode{is_empty_v} is \tcode{false}. & + If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{is_polymorphic}% +\tcode{template}\br + \tcode{struct is_polymorphic;} & + \tcode{T} is a polymorphic class\iref{class.virtual} & + If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{is_abstract}% +\tcode{template}\br + \tcode{struct is_abstract;} & + \tcode{T} is an abstract class\iref{class.abstract} & + If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{is_final}% +\tcode{template}\br + \tcode{struct is_final;} & + \tcode{T} is a class type marked with the \grammarterm{class-virt-specifier} + \tcode{final}\iref{class.pre}. +\begin{tailnote} +A union is a class type that + can be marked with \tcode{final}. +\end{tailnote} +& + If \tcode{T} is a class type, \tcode{T} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{is_aggregate}% +\tcode{template}\br + \tcode{struct is_aggregate;} & + \tcode{T} is an aggregate type\iref{dcl.init.aggr} & + \tcode{remove_all_extents_t} shall be a complete type or \cv~\keyword{void}. \\ \rowsep + +\indexlibrary{\idxcode{is_signed}!class}% +\tcode{template}\br + \tcode{struct is_signed;} & + If \tcode{is_arithmetic_v} is \tcode{true}, the same result as + \tcode{T(-1) < T(0)}; + otherwise, \tcode{false} & \\ \rowsep + +\indexlibraryglobal{is_unsigned}% +\tcode{template}\br + \tcode{struct is_unsigned;} & + If \tcode{is_arithmetic_v} is \tcode{true}, the same result as + \tcode{T(0) < T(-1)}; + otherwise, \tcode{false} & \\ \rowsep + +\indexlibraryglobal{is_bounded_array}% +\tcode{template}\br + \tcode{struct is_bounded_array;} & + \tcode{T} is an array type of known bound\iref{dcl.array} + & \\ \rowsep + +\indexlibraryglobal{is_unbounded_array}% +\tcode{template}\br + \tcode{struct is_unbounded_array;} & + \tcode{T} is an array type of unknown bound\iref{dcl.array} + & \\ \rowsep + +\indexlibraryglobal{is_scoped_enum}% +\tcode{template}\br + \tcode{struct is_scoped_enum;} & + \tcode{T} is a scoped enumeration\iref{dcl.enum} + & \\ \rowsep + +\indexlibraryglobal{is_constructible}% +\tcode{template}\br + \tcode{struct is_constructible;} & + For a function type \tcode{T} or + for a \cv{}~\keyword{void} type \tcode{T}, + \tcode{is_constructible_v} is \tcode{false}, + otherwise \seebelow & + \tcode{T} and all types in the template parameter pack \tcode{Args} + shall be complete types, \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_default_constructible}% +\tcode{template}\br + \tcode{struct is_default_constructible;} & + \tcode{is_constructible_v} is \tcode{true}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_copy_constructible}% +\tcode{template}\br + \tcode{struct is_copy_constructible;} & + For a referenceable type \tcode{T}\iref{defns.referenceable}, the same result as + \tcode{is_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_move_constructible}% +\tcode{template}\br + \tcode{struct is_move_constructible;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_assignable}% +\tcode{template}\br + \tcode{struct is_assignable;} & + The expression \tcode{declval() =} \tcode{declval()} is well-formed + when treated as an unevaluated + operand\iref{term.unevaluated.operand}. Access checking is performed as if in a context + unrelated to \tcode{T} and \tcode{U}. Only the validity of the immediate context + of the assignment expression is considered. +\begin{tailnote} +The compilation of the + expression can result in side effects such as the instantiation of class template + specializations and function template specializations, the generation of + implicitly-defined functions, and so on. Such side effects are not in the ``immediate + context'' and can result in the program being ill-formed. +\end{tailnote} +& + \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_copy_assignable}% +\tcode{template}\br + \tcode{struct is_copy_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_move_assignable}% +\tcode{template}\br + \tcode{struct is_move_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_swappable_with}% +\tcode{template}\br + \tcode{struct is_swappable_with;} & + The expressions \tcode{swap(declval(), declval())} and + \tcode{swap(declval(), declval())} are each well-formed + when treated as an unevaluated operand\iref{term.unevaluated.operand} + in an overload-resolution context + for swappable values\iref{swappable.requirements}. + Access checking is performed as if in a context + unrelated to \tcode{T} and \tcode{U}. + Only the validity of the immediate context + of the \tcode{swap} expressions is considered. + \begin{tailnote} + The compilation of the expressions can result in side effects + such as the instantiation of class template specializations and + function template specializations, + the generation of implicitly-defined functions, and so on. + Such side effects are not in the ``immediate context'' and + can result in the program being ill-formed. + \end{tailnote} +& + \tcode{T} and \tcode{U} shall be complete types, + \cv{}~\keyword{void}, or + arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_swappable}% +\tcode{template}\br + \tcode{struct is_swappable;} & + For a referenceable type \tcode{T}, + the same result as \tcode{is_swappable_with_v}, + otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or + an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_destructible}% +\tcode{template}\br + \tcode{struct is_destructible;} & + Either \tcode{T} is a reference type, + or \tcode{T} is a complete object type + for which the expression + \tcode{declval().\~U()} + is well-formed + when treated as an unevaluated operand\iref{term.unevaluated.operand}, + where \tcode{U} is + \tcode{remove_all_extents_t}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_constructible}% +\tcode{template}\br + \keyword{struct}\br + \tcode{is_trivially_constructible;} & + \tcode{is_constructible_v} is \tcode{true} and the variable + definition for \tcode{is_constructible}, as defined below, is known to call + no operation that is not trivial\iref{term.trivial.type,special}. & + \tcode{T} and all types in the template parameter pack \tcode{Args} shall be complete types, + \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_default_constructible}% +\tcode{template}\br + \tcode{struct is_trivially_default_constructible;} & + \tcode{is_trivially_constructible_v} is \tcode{true}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_copy_constructible}% +\tcode{template}\br + \tcode{struct is_trivially_copy_constructible;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_trivially_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_move_constructible}% +\tcode{template}\br + \tcode{struct is_trivially_move_constructible;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_trivially_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_assignable}% +\tcode{template}\br + \tcode{struct is_trivially_assignable;} & + \tcode{is_assignable_v} is \tcode{true} and the assignment, as defined by + \tcode{is_assignable}, is known to call no operation that is not + trivial\iref{term.trivial.type,special}. & + \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_copy_assignable}% +\tcode{template}\br + \tcode{struct is_trivially_copy_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_trivially_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_move_assignable}% +\tcode{template}\br + \tcode{struct is_trivially_move_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_trivially_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_destructible}% +\tcode{template}\br + \tcode{struct is_trivially_destructible;} & + \tcode{is_destructible_v} is \tcode{true} and + \tcode{remove_all_extents_t} is either a non-class type or + a class type with a trivial destructor. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_constructible}% +\tcode{template}\br + \tcode{struct is_nothrow_constructible;} & + \tcode{is_constructible_v} is \tcode{true} + and the + variable definition for \tcode{is_constructible}, as defined below, is known not to + throw any exceptions\iref{expr.unary.noexcept}. + & + \tcode{T} and all types in the template parameter pack \tcode{Args} + shall be complete types, \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_default_constructible}% +\tcode{template}\br + \tcode{struct is_nothrow_default_constructible;} & + \tcode{is_nothrow_constructible_v} is \tcode{true}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_copy_constructible}% +\tcode{template}\br + \tcode{struct is_nothrow_copy_constructible;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_nothrow_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_move_constructible}% +\tcode{template}\br + \tcode{struct is_nothrow_move_constructible;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_nothrow_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_assignable}% +\tcode{template}\br + \tcode{struct is_nothrow_assignable;} & + \tcode{is_assignable_v} is \tcode{true} and the assignment is known not to + throw any exceptions\iref{expr.unary.noexcept}. & + \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_copy_assignable}% +\tcode{template}\br + \tcode{struct is_nothrow_copy_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_nothrow_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_move_assignable}% +\tcode{template}\br + \tcode{struct is_nothrow_move_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_nothrow_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_swappable_with}% +\tcode{template}\br + \tcode{struct is_nothrow_swappable_with;} & + \tcode{is_swappable_with_v} is \tcode{true} and + each \tcode{swap} expression of the definition of + \tcode{is_swappable_with} is known not to throw + any exceptions\iref{expr.unary.noexcept}. & + \tcode{T} and \tcode{U} shall be complete types, + \cv{}~\keyword{void}, or + arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_swappable}% +\tcode{template}\br + \tcode{struct is_nothrow_swappable;} & + For a referenceable type \tcode{T}, + the same result as \tcode{is_nothrow_swappable_with_v}, + otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or + an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_destructible}% +\tcode{template}\br + \tcode{struct is_nothrow_destructible;} & + \tcode{is_destructible_v} is \tcode{true} and the indicated destructor is known + not to throw any exceptions\iref{expr.unary.noexcept}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{has_virtual_destructor}% +\tcode{template}\br + \tcode{struct has_virtual_destructor;} & + \tcode{T} has a virtual destructor\iref{class.dtor} & + If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{has_unique_object_representations}% +\tcode{template}\br + \tcode{struct has_unique_object_representations;} & + For an array type \tcode{T}, the same result as + \tcode{has_unique_object_representations_v>}, + otherwise \seebelow. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, or + an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{reference_constructs_from_temporary}% +\tcode{template}\br + \tcode{struct reference_constructs_from_temporary;} & + \tcode{conjunction_v, is_constructible>} + is \tcode{true}, and + the initialization \tcode{T t(\exposidnc{VAL});} binds \tcode{t} to + a temporary object whose lifetime is extended\iref{class.temporary}. & + \tcode{T} and \tcode{U} shall be + complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{reference_converts_from_temporary}% +\tcode{template}\br + \tcode{struct reference_converts_from_temporary;} & + \tcode{conjunction_v, is_convertible>} is \tcode{true}, + and the initialization \tcode{T t = \exposidnc{VAL};} binds \tcode{t} to + a temporary object whose lifetime is extended\iref{class.temporary}. & + \tcode{T} and \tcode{U} shall be + complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + +\end{libreqtab3b} + +\pnum +\begin{example} +\begin{codeblock} +is_const_v // \tcode{true} +is_const_v // \tcode{false} +is_const_v // \tcode{false} +is_const_v // \tcode{false} +is_const_v // \tcode{true} +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +remove_const_t // \tcode{volatile int} +remove_const_t // \tcode{const int*} +remove_const_t // \tcode{const int\&} +remove_const_t // \tcode{int[3]} +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +// Given: +struct P final { }; +union U1 { }; +union U2 final { }; + +// the following assertions hold: +static_assert(!is_final_v); +static_assert(is_final_v

); +static_assert(!is_final_v); +static_assert(is_final_v); +\end{codeblock} +\end{example} + +\indexlibraryglobal{is_constructible}% +\pnum +The predicate condition for a template specialization +\tcode{is_constructible} shall be satisfied if and only if the +following variable definition would be well-formed for some invented variable \tcode{t}: + +\begin{codeblock} +T t(declval()...); +\end{codeblock} + +\begin{note} +These tokens are never interpreted as a function declaration. +\end{note} +Access checking is performed as if in a context unrelated to \tcode{T} +and any of the \tcode{Args}. Only the validity of the immediate context of the +variable initialization is considered. +\begin{note} +The evaluation of the +initialization can result in side effects such as the instantiation of class +template specializations and function template specializations, the generation +of implicitly-defined functions, and so on. Such side effects are not in the +``immediate context'' and can result in the program being ill-formed. +\end{note} + +\indexlibraryglobal{has_unique_object_representations}% +\pnum +The predicate condition for a template specialization +\tcode{has_unique_object_representations} +shall be satisfied if and only if: +\begin{itemize} +\item \tcode{T} is trivially copyable, and +\item any two objects of type \tcode{T} with the same value +have the same object representation, where +two objects of array or non-union class type are considered to have the same value +if their respective sequences of direct subobjects have the same values, and +two objects of union type are considered to have the same value +if they have the same active member and the corresponding members have the same value. +\end{itemize} +The set of scalar types for which this condition holds is +\impldef{which scalar types have unique object representations}. +\begin{note} +If a type has padding bits, the condition does not hold; +otherwise, the condition holds true for integral types. +\end{note} + +\rSec2[meta.unary.prop.query]{Type property queries} + +\pnum +This subclause contains templates that may be used to query +properties of types at compile time. + +\begin{libreqtab2a}{Type property queries}{meta.unary.prop.query} +\\ \topline +\lhdr{Template} & \rhdr{Value} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Value} \\ \capsep +\endhead + +\indexlibraryglobal{alignment_of}% +\tcode{template\br + struct alignment_of;} & + \tcode{alignof(T)}.\br + \mandates + \tcode{alignof(T)} is a valid expression\iref{expr.alignof} \\ \rowsep + +\indexlibraryglobal{rank}% +\tcode{template\br + struct rank;} & + If \tcode{T} names an array type, an integer value representing + the number of dimensions of \tcode{T}; otherwise, 0. \\ \rowsep + +\indexlibraryglobal{extent}% +\tcode{template\br + struct extent;} & + If \tcode{T} is not an array type, or if it has rank less + than or equal to \tcode{I}, or if \tcode{I} is 0 and \tcode{T} + has type ``array of unknown bound of \tcode{U}'', then + 0; otherwise, the bound\iref{dcl.array} of the $\tcode{I}^\text{th}$ dimension of +\tcode{T}, where indexing of \tcode{I} is zero-based \\ +\end{libreqtab2a} + +\pnum +Each of these templates shall be a \oldconcept{UnaryTypeTrait}\iref{meta.rqmts} with a +base characteristic of \tcode{integral_constant}. + +\pnum +\begin{example} +\begin{codeblock} +// the following assertions hold: +assert(rank_v == 0); +assert(rank_v == 1); +assert(rank_v == 2); +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +// the following assertions hold: +assert(extent_v == 0); +assert(extent_v == 2); +assert(extent_v == 2); +assert(extent_v == 0); +assert((extent_v) == 0); +assert((extent_v) == 0); +assert((extent_v) == 4); +assert((extent_v) == 4); +\end{codeblock} +\end{example} + +\rSec2[meta.rel]{Relationships between types} + +\pnum +This subclause contains templates that may be used to query +relationships between types at compile time. + +\pnum +Each of these templates shall be a +\oldconcept{BinaryTypeTrait}\iref{meta.rqmts} +with a base characteristic of +\tcode{true_type} if the corresponding condition is true, otherwise +\tcode{false_type}. + +\begin{libreqtab3f}{Type relationship predicates}{meta.rel} +\\ \topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep +\endhead +\tcode{template}\br + \tcode{struct is_same;} & + \tcode{T} and \tcode{U} name the same type with the same cv-qualifications & \\ \rowsep + +\indexlibraryglobal{is_base_of}% +\tcode{template}\br + \tcode{struct is_base_of;} & + \tcode{Base} is a base class of \tcode{Derived}\iref{class.derived} + without regard to cv-qualifiers + or \tcode{Base} and \tcode{Derived} are not unions and + name the same class type + without regard to cv-qualifiers & + If \tcode{Base} and + \tcode{Derived} are non-union class types and are +not possibly cv-qualified versions of the same type, + \tcode{Derived} shall be a complete + type. + \begin{tailnote} +Base classes that are private, protected, or ambiguous + are, nonetheless, base classes. +\end{tailnote} +\\ \rowsep + +\indexlibraryglobal{is_convertible}% +\tcode{template}\br + \tcode{struct is_convertible;} & + \seebelow & + \tcode{From} and \tcode{To} shall be complete types, + \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_convertible}% +\tcode{template}\br + \tcode{struct is_nothrow_convertible;} & + \tcode{is_convertible_v} is \tcode{true} and + the conversion, as defined by \tcode{is_convertible}, + is known not to throw any exceptions\iref{expr.unary.noexcept} & + \tcode{From} and \tcode{To} shall be complete types, + \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_layout_compatible}% +\tcode{template}\br + \tcode{struct is_layout_compatible;} & + \tcode{T} and \tcode{U} are layout-compatible\iref{term.layout.compatible.type} & + \tcode{T} and \tcode{U} shall be complete types, + \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_pointer_interconvertible_base_of}% +\tcode{template}\br + \tcode{struct is_pointer_interconvertible_base_of;} & + \tcode{Derived} is unambiguously derived from \tcode{Base} + without regard to cv-qualifiers, + and each object of type \tcode{Derived} + is pointer-interconvertible\iref{basic.compound} with + its \tcode{Base} subobject, + or \tcode{Base} and \tcode{Derived} are not unions + and name the same class type + without regard to cv-qualifiers. & + If \tcode{Base} and \tcode{Derived} are non-union class types + and are not (possibly cv-qualified versions of) the same type, + \tcode{Derived} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{is_invocable}% +\tcode{template}\br + \tcode{struct is_invocable;} & + The expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand} & + \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} + shall be complete types, \cv{}~\keyword{void}, or + arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_invocable_r}% +\tcode{template}\br + \tcode{struct is_invocable_r;} & + The expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + is well-formed when treated as an unevaluated operand & + \tcode{Fn}, \tcode{R}, and all types in the template parameter pack \tcode{ArgTypes} + shall be complete types, \cv{}~\keyword{void}, or + arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_invocable}% +\tcode{template}\br + \tcode{struct is_nothrow_invocable;} & + \tcode{is_invocable_v<}\br\tcode{Fn, ArgTypes...>} is \tcode{true} and + the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + is known not to throw any exceptions\iref{expr.unary.noexcept} & + \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} + shall be complete types, \cv{}~\keyword{void}, or + arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_invocable_r}% +\tcode{template}\br + \tcode{struct is_nothrow_invocable_r;} & + \tcode{is_invocable_r_v<}\br\tcode{R, Fn, ArgTypes...>} is \tcode{true} and + the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + is known not to throw any exceptions\iref{expr.unary.noexcept} & + \tcode{Fn}, \tcode{R}, and all types in the template parameter pack \tcode{ArgTypes} + shall be complete types, \cv{}~\keyword{void}, or + arrays of unknown bound. \\ +\end{libreqtab3f} + +\pnum +For the purpose of defining the templates in this subclause, +a function call expression \tcode{declval()} for any type \tcode{T} +is considered to be a trivial\iref{term.trivial.type,special} function call +that is not an odr-use\iref{term.odr.use} of \tcode{declval} +in the context of the corresponding definition +notwithstanding the restrictions of~\ref{declval}. + +\pnum +\begin{example} +\begin{codeblock} +struct B {}; +struct B1 : B {}; +struct B2 : B {}; +struct D : private B1, private B2 {}; + +is_base_of_v // \tcode{true} +is_base_of_v // \tcode{true} +is_base_of_v // \tcode{true} +is_base_of_v // \tcode{true} +is_base_of_v // \tcode{false} +is_base_of_v // \tcode{false} +is_base_of_v // \tcode{false} +is_base_of_v // \tcode{false} +\end{codeblock} +\end{example} + +\indexlibraryglobal{is_convertible}% +\pnum +The predicate condition for a template specialization \tcode{is_convertible} +shall be satisfied if and only if the return expression in the following code would be +well-formed, including any implicit conversions to the return type of the function: + +\begin{codeblock} +To test() { + return declval(); +} +\end{codeblock} + +\begin{note} +This requirement gives well-defined results for reference types, +array types, function types, and \cv{}~\keyword{void}. +\end{note} +Access checking is performed +in a context unrelated to \tcode{To} and \tcode{From}. Only the validity of +the immediate context of the \grammarterm{expression} of the \tcode{return} statement\iref{stmt.return} +(including initialization of the returned object or reference) is considered. +\begin{note} +The +initialization can result in side effects such as the +instantiation of class template specializations and function template +specializations, the generation of implicitly-defined functions, and so on. Such +side effects are not in the ``immediate context'' and can result in the program +being ill-formed. +\end{note} + +\rSec2[meta.trans]{Transformations between types} + +\rSec3[meta.trans.general]{General} +\pnum +Subclause \ref{meta.trans} contains templates that may be used to transform one +type to another following some predefined rule. + +\pnum +Each of the templates in \ref{meta.trans} shall be a +\oldconcept{TransformationTrait}\iref{meta.rqmts}. + +\rSec3[meta.trans.cv]{Const-volatile modifications} + +\begin{libreqtab2a}{Const-volatile modifications}{meta.trans.cv} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{remove_const}% +\tcode{template\br + struct remove_const;} & + The member typedef \tcode{type} names + the same type as \tcode{T} + except that any top-level const-qualifier has been removed. + \begin{tailexample} +\tcode{remove_const_t} evaluates + to \tcode{volatile int}, whereas \tcode{remove_const_t} evaluates to + \tcode{const int*}. +\end{tailexample} +\\ \rowsep + +\indexlibraryglobal{remove_volatile}% +\tcode{template\br + struct remove_volatile;} & + The member typedef \tcode{type} names + the same type as \tcode{T} + except that any top-level volatile-qualifier has been removed. + \begin{tailexample} +\tcode{remove_volatile_t} + evaluates to \tcode{const int}, + whereas \tcode{remove_volatile_t} evaluates to \tcode{volatile int*}. + \end{tailexample} +\\ \rowsep + +\indexlibraryglobal{remove_cv}% +\tcode{template\br + struct remove_cv;} & + The member typedef \tcode{type} shall be the same as \tcode{T} + except that any top-level cv-qualifier has been removed. + \begin{tailexample} +\tcode{remove_cv_t} + evaluates to \tcode{int}, whereas \tcode{remove_cv_t} + evaluates to \tcode{const volatile int*}. +\end{tailexample} +\\ \rowsep + +\indexlibraryglobal{add_const}% +\tcode{template\br + struct add_const;} & + If \tcode{T} is a reference, function, or top-level const-qualified + type, then \tcode{type} names + the same type as \tcode{T}, otherwise + \tcode{T const}. \\ \rowsep + +\indexlibraryglobal{add_volatile}% +\tcode{template\br + struct add_volatile;} & + If \tcode{T} is a reference, function, or top-level volatile-qualified + type, then \tcode{type} names + the same type as \tcode{T}, otherwise + \tcode{T volatile}. \\ \rowsep + +\indexlibraryglobal{add_cv}% +\tcode{template\br + struct add_cv;} & + The member typedef \tcode{type} names + the same type as + \tcode{add_const_t>}. \\ +\end{libreqtab2a} + +\rSec3[meta.trans.ref]{Reference modifications} + +\begin{libreqtab2a}{Reference modifications}{meta.trans.ref} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{remove_reference}% +\tcode{template\br + struct remove_reference;} & + If \tcode{T} has type ``reference to \tcode{T1}'' then the + member typedef \tcode{type} names \tcode{T1}; + otherwise, \tcode{type} names \tcode{T}.\\ \rowsep + +\indexlibraryglobal{add_lvalue_reference}% +\tcode{template\br + struct add_lvalue_reference;} & + If \tcode{T} names a referenceable type\iref{defns.referenceable} then + the member typedef \tcode{type} names \tcode{T\&}; + otherwise, \tcode{type} names \tcode{T}. + \begin{tailnote} + This rule reflects the semantics of reference collapsing\iref{dcl.ref}. + \end{tailnote} +\\ \rowsep + +\indexlibraryglobal{add_rvalue_reference}% +\tcode{template}\br + \tcode{struct add_rvalue_reference;} & + If \tcode{T} names a referenceable type then + the member typedef \tcode{type} names \tcode{T\&\&}; + otherwise, \tcode{type} names \tcode{T}. + \begin{tailnote} +This rule reflects the semantics of reference collapsing\iref{dcl.ref}. + For example, when a type \tcode{T} names a type \tcode{T1\&}, the type + \tcode{add_rvalue_reference_t} is not an rvalue reference. + \end{tailnote} +\\ +\end{libreqtab2a} + +\rSec3[meta.trans.sign]{Sign modifications} +\begin{libreqtab2a}{Sign modifications}{meta.trans.sign} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{make_signed}% +\tcode{template}\br + \tcode{struct make_signed;} & + If \tcode{T} names a (possibly cv-qualified) signed integer + type\iref{basic.fundamental} then the member typedef + \tcode{type} names the type \tcode{T}; otherwise, + if \tcode{T} names a (possibly cv-qualified) unsigned integer + type then \tcode{type} names the corresponding + signed integer type, with the same cv-qualifiers as \tcode{T}; + otherwise, \tcode{type} names the signed integer type with smallest + rank\iref{conv.rank} for which + \tcode{sizeof(T) == sizeof(type)}, with the same + cv-qualifiers as \tcode{T}.\br + \mandates \tcode{T} is an integral or enumeration type + other than \cv~\tcode{bool}.\\ \rowsep + +\indexlibraryglobal{make_unsigned}% +\tcode{template}\br + \tcode{struct make_unsigned;} & + If \tcode{T} names a (possibly cv-qualified) unsigned integer + type\iref{basic.fundamental} then the member typedef + \tcode{type} names the type \tcode{T}; otherwise, + if \tcode{T} names a (possibly cv-qualified) signed integer + type then \tcode{type} names the corresponding + unsigned integer type, with the same cv-qualifiers as \tcode{T}; + otherwise, \tcode{type} names the unsigned integer type with smallest + rank\iref{conv.rank} for which + \tcode{sizeof(T) == sizeof(type)}, with the same + cv-qualifiers as \tcode{T}.\br + \mandates \tcode{T} is an integral or enumeration type + other than \cv~\tcode{bool}.\\ +\end{libreqtab2a} + +\rSec3[meta.trans.arr]{Array modifications} +\begin{libreqtab2a}{Array modifications}{meta.trans.arr} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{remove_extent}% +\tcode{template\br + struct remove_extent;} & + If \tcode{T} names a type ``array of \tcode{U}'', + the member typedef \tcode{type} shall + be \tcode{U}, otherwise \tcode{T}. + \begin{tailnote} +For multidimensional arrays, only the first array dimension is + removed. For a type ``array of \tcode{const U}'', the resulting type is + \tcode{const U}. +\end{tailnote} +\\ \rowsep + +\indexlibraryglobal{remove_all_extents}% +\tcode{template\br + struct remove_all_extents;} & + If \tcode{T} is ``multi-dimensional array of \tcode{U}'', the resulting member + typedef \tcode{type} is \tcode{U}, otherwise \tcode{T}. \\ +\end{libreqtab2a} + +\pnum +\begin{example} +\begin{codeblock} +// the following assertions hold: +assert((is_same_v, int>)); +assert((is_same_v, int>)); +assert((is_same_v, int[3]>)); +assert((is_same_v, int[3]>)); +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +// the following assertions hold: +assert((is_same_v, int>)); +assert((is_same_v, int>)); +assert((is_same_v, int>)); +assert((is_same_v, int>)); +\end{codeblock} +\end{example} + +\rSec3[meta.trans.ptr]{Pointer modifications} +\begin{libreqtab2a}{Pointer modifications}{meta.trans.ptr} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{remove_pointer}% +\tcode{template\br + struct remove_pointer;} & + If \tcode{T} has type ``(possibly cv-qualified) pointer + to \tcode{T1}'' then the member typedef \tcode{type} + names \tcode{T1}; otherwise, it names \tcode{T}.\\ \rowsep + +\indexlibraryglobal{add_pointer}% +\tcode{template\br + struct add_pointer;} & + If \tcode{T} names a referenceable type\iref{defns.referenceable} or a + \cv{}~\keyword{void} type then + the member typedef \tcode{type} names the same type as + \tcode{remove_reference_t*}; + otherwise, \tcode{type} names \tcode{T}. \\ +\end{libreqtab2a} + +\rSec3[meta.trans.other]{Other transformations} + +\begin{libreqtab2a}{Other transformations}{meta.trans.other} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{type_identity}% +\tcode{template\br + struct type_identity;} + & + The member typedef \tcode{type} names the type \tcode{T}. \\ \rowsep + +\indexlibraryglobal{remove_cvref}% +\tcode{template\br struct remove_cvref;} + & + The member typedef \tcode{type} names the same type as + \tcode{remove_cv_t>}. + \\ \rowsep + +\indexlibraryglobal{decay}% +\tcode{template\br struct decay;} + & + Let \tcode{U} be \tcode{remove_reference_t}. If \tcode{is_array_v} is + \tcode{true}, the member typedef \tcode{type} equals + \tcode{remove_extent_t*}. If \tcode{is_function_v} is \tcode{true}, + the member typedef \tcode{type} equals \tcode{add_pointer_t}. Otherwise + the member typedef \tcode{type} equals \tcode{remove_cv_t}. +\begin{tailnote} +This behavior is similar to the lvalue-to-rvalue\iref{conv.lval}, +array-to-pointer\iref{conv.array}, and function-to-pointer\iref{conv.func} +conversions applied when an lvalue is used as an rvalue, but also +strips cv-qualifiers from class types in order to more closely model by-value +argument passing. +\end{tailnote} + \\ \rowsep + +\indexlibraryglobal{enable_if}% +\tcode{template} \tcode{struct enable_if;} + & + If \tcode{B} is \tcode{true}, the member typedef \tcode{type} + shall equal \tcode{T}; otherwise, there shall be no member + \tcode{type}. \\ \rowsep + +\tcode{template}\br + \tcode{struct conditional;} + & + If \tcode{B} is \tcode{true}, the member typedef \tcode{type} shall equal \tcode{T}. + If \tcode{B} is \tcode{false}, the member typedef \tcode{type} shall equal \tcode{F}. \\ \rowsep + + \tcode{template} \tcode{struct common_type;} + & + Unless this trait is specialized (as specified in Note B, below), + the member \tcode{type} is defined or omitted as specified in Note A, below. + If it is omitted, there shall be no member \tcode{type}. + Each type in the template parameter pack \tcode{T} shall be + complete, \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{basic_common_reference}% +\tcode{template class,} + \hspace*{2ex}\tcode{template class>} + \keyword{struct} + \hspace*{2ex}\tcode{basic_common_reference;} + & + Unless this trait is specialized (as specified in Note D, below), + there shall be no member \tcode{type}. \\ \rowsep + +\indexlibraryglobal{common_reference}% +\tcode{template} \tcode{struct common_reference;} + & + The member \grammarterm{typedef-name} \tcode{type} is defined or omitted + as specified in Note C, below. Each type in the parameter pack \tcode{T} shall + be complete or \cv{} \keyword{void}. \\ \rowsep + +\indexlibraryglobal{underlying_type}% +\tcode{template}\br + \tcode{struct underlying_type;} + & + If \tcode{T} is an enumeration type, the member typedef \tcode{type} names + the underlying type of \tcode{T}\iref{dcl.enum}; + otherwise, there is no member \tcode{type}.\br + \mandates \tcode{T} is not an incomplete enumeration type. \\ \rowsep + +\tcode{template}\br + \tcode{struct invoke_result;} + & + If the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand}, + the member typedef \tcode{type} names the type + \tcode{decltype(\placeholdernc{INVOKE}(declval(), declval()...))}; + otherwise, there shall be no member \tcode{type}. Access checking is + performed as if in a context unrelated to \tcode{Fn} and + \tcode{ArgTypes}. Only the validity of the immediate context of the + expression is considered. + \begin{note} + The compilation of the expression can result in side effects such as + the instantiation of class template specializations and function + template specializations, the generation of implicitly-defined + functions, and so on. Such side effects are not in the ``immediate + context'' and can result in the program being ill-formed. + \end{note} + \expects \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} + are complete types, \cv{}~\keyword{void}, or arrays of + unknown bound.\\ \rowsep + +\indexlibraryglobal{unwrap_reference}% +\tcode{template} \tcode{struct unwrap_reference;} + & + If \tcode{T} is + a specialization \tcode{reference_wrapper} for some type \tcode{X}, + the member typedef \tcode{type} of \tcode{unwrap_reference} is \tcode{X\&}, + otherwise it is \tcode{T}. \\ \rowsep + +\indexlibraryglobal{unwrap_ref_decay}% +\tcode{template} \tcode{unwrap_ref_decay;} + & + The member typedef \tcode{type} of \tcode{unwrap_ref_decay} + denotes the type \tcode{unwrap_reference_t>}.\\ +\end{libreqtab2a} + +\pnum +In addition to being available via inclusion +of the \tcode{} header, the templates +\tcode{unwrap_reference}, +\tcode{unwrap_ref_decay}, +\tcode{unwrap_reference_t}, and +\tcode{unwrap_ref_decay_t} +are available +when the header \tcode{}\iref{functional.syn} is included. + +\indexlibraryglobal{common_type}% +\pnum +Let: +\begin{itemize} +\item \tcode{\placeholdernc{CREF}(A)} be + \tcode{add_lvalue_reference_t{}>}, +\item \tcode{\placeholdernc{XREF}(A)} denote a unary alias template \tcode{T} + such that \tcode{T} denotes the same type as \tcode{U} with the addition + of \tcode{A}'s cv and reference qualifiers, for a non-reference cv-unqualified + type \tcode{U}, +\item \tcode{\placeholdernc{COPYCV}(FROM, TO)} be an alias for type \tcode{TO} + with the addition of \tcode{FROM}'s top-level cv-qualifiers, + \begin{example} + \tcode{\placeholdernc{COPYCV}(const int, volatile short)} is an alias for + \tcode{const volatile short}. + \end{example} +\item \tcode{\placeholdernc{COND-RES}(X, Y)} be + \tcode{decltype(false ?\ declval()() :\ declval()())}. +\end{itemize} +Given types \tcode{A} and \tcode{B}, +let \tcode{X} be \tcode{remove_reference_t}, +let \tcode{Y} be \tcode{remove_reference_t}, and +let \tcode{\placeholdernc{COMMON-\brk{}REF}(A, B)} be: +\begin{itemize} +\item If \tcode{A} and \tcode{B} are both lvalue reference types, + \tcode{\placeholdernc{COMMON-REF}(A, B)} is + \tcode{\placeholdernc{COND-RES}(\placeholdernc{COPYCV}(X, Y) \&, + \placeholdernc{COPYCV}(\brk{}Y, X) \&)} if that type exists + and is a reference type. +\item Otherwise, let \tcode{C} be + \tcode{remove_reference_t<\placeholdernc{COMMON-REF}(X\&, Y\&)>\&\&}. + If \tcode{A} and \tcode{B} are both rvalue reference types, + \tcode{C} is well-formed, and + \tcode{is_convertible_v \&\& is_convertible_v} is \tcode{true}, + then \tcode{\placeholdernc{COMMON-REF}(A, B)} is \tcode{C}. +\item Otherwise, let \tcode{D} be + \tcode{\placeholdernc{COMMON-REF}(const X\&, Y\&)}. If \tcode{A} is an rvalue + reference and \tcode{B} is an lvalue reference and \tcode{D} is + well-formed and \tcode{is_convertible_v} is + \tcode{true}, then \tcode{\placeholdernc{COMMON-REF}(A, B)} is \tcode{D}. +\item Otherwise, if \tcode{A} is an lvalue reference and \tcode{B} + is an rvalue reference, then \tcode{\placeholdernc{COMMON-REF}(A, B)} is + \tcode{\placeholdernc{COMMON-REF}(B, A)}. +\item Otherwise, \tcode{\placeholdernc{COMMON-REF}(A, B)} is ill-formed. +\end{itemize} + +If any of the types computed above is ill-formed, then +\tcode{\placeholdernc{COMMON-REF}(A, B)} is ill-formed. + +\pnum +Note A: +For the \tcode{common_type} trait applied to a template parameter pack \tcode{T} of types, +the member \tcode{type} shall be either defined or not present as follows: + +\begin{itemize} +\item If \tcode{sizeof...(T)} is zero, there shall be no member \tcode{type}. + +\item If \tcode{sizeof...(T)} is one, let \tcode{T0} denote the sole type +constituting the pack \tcode{T}. +The member \grammarterm{typedef-name} \tcode{type} shall denote the same +type, if any, as \tcode{common_type_t}; +otherwise there shall be no member \tcode{type}. + +\item If \tcode{sizeof...(T)} is two, +let the first and second types constituting \tcode{T} be denoted +by \tcode{T1} and \tcode{T2}, respectively, and +let \tcode{D1} and \tcode{D2} denote +the same types as \tcode{decay_t} and \tcode{decay_t}, respectively. + \begin{itemize} + \item If \tcode{is_same_v} is \tcode{false} or + \tcode{is_same_v} is \tcode{false}, + let \tcode{C} denote the same type, if any, + as \tcode{common_type_t}. + \item + \begin{note} + None of the following will apply if there is a specialization + \tcode{common_type}. + \end{note} + \item Otherwise, if +\begin{codeblock} +decay_t() : declval())> +\end{codeblock} + denotes a valid type, let \tcode{C} denote that type. + \item Otherwise, if + \tcode{\placeholdernc{COND-RES}(\placeholdernc{CREF}(D1), + \placeholdernc{CREF}(D2))} + denotes a type, let \tcode{C} denote the type + \tcode{decay_t<\placeholdernc{COND-RES}(\placeholdernc{CREF}(D1), + \placeholdernc{CREF}(D2))>}. + \end{itemize} +In either case, the member \grammarterm{typedef-name} \tcode{type} shall denote +the same type, if any, as \tcode{C}. +Otherwise, there shall be no member \tcode{type}. + +\item If \tcode{sizeof...(T)} is greater than two, +let \tcode{T1}, \tcode{T2}, and \tcode{R}, respectively, +denote the first, second, and (pack of) remaining types constituting \tcode{T}. +Let \tcode{C} denote the same type, if any, as \tcode{common_type_t}. +If there is such a type \tcode{C}, the member \grammarterm{typedef-name} \tcode{type} +shall denote the same type, if any, as \tcode{common_type_t}. +Otherwise, there shall be no member \tcode{type}. +\end{itemize} + +\pnum +Note B: Notwithstanding the provisions of \ref{meta.type.synop}, and +pursuant to \ref{namespace.std}, +a program may specialize \tcode{common_type} +for types \tcode{T1} and \tcode{T2} such that +\tcode{is_same_v>} and +\tcode{is_same_v>} are each \tcode{true}. +\begin{note} +Such specializations are needed when only explicit conversions +are desired between the template arguments. +\end{note} +Such a specialization need not have a member named \tcode{type}, +but if it does, +the \grammarterm{qualified-id} \tcode{common_type::type} shall denote +a cv-unqualified non-reference type +to which each of the types \tcode{T1} and \tcode{T2} is explicitly convertible. +Moreover, \tcode{common_type_t} shall denote +the same type, if any, as does \tcode{common_type_t}. +No diagnostic is required for a violation of this Note's rules. + +\pnum +Note C: For the \tcode{common_reference} trait applied to a parameter pack +\tcode{T} of types, the member \tcode{type} shall be either defined or not +present as follows: +\begin{itemize} +\item If \tcode{sizeof...(T)} is zero, there shall be no member \tcode{type}. + +\item Otherwise, if \tcode{sizeof...(T)} is one, let \tcode{T0} denote the sole + type in the pack \tcode{T}. The member typedef \tcode{type} shall denote the + same type as \tcode{T0}. + +\item Otherwise, if \tcode{sizeof...(T)} is two, let \tcode{T1} and \tcode{T2} + denote the two types in the pack \tcode{T}. Then + \begin{itemize} + \item If \tcode{T1} and \tcode{T2} are reference types and + \tcode{\placeholdernc{COMMON-REF}(T1, T2)} is well-formed, then the member + typedef \tcode{type} denotes that type. + + \item Otherwise, if + \tcode{basic_common_reference, remove_cvref_t, + \brk{}\placeholdernc{XREF}(\brk{}T1), \placeholdernc{XREF}(T2)>::type} + is well-formed, then the member typedef \tcode{type} denotes that type. + + \item Otherwise, if \tcode{\placeholdernc{COND-RES}(T1, T2)} is well-formed, + then the member typedef \tcode{type} denotes that type. + + \item Otherwise, if \tcode{common_type_t} is well-formed, then the + member typedef \tcode{type} denotes that type. + + \item Otherwise, there shall be no member \tcode{type}. + \end{itemize} + +\item Otherwise, if \tcode{sizeof...(T)} is greater than two, let \tcode{T1}, + \tcode{T2}, and \tcode{Rest}, respectively, denote the first, second, and + (pack of) remaining types comprising \tcode{T}. Let \tcode{C} be the type + \tcode{common_reference_t}. Then: + \begin{itemize} + \item If there is such a type \tcode{C}, the member typedef \tcode{type} shall + denote the same type, if any, as \tcode{common_reference_t}. + + \item Otherwise, there shall be no member \tcode{type}. + \end{itemize} +\end{itemize} + +\pnum +Note D: Notwithstanding the provisions of \ref{meta.type.synop}, and +pursuant to \ref{namespace.std}, a program may partially specialize +\tcode{basic_common_reference} +for types \tcode{T} and \tcode{U} such that +\tcode{is_same_v>} and +\tcode{is_same_v>} are each \tcode{true}. +\begin{note} +Such specializations +can be used to influence the result of \tcode{common_reference}, and +are needed when only explicit conversions are desired +between the template arguments. +\end{note} +Such a specialization need not have a member named \tcode{type}, but if it does, +the \grammarterm{qualified-id} +\tcode{basic_common_reference::type} +shall denote a type +to which each of the types \tcode{TQual} and +\tcode{UQual} is convertible. +Moreover, \tcode{basic_common_reference::type} shall denote +the same type, if any, as does +\tcode{basic_common_reference::type}. +No diagnostic is required for a violation of these rules. + +\pnum +\begin{example} +Given these definitions: +\begin{codeblock} +using PF1 = bool (&)(); +using PF2 = short (*)(long); + +struct S { + operator PF2() const; + double operator()(char, int&); + void fn(long) const; + char data; +}; + +using PMF = void (S::*)(long) const; +using PMD = char S::*; +\end{codeblock} +the following assertions will hold: +\begin{codeblock} +static_assert(is_same_v, short>); +static_assert(is_same_v, double>); +static_assert(is_same_v, bool>); +static_assert(is_same_v, int>, void>); +static_assert(is_same_v, char&&>); +static_assert(is_same_v, const char&>); +\end{codeblock} +\end{example} + +\rSec2[meta.logical]{Logical operator traits} + +\pnum +This subclause describes type traits for applying logical operators +to other type traits. + +\indexlibraryglobal{conjunction}% +\begin{itemdecl} +template struct conjunction : @\seebelow@ { }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The class template \tcode{conjunction} +forms the logical conjunction of its template type arguments. + +\pnum +For a specialization \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>}, +if there is a template type argument $\tcode{B}_{i}$ +for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{false}, +then instantiating \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>::value} +does not require the instantiation of \tcode{$\tcode{B}_{j}$::value} for $j > i$. +\begin{note} +This is analogous to the short-circuiting behavior of +the built-in operator \tcode{\&\&}. +\end{note} + +\pnum +Every template type argument +for which \tcode{$\tcode{B}_{i}$::value} is instantiated +shall be usable as a base class and +shall have a member \tcode{value} which +is convertible to \tcode{bool}, +is not hidden, and +is unambiguously available in the type. + +\pnum +The specialization \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} +has a public and unambiguous base that is either +\begin{itemize} +\item +the first type $\tcode{B}_{i}$ in the list \tcode{true_type, $\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} +for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{false}, or +\item +if there is no such $\tcode{B}_{i}$, the last type in the list. +\end{itemize} +\begin{note} +This means a specialization of \tcode{conjunction} +does not necessarily inherit from +either \tcode{true_type} or \tcode{false_type}. +\end{note} + +\pnum +The member names of the base class, other than \tcode{conjunction} and +\tcode{operator=}, shall not be hidden and shall be unambiguously available +in \tcode{conjunction}. +\end{itemdescr} + +\indexlibraryglobal{disjunction}% +\begin{itemdecl} +template struct disjunction : @\seebelow@ { }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The class template \tcode{disjunction} +forms the logical disjunction of its template type arguments. + +\pnum +For a specialization \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>}, +if there is a template type argument $\tcode{B}_{i}$ +for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{true}, +then instantiating \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>::value} +does not require the instantiation of \tcode{$\tcode{B}_{j}$::value} for $j > i$. +\begin{note} +This is analogous to the short-circuiting behavior of +the built-in operator \tcode{||}. +\end{note} + +\pnum +Every template type argument +for which \tcode{$\tcode{B}_{i}$::value} is instantiated +shall be usable as a base class and +shall have a member \tcode{value} which +is convertible to \tcode{bool}, +is not hidden, and +is unambiguously available in the type. + +\pnum +The specialization \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} +has a public and unambiguous base that is either +\begin{itemize} +\item the first type $\tcode{B}_{i}$ in the list \tcode{false_type, $\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} +for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{true}, or +\item if there is no such $\tcode{B}_{i}$, the last type in the list. +\end{itemize} +\begin{note} +This means a specialization of \tcode{disjunction} +does not necessarily inherit from +either \tcode{true_type} or \tcode{false_type}. +\end{note} + +\pnum +The member names of the base class, +other than \tcode{disjunction} and \tcode{operator=}, +shall not be hidden and shall be unambiguously available in \tcode{disjunction}. +\end{itemdescr} + +\indexlibraryglobal{negation}% +\begin{itemdecl} +template struct negation : @\seebelow@ { }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The class template \tcode{negation} +forms the logical negation of its template type argument. +The type \tcode{negation} +is a \oldconcept{UnaryTypeTrait} with a base characteristic of \tcode{bool_constant}. +\end{itemdescr} + +\rSec2[meta.member]{Member relationships} + +\indexlibraryglobal{is_pointer_interconvertible_with_class} +\begin{itemdecl} +template + constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{S} is a complete type. + +\pnum +\returns +\tcode{true} if and only if + \tcode{S} is a standard-layout type, + \tcode{M} is an object type, + \tcode{m} is not null, + and each object \tcode{s} of type \tcode{S} + is pointer-interconvertible\iref{basic.compound} + with its subobject \tcode{s.*m}. +\end{itemdescr} + +\indexlibraryglobal{is_corresponding_member} +\begin{itemdecl} +template + constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{S1} and \tcode{S2} are complete types. + +\pnum +\returns +\tcode{true} if and only if + \tcode{S1} and \tcode{S2} are standard-layout struct\iref{class.prop} types, + \tcode{M1} and \tcode{M2} are object types, + \tcode{m1} and \tcode{m2} are not null, + and \tcode{m1} and \tcode{m2} point to corresponding members of + the common initial sequence\iref{class.mem} of \tcode{S1} and \tcode{S2}. +\end{itemdescr} + +\pnum +\begin{note} +The type of a pointer-to-member expression \tcode{\&C::b} +is not always a pointer to member of \tcode{C}, +leading to potentially surprising results +when using these functions in conjunction with inheritance. +\begin{example} +\begin{codeblock} +struct A { int a; }; // a standard-layout class +struct B { int b; }; // a standard-layout class +struct C: public A, public B { }; // not a standard-layout class + +static_assert( is_pointer_interconvertible_with_class( &C::b ) ); + // Succeeds because, despite its appearance, \tcode{\&C::b} has type + // ``pointer to member of \tcode{B} of type \tcode{int}''. +static_assert( is_pointer_interconvertible_with_class( &C::b ) ); + // Forces the use of class \tcode{C}, and fails. + +static_assert( is_corresponding_member( &C::a, &C::b ) ); + // Succeeds because, despite its appearance, \tcode{\&C::a} and \tcode{\&C::b} have types + // ``pointer to member of \tcode{A} of type \tcode{int}'' and + // ``pointer to member of \tcode{B} of type \tcode{int}'', respectively. +static_assert( is_corresponding_member( &C::a, &C::b ) ); + // Forces the use of class \tcode{C}, and fails. +\end{codeblock} +\end{example} +\end{note} + +\rSec2[meta.const.eval]{Constant evaluation context} +\begin{itemdecl} +constexpr bool is_constant_evaluated() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if consteval { + return true; +} else { + return false; +} +\end{codeblock} + +\pnum +\begin{example} +\begin{codeblock} +constexpr void f(unsigned char *p, int n) { + if (std::is_constant_evaluated()) { // should not be a constexpr if statement + for (int k = 0; k} synopsis} + +\indexheader{ratio}% +\begin{codeblockdigitsep} +namespace std { + // \ref{ratio.ratio}, class template \tcode{ratio} + template class ratio; + + // \ref{ratio.arithmetic}, ratio arithmetic + template using ratio_add = @\seebelow@; + template using ratio_subtract = @\seebelow@; + template using ratio_multiply = @\seebelow@; + template using ratio_divide = @\seebelow@; + + // \ref{ratio.comparison}, ratio comparison + template struct ratio_equal; + template struct ratio_not_equal; + template struct ratio_less; + template struct ratio_less_equal; + template struct ratio_greater; + template struct ratio_greater_equal; + + template + inline constexpr bool @\libglobal{ratio_equal_v}@ = ratio_equal::value; + template + inline constexpr bool @\libglobal{ratio_not_equal_v}@ = ratio_not_equal::value; + template + inline constexpr bool @\libglobal{ratio_less_v}@ = ratio_less::value; + template + inline constexpr bool @\libglobal{ratio_less_equal_v}@ = ratio_less_equal::value; + template + inline constexpr bool @\libglobal{ratio_greater_v}@ = ratio_greater::value; + template + inline constexpr bool @\libglobal{ratio_greater_equal_v}@ = ratio_greater_equal::value; + + // \ref{ratio.si}, convenience SI typedefs + using yocto = ratio<1, 1'000'000'000'000'000'000'000'000>; // see below + using zepto = ratio<1, 1'000'000'000'000'000'000'000>; // see below + using atto = ratio<1, 1'000'000'000'000'000'000>; + using femto = ratio<1, 1'000'000'000'000'000>; + using pico = ratio<1, 1'000'000'000'000>; + using nano = ratio<1, 1'000'000'000>; + using micro = ratio<1, 1'000'000>; + using milli = ratio<1, 1'000>; + using centi = ratio<1, 100>; + using deci = ratio<1, 10>; + using deca = ratio< 10, 1>; + using hecto = ratio< 100, 1>; + using kilo = ratio< 1'000, 1>; + using mega = ratio< 1'000'000, 1>; + using giga = ratio< 1'000'000'000, 1>; + using tera = ratio< 1'000'000'000'000, 1>; + using peta = ratio< 1'000'000'000'000'000, 1>; + using exa = ratio< 1'000'000'000'000'000'000, 1>; + using zetta = ratio< 1'000'000'000'000'000'000'000, 1>; // see below + using yotta = ratio<1'000'000'000'000'000'000'000'000, 1>; // see below +} +\end{codeblockdigitsep} + +\rSec2[ratio.ratio]{Class template \tcode{ratio}} + +\indexlibraryglobal{ratio}% +\begin{codeblock} +namespace std { + template class ratio { + public: + static constexpr intmax_t num; + static constexpr intmax_t den; + using type = ratio; + }; +} +\end{codeblock} + +\pnum +\indextext{signed integer representation!two's complement}% +If the template argument \tcode{D} is zero or the absolute values of either of the +template arguments \tcode{N} and \tcode{D} is not representable by type +\tcode{intmax_t}, the program is ill-formed. +\begin{note} +These rules ensure that infinite +ratios are avoided and that for any negative input, there exists a representable value +of its absolute value which is positive. +This excludes the most negative value. +\end{note} + +\pnum +The static data members \tcode{num} and \tcode{den} shall have the following values, +where \tcode{gcd} represents the greatest common divisor of the absolute values of +\tcode{N} and \tcode{D}: + +\begin{itemize} +\item \tcode{num} shall have the value \tcode{sign(N) * sign(D) * abs(N) / gcd}. +\item \tcode{den} shall have the value \tcode{abs(D) / gcd}. +\end{itemize} + +\rSec2[ratio.arithmetic]{Arithmetic on \tcode{ratio}{s}} + +\pnum +Each of the alias templates \tcode{ratio_add}, \tcode{ratio_subtract}, \tcode{ratio_multiply}, +and \tcode{ratio_divide} denotes the result of an arithmetic computation on two +\tcode{ratio}{s} \tcode{R1} and \tcode{R2}. With \tcode{X} and \tcode{Y} computed (in the +absence of arithmetic overflow) as specified by \tref{ratio.arithmetic}, each alias +denotes a \tcode{ratio} such that \tcode{U} is the same as \tcode{ratio::num} and +\tcode{V} is the same as \tcode{ratio::den}. + +\pnum +If it is not possible to represent \tcode{U} or \tcode{V} with \tcode{intmax_t}, the program is +ill-formed. Otherwise, an implementation should yield correct values of \tcode{U} and +\tcode{V}. If it is not possible to represent \tcode{X} or \tcode{Y} with \tcode{intmax_t}, the +program is ill-formed unless the implementation yields correct values of \tcode{U} and +\tcode{V}. + +\begin{floattable}{Expressions used to perform ratio arithmetic}{ratio.arithmetic} +{lll} +\topline +\lhdr{Type} & + \chdr{Value of \tcode{X}} & + \rhdr{Value of \tcode{Y}} \\ \rowsep + +\tcode{ratio_add} & + \tcode{R1::num * R2::den +} & + \tcode{R1::den * R2::den} \\ + & + \tcode{R2::num * R1::den} & + \\ \rowsep + +\tcode{ratio_subtract} & + \tcode{R1::num * R2::den -} & + \tcode{R1::den * R2::den} \\ + & + \tcode{R2::num * R1::den} & + \\ \rowsep + +\tcode{ratio_multiply} & + \tcode{R1::num * R2::num} & + \tcode{R1::den * R2::den} \\ \rowsep + +\tcode{ratio_divide} & + \tcode{R1::num * R2::den} & + \tcode{R1::den * R2::num} \\ +\end{floattable} + +\pnum +\begin{example} +\begin{codeblock} +static_assert(ratio_add, ratio<1, 6>>::num == 1, "1/3+1/6 == 1/2"); +static_assert(ratio_add, ratio<1, 6>>::den == 2, "1/3+1/6 == 1/2"); +static_assert(ratio_multiply, ratio<3, 2>>::num == 1, "1/3*3/2 == 1/2"); +static_assert(ratio_multiply, ratio<3, 2>>::den == 2, "1/3*3/2 == 1/2"); + +// The following cases may cause the program to be ill-formed under some implementations +static_assert(ratio_add, ratio<1, INT_MAX>>::num == 2, + "1/MAX+1/MAX == 2/MAX"); +static_assert(ratio_add, ratio<1, INT_MAX>>::den == INT_MAX, + "1/MAX+1/MAX == 2/MAX"); +static_assert(ratio_multiply, ratio>::num == 1, + "1/MAX * MAX/2 == 1/2"); +static_assert(ratio_multiply, ratio>::den == 2, + "1/MAX * MAX/2 == 1/2"); +\end{codeblock} + +\end{example} + +\rSec2[ratio.comparison]{Comparison of \tcode{ratio}{s}} + +\indexlibraryglobal{ratio_equal}% +\begin{itemdecl} +template + struct ratio_equal : bool_constant { }; +\end{itemdecl} + +\indexlibraryglobal{ratio_not_equal}% +\begin{itemdecl} +template + struct ratio_not_equal : bool_constant> { }; +\end{itemdecl} + +\indexlibraryglobal{ratio_less}% +\begin{itemdecl} +template + struct ratio_less : bool_constant<@\seebelow@> { }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +If \tcode{R1::num} $\times$ \tcode{R2::den} is less than \tcode{R2::num} $\times$ \tcode{R1::den}, +\tcode{ratio_less} shall be +derived from \tcode{bool_constant}; otherwise it shall be derived from +\tcode{bool_constant}. Implementations may use other algorithms to +compute this relationship to avoid overflow. If overflow occurs, the program is ill-formed. +\end{itemdescr} + +\indexlibraryglobal{ratio_less_equal}% +\begin{itemdecl} +template + struct ratio_less_equal : bool_constant> { }; +\end{itemdecl} + +\indexlibraryglobal{ratio_greater}% +\begin{itemdecl} +template + struct ratio_greater : bool_constant> { }; +\end{itemdecl} + +\indexlibraryglobal{ratio_greater_equal}% +\begin{itemdecl} +template + struct ratio_greater_equal : bool_constant> { }; +\end{itemdecl} + +\rSec2[ratio.si]{SI types for \tcode{ratio}} + +\pnum +For each of the \grammarterm{typedef-name}{s} \tcode{yocto}, \tcode{zepto}, +\tcode{zetta}, and \tcode{yotta}, if both of the constants used in its +specification are representable by \tcode{intmax_t}, the typedef is +defined; if either of the constants is not representable by \tcode{intmax_t}, +the typedef is not defined. diff --git a/source/modules.tex b/source/modules.tex index d22202e246..cfd4928bb7 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -149,7 +149,7 @@ \item Otherwise, if the declaration \begin{itemize} \item is a replaceable global allocation or deallocation -function (\ref{new.delete.single}, \ref{new.delete.array}), or +function\iref{new.delete.single,new.delete.array}, or \item is a \grammarterm{namespace-definition} with external linkage, or \item appears within a \grammarterm{linkage-specification}, \end{itemize} @@ -266,7 +266,7 @@ \end{example} \pnum -If the declaration is a \grammarterm{using-declaration}\iref{namespace.udecl} +If an exported declaration is a \grammarterm{using-declaration}\iref{namespace.udecl} and is not within a header unit, all entities to which all of the \grammarterm{using-declarator}{s} ultimately refer (if any) @@ -810,7 +810,7 @@ \item where definitions for inline functions and templates -must appear~(\ref{basic.def.odr}, \ref{dcl.inline}, \ref{temp.pre}), +must appear\iref{basic.def.odr,dcl.inline,temp.pre}, \item the instantiation contexts of templates @@ -858,7 +858,7 @@ \pnum During the implicit definition of -a defaulted function (\ref{special}, \ref{class.compare.default}), +a defaulted function\iref{special,class.compare.default}, the instantiation context is the union of the instantiation context from the definition of the class and the instantiation context of the program construct that diff --git a/source/numerics.tex b/source/numerics.tex index 3dbad178de..811f7d9d90 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -20,7 +20,6 @@ \ref{numeric.requirements} & Requirements & \\ \rowsep \ref{cfenv} & Floating-point environment & \tcode{} \\ \rowsep \ref{complex.numbers} & Complex numbers & \tcode{} \\ \rowsep -\ref{bit} & Bit manipulation & \tcode{} \\ \rowsep \ref{rand} & Random number generation & \tcode{} \\ \rowsep \ref{numarray} & Numeric arrays & \tcode{} \\ \rowsep \ref{c.math} & Mathematical functions for floating-point types & @@ -197,7 +196,7 @@ The specializations \tcode{complex}, \tcode{complex}, and -\tcode{complex} are literal types\iref{basic.types}. +\tcode{complex} are literal types\iref{term.literal.type}. \pnum If the result of a function is not mathematically defined or not in @@ -1274,420 +1273,6 @@ \end{itemdescr} -\rSec1[bit]{Bit manipulation} - -\rSec2[bit.general]{General} - -\pnum -The header \libheaderdef{bit} provides components to access, -manipulate and process both individual bits and bit sequences. - -\rSec2[bit.syn]{Header \tcode{} synopsis} - -\begin{codeblock} -namespace std { - // \ref{bit.cast}, \tcode{bit_cast} - template - constexpr To bit_cast(const From& from) noexcept; - - // \ref{bit.byteswap}, \tcode{byteswap} - template - constexpr T byteswap(T value) noexcept; - - // \ref{bit.pow.two}, integral powers of 2 - template - constexpr bool has_single_bit(T x) noexcept; - template - constexpr T bit_ceil(T x); - template - constexpr T bit_floor(T x) noexcept; - template - constexpr T bit_width(T x) noexcept; - - // \ref{bit.rotate}, rotating - template - [[nodiscard]] constexpr T rotl(T x, int s) noexcept; - template - [[nodiscard]] constexpr T rotr(T x, int s) noexcept; - - // \ref{bit.count}, counting - template - constexpr int countl_zero(T x) noexcept; - template - constexpr int countl_one(T x) noexcept; - template - constexpr int countr_zero(T x) noexcept; - template - constexpr int countr_one(T x) noexcept; - template - constexpr int popcount(T x) noexcept; - - // \ref{bit.endian}, endian - enum class endian { - little = @\seebelow@, - big = @\seebelow@, - native = @\seebelow@ - }; -} -\end{codeblock} - -\rSec2[bit.cast]{Function template \tcode{bit_cast}} - -\indexlibraryglobal{bit_cast}% -\begin{itemdecl} -template - constexpr To bit_cast(const From& from) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item \tcode{sizeof(To) == sizeof(From)} is \tcode{true}; -\item \tcode{is_trivially_copyable_v} is \tcode{true}; and -\item \tcode{is_trivially_copyable_v} is \tcode{true}. -\end{itemize} - -\pnum -\returns -An object of type \tcode{To}. -Implicitly creates objects nested within the result\iref{intro.object}. -Each bit of the value representation of the result -is equal to the corresponding bit in the object representation -of \tcode{from}. Padding bits of the result are unspecified. -For the result and each object created within it, -if there is no value of the object's type corresponding to the -value representation produced, the behavior is undefined. -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 -has an indeterminate value\iref{basic.indet}. -For each bit in the value representation of the result that is indeterminate, -the smallest object containing that bit has an indeterminate value; -the behavior is undefined unless that object is -of unsigned ordinary character type or \tcode{std::byte} type. -The result does not otherwise contain any indeterminate values. - -\pnum -\remarks -This function is \keyword{constexpr} if and only if -\tcode{To}, \tcode{From}, and the types of all subobjects -of \tcode{To} and \tcode{From} are types \tcode{T} such that: -\begin{itemize} -\item \tcode{is_union_v} is \tcode{false}; -\item \tcode{is_pointer_v} is \tcode{false}; -\item \tcode{is_member_pointer_v} is \tcode{false}; -\item \tcode{is_volatile_v} is \tcode{false}; and -\item \tcode{T} has no non-static data members of reference type. -\end{itemize} -\end{itemdescr} - -\rSec2[bit.byteswap]{\tcode{byteswap}} - -\indexlibraryglobal{byteswap}% -\begin{itemdecl} -template - constexpr T byteswap(T value) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} models \libconcept{integral}. - -\pnum -\mandates -\tcode{T} does not have padding bits\iref{basic.types.general}. - -\pnum -Let the sequence $R$ comprise -the bytes of the object representation of \tcode{value} in reverse order. - -\pnum -\returns -An object \tcode{v} of type \tcode{T} -such that each byte in the object representation of \tcode{v} is equal to -the byte in the corresponding position in $R$. -\end{itemdescr} - -\rSec2[bit.pow.two]{Integral powers of 2} - -\indexlibraryglobal{has_single_bit}% -\begin{itemdecl} -template - constexpr bool has_single_bit(T x) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -\tcode{true} if \tcode{x} is an integral power of two; -\tcode{false} otherwise. - -\end{itemdescr} - -\indexlibraryglobal{bit_ceil}% -\begin{itemdecl} -template - constexpr T bit_ceil(T x); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let $N$ be the smallest power of 2 greater than or equal to \tcode{x}. - -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\expects -$N$ is representable as a value of type \tcode{T}. - -\pnum -\returns -$N$. - -\pnum -\throws -Nothing. - -\pnum -\remarks -A function call expression -that violates the precondition in the \expects element -is not a core constant expression\iref{expr.const}. -\end{itemdescr} - -\indexlibraryglobal{bit_floor}% -\begin{itemdecl} -template - constexpr T bit_floor(T x) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -If \tcode{x == 0}, \tcode{0}; -otherwise the maximal value \tcode{y} -such that \tcode{has_single_bit(y)} is \tcode{true} and \tcode{y <= x}. - -\end{itemdescr} - -\indexlibraryglobal{bit_width}% -\begin{itemdecl} -template - constexpr T bit_width(T x) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -If \tcode{x == 0}, \tcode{0}; -otherwise one plus the base-2 logarithm of \tcode{x}, -with any fractional part discarded. - -\end{itemdescr} - -\rSec2[bit.rotate]{Rotating} - -\pnum -In the following descriptions, -let \tcode{N} denote \tcode{numeric_limits::digits}. - -\begin{itemdecl} -template - [[nodiscard]] constexpr T rotl(T x, int s) noexcept; -\end{itemdecl} - -\indexlibraryglobal{rotl}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -Let \tcode{r} be \tcode{s \% N}. - -\pnum -\returns -If \tcode{r} is \tcode{0}, \tcode{x}; -if \tcode{r} is positive, \tcode{(x << r) | (x >> (N - r))}; -if \tcode{r} is negative, \tcode{rotr(x, -r)}. -\end{itemdescr} - -\begin{itemdecl} -template - [[nodiscard]] constexpr T rotr(T x, int s) noexcept; -\end{itemdecl} - -\indexlibraryglobal{rotr}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -Let \tcode{r} be \tcode{s \% N}. - -\pnum -\returns -If \tcode{r} is \tcode{0}, \tcode{x}; -if \tcode{r} is positive, \tcode{(x >> r) | (x << (N - r))}; -if \tcode{r} is negative, \tcode{rotl(x, -r)}. -\end{itemdescr} - -\rSec2[bit.count]{Counting} - -\pnum -In the following descriptions, -let \tcode{N} denote \tcode{numeric_limits::digits}. - -\begin{itemdecl} -template - constexpr int countl_zero(T x) noexcept; -\end{itemdecl} - -\indexlibraryglobal{countl_zero}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -The number of consecutive \tcode{0} bits in the value of \tcode{x}, -starting from the most significant bit. -\begin{note} -Returns \tcode{N} if \tcode{x == 0}. -\end{note} -\end{itemdescr} - -\begin{itemdecl} -template - constexpr int countl_one(T x) noexcept; -\end{itemdecl} - -\indexlibraryglobal{countl_one}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -The number of consecutive \tcode{1} bits in the value of \tcode{x}, -starting from the most significant bit. -\begin{note} -Returns \tcode{N} if \tcode{x == numeric_limits::max()}. -\end{note} -\end{itemdescr} - -\begin{itemdecl} -template - constexpr int countr_zero(T x) noexcept; -\end{itemdecl} - -\indexlibraryglobal{countr_zero}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -The number of consecutive \tcode{0} bits in the value of \tcode{x}, -starting from the least significant bit. -\begin{note} -Returns \tcode{N} if \tcode{x == 0}. -\end{note} -\end{itemdescr} - -\begin{itemdecl} -template - constexpr int countr_one(T x) noexcept; -\end{itemdecl} - -\indexlibraryglobal{countr_one}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -The number of consecutive \tcode{1} bits in the value of \tcode{x}, -starting from the least significant bit. -\begin{note} -Returns \tcode{N} if \tcode{x == numeric_limits::max()}. -\end{note} -\end{itemdescr} - -\begin{itemdecl} -template - constexpr int popcount(T x) noexcept; -\end{itemdecl} - -\indexlibraryglobal{popcount}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -The number of \tcode{1} bits in the value of \tcode{x}. -\end{itemdescr} - -\rSec2[bit.endian]{Endian} - -\pnum -Two common methods of byte ordering in multibyte scalar types are big-endian -and little-endian in the execution environment. Big-endian is a format for -storage of binary data in which the most significant byte is placed first, -with the rest in descending order. Little-endian is a format for storage of -binary data in which the least significant byte is placed first, with the rest -in ascending order. This subclause describes the endianness of the scalar types -of the execution environment. - -\indexlibraryglobal{endian}% -\indexlibrarymember{little}{endian}% -\indexlibrarymember{big}{endian}% -\indexlibrarymember{native}{endian}% -\begin{itemdecl} -enum class endian { - little = @\seebelow@, - big = @\seebelow@, - native = @\seebelow@ -}; -\end{itemdecl} - -\begin{itemdescr} -\pnum -If all scalar types have size 1 byte, then all of \tcode{endian::little}, -\tcode{endian::big}, and \tcode{endian::native} have the same value. -Otherwise, \tcode{endian::little} is not equal to \tcode{endian::big}. -If all scalar types are big-endian, \tcode{endian::native} is -equal to \tcode{endian::big}. -If all scalar types are little-endian, \tcode{endian::native} is -equal to \tcode{endian::little}. -Otherwise, \tcode{endian::native} is not equal -to either \tcode{endian::big} or \tcode{endian::little}. -\end{itemdescr} - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -3010,7 +2595,8 @@ \indexlibraryglobal{linear_congruential_engine}% \indexlibrarymember{result_type}{linear_congruential_engine}% \begin{codeblock} -template +namespace std { + template class linear_congruential_engine { public: // types @@ -3047,6 +2633,7 @@ friend basic_istream& operator>>(basic_istream& is, linear_congruential_engine& x); }; +} \end{codeblock} \pnum @@ -3176,10 +2763,11 @@ \indexlibraryglobal{mersenne_twister_engine}% \indexlibrarymember{result_type}{mersenne_twister_engine}% \begin{codeblock} -template +namespace std { + template class mersenne_twister_engine { public: // types @@ -3225,6 +2813,7 @@ friend basic_istream& operator>>(basic_istream& is, mersenne_twister_engine& x); }; +} \end{codeblock} \pnum @@ -3352,7 +2941,8 @@ \indexlibraryglobal{subtract_with_carry_engine}% \indexlibrarymember{result_type}{subtract_with_carry_engine}% \begin{codeblock} -template +namespace std { + template class subtract_with_carry_engine { public: // types @@ -3389,6 +2979,7 @@ friend basic_istream& operator>>(basic_istream& is, subtract_with_carry_engine& x); }; +} \end{codeblock} \pnum @@ -3556,7 +3147,8 @@ \indexlibraryglobal{discard_block_engine}% \indexlibrarymember{result_type}{discard_block_engine}% \begin{codeblock} -template +namespace std { + template class discard_block_engine { public: // types @@ -3600,6 +3192,7 @@ Engine e; // \expos size_t n; // \expos }; +} \end{codeblock} \pnum @@ -3805,7 +3398,8 @@ \indexlibraryglobal{shuffle_order_engine}% \indexlibrarymember{result_type}{shuffle_order_engine}% \begin{codeblock} -template +namespace std { + template class shuffle_order_engine { public: // types @@ -3849,6 +3443,7 @@ result_type V[k]; // \expos result_type Y; // \expos }; +} \end{codeblock} \pnum @@ -4085,29 +3680,31 @@ \indexlibraryglobal{random_device}% \indexlibrarymember{result_type}{random_device}% \begin{codeblock} -class random_device { -public: - // types - using result_type = unsigned int; +namespace std { + class random_device { + public: + // types + using result_type = unsigned int; - // generator characteristics - static constexpr result_type min() { return numeric_limits::min(); } - static constexpr result_type max() { return numeric_limits::max(); } + // generator characteristics + static constexpr result_type min() { return numeric_limits::min(); } + static constexpr result_type max() { return numeric_limits::max(); } - // constructors - random_device() : random_device(@\textit{implementation-defined}@) {} - explicit random_device(const string& token); + // constructors + random_device() : random_device(@\textit{implementation-defined}@) {} + explicit random_device(const string& token); - // generating functions - result_type operator()(); + // generating functions + result_type operator()(); - // property functions - double entropy() const noexcept; + // property functions + double entropy() const noexcept; - @\textit{// no copy functions}@ - random_device(const random_device&) = delete; - void operator=(const random_device&) = delete; -}; + @\textit{// no copy functions}@ + random_device(const random_device&) = delete; + void operator=(const random_device&) = delete; + }; +} \end{codeblock} @@ -4202,34 +3799,36 @@ \indexlibraryglobal{seed_seq}% \indexlibrarymember{result_type}{seed_seq}% \begin{codeblock} -class seed_seq { -public: - // types - using result_type = uint_least32_t; - - // constructors - seed_seq() noexcept; - template - seed_seq(initializer_list il); - template - seed_seq(InputIterator begin, InputIterator end); - - // generating functions - template - void generate(RandomAccessIterator begin, RandomAccessIterator end); - - // property functions - size_t size() const noexcept; - template - void param(OutputIterator dest) const; - - // no copy functions - seed_seq(const seed_seq&) = delete; - void operator=(const seed_seq&) = delete; - -private: - vector v; // \expos -}; +namespace std { + class seed_seq { + public: + // types + using result_type = uint_least32_t; + + // constructors + seed_seq() noexcept; + template + seed_seq(initializer_list il); + template + seed_seq(InputIterator begin, InputIterator end); + + // generating functions + template + void generate(RandomAccessIterator begin, RandomAccessIterator end); + + // property functions + size_t size() const noexcept; + template + void param(OutputIterator dest) const; + + // no copy functions + seed_seq(const seed_seq&) = delete; + void operator=(const seed_seq&) = delete; + + private: + vector v; // \expos + }; +} \end{codeblock} @@ -4574,7 +4173,8 @@ \indexlibraryglobal{uniform_int_distribution}% \indexlibrarymember{result_type}{uniform_int_distribution}% \begin{codeblock} -template +namespace std { + template class uniform_int_distribution { public: // types @@ -4612,6 +4212,7 @@ friend basic_istream& operator>>(basic_istream& is, uniform_int_distribution& x); }; +} \end{codeblock} @@ -4675,7 +4276,8 @@ \indexlibraryglobal{uniform_real_distribution}% \indexlibrarymember{result_type}{uniform_real_distribution}% \begin{codeblock} -template +namespace std { + template class uniform_real_distribution { public: // types @@ -4714,6 +4316,7 @@ friend basic_istream& operator>>(basic_istream& is, uniform_real_distribution& x); }; +} \end{codeblock} @@ -4792,42 +4395,44 @@ \indexlibraryglobal{bernoulli_distribution}% \indexlibrarymember{result_type}{bernoulli_distribution}% \begin{codeblock} -class bernoulli_distribution { -public: - // types - using result_type = bool; - using param_type = @\unspec@; - - // constructors and reset functions - bernoulli_distribution() : bernoulli_distribution(0.5) {} - explicit bernoulli_distribution(double p); - explicit bernoulli_distribution(const param_type& parm); - void reset(); - - // equality operators - friend bool operator==(const bernoulli_distribution& x, const bernoulli_distribution& y); - - // generating functions - template - result_type operator()(URBG& g); - template - result_type operator()(URBG& g, const param_type& parm); - - // property functions - double p() const; - param_type param() const; - void param(const param_type& parm); - result_type min() const; - result_type max() const; - - // inserters and extractors - template - friend basic_ostream& - operator<<(basic_ostream& os, const bernoulli_distribution& x); - template - friend basic_istream& - operator>>(basic_istream& is, bernoulli_distribution& x); -}; +namespace std { + class bernoulli_distribution { + public: + // types + using result_type = bool; + using param_type = @\unspec@; + + // constructors and reset functions + bernoulli_distribution() : bernoulli_distribution(0.5) {} + explicit bernoulli_distribution(double p); + explicit bernoulli_distribution(const param_type& parm); + void reset(); + + // equality operators + friend bool operator==(const bernoulli_distribution& x, const bernoulli_distribution& y); + + // generating functions + template + result_type operator()(URBG& g); + template + result_type operator()(URBG& g, const param_type& parm); + + // property functions + double p() const; + param_type param() const; + void param(const param_type& parm); + result_type min() const; + result_type max() const; + + // inserters and extractors + template + friend basic_ostream& + operator<<(basic_ostream& os, const bernoulli_distribution& x); + template + friend basic_istream& + operator>>(basic_istream& is, bernoulli_distribution& x); + }; +} \end{codeblock} @@ -4875,7 +4480,8 @@ \indexlibraryglobal{binomial_distribution}% \indexlibrarymember{result_type}{binomial_distribution}% \begin{codeblock} -template +namespace std { + template class binomial_distribution { public: // types @@ -4913,6 +4519,7 @@ friend basic_istream& operator>>(basic_istream& is, binomial_distribution& x); }; +} \end{codeblock} @@ -4971,7 +4578,8 @@ \indexlibraryglobal{geometric_distribution}% \indexlibrarymember{result_type}{geometric_distribution}% \begin{codeblock} -template +namespace std { + template class geometric_distribution { public: // types @@ -5008,6 +4616,7 @@ friend basic_istream& operator>>(basic_istream& is, geometric_distribution& x); }; +} \end{codeblock} @@ -5059,7 +4668,8 @@ \indexlibraryglobal{negative_binomial_distribution}% \indexlibrarymember{result_type}{negative_binomial_distribution}% \begin{codeblock} -template +namespace std { + template class negative_binomial_distribution { public: // types @@ -5098,6 +4708,7 @@ friend basic_istream& operator>>(basic_istream& is, negative_binomial_distribution& x); }; +} \end{codeblock} @@ -5257,7 +4868,8 @@ \indexlibraryglobal{exponential_distribution}% \indexlibrarymember{result_type}{exponential_distribution}% \begin{codeblock} -template +namespace std { + template class exponential_distribution { public: // types @@ -5294,6 +4906,7 @@ friend basic_istream& operator>>(basic_istream& is, exponential_distribution& x); }; +} \end{codeblock} @@ -5342,7 +4955,8 @@ \indexlibraryglobal{gamma_distribution}% \indexlibrarymember{result_type}{gamma_distribution}% \begin{codeblock} -template +namespace std { + template class gamma_distribution { public: // types @@ -5380,6 +4994,7 @@ friend basic_istream& operator>>(basic_istream& is, gamma_distribution& x); }; +} \end{codeblock} @@ -5443,7 +5058,8 @@ \indexlibraryglobal{weibull_distribution}% \indexlibrarymember{result_type}{weibull_distribution}% \begin{codeblock} -template +namespace std { + template class weibull_distribution { public: // types @@ -5481,6 +5097,7 @@ friend basic_istream& operator>>(basic_istream& is, weibull_distribution& x); }; +} \end{codeblock} \indexlibraryctor{weibull_distribution}% @@ -5552,7 +5169,8 @@ \indexlibraryglobal{extreme_value_distribution}% \indexlibrarymember{result_type}{extreme_value_distribution}% \begin{codeblock} -template +namespace std { + template class extreme_value_distribution { public: // types @@ -5591,6 +5209,7 @@ friend basic_istream& operator>>(basic_istream& is, extreme_value_distribution& x); }; +} \end{codeblock} @@ -5676,7 +5295,8 @@ \indexlibraryglobal{normal_distribution}% \indexlibrarymember{result_type}{normal_distribution}% \begin{codeblock} -template +namespace std { + template class normal_distribution { public: // types @@ -5714,6 +5334,7 @@ friend basic_istream& operator>>(basic_istream& is, normal_distribution& x); }; +} \end{codeblock} @@ -5776,7 +5397,8 @@ \indexlibraryglobal{lognormal_distribution}% \indexlibrarymember{result_type}{lognormal_distribution}% \begin{codeblock} -template +namespace std { + template class lognormal_distribution { public: // types @@ -5814,6 +5436,7 @@ friend basic_istream& operator>>(basic_istream& is, lognormal_distribution& x); }; +} \end{codeblock} @@ -5874,7 +5497,8 @@ \indexlibraryglobal{chi_squared_distribution}% \indexlibrarymember{result_type}{chi_squared_distribution}% \begin{codeblock} -template +namespace std { + template class chi_squared_distribution { public: // types @@ -5911,6 +5535,7 @@ friend basic_istream& operator>>(basic_istream& is, chi_squared_distribution& x); }; +} \end{codeblock} @@ -5958,7 +5583,8 @@ \indexlibraryglobal{cauchy_distribution}% \indexlibrarymember{result_type}{cauchy_distribution}% \begin{codeblock} -template +namespace std { + template class cauchy_distribution { public: // types @@ -5996,6 +5622,7 @@ friend basic_istream& operator>>(basic_istream& is, cauchy_distribution& x); }; +} \end{codeblock} @@ -6060,7 +5687,8 @@ \indexlibraryglobal{fisher_f_distribution}% \indexlibrarymember{result_type}{fisher_distribution}% \begin{codeblock} -template +namespace std { + template class fisher_f_distribution { public: // types @@ -6098,6 +5726,7 @@ friend basic_istream& operator>>(basic_istream& is, fisher_f_distribution& x); }; +} \end{codeblock} @@ -6161,7 +5790,8 @@ \indexlibraryglobal{student_t_distribution}% \indexlibrarymember{result_type}{student_t_distribution}% \begin{codeblock} -template +namespace std { + template class student_t_distribution { public: // types @@ -6198,6 +5828,7 @@ friend basic_istream& operator>>(basic_istream& is, student_t_distribution& x); }; +} \end{codeblock} @@ -6269,7 +5900,8 @@ \indexlibraryglobal{discrete_distribution}% \indexlibrarymember{result_type}{discrete_distribution}% \begin{codeblock} -template +namespace std { + template class discrete_distribution { public: // types @@ -6310,6 +5942,7 @@ friend basic_istream& operator>>(basic_istream& is, discrete_distribution& x); }; +} \end{codeblock} \indexlibraryctor{discrete_distribution} @@ -6451,7 +6084,8 @@ \indexlibraryglobal{piecewise_constant_distribution}% \indexlibrarymember{result_type}{piecewise_constant_distribution}% \begin{codeblock} -template +namespace std { + template class piecewise_constant_distribution { public: // types @@ -6497,6 +6131,7 @@ friend basic_istream& operator>>(basic_istream& is, piecewise_constant_distribution& x); }; +} \end{codeblock} @@ -6685,7 +6320,8 @@ \indexlibraryglobal{piecewise_linear_distribution}% \indexlibrarymember{result_type}{piecewise_linear_distribution}% \begin{codeblock} -template +namespace std { + template class piecewise_linear_distribution { public: // types @@ -6730,6 +6366,7 @@ friend basic_istream& operator>>(basic_istream& is, piecewise_linear_distribution& x); }; +} \end{codeblock} \indexlibraryctor{piecewise_linear_distribution} @@ -7341,6 +6978,7 @@ \expects \range{p}{p + n} is a valid range. +\pnum \effects Constructs a \tcode{valarray} that has length \tcode{n}. The values of the elements of the array are initialized with the @@ -9486,23 +9124,23 @@ float expm1f(float x); long double expm1l(long double x); - float frexp(float value, int* exp); // see \ref{library.c} - double frexp(double value, int* exp); - long double frexp(long double value, int* exp); // see \ref{library.c} - float frexpf(float value, int* exp); - long double frexpl(long double value, int* exp); + constexpr float frexp(float value, int* exp); // see \ref{library.c} + constexpr double frexp(double value, int* exp); + constexpr long double frexp(long double value, int* exp); // see \ref{library.c} + constexpr float frexpf(float value, int* exp); + constexpr long double frexpl(long double value, int* exp); - int ilogb(float x); // see \ref{library.c} - int ilogb(double x); - int ilogb(long double x); // see \ref{library.c} - int ilogbf(float x); - int ilogbl(long double x); + constexpr int ilogb(float x); // see \ref{library.c} + constexpr int ilogb(double x); + constexpr int ilogb(long double x); // see \ref{library.c} + constexpr int ilogbf(float x); + constexpr int ilogbl(long double x); - float ldexp(float x, int exp); // see \ref{library.c} - double ldexp(double x, int exp); - long double ldexp(long double x, int exp); // see \ref{library.c} - float ldexpf(float x, int exp); - long double ldexpl(long double x, int exp); + constexpr float ldexp(float x, int exp); // see \ref{library.c} + constexpr double ldexp(double x, int exp); + constexpr long double ldexp(long double x, int exp); // see \ref{library.c} + constexpr float ldexpf(float x, int exp); + constexpr long double ldexpl(long double x, int exp); float log(float x); // see \ref{library.c} double log(double x); @@ -9528,29 +9166,29 @@ float log2f(float x); long double log2l(long double x); - float logb(float x); // see \ref{library.c} - double logb(double x); - long double logb(long double x); // see \ref{library.c} - float logbf(float x); - long double logbl(long double x); - - float modf(float value, float* iptr); // see \ref{library.c} - double modf(double value, double* iptr); - long double modf(long double value, long double* iptr); // see \ref{library.c} - float modff(float value, float* iptr); - long double modfl(long double value, long double* iptr); - - float scalbn(float x, int n); // see \ref{library.c} - double scalbn(double x, int n); - long double scalbn(long double x, int n); // see \ref{library.c} - float scalbnf(float x, int n); - long double scalbnl(long double x, int n); - - float scalbln(float x, long int n); // see \ref{library.c} - double scalbln(double x, long int n); - long double scalbln(long double x, long int n); // see \ref{library.c} - float scalblnf(float x, long int n); - long double scalblnl(long double x, long int n); + constexpr float logb(float x); // see \ref{library.c} + constexpr double logb(double x); + constexpr long double logb(long double x); // see \ref{library.c} + constexpr float logbf(float x); + constexpr long double logbl(long double x); + + constexpr float modf(float value, float* iptr); // see \ref{library.c} + constexpr double modf(double value, double* iptr); + constexpr long double modf(long double value, long double* iptr); // see \ref{library.c} + constexpr float modff(float value, float* iptr); + constexpr long double modfl(long double value, long double* iptr); + + constexpr float scalbn(float x, int n); // see \ref{library.c} + constexpr double scalbn(double x, int n); + constexpr long double scalbn(long double x, int n); // see \ref{library.c} + constexpr float scalbnf(float x, int n); + constexpr long double scalbnl(long double x, int n); + + constexpr float scalbln(float x, long int n); // see \ref{library.c} + constexpr double scalbln(double x, long int n); + constexpr long double scalbln(long double x, long int n); // see \ref{library.c} + constexpr float scalblnf(float x, long int n); + constexpr long double scalblnl(long double x, long int n); float cbrt(float x); // see \ref{library.c} double cbrt(double x); @@ -9559,18 +9197,18 @@ long double cbrtl(long double x); // \ref{c.math.abs}, absolute values - int abs(int j); - long int abs(long int j); - long long int abs(long long int j); - float abs(float j); - double abs(double j); - long double abs(long double j); - - float fabs(float x); // see \ref{library.c} - double fabs(double x); - long double fabs(long double x); // see \ref{library.c} - float fabsf(float x); - long double fabsl(long double x); + constexpr int abs(int j); + constexpr long int abs(long int j); + constexpr long long int abs(long long int j); + constexpr float abs(float j); + constexpr double abs(double j); + constexpr long double abs(long double j); + + constexpr float fabs(float x); // see \ref{library.c} + constexpr double fabs(double x); + constexpr long double fabs(long double x); // see \ref{library.c} + constexpr float fabsf(float x); + constexpr long double fabsl(long double x); float hypot(float x, float y); // see \ref{library.c} double hypot(double x, double y); @@ -9619,17 +9257,17 @@ float tgammaf(float x); long double tgammal(long double x); - float ceil(float x); // see \ref{library.c} - double ceil(double x); - long double ceil(long double x); // see \ref{library.c} - float ceilf(float x); - long double ceill(long double x); + constexpr float ceil(float x); // see \ref{library.c} + constexpr double ceil(double x); + constexpr long double ceil(long double x); // see \ref{library.c} + constexpr float ceilf(float x); + constexpr long double ceill(long double x); - float floor(float x); // see \ref{library.c} - double floor(double x); - long double floor(long double x); // see \ref{library.c} - float floorf(float x); - long double floorl(long double x); + constexpr float floor(float x); // see \ref{library.c} + constexpr double floor(double x); + constexpr long double floor(long double x); // see \ref{library.c} + constexpr float floorf(float x); + constexpr long double floorl(long double x); float nearbyint(float x); // see \ref{library.c} double nearbyint(double x); @@ -9655,93 +9293,93 @@ long long int llrintf(float x); long long int llrintl(long double x); - float round(float x); // see \ref{library.c} - double round(double x); - long double round(long double x); // see \ref{library.c} - float roundf(float x); - long double roundl(long double x); - - long int lround(float x); // see \ref{library.c} - long int lround(double x); - long int lround(long double x); // see \ref{library.c} - long int lroundf(float x); - long int lroundl(long double x); - - long long int llround(float x); // see \ref{library.c} - long long int llround(double x); - long long int llround(long double x); // see \ref{library.c} - long long int llroundf(float x); - long long int llroundl(long double x); - - float trunc(float x); // see \ref{library.c} - double trunc(double x); - long double trunc(long double x); // see \ref{library.c} - float truncf(float x); - long double truncl(long double x); - - float fmod(float x, float y); // see \ref{library.c} - double fmod(double x, double y); - long double fmod(long double x, long double y); // see \ref{library.c} - float fmodf(float x, float y); - long double fmodl(long double x, long double y); - - float remainder(float x, float y); // see \ref{library.c} - double remainder(double x, double y); - long double remainder(long double x, long double y); // see \ref{library.c} - float remainderf(float x, float y); - long double remainderl(long double x, long double y); - - float remquo(float x, float y, int* quo); // see \ref{library.c} - double remquo(double x, double y, int* quo); - long double remquo(long double x, long double y, int* quo); // see \ref{library.c} - float remquof(float x, float y, int* quo); - long double remquol(long double x, long double y, int* quo); - - float copysign(float x, float y); // see \ref{library.c} - double copysign(double x, double y); - long double copysign(long double x, long double y); // see \ref{library.c} - float copysignf(float x, float y); - long double copysignl(long double x, long double y); + constexpr float round(float x); // see \ref{library.c} + constexpr double round(double x); + constexpr long double round(long double x); // see \ref{library.c} + constexpr float roundf(float x); + constexpr long double roundl(long double x); + + constexpr long int lround(float x); // see \ref{library.c} + constexpr long int lround(double x); + constexpr long int lround(long double x); // see \ref{library.c} + constexpr long int lroundf(float x); + constexpr long int lroundl(long double x); + + constexpr long long int llround(float x); // see \ref{library.c} + constexpr long long int llround(double x); + constexpr long long int llround(long double x); // see \ref{library.c} + constexpr long long int llroundf(float x); + constexpr long long int llroundl(long double x); + + constexpr float trunc(float x); // see \ref{library.c} + constexpr double trunc(double x); + constexpr long double trunc(long double x); // see \ref{library.c} + constexpr float truncf(float x); + constexpr long double truncl(long double x); + + constexpr float fmod(float x, float y); // see \ref{library.c} + constexpr double fmod(double x, double y); + constexpr long double fmod(long double x, long double y); // see \ref{library.c} + constexpr float fmodf(float x, float y); + constexpr long double fmodl(long double x, long double y); + + constexpr float remainder(float x, float y); // see \ref{library.c} + constexpr double remainder(double x, double y); + constexpr long double remainder(long double x, long double y); // see \ref{library.c} + constexpr float remainderf(float x, float y); + constexpr long double remainderl(long double x, long double y); + + constexpr float remquo(float x, float y, int* quo); // see \ref{library.c} + constexpr double remquo(double x, double y, int* quo); + constexpr long double remquo(long double x, long double y, int* quo); // see \ref{library.c} + constexpr float remquof(float x, float y, int* quo); + constexpr long double remquol(long double x, long double y, int* quo); + + constexpr float copysign(float x, float y); // see \ref{library.c} + constexpr double copysign(double x, double y); + constexpr long double copysign(long double x, long double y); // see \ref{library.c} + constexpr float copysignf(float x, float y); + constexpr long double copysignl(long double x, long double y); double nan(const char* tagp); float nanf(const char* tagp); long double nanl(const char* tagp); - float nextafter(float x, float y); // see \ref{library.c} - double nextafter(double x, double y); - long double nextafter(long double x, long double y); // see \ref{library.c} - float nextafterf(float x, float y); - long double nextafterl(long double x, long double y); - - float nexttoward(float x, long double y); // see \ref{library.c} - double nexttoward(double x, long double y); - long double nexttoward(long double x, long double y); // see \ref{library.c} - float nexttowardf(float x, long double y); - long double nexttowardl(long double x, long double y); - - float fdim(float x, float y); // see \ref{library.c} - double fdim(double x, double y); - long double fdim(long double x, long double y); // see \ref{library.c} - float fdimf(float x, float y); - long double fdiml(long double x, long double y); - - float fmax(float x, float y); // see \ref{library.c} - double fmax(double x, double y); - long double fmax(long double x, long double y); // see \ref{library.c} - float fmaxf(float x, float y); - long double fmaxl(long double x, long double y); - - float fmin(float x, float y); // see \ref{library.c} - double fmin(double x, double y); - long double fmin(long double x, long double y); // see \ref{library.c} - float fminf(float x, float y); - long double fminl(long double x, long double y); - - float fma(float x, float y, float z); // see \ref{library.c} - double fma(double x, double y, double z); - long double fma(long double x, long double y, long double z); // see \ref{library.c} - float fmaf(float x, float y, float z); - long double fmal(long double x, long double y, long double z); + constexpr float nextafter(float x, float y); // see \ref{library.c} + constexpr double nextafter(double x, double y); + constexpr long double nextafter(long double x, long double y); // see \ref{library.c} + constexpr float nextafterf(float x, float y); + constexpr long double nextafterl(long double x, long double y); + + constexpr float nexttoward(float x, long double y); // see \ref{library.c} + constexpr double nexttoward(double x, long double y); + constexpr long double nexttoward(long double x, long double y); // see \ref{library.c} + constexpr float nexttowardf(float x, long double y); + constexpr long double nexttowardl(long double x, long double y); + + constexpr float fdim(float x, float y); // see \ref{library.c} + constexpr double fdim(double x, double y); + constexpr long double fdim(long double x, long double y); // see \ref{library.c} + constexpr float fdimf(float x, float y); + constexpr long double fdiml(long double x, long double y); + + constexpr float fmax(float x, float y); // see \ref{library.c} + constexpr double fmax(double x, double y); + constexpr long double fmax(long double x, long double y); // see \ref{library.c} + constexpr float fmaxf(float x, float y); + constexpr long double fmaxl(long double x, long double y); + + constexpr float fmin(float x, float y); // see \ref{library.c} + constexpr double fmin(double x, double y); + constexpr long double fmin(long double x, long double y); // see \ref{library.c} + constexpr float fminf(float x, float y); + constexpr long double fminl(long double x, long double y); + + constexpr float fma(float x, float y, float z); // see \ref{library.c} + constexpr double fma(double x, double y, double z); + constexpr long double fma(long double x, long double y, long double z); // see \ref{library.c} + constexpr float fmaf(float x, float y, float z); + constexpr long double fmal(long double x, long double y, long double z); // \ref{c.math.lerp}, linear interpolation constexpr float lerp(float a, float b, float t) noexcept; @@ -9749,53 +9387,53 @@ constexpr long double lerp(long double a, long double b, long double t) noexcept; // \ref{c.math.fpclass}, classification / comparison functions - int fpclassify(float x); - int fpclassify(double x); - int fpclassify(long double x); + constexpr int fpclassify(float x); + constexpr int fpclassify(double x); + constexpr int fpclassify(long double x); - bool isfinite(float x); - bool isfinite(double x); - bool isfinite(long double x); + constexpr bool isfinite(float x); + constexpr bool isfinite(double x); + constexpr bool isfinite(long double x); - bool isinf(float x); - bool isinf(double x); - bool isinf(long double x); + constexpr bool isinf(float x); + constexpr bool isinf(double x); + constexpr bool isinf(long double x); - bool isnan(float x); - bool isnan(double x); - bool isnan(long double x); + constexpr bool isnan(float x); + constexpr bool isnan(double x); + constexpr bool isnan(long double x); - bool isnormal(float x); - bool isnormal(double x); - bool isnormal(long double x); + constexpr bool isnormal(float x); + constexpr bool isnormal(double x); + constexpr bool isnormal(long double x); - bool signbit(float x); - bool signbit(double x); - bool signbit(long double x); + constexpr bool signbit(float x); + constexpr bool signbit(double x); + constexpr bool signbit(long double x); - bool isgreater(float x, float y); - bool isgreater(double x, double y); - bool isgreater(long double x, long double y); + constexpr bool isgreater(float x, float y); + constexpr bool isgreater(double x, double y); + constexpr bool isgreater(long double x, long double y); - bool isgreaterequal(float x, float y); - bool isgreaterequal(double x, double y); - bool isgreaterequal(long double x, long double y); + constexpr bool isgreaterequal(float x, float y); + constexpr bool isgreaterequal(double x, double y); + constexpr bool isgreaterequal(long double x, long double y); - bool isless(float x, float y); - bool isless(double x, double y); - bool isless(long double x, long double y); + constexpr bool isless(float x, float y); + constexpr bool isless(double x, double y); + constexpr bool isless(long double x, long double y); - bool islessequal(float x, float y); - bool islessequal(double x, double y); - bool islessequal(long double x, long double y); + constexpr bool islessequal(float x, float y); + constexpr bool islessequal(double x, double y); + constexpr bool islessequal(long double x, long double y); - bool islessgreater(float x, float y); - bool islessgreater(double x, double y); - bool islessgreater(long double x, long double y); + constexpr bool islessgreater(float x, float y); + constexpr bool islessgreater(double x, double y); + constexpr bool islessgreater(long double x, long double y); - bool isunordered(float x, float y); - bool isunordered(double x, double y); - bool isunordered(long double x, long double y); + constexpr bool isunordered(float x, float y); + constexpr bool isunordered(double x, double y); + constexpr bool isunordered(long double x, long double y); // \ref{sf.cmath}, mathematical special functions @@ -9949,8 +9587,7 @@ \tcode{abs} is exempted from these rules in order to stay compatible with C. \end{note} -\xref -ISO C 7.12 +\xrefc{7.12} \rSec2[c.math.abs]{Absolute values} @@ -9963,12 +9600,12 @@ \indexlibraryglobal{abs}% \begin{itemdecl} -int abs(int j); -long int abs(long int j); -long long int abs(long long int j); -float abs(float j); -double abs(double j); -long double abs(long double j); +constexpr int abs(int j); +constexpr long int abs(long int j); +constexpr long long int abs(long long int j); +constexpr float abs(float j); +constexpr double abs(double j); +constexpr long double abs(long double j); \end{itemdecl} \begin{itemdescr} @@ -10047,8 +9684,7 @@ corresponding names defined in the C standard library. Each function is overloaded for the three floating-point types. -\xref -ISO C 7.12.3, 7.12.4 +\xrefc{7.12.3, 7.12.4} \rSec2[sf.cmath]{Mathematical special functions}% @@ -10183,7 +9819,7 @@ \indexlibraryglobal{beta}% \indexlibraryglobal{betaf}% \indexlibraryglobal{betal}% -\indextext{Eulerian integral of the first kind|see{\tcode{beta}}}% +\indextext{Eulerian integral of the first kind|see{beta functions $\mathsf{B}$}}% \indextext{beta functions $\mathsf{B}$}% \begin{itemdecl} double beta(double x, double y); diff --git a/source/overloading.tex b/source/overloading.tex index 9628d1d6aa..516ef0ed39 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -239,8 +239,7 @@ is allowed in an implicit conversion sequence, special rules apply when selecting -the best user-defined conversion~(\ref{over.match.best}, -\ref{over.best.ics}). +the best user-defined conversion\iref{over.match.best,over.best.ics}. \begin{example} \begin{codeblock} class T { @@ -285,8 +284,7 @@ \pnum In each case where a candidate is a function template, candidate function template specializations -are generated using template argument deduction~(\ref{temp.over}, -\ref{temp.deduct}). +are generated using template argument deduction\iref{temp.over,temp.deduct}. If a constructor template or conversion function template has an \grammarterm{explicit-specifier} whose \grammarterm{constant-expression} is value-dependent\iref{temp.dep}, @@ -318,7 +316,7 @@ \pnum A -defaulted move special member function~(\ref{class.copy.ctor}, \ref{class.copy.assign}) +defaulted move special member function\iref{class.copy.ctor,class.copy.assign} that is defined as deleted is excluded from the set of candidate functions in all contexts. A constructor inherited from class type \tcode{C}\iref{class.inhctor.init} @@ -694,8 +692,7 @@ the set of non-member candidates is empty; otherwise, it includes the result of unqualified lookup for \tcode{\keyword{operator}@} -in the rewritten function call -(\ref{basic.lookup.unqual}, \ref{basic.lookup.argdep}), +in the rewritten function call\iref{basic.lookup.unqual,basic.lookup.argdep}, ignoring all member functions. However, if no operand has a class type, only those non-member functions in the lookup set that have a first parameter of type @@ -936,7 +933,7 @@ void B::f() { operator+ (a,a); // error: global operator hidden by member - a + a; // OK: calls global \tcode{\keyword{operator}+} + a + a; // OK, calls global \tcode{\keyword{operator}+} } \end{codeblock} \end{note} @@ -1121,7 +1118,7 @@ In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed. \begin{note} -This differs from other situations~(\ref{over.match.ctor}, \ref{over.match.copy}), +This differs from other situations\iref{over.match.ctor,over.match.copy}, where only converting constructors are considered for copy-initialization. This restriction only applies if this initialization is part of the final result of overload @@ -1857,7 +1854,7 @@ sequence of conversions is an implicit conversion as defined in \ref{conv}, which means it is governed by the rules for initialization of an object or reference by a single -expression~(\ref{dcl.init}, \ref{dcl.init.ref}). +expression\iref{dcl.init,dcl.init.ref}. \pnum Implicit conversion sequences are concerned only with the type, @@ -2154,8 +2151,8 @@ \end{example} If the parameter binds directly to the result of applying a conversion function to the argument expression, the implicit -conversion sequence is a user-defined conversion sequence\iref{over.ics.user}, -with the second standard conversion sequence either an identity conversion or, +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. @@ -2274,9 +2271,9 @@ \begin{example} \begin{codeblock} void f(std::initializer_list); -f( {} ); // OK: \tcode{f(initializer_list)} identity conversion -f( {1,2,3} ); // OK: \tcode{f(initializer_list)} identity conversion -f( {'a','b'} ); // OK: \tcode{f(initializer_list)} integral promotion +f( {} ); // OK, \tcode{f(initializer_list)} identity conversion +f( {1,2,3} ); // OK, \tcode{f(initializer_list)} identity conversion +f( {'a','b'} ); // OK, \tcode{f(initializer_list)} integral promotion f( {1.0} ); // error: narrowing struct A { @@ -2291,7 +2288,7 @@ typedef int IA[3]; void h(const IA&); -h({ 1, 2, 3 }); // OK: identity conversion +h({ 1, 2, 3 }); // OK, identity conversion \end{codeblock} \end{example} @@ -2319,7 +2316,7 @@ or Conversion rank if \tcode{U} is derived from \tcode{X}. \item Otherwise, the implicit conversion sequence is a user-defined -conversion sequence with the second standard conversion sequence an +conversion sequence whose second standard conversion sequence is an identity conversion. \end{itemize} If multiple constructors are viable but none is better than @@ -2333,13 +2330,13 @@ A(std::initializer_list); }; void f(A); -f( {'a', 'b'} ); // OK: \tcode{f(A(std::initializer_list))} user-defined conversion +f( {'a', 'b'} ); // OK, \tcode{f(A(std::initializer_list))} user-defined conversion struct B { B(int, double); }; void g(B); -g( {'a', 'b'} ); // OK: \tcode{g(B(int, double))} user-defined conversion +g( {'a', 'b'} ); // OK, \tcode{g(B(int, double))} user-defined conversion g( {1.0, 1.0} ); // error: narrowing void f(B); @@ -2349,13 +2346,13 @@ C(std::string); }; void h(C); -h({"foo"}); // OK: \tcode{h(C(std::string("foo")))} +h({"foo"}); // OK, \tcode{h(C(std::string("foo")))} struct D { D(A, C); }; void i(D); -i({ {1,2}, {"bar"} }); // OK: \tcode{i(D(A(std::initializer_list\{1,2\}), C(std::string("bar"))))} +i({ {1,2}, {"bar"} }); // OK, \tcode{i(D(A(std::initializer_list\{1,2\}), C(std::string("bar"))))} \end{codeblock} \end{example} @@ -2363,8 +2360,8 @@ Otherwise, if the parameter has an aggregate type which can be initialized from the initializer list according to the rules for aggregate initialization\iref{dcl.init.aggr}, the implicit conversion sequence is a -user-defined conversion sequence with the second standard conversion -sequence an identity conversion. +user-defined conversion sequence whose second standard conversion +sequence is an identity conversion. \begin{example} \begin{codeblock} struct A { @@ -2373,7 +2370,7 @@ }; void f(A); -f( {'a', 'b'} ); // OK: \tcode{f(A(int,double))} user-defined conversion +f( {'a', 'b'} ); // OK, \tcode{f(A(int,double))} user-defined conversion f( {1.0} ); // error: narrowing \end{codeblock} \end{example} @@ -2392,7 +2389,7 @@ }; void f(const A&); -f( {'a', 'b'} ); // OK: \tcode{f(A(int,double))} user-defined conversion +f( {'a', 'b'} ); // OK, \tcode{f(A(int,double))} user-defined conversion f( {1.0} ); // error: narrowing void g(const double &); @@ -2409,7 +2406,7 @@ \begin{example} \begin{codeblock} void f(int); -f( {'a'} ); // OK: same conversion as \tcode{char} to \tcode{int} +f( {'a'} ); // OK, same conversion as \tcode{char} to \tcode{int} f( {1.0} ); // error: narrowing \end{codeblock} \end{example} @@ -2419,7 +2416,7 @@ \begin{example} \begin{codeblock} void f(int); -f( { } ); // OK: identity conversion +f( { } ); // OK, identity conversion \end{codeblock} \end{example} \end{itemize} @@ -2830,8 +2827,7 @@ The target can be \begin{itemize} \item -an object or reference being initialized~(\ref{dcl.init}, \ref{dcl.init.ref}, -\ref{dcl.init.list}), +an object or reference being initialized\iref{dcl.init,dcl.init.ref,dcl.init.list}, \item the left side of an assignment\iref{expr.ass}, \item @@ -2841,8 +2837,7 @@ \item the return value of a function, operator function, or conversion\iref{stmt.return}, \item -an explicit type conversion~(\ref{expr.type.conv}, \ref{expr.static.cast}, -\ref{expr.cast}), or +an explicit type conversion\iref{expr.type.conv,expr.static.cast,expr.cast}, or \item a non-type \grammarterm{template-parameter}\iref{temp.arg.nontype}. @@ -2866,8 +2861,8 @@ \end{note} \pnum -The specialization, if any, generated by template argument deduction -(\ref{temp.over}, \ref{temp.deduct.funcaddr}, \ref{temp.arg.explicit}) +The specialization, if any, generated by template argument +deduction\iref{temp.over,temp.deduct.funcaddr,temp.arg.explicit} for each function template named is added to the set of selected functions considered. @@ -3315,7 +3310,7 @@ \begin{codeblock} struct X { Z operator[](std::initializer_list); - Z oeprator[](auto...); + Z operator[](auto...); }; X x; x[{1,2,3}] = 7; // OK, meaning \tcode{x.\keyword{operator}[](\{1,2,3\})} @@ -3352,6 +3347,7 @@ \indextext{postfix ++ and -{-} overloading@postfix \tcode{++} and \tcode{--}!overloading}% \pnum +\indextext{overloading!increment operator}% An \defnadj{increment}{operator function} is a function named \tcode{\keyword{operator}++}. If this function is a non-static member function with no non-object parameters, or a non-member @@ -3408,6 +3404,7 @@ \end{example} \pnum +\indextext{overloading!decrement operator}% A \defnadj{decrement}{operator function} is a function named \tcode{\keyword{operator}--} and is handled analogously to an increment operator function. @@ -3844,11 +3841,11 @@ \begin{codeblock} void operator "" _km(long double); // OK string operator "" _i18n(const char*, std::size_t); // OK -template double operator "" _\u03C0(); // OK: UCN for lowercase pi +template double operator "" _\u03C0(); // OK, UCN for lowercase pi float operator ""_e(const char*); // OK float operator ""E(const char*); // ill-formed, no diagnostic required: - // reserved literal suffix~(\ref{usrlit.suffix}, \ref{lex.ext}) -double operator""_Bq(long double); // OK: does not use the reserved \grammarterm{identifier} \tcode{_Bq}\iref{lex.name} + // reserved literal suffix\iref{usrlit.suffix,lex.ext} +double operator""_Bq(long double); // OK, does not use the reserved \grammarterm{identifier} \tcode{_Bq}\iref{lex.name} double operator"" _Bq(long double); // ill-formed, no diagnostic required: // uses the reserved \grammarterm{identifier} \tcode{_Bq}\iref{lex.name} float operator " " B(const char*); // error: non-empty \grammarterm{string-literal} diff --git a/source/preprocessor.tex b/source/preprocessor.tex index fb03b852f9..7528bd6c83 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -1229,7 +1229,7 @@ If the substitution of \mname{VA_ARGS} as neither an operand of \tcode{\#} nor \tcode{\#\#} consists of no preprocessing tokens, the argument consists of -a single placemarker preprocessing token~(\ref{cpp.concat}, \ref{cpp.rescan}). +a single placemarker preprocessing token\iref{cpp.concat,cpp.rescan}. Otherwise, the argument consists of the results of the expansion of the contained \grammarterm{pp-tokens} as the replacement list of the current function-like macro @@ -1754,7 +1754,7 @@ \defnxname{cpp_binary_literals} & \tcode{201304L} \\ \rowsep \defnxname{cpp_capture_star_this} & \tcode{201603L} \\ \rowsep \defnxname{cpp_char8_t} & \tcode{201811L} \\ \rowsep -\defnxname{cpp_concepts} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_concepts} & \tcode{202002L} \\ \rowsep \defnxname{cpp_conditional_explicit} & \tcode{201806L} \\ \rowsep \defnxname{cpp_constexpr} & \tcode{202110L} \\ \rowsep \defnxname{cpp_constexpr_dynamic_alloc} & \tcode{201907L} \\ \rowsep diff --git a/source/ranges.tex b/source/ranges.tex index 4e6a0286c5..f980dd7eca 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -139,6 +139,16 @@ template<@\libconcept{range}@ R> using borrowed_subrange_t = @\seebelow@; + // \ref{range.utility.conv}, range conversions + template requires (!@\libconcept{view}@) + constexpr C to(R&& r, Args&&... args); + template class C, @\libconcept{input_range}@ R, class... Args> + constexpr auto to(R&& r, Args&&... args) -> @\seebelow@; + template requires (!@\libconcept{view}@) + constexpr auto to(Args&&... args) -> @\seebelow@; + template class C, class... Args> + constexpr auto to(Args&&... args) -> @\seebelow@; + // \ref{range.empty}, empty view template requires is_object_v @@ -183,6 +193,11 @@ namespace views { template inline constexpr @\unspec@ istream = @\unspec@; } + // \ref{range.adaptor.object}, range adaptor objects + template + requires is_class_v && @\libconcept{same_as}@> + class range_adaptor_closure { }; + // \ref{range.all}, all view namespace views { inline constexpr @\unspec@ all = @\unspec@; @@ -266,6 +281,18 @@ namespace views { inline constexpr @\unspec@ join = @\unspec@; } + // \ref{range.join.with}, join with view + template + concept @\exposconcept{compatible-joinable-ranges}@ = @\seebelow@; // \expos + + template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> + requires @\libconcept{view}@ && @\libconcept{input_range}@> + && @\libconcept{view}@ + && @\exposconcept{compatible-joinable-ranges}@, Pattern> + class join_with_view; + + namespace views { inline constexpr @\unspec@ join_with = @\unspec@; } + // \ref{range.lazy.split}, lazy split view template concept @\exposconcept{tiny-range}@ = @\seebelow@; // \expos @@ -375,6 +402,39 @@ inline constexpr @\unspec@ adjacent_transform = @\unspec@; inline constexpr auto @\libmember{pairwise_transform}{views}@ = adjacent_transform<2>; } + + // \ref{range.chunk}, chunk view + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + class chunk_view; + + template<@\libconcept{view}@ V> + requires @\libconcept{forward_range}@ + class chunk_view; + + template + inline constexpr bool enable_borrowed_range> = + @\libconcept{forward_range}@ && enable_borrowed_range; + + namespace views { inline constexpr @\unspec@ chunk = @\unspec@; } + + // \ref{range.slide}, slide view + template<@\libconcept{view}@ V> + requires @\libconcept{forward_range}@ + class slide_view; + + template + inline constexpr bool enable_borrowed_range> = + enable_borrowed_range; + + namespace views { inline constexpr @\unspec@ slide = @\unspec@; } + + // \ref{range.chunk.by}, chunk by view + template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@, iterator_t> Pred> + requires @\libconcept{view}@ && is_object_v + class chunk_by_view; + + namespace views { inline constexpr @\unspec@ chunk_by = @\unspec@; } } namespace std { @@ -402,6 +462,9 @@ struct tuple_element<1, const ranges::subrange> { using type = S; }; + + struct from_range_t { explicit from_range_t() = default; }; + inline constexpr from_range_t from_range{}; } \end{codeblock} @@ -465,7 +528,7 @@ \tcode{ranges::begin(E)} is ill-formed. \item - Otherwise, if \tcode{T} is an array type\iref{basic.compound} and + Otherwise, if \tcode{T} is an array type\iref{term.array.type} and \tcode{remove_all_extents_t} is an incomplete type, \tcode{ranges::begin(E)} is ill-formed with no diagnostic required. @@ -531,7 +594,7 @@ \tcode{ranges::end(E)} is ill-formed. \item - Otherwise, if \tcode{T} is an array type\iref{basic.compound} and + Otherwise, if \tcode{T} is an array type\iref{term.array.type} and \tcode{remove_all_extents_t} is an incomplete type, \tcode{ranges::end(E)} is ill-formed with no diagnostic required. @@ -644,7 +707,7 @@ \tcode{ranges::rbegin(E)} is ill-formed. \item - Otherwise, if \tcode{T} is an array type\iref{basic.compound} and + Otherwise, if \tcode{T} is an array type\iref{term.array.type} and \tcode{remove_all_extents_t} is an incomplete type, \tcode{ranges::rbegin(E)} is ill-formed with no diagnostic required. @@ -713,7 +776,7 @@ \tcode{ranges::rend(E)} is ill-formed. \item - Otherwise, if \tcode{T} is an array type\iref{basic.compound} and + Otherwise, if \tcode{T} is an array type\iref{term.array.type} and \tcode{remove_all_extents_t} is an incomplete type, \tcode{ranges::rend(E)} is ill-formed with no diagnostic required. @@ -821,7 +884,7 @@ \begin{itemize} \item - If \tcode{T} is an array of unknown bound\iref{dcl.array}, + If \tcode{T} is an array of unknown bound\iref{term.array.type}, \tcode{ranges::size(E)} is ill-formed. \item @@ -912,7 +975,7 @@ \begin{itemize} \item - If \tcode{T} is an array of unknown bound\iref{basic.compound}, + If \tcode{T} is an array of unknown bound\iref{term.array.type}, \tcode{ranges::empty(E)} is ill-formed. \item @@ -968,7 +1031,7 @@ \tcode{ranges::data(E)} is ill-formed. \item - Otherwise, if \tcode{T} is an array type\iref{basic.compound} and + Otherwise, if \tcode{T} is an array type\iref{term.array.type} and \tcode{remove_all_extents_t} is an incomplete type, \tcode{ranges::data(E)} is ill-formed with no diagnostic required. @@ -1044,8 +1107,8 @@ return an iterator and a sentinel, respectively. The \libconcept{sized_range} concept refines \libconcept{range} with the requirement that \tcode{ranges::size} be amortized \bigoh{1}. -The \libconcept{view} concept specifies requirements on a \libconcept{range} type -with constant-time destruction and move operations. +The \libconcept{view} concept specifies requirements on +a \libconcept{range} type to provide operations with predictable complexity. \pnum Several refinements of \libconcept{range} group requirements @@ -1987,6 +2050,221 @@ denote \tcode{dangling}. \end{itemize} +\rSec2[range.utility.conv]{Range conversions} + +\rSec3[range.utility.conv.general]{General} + +\pnum +The range conversion functions construct +an object (usually a container) from a range, +by using a constructor taking a range, +a \tcode{from_range_t} tagged constructor, or +a constructor taking a pair of iterators, or +by inserting each element of the range into the default-constructed object. + +\pnum +\tcode{ranges::to} is applied recursively, +allowing the conversion of a range of ranges. + +\begin{example} +\begin{codeblock} +string_view str = "the quick brown fox"; +auto words = views::split(str, ' ') | to>(); +// \tcode{words} is \tcode{vector\{"the", "quick", "brown", "fox"\}} +\end{codeblock} +\end{example} + +\pnum +Let \exposid{reservable-container} be defined as follows: +\begin{codeblock} +template +constexpr bool @\exposid{reservable-container}@ = // \expos + @\libconcept{sized_range}@ && + requires(Container& c, range_size_t n) { + c.reserve(n); + { c.capacity() } -> @\libconcept{same_as}@; + { c.max_size() } -> @\libconcept{same_as}@; + }; +\end{codeblock} + +\pnum +Let \exposid{container-insertable} be defined as follows: +\begin{codeblock} +template +constexpr bool @\exposid{container-insertable}@ = // \expos + requires(Container& c, Ref&& ref) { + requires (requires { c.push_back(std::forward(ref)); } || + requires { c.insert(c.end(), std::forward(ref)); }); + }; +\end{codeblock} + +\pnum +Let \exposid{container-inserter} be defined as follows: +\begin{codeblock} +template +auto @\exposid{container-inserter}@(C& c) { // \expos + if constexpr (requires { c.push_back(declval()); }) + return back_inserter(c); + else + return inserter(c, c.end()); +}; +\end{codeblock} + +\rSec3[range.utility.conv.to]{\tcode{ranges::to}} + +\indexlibrarymember{to}{ranges}% +\begin{itemdecl} +template requires (!@\libconcept{view}@) + constexpr C to(R&& r, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An object of type \tcode{C} +constructed from the elements of \tcode{r} in the following manner: +\begin{itemize} +\item +If \tcode{\libconcept{convertible_to}, range_value_t>} +is \tcode{true}: +\begin{itemize} +\item +If \tcode{\libconcept{constructible_from}} is \tcode{true}: +\begin{codeblock} +C(std::forward(r), std::forward(args)...) +\end{codeblock} +\item +Otherwise, if +\tcode{\libconcept{constructible_from}} +is \tcode{true}: +\begin{codeblock} +C(from_range, std::forward(r), std::forward(args)...) +\end{codeblock} +\item +Otherwise, if +\begin{itemize} +\item +\tcode{\libconcept{common_range}} is \tcode{true}, +\item +\tcode{\exposconcept{cpp17-input-iterator}>} is \tcode{true}, and +\item +\tcode{\libconcept{constructible_from}, sentinel_t, Args...>} +is \tcode{true}: +\end{itemize} +\begin{codeblock} +C(ranges::begin(r), ranges::end(r), std::forward(args)...) +\end{codeblock} +\item +Otherwise, if +\begin{itemize} +\item +\tcode{\libconcept{constructible_from}} is \tcode{true}, and +\item +\tcode{\exposid{container-insertable}>} is \tcode{true}: +\end{itemize} +\begin{codeblock} +C c(std::forward(args)...); +if constexpr (@\libconcept{sized_range}@ && @\exposid{reservable-container}@) + c.reserve(ranges::size(r)); +ranges::copy(r, @\exposid{container-inserter}@>(c)); +\end{codeblock} +\end{itemize} + +\item +Otherwise, +if \tcode{\libconcept{input_range}>} is \tcode{true}: +\begin{codeblock} +to(r | views::transform([](auto&& elem) { + return to>(std::forward(elem)); +}), std::forward(args)...); +\end{codeblock} + +\item +Otherwise, the program is ill-formed. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{to}{ranges}% +\begin{itemdecl} +template class C, @\libconcept{input_range}@ R, class... Args> + constexpr auto to(R&& r, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \exposid{input-iterator} be an exposition-only type: +\begin{codeblock} +struct @\exposid{input-iterator}@ { // \expos + using iterator_category = input_iterator_tag; + using value_type = range_value_t; + using difference_type = ptrdiff_t; + using pointer = add_pointer_t>; + using reference = range_reference_t; + reference operator*() const; + pointer operator->() const; + @\exposid{input-iterator}@& operator++(); + @\exposid{input-iterator}@ operator++(int); + bool operator==(const @\exposid{input-iterator}@&) const; +}; +\end{codeblock} +\begin{note} +\exposid{input-iterator} meets +the syntactic requirements of \oldconcept{InputIterator}. +\end{note} + +\pnum +Let \tcode{\placeholder{DEDUCE_EXPR}} be defined as follows: +\begin{itemize} +\item +\tcode{C(declval(), declval()...)} if that is a valid expression, +\item +otherwise, \tcode{C(from_range, declval(), declval()...)} +if that is a valid expression, +\item +otherwise, +\begin{codeblock} +C(declval<@\exposid{input-iterator}@>(), declval<@\exposid{input-iterator}@>(), declval()...) +\end{codeblock} +if that is a valid expression, +\item +otherwise, the program is ill-formed. +\end{itemize} + +\pnum +\returns +\tcode{to(std::forward(r), std::forward(args)...)}. +\end{itemdescr} + +\rSec3[range.utility.conv.adaptors]{\tcode{ranges::to} adaptors} + +\indexlibrarymember{to}{ranges}% +\begin{itemdecl} +template requires (!@\libconcept{view}@) + constexpr auto to(Args&&... args); +template class C, class... Args> + constexpr auto to(Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A range adaptor closure object\iref{range.adaptor.object} \tcode{f} +that is a perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} +with the following properties: +\begin{itemize} +\item +It has no target object. +\item +Its bound argument entities \tcode{bound_args} consist of +objects of types \tcode{decay_t...} +direct-non-list-initialized with \tcode{std::forward(args)...}, +respectively. +\item +Its call pattern is \tcode{to(r, bound_args...)}, +where \tcode{r} is the argument used in a function call expression of \tcode{f}. +\end{itemize} +\end{itemdescr} + \rSec1[range.factories]{Range factories} \rSec2[range.factories.general]{General} @@ -2471,7 +2749,7 @@ \remarks The expression in the \grammarterm{requires-clause} is equivalent to: \begin{codeblock} -(@\libconcept{same_as}@ && @\exposconcept{advanceable}@) || (@\libconcept{integral}@ && @\libconcept{integral}@) || +(@\libconcept{same_as}@ && @\exposconcept{advanceable}@) || (@\exposid{is-integer-like}@ && @\exposid{is-integer-like}@) || @\libconcept{sized_sentinel_for}@ \end{codeblock} \end{itemdescr} @@ -3016,7 +3294,7 @@ template<@\libconcept{movable}@ Val, class CharT, class Traits> requires @\libconcept{default_initializable}@ && @\exposconcept{stream-extractable}@ - class basic_istream_view::@\exposid{iterator}@ { // \expos + class basic_istream_view::@\exposid{iterator}@ { public: using iterator_concept = input_iterator_tag; using difference_type = ptrdiff_t; @@ -3137,10 +3415,10 @@ \pnum A \term{range adaptor closure object} is a unary function object that accepts -a \libconcept{viewable_range} argument and returns a \libconcept{view}. For +a \libconcept{range} argument. For a range adaptor closure object \tcode{C} and an expression \tcode{R} such that -\tcode{decltype((R))} models \libconcept{viewable_range}, the following -expressions are equivalent and yield a \libconcept{view}: +\tcode{decltype((R))} models \libconcept{range}, the following +expressions are equivalent: \begin{codeblock} C(R) R | C @@ -3148,7 +3426,7 @@ Given an additional range adaptor closure object \tcode{D}, the expression \tcode{C | D} produces another range adaptor closure object \tcode{E}. -\tcode{E} is a perfect forwarding call wrapper\iref{func.require} +\tcode{E} is a perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} with the following properties: \begin{itemize} \item @@ -3166,6 +3444,42 @@ The expression \tcode{C | D} is well-formed if and only if the initializations of the state entities of \tcode{E} are all well-formed. +\pnum +Given an object \tcode{t} of type \tcode{T}, where +\begin{itemize} +\item +\tcode{t} is a unary function object that accepts a \libconcept{range} argument, +\item +\tcode{T} models \tcode{\libconcept{derived_from}>}, +\item +\tcode{T} has no other base classes of type \tcode{range_adaptor_closure} for any other type \tcode{U}, and +\item +\tcode{T} does not model \libconcept{range} +\end{itemize} +then the implementation ensures +that \tcode{t} is a range adaptor closure object. + +\pnum +The template parameter \tcode{D} for \tcode{range_adaptor_closure} +may be an incomplete type. +If an expression of type \cv{} \tcode{D} +is used as an operand to the \tcode{|} operator, +\tcode{D} shall be complete and +model \tcode{\libconcept{derived_from}>}. +The behavior of an expression involving an object of type \cv{} \tcode{D} +as an operand to the \tcode{|} operator is undefined +if overload resolution selects a program-defined \tcode{operator|} function. + +\pnum +If an expression of type \cv{} \tcode{U} +is used as an operand to the \tcode{|} operator, +where \tcode{U} has a base class of type \tcode{range_adaptor_closure} +for some type \tcode{T} other than \tcode{U}, the behavior is undefined. + +\pnum +The behavior of a program +that adds a specialization for \tcode{range_adaptor_closure} is undefined. + \pnum A \term{range adaptor object} is a customization point object\iref{customization.point.object} @@ -3186,7 +3500,7 @@ let \tcode{BoundArgs} be a pack that denotes \tcode{decay_t...}. The expression \tcode{adaptor(args...)} produces a range adaptor closure object \tcode{f} -that is a perfect forwarding call wrapper with the following properties: +that is a perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} with the following properties: \begin{itemize} \item Its target object is a copy of \tcode{adaptor}. @@ -3447,9 +3761,9 @@ owning_view& operator=(owning_view&&) = default; constexpr R& base() & noexcept { return @\exposid{r_}@; } - constexpr const R& base() const& noexcept { return @\exposid{r_}@; } + constexpr const R& base() const & noexcept { return @\exposid{r_}@; } constexpr R&& base() && noexcept { return std::move(@\exposid{r_}@); } - constexpr const R&& base() const&& noexcept { return std::move(@\exposid{r_}@); } + constexpr const R&& base() const && noexcept { return std::move(@\exposid{r_}@); } constexpr iterator_t begin() { return ranges::begin(@\exposid{r_}@); } constexpr sentinel_t end() { return ranges::end(@\exposid{r_}@); } @@ -3537,7 +3851,7 @@ filter_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; constexpr filter_view(V base, Pred pred); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr const Pred& pred() const; @@ -3964,7 +4278,7 @@ transform_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; constexpr transform_view(V base, F fun); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr @\exposid{iterator}@ begin(); @@ -4125,7 +4439,8 @@ constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; constexpr iterator_t<@\exposid{Base}@> base() &&; - constexpr decltype(auto) operator*() const { + constexpr decltype(auto) operator*() const + noexcept(noexcept(invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *@\exposid{current_}@))) { return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *@\exposid{current_}@); } @@ -4169,14 +4484,6 @@ requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; - - friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& i) - noexcept(noexcept(invoke(*i.@\exposid{parent_}@->@\exposid{fun_}@, *i.@\exposid{current_}@))) { - if constexpr (is_lvalue_reference_v) - return std::move(*i); - else - return *i; - } }; } \end{codeblock} @@ -4695,7 +5002,7 @@ take_view() requires @\libconcept{default_initializable}@ = default; constexpr take_view(V base, range_difference_t count); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() requires (!@\exposconcept{simple-view}@) { @@ -4910,7 +5217,7 @@ take_while_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; constexpr take_while_view(V base, Pred pred); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr const Pred& pred() const; @@ -4969,7 +5276,7 @@ requires @\libconcept{input_range}@ && is_object_v && @\libconcept{indirect_unary_predicate}@> template - class take_while_view::@\exposidnc{sentinel}@ { // \expos + class take_while_view::@\exposidnc{sentinel}@ { using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos sentinel_t<@\exposidnc{Base}@> @\exposid{end_}@ = sentinel_t<@\exposidnc{Base}@>(); // \expos @@ -5119,7 +5426,7 @@ drop_view() requires @\libconcept{default_initializable}@ = default; constexpr drop_view(V base, range_difference_t count); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() @@ -5244,7 +5551,7 @@ drop_while_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; constexpr drop_while_view(V base, Pred pred); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr const Pred& pred() const; @@ -5370,7 +5677,7 @@ join_view() requires @\libconcept{default_initializable}@ = default; constexpr explicit join_view(V base); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() { @@ -5804,305 +6111,403 @@ Equivalent to: \tcode{return x.\exposid{outer_} == y.\exposid{end_};} \end{itemdescr} -\rSec2[range.lazy.split]{Lazy split view} +\rSec2[range.join.with]{Join with view} -\rSec3[range.lazy.split.overview]{Overview} +\rSec3[range.join.with.overview]{Overview} \pnum -\tcode{lazy_split_view} takes a \libconcept{view} and a delimiter, and splits -the \libconcept{view} into subranges on the delimiter. The delimiter can be -a single element or a \libconcept{view} of elements. +\tcode{join_with_view} takes a \libconcept{view} and a delimiter, and +flattens the \libconcept{view}, +inserting every element of the delimiter +in between elements of the \libconcept{view}. +The delimiter can be a single element or a \libconcept{view} of elements. \pnum -\indexlibrarymember{lazy_split}{views}% -The name \tcode{views::lazy_split} denotes a -range adaptor object\iref{range.adaptor.object}. +\indexlibrarymember{join_with}{views}% +The name \tcode{views::join_with} denotes +a range adaptor object\iref{range.adaptor.object}. Given subexpressions \tcode{E} and \tcode{F}, -the expression \tcode{views::lazy_split(E, F)} is expression-equivalent to -\tcode{lazy_split_view(E, F)}. +the expression \tcode{views::join_with(E, F)} is expression-equivalent to +\tcode{join_with_view(E, F)}. \pnum \begin{example} \begin{codeblock} -string str{"the quick brown fox"}; -for (auto word : str | views::lazy_split(' ')) { - for (char ch : word) - cout << ch; - cout << '*'; +vector vs = {"the", "quick", "brown", "fox"}; +for (char c : vs | join_with('-')) { + cout << c; } -// The above prints: the*quick*brown*fox* \end{codeblock} +The above prints: \tcode{the-quick-brown-fox} \end{example} -\rSec3[range.lazy.split.view]{Class template \tcode{lazy_split_view}} +\rSec3[range.join.with.view]{Class template \tcode{join_with_view}} -\indexlibraryglobal{lazy_split_view}% -\indexlibrarymember{base}{lazy_split_view}% -\indexlibrarymember{begin}{lazy_split_view}% -\indexlibrarymember{end}{lazy_split_view}% \begin{codeblock} namespace std::ranges { - template struct @\exposidnc{require-constant}@; // \expos + template + concept @\defexposconcept{compatible-joinable-ranges}@ = // \expos + @\libconcept{common_with}@, range_value_t

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

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

>; template - concept @\defexposconceptnc{tiny-range}@ = // \expos - @\libconcept{sized_range}@ && - requires { typename @\exposid{require-constant}@::size()>; } && - (remove_reference_t::size() <= 1); + concept @\defexposconcept{bidirectional-common}@ = @\libconcept{bidirectional_range}@ && @\libconcept{common_range}@; // \expos template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> - requires @\libconcept{view}@ && @\libconcept{view}@ && - @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> && - (@\libconcept{forward_range}@ || @\exposconcept{tiny-range}@) - class lazy_split_view : public view_interface> { - private: - V @\exposid{base_}@ = V(); // \expos - Pattern @\exposid{pattern_}@ = Pattern(); // \expos + requires @\libconcept{view}@ && @\libconcept{input_range}@> + && @\libconcept{view}@ + && @\exposconcept{compatible-joinable-ranges}@, Pattern> + class join_with_view : public view_interface> { + using @\exposid{InnerRng}@ = range_reference_t; // \expos - @\exposidnc{non-propagating-cache}@> @\exposid{current_}@; // \expos, present only - // if \tcode{!\libconcept{forward_range}} + V @\exposid{base_}@ = V(); // \expos + @\exposid{non-propagating-cache}@> @\exposid{inner_}@; // \expos, present only + // when \tcode{!is_reference_v<\exposid{InnerRng}>} + Pattern @\exposid{pattern_}@ = Pattern(); // \expos - // \ref{range.lazy.split.outer}, class template \tcode{lazy_split_view::\exposid{outer-iterator}} - template struct @\exposidnc{outer-iterator}@; // \expos + // \ref{range.join.with.iterator}, class template \tcode{join_with_view::\exposid{iterator}} + template struct @\exposid{iterator}@; // \expos - // \ref{range.lazy.split.inner}, class template \tcode{lazy_split_view::\exposid{inner-iterator}} - template struct @\exposidnc{inner-iterator}@; // \expos + // \ref{range.join.with.sentinel}, class template \tcode{join_with_view::\exposid{sentinel}} + template struct @\exposid{sentinel}@; // \expos public: - lazy_split_view() + join_with_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; - constexpr lazy_split_view(V base, Pattern pattern); - template<@\libconcept{input_range}@ R> + constexpr join_with_view(V base, Pattern pattern); + + template requires @\libconcept{constructible_from}@> && - @\libconcept{constructible_from}@>> - constexpr lazy_split_view(R&& r, range_value_t e); + @\libconcept{constructible_from}@>> + constexpr join_with_view(R&& r, range_value_t<@\exposid{InnerRng}@> e); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() { - if constexpr (@\libconcept{forward_range}@) { - return @\exposid{outer-iterator}@<@\exposconcept{simple-view}@ && @\exposconcept{simple-view}@> - {*this, ranges::begin(@\exposid{base_}@)}; - } else { - @\exposid{current_}@ = ranges::begin(@\exposid{base_}@); - return @\exposid{outer-iterator}@{*this}; - } + constexpr bool use_const = + @\exposconcept{simple-view}@ && is_reference_v<@\exposid{InnerRng}@> && @\exposconcept{simple-view}@; + return @\exposid{iterator}@{*this, ranges::begin(@\exposid{base_}@)}; } - - constexpr auto begin() const requires @\libconcept{forward_range}@ && @\libconcept{forward_range}@ { - return @\exposid{outer-iterator}@{*this, ranges::begin(@\exposid{base_}@)}; + constexpr auto begin() const + requires @\libconcept{input_range}@ && + @\libconcept{forward_range}@ && + is_reference_v> { + return @\exposid{iterator}@{*this, ranges::begin(@\exposid{base_}@)}; } - constexpr auto end() requires @\libconcept{forward_range}@ && @\libconcept{common_range}@ { - return @\exposid{outer-iterator}@<@\exposconcept{simple-view}@ && @\exposconcept{simple-view}@> - {*this, ranges::end(@\exposid{base_}@)}; + constexpr auto end() { + if constexpr (@\libconcept{forward_range}@ && + is_reference_v<@\exposid{InnerRng}@> && @\libconcept{forward_range}@<@\exposid{InnerRng}@> && + @\libconcept{common_range}@ && @\libconcept{common_range}@<@\exposid{InnerRng}@>) + return @\exposid{iterator}@<@\exposconcept{simple-view}@ && @\exposconcept{simple-view}@>{*this, ranges::end(@\exposid{base_}@)}; + else + return @\exposid{sentinel}@<@\exposconcept{simple-view}@ && @\exposconcept{simple-view}@>{*this}; } - - constexpr auto end() const { - if constexpr (@\libconcept{forward_range}@ && @\libconcept{forward_range}@ && @\libconcept{common_range}@) - return @\exposid{outer-iterator}@{*this, ranges::end(@\exposid{base_}@)}; + constexpr auto end() const + requires @\libconcept{input_range}@ && @\libconcept{forward_range}@ && + is_reference_v> { + using InnerConstRng = range_reference_t; + if constexpr (@\libconcept{forward_range}@ && @\libconcept{forward_range}@ && + @\libconcept{common_range}@ && common_range) + return @\exposid{iterator}@{*this, ranges::end(@\exposid{base_}@)}; else - return default_sentinel; + return @\exposid{sentinel}@{*this}; } }; template - lazy_split_view(R&&, P&&) -> lazy_split_view, views::all_t

>; + join_with_view(R&&, P&&) -> join_with_view, views::all_t

>; template<@\libconcept{input_range}@ R> - lazy_split_view(R&&, range_value_t) - -> lazy_split_view, single_view>>; + join_with_view(R&&, range_value_t>) + -> join_with_view, single_view>>>; } \end{codeblock} -\indexlibraryctor{lazy_split_view}% \begin{itemdecl} -constexpr lazy_split_view(V base, Pattern pattern); +constexpr join_with_view(V base, Pattern pattern); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{base_} with \tcode{std::move(base)}, and +Initializes \exposid{base_} with \tcode{std::move(base)} and \exposid{pattern_} with \tcode{std::move(pattern)}. \end{itemdescr} -\indexlibraryctor{lazy_split_view}% \begin{itemdecl} template<@\libconcept{input_range}@ R> requires @\libconcept{constructible_from}@> && - @\libconcept{constructible_from}@>> -constexpr lazy_split_view(R&& r, range_value_t e); + @\libconcept{constructible_from}@>> +constexpr join_with_view(R&& r, range_value_t<@\exposid{InnerRng}@> e); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{base_} with \tcode{views::all(std::forward(r))}, and -\exposid{pattern_} with \tcode{views::\linebreak single(std::move(e))}. +Initializes \exposid{base_} with \tcode{views::all(std::forward(r))} and +\exposid{pattern_} with \tcode{views::sin\-gle(std::move(e))}. \end{itemdescr} -\rSec3[range.lazy.split.outer]{Class template \tcode{lazy_split_view::\exposid{outer-iterator}}} +\rSec3[range.join.with.iterator]{Class template \tcode{join_with_view::\exposid{iterator}}} -\indexlibraryglobal{lazy_split_view::\exposid{outer-iterator}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> - requires @\libconcept{view}@ && @\libconcept{view}@ && - @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> && - (@\libconcept{forward_range}@ || @\exposconcept{tiny-range}@) + requires @\libconcept{view}@ && @\libconcept{input_range}@> + && @\libconcept{view}@ && @\exposconcept{compatible-joinable-ranges}@, Pattern> template - struct lazy_split_view::@\exposid{outer-iterator}@ { - private: - using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + class join_with_view::@\exposid{iterator}@ { + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{InnerBase}@ = range_reference_t; // \expos + using @\exposid{PatternBase}@ = @\exposid{maybe-const}@; // \expos - iterator_t<@\exposidnc{Base}@> @\exposid{current_}@ = iterator_t<@\exposidnc{Base}@>(); // \expos, present only - // if \tcode{V} models \libconcept{forward_range} + using @\exposid{OuterIter}@ = iterator_t<@\exposid{Base}@>; // \expos + using @\exposid{InnerIter}@ = iterator_t<@\exposid{InnerBase}@>; // \expos + using @\exposid{PatternIter}@ = iterator_t<@\exposid{PatternBase}@>; // \expos - bool @\exposid{trailing_empty_}@ = false; // \expos + static constexpr bool @\exposid{ref-is-glvalue}@ = is_reference_v<@\exposid{InnerBase}@>; // \expos + + @\exposid{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposid{OuterIter}@ @\exposid{outer_it_}@ = @\exposid{OuterIter}@(); // \expos + variant<@\exposid{PatternIter}@, @\exposid{InnerIter}@> @\exposid{inner_it_}@; // \expos + + constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> outer); // \expos + constexpr auto&& @\exposid{update-inner}@(const @\exposid{OuterIter}@&); // \expos + constexpr auto&& @\exposid{get-inner}@(const @\exposid{OuterIter}@&); // \expos + constexpr void @\exposid{satisfy}@(); // \expos public: - using iterator_concept = - conditional_t<@\libconcept{forward_range}@<@\exposid{Base}@>, forward_iterator_tag, input_iterator_tag>; + using iterator_concept = @\seebelow@; + using iterator_category = @\seebelow@; // not always present + using value_type = @\seebelow@; + using difference_type = @\seebelow@; - using iterator_category = input_iterator_tag; // present only if \exposid{Base} - // models \libconcept{forward_range} + @\exposid{iterator}@() requires @\libconcept{default_initializable}@<@\exposid{OuterIter}@> = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, @\exposid{OuterIter}@> && + @\libconcept{convertible_to}@, @\exposid{InnerIter}@> && + @\libconcept{convertible_to}@, @\exposid{PatternIter}@>; - // \ref{range.lazy.split.outer.value}, class \tcode{lazy_split_view::\exposid{outer-iterator}::value_type} - struct value_type; - using difference_type = range_difference_t<@\exposid{Base}@>; + constexpr decltype(auto) operator*() const; - @\exposid{outer-iterator}@() = default; - constexpr explicit @\exposid{outer-iterator}@(@\exposid{Parent}@& parent) - requires (!@\libconcept{forward_range}@<@\exposid{Base}@>); - constexpr @\exposid{outer-iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current) - requires @\libconcept{forward_range}@<@\exposid{Base}@>; - constexpr @\exposid{outer-iterator}@(@\exposid{outer-iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); + constexpr @\exposid{iterator}@ operator++(int) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_iterator}@<@\exposid{OuterIter}@> && + @\libconcept{forward_iterator}@<@\exposid{InnerIter}@>; - constexpr value_type operator*() const; + constexpr @\exposid{iterator}@& operator--() + requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && + @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; + constexpr @\exposid{iterator}@ operator--(int) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && + @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; - constexpr @\exposid{outer-iterator}@& operator++(); - constexpr decltype(auto) operator++(int) { - if constexpr (@\libconcept{forward_range}@<@\exposid{Base}@>) { - auto tmp = *this; - ++*this; - return tmp; - } else - ++*this; + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{equality_comparable}@<@\exposid{OuterIter}@> && + @\libconcept{equality_comparable}@<@\exposid{InnerIter}@>; + + friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& x) { + using rvalue_reference = common_reference_t< + iter_rvalue_reference_t<@\exposid{InnerIter}@>, + iter_rvalue_reference_t<@\exposid{PatternIter}@>>; + return visit(ranges::iter_move, x.@\exposid{inner_it_}@); } - friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, const @\exposid{outer-iterator}@& y) - requires @\libconcept{forward_range}@<@\exposid{Base}@>; - - friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); + friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{indirectly_swappable}@<@\exposid{InnerIter}@, @\exposid{PatternIter}@> { + visit(ranges::iter_swap, x.@\exposid{inner_it_}@, y.@\exposid{inner_it_}@); + } }; } \end{codeblock} \pnum -Many of the specifications in \ref{range.lazy.split} refer to the notional member -\placeholder{current} of \exposid{outer-iterator}. -\placeholder{current} is equivalent to \exposid{current_} if \tcode{V} -models \libconcept{forward_range}, and \tcode{*\exposid{parent_}->\exposid{current_}} otherwise. +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If \exposid{ref-is-glvalue} is \tcode{true}, +\exposid{Base} models \libconcept{bidirectional_range}, and +\exposid{InnerBase} and \exposid{PatternBase} +each model \exposconcept{bidirectional-common}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, if \exposid{ref-is-glvalue} is \tcode{true} and +\exposid{Base} and \exposid{InnerBase} each model \libconcept{forward_range}, +then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. +\end{itemize} + +\pnum +The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +if and only if \exposid{ref-is-glvalue} is \tcode{true}, and +\exposid{Base} and \exposid{InnerBase} each model \libconcept{forward_range}. +In that case, +\tcode{\exposid{iterator}::iterator_category} is defined as follows: + +\begin{itemize} +\item +Let \placeholder{OUTERC} denote +\tcode{iterator_traits<\exposid{OuterIter}>::iterator_category}, +let \placeholder{INNERC} denote +\tcode{iterator_traits<\exposid{InnerIter}>::iterator_category}, and +let \placeholder{PATTERNC} denote +\tcode{iterator_-\linebreak traits<\exposid{PatternIter}>::iterator_category}. +\item +If +\begin{codeblock} +is_lvalue_reference_v, + iter_reference_t<@\exposid{PatternIter}@>>> +\end{codeblock} +is \tcode{false}, +\tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\item +Otherwise, +if \placeholder{OUTERC}, \placeholder{INNERC}, and \placeholder{PATTERNC} +each model \tcode{\libconcept{derived_from}} +and \exposid{InnerBase} and \exposid{PatternBase} +each model \libconcept{common_range}, +\tcode{iterator_cate\-gory} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, +if \placeholder{OUTERC}, \placeholder{INNERC}, and \placeholder{PATTERNC} +each model \tcode{\libconcept{derived_from}}, +\tcode{iterator_category} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\end{itemize} + +\pnum +\tcode{\exposid{iterator}::value_type} denotes the type: +\begin{codeblock} +common_type_t, iter_value_t<@\exposid{PatternIter}@>> +\end{codeblock} + +\pnum +\tcode{\exposid{iterator}::difference_type} denotes the type: +\begin{codeblock} +common_type_t< + iter_difference_t<@\exposid{OuterIter}@>, + iter_difference_t<@\exposid{InnerIter}@>, + iter_difference_t<@\exposid{PatternIter}@>> +\end{codeblock} -\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -constexpr explicit @\exposid{outer-iterator}@(@\exposid{Parent}@& parent) - requires (!@\libconcept{forward_range}@<@\exposid{Base}@>); +constexpr auto&& @\exposid{update-inner}@(const @\exposid{OuterIter}@& x); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{addressof(parent)}. +Equivalent to: +\begin{codeblock} +if constexpr (@\exposid{ref-is-glvalue}@) + return *x; +else + return @\exposid{parent_}@->@\exposid{inner_}@.@\exposid{emplace-deref}@(x); +\end{codeblock} \end{itemdescr} -\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -constexpr @\exposid{outer-iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current) - requires @\libconcept{forward_range}@<@\exposid{Base}@>; +constexpr auto&& @\exposid{get-inner}@(const @\exposid{OuterIter}@& x); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{addressof(parent)} -and \exposid{current_} with \tcode{std::move(current)}. +Equivalent to: +\begin{codeblock} +if constexpr (@\exposid{ref-is-glvalue}@) + return *x; +else + return *@\exposid{parent_}@->@\exposid{inner_}@; +\end{codeblock} \end{itemdescr} -\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -constexpr @\exposid{outer-iterator}@(@\exposid{outer-iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +constexpr void @\exposid{satisfy}@(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and -\exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +Equivalent to: +\begin{codeblock} +while (true) { + if (@\exposid{inner_it_}@.index() == 0) { + if (std::get<0>(@\exposid{inner_it_}@) != ranges::end(@\exposid{parent_}@->@\exposid{pattern_}@)) + break; + auto&& inner = @\exposid{update-inner}@(@\exposid{outer_it_}@); + @\exposid{inner_it_}@.emplace<1>(ranges::begin(inner)); + } else { + auto&& inner = @\exposid{get-inner}@(@\exposid{outer_it_}@); + if (std::get<1>(@\exposid{inner_it_}@) != ranges::end(inner)) + break; + if (++@\exposid{outer_it_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { + if constexpr (@\exposid{ref-is-glvalue}@) + @\exposid{inner_it_}@.emplace<0>(); + break; + } + @\exposid{inner_it_}@.emplace<0>(ranges::begin(@\exposid{parent_}@->@\exposid{pattern_}@)); + } +} +\end{codeblock} + +\begin{note} +\tcode{join_with_view} iterators use the \exposid{satisfy} function +to skip over empty inner ranges. +\end{note} \end{itemdescr} -\indexlibrarymember{operator*}{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -constexpr value_type operator*() const; +constexpr iterator(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> outer); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return value_type\{*this\};} +Initializes \exposid{parent_} with \tcode{addressof(parent)} and +\exposid{outer_it_} with \tcode{std::move(outer)}. +Then, equivalent to: +\begin{codeblock} +if (@\exposid{outer_it_}@ != ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { + auto&& inner = @\exposid{update-inner}@(@\exposid{outer_it_}@); + @\exposid{inner_it_}@.emplace<1>(ranges::begin(inner)); + @\exposidnc{satisfy}@(); +} +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -constexpr @\exposid{outer-iterator}@& operator++(); +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && convertible_to, @\exposid{OuterIter}@> && + convertible_to, @\exposid{InnerIter}@> && + convertible_to, @\exposid{PatternIter}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: +Initializes \exposid{outer_it_} with +\tcode{std::move(i.\exposid{outer_it_})} and +\exposid{parent_} with \tcode{i.\exposid{parent_}}. +Then, equivalent to: \begin{codeblock} -const auto end = ranges::end(@\exposid{parent_}@->@\exposid{base_}@); -if (@\placeholder{current}@ == end) { - @\exposid{trailing_empty_}@ = false; - return *this; -} -const auto [pbegin, pend] = subrange{@\exposid{parent_}@->@\exposid{pattern_}@}; -if (pbegin == pend) ++@\placeholder{current}@; -else if constexpr (@\exposconcept{tiny-range}@) { - @\placeholder{current}@ = ranges::find(std::move(@\placeholder{current}@), end, *pbegin); - if (@\placeholder{current}@ != end) { - ++@\placeholder{current}@; - if (@\placeholder{current}@ == end) - @\exposid{trailing_empty_}@ = true; - } -} -else { - do { - auto [b, p] = ranges::mismatch(@\placeholder{current}@, end, pbegin, pend); - if (p == pend) { - @\placeholder{current}@ = b; - if (@\placeholder{current}@ == end) - @\exposid{trailing_empty_}@ = true; - break; // The pattern matched; skip it - } - } while (++@\placeholder{current}@ != end); -} -return *this; +if (i.@\exposid{inner_it_}@.index() == 0) + @\exposid{inner_it_}@.emplace<0>(std::get<0>(std::move(i.@\exposid{inner_it_}@))); +else + @\exposid{inner_it_}@.emplace<1>(std::get<1>(std::move(i.@\exposid{inner_it_}@))); \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator==}{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, const @\exposid{outer-iterator}@& y) - requires @\libconcept{forward_range}@<@\exposid{Base}@>; +constexpr decltype(auto) operator*() const; \end{itemdecl} \begin{itemdescr} @@ -6110,13 +6515,14 @@ \effects Equivalent to: \begin{codeblock} -return x.@\exposid{current_}@ == y.@\exposid{current_}@ && x.@\exposid{trailing_empty_}@ == y.@\exposid{trailing_empty_}@; +using reference = + common_reference_t, iter_reference_t<@\exposid{PatternIter}@>>; +return visit([](auto& it) -> reference { return *it; }, @\exposid{inner_it_}@); \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator==}{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); +constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} @@ -6124,330 +6530,285 @@ \effects Equivalent to: \begin{codeblock} -return x.@\placeholdernc{current}@ == ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) && !x.@\exposid{trailing_empty_}@; +visit([](auto& it){ ++it; }, @\exposid{inner_it_}@); +@\exposidnc{satisfy}@(); +return *this; \end{codeblock} \end{itemdescr} -\rSec3[range.lazy.split.outer.value]{Class \tcode{lazy_split_view::\exposid{outer-iterator}::value_type}} +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} -\indexlibraryglobal{lazy_split_view::\exposid{outer-iterator}::value_type}% -\begin{codeblock} -namespace std::ranges { - template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> - requires @\libconcept{view}@ && @\libconcept{view}@ && - @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> && - (@\libconcept{forward_range}@ || @\exposconcept{tiny-range}@) - template - struct lazy_split_view::@\exposid{outer-iterator}@::value_type - : view_interface { - private: - @\exposid{outer-iterator}@ @\exposid{i_}@ = @\exposid{outer-iterator}@(); // \expos - public: - value_type() = default; - constexpr explicit value_type(@\exposid{outer-iterator}@ i); +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{++*this}. +\end{itemdescr} - constexpr @\exposid{inner-iterator}@ begin() const; - constexpr default_sentinel_t end() const noexcept; - }; -} +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_iterator}@<@\exposid{OuterIter}@> && @\libconcept{forward_iterator}@<@\exposid{InnerIter}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{iterator}@ tmp = *this; +++*this; +return tmp; \end{codeblock} +\end{itemdescr} -\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}::value_type}% \begin{itemdecl} -constexpr explicit value_type(@\exposid{outer-iterator}@ i); +constexpr @\exposid{iterator}@& operator--() + requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && + @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{i_} with \tcode{std::move(i)}. +Equivalent to: +\begin{codeblock} +if (@\exposid{outer_it_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { + auto&& inner = *--@\exposid{outer_it_}@; + @\exposid{inner_it_}@.emplace<1>(ranges::end(inner)); +} + +while (true) { + if (@\exposid{inner_it_}@.index() == 0) { + auto& it = std::get<0>(@\exposid{inner_it_}@); + if (it == ranges::begin(@\exposid{parent_}@->@\exposid{pattern_}@)) { + auto&& inner = *--@\exposid{outer_it_}@; + @\exposid{inner_it_}@.emplace<1>(ranges::end(inner)); + } else { + break; + } + } else { + auto& it = std::get<1>(@\exposid{inner_it_}@); + auto&& inner = *@\exposid{outer_it_}@; + if (it == ranges::begin(inner)) { + @\exposid{inner_it_}@.emplace<0>(ranges::end(@\exposid{parent_}@->@\exposid{pattern_}@)); + } else { + break; + } + } +} +visit([](auto& it){ --it; }, @\exposid{inner_it_}@); +return *this; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{begin}{lazy_split_view::\exposid{outer-iterator}::value_type}% \begin{itemdecl} -constexpr @\exposid{inner-iterator}@ begin() const; +constexpr @\exposid{iterator}@ operator--(int) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && + @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{inner-iterator}\{\exposid{i_}\};} +Equivalent to: +\begin{codeblock} +@\exposid{iterator}@ tmp = *this; +--*this; +return tmp; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{end}{lazy_split_view::\exposid{outer-iterator}::value_type}% \begin{itemdecl} -constexpr default_sentinel_t end() const noexcept; +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{equality_comparable}@<@\exposid{OuterIter}@> && + @\libconcept{equality_comparable}@<@\exposid{InnerIter}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return default_sentinel;} +Equivalent to: +\begin{codeblock} +return x.@\exposid{outer_it_}@ == y.@\exposid{outer_it_}@ && x.@\exposid{inner_it_}@ == y.@\exposid{inner_it_}@; +\end{codeblock} \end{itemdescr} -\rSec3[range.lazy.split.inner]{Class template \tcode{lazy_split_view::\exposid{inner-iterator}}} +\rSec3[range.join.with.sentinel]{Class template \tcode{join_with_view::\exposid{sentinel}}} -\indexlibraryglobal{lazy_split_view::\exposid{inner-iterator}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> - requires @\libconcept{view}@ && @\libconcept{view}@ && - @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> && - (@\libconcept{forward_range}@ || @\exposconcept{tiny-range}@) + requires @\libconcept{view}@ && @\libconcept{input_range}@> + && @\libconcept{view}@ && @\exposconcept{compatible-joinable-ranges}@, Pattern> template - struct lazy_split_view::@\exposid{inner-iterator}@ { - private: - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - @\exposidnc{outer-iterator}@ @\exposid{i_}@ = @\exposidnc{outer-iterator}@(); // \expos - bool @\exposid{incremented_}@ = false; // \expos - - public: - using iterator_concept = typename @\exposid{outer-iterator}@::iterator_concept; - - using iterator_category = @\seebelownc@; // present only if \exposid{Base} - // models \libconcept{forward_range} - using value_type = range_value_t<@\exposid{Base}@>; - using difference_type = range_difference_t<@\exposid{Base}@>; - - @\exposid{inner-iterator}@() = default; - constexpr explicit @\exposid{inner-iterator}@(@\exposid{outer-iterator}@ i); - - constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; - constexpr iterator_t<@\exposid{Base}@> base() && requires @\libconcept{forward_range}@; - - constexpr decltype(auto) operator*() const { return *@\exposid{i_}@.@\placeholder{current}@; } - - constexpr @\exposid{inner-iterator}@& operator++(); - constexpr decltype(auto) operator++(int) { - if constexpr (@\libconcept{forward_range}@<@\exposid{Base}@>) { - auto tmp = *this; - ++*this; - return tmp; - } else - ++*this; - } - - friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) - requires @\libconcept{forward_range}@<@\exposid{Base}@>; - - friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); - - friend constexpr decltype(auto) iter_move(const @\exposid{inner-iterator}@& i) - noexcept(noexcept(ranges::iter_move(i.@\exposid{i_}@.@\placeholdernc{current}@))) { - return ranges::iter_move(i.@\exposid{i_}@.@\placeholdernc{current}@); - } - - friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) - noexcept(noexcept(ranges::iter_swap(x.@\exposid{i_}@.@\placeholdernc{current}@, y.@\exposid{i_}@.@\placeholdernc{current}@))) - requires @\libconcept{indirectly_swappable}@>; - }; -} -\end{codeblock} - -\pnum -If \exposid{Base} does not model \libconcept{forward_range} -there is no member \tcode{iterator_category}. -Otherwise, the \grammarterm{typedef-name} \tcode{iterator_category} denotes: -\begin{itemize} -\item -\tcode{forward_iterator_tag} if -\tcode{iterator_traits>::iterator_category} models \linebreak -\tcode{\libconcept{derived_from}}; -\item otherwise, \tcode{iterator_traits>::iterator_category}. -\end{itemize} - -\indexlibraryctor{lazy_split_view::\exposid{inner-iterator}}% -\begin{itemdecl} -constexpr explicit @\exposid{inner-iterator}@(@\exposid{outer-iterator}@ i); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \exposid{i_} with \tcode{std::move(i)}. -\end{itemdescr} - -\indexlibrarymember{base}{lazy_split_view::\exposid{inner-iterator}}% -\begin{itemdecl} -constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return \exposid{i_}.\placeholder{current};} -\end{itemdescr} - -\indexlibrarymember{base}{lazy_split_view::\exposid{inner-iterator}}% -\begin{itemdecl} -constexpr iterator_t<@\exposid{Base}@> base() && requires @\libconcept{forward_range}@; -\end{itemdecl} + class join_with_view::@\exposid{sentinel}@ { + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return std::move(\exposid{i_}.\placeholder{current});} -\end{itemdescr} + constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent); // \expos -\indexlibrarymember{operator++}{lazy_split_view::\exposid{inner-iterator}}% -\begin{itemdecl} -constexpr @\exposid{inner-iterator}@& operator++(); -\end{itemdecl} + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ s) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{incremented_}@ = true; -if constexpr (!@\libconcept{forward_range}@<@\exposid{Base}@>) { - if constexpr (Pattern::size() == 0) { - return *this; - } -} -++@\exposid{i_}@.@\placeholder{current}@; -return *this; + template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +}; \end{codeblock} -\end{itemdescr} -\indexlibrarymember{operator==}{lazy_split_view::\exposid{inner-iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) - requires @\libconcept{forward_range}@<@\exposid{Base}@>; +constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{i_}.\placeholder{current} == y.\exposid{i_}.\placeholder{current};} +Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}. \end{itemdescr} -\indexlibrarymember{operator==}{lazy_split_view::\exposid{inner-iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ s) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -auto [pcur, pend] = subrange{x.@\exposid{i_}@.@\exposid{parent_}@->@\exposid{pattern_}@}; -auto end = ranges::end(x.@\exposid{i_}@.@\exposid{parent_}@->@\exposid{base_}@); -if constexpr (@\exposconcept{tiny-range}@) { - const auto & cur = x.@\exposid{i_}@.@\placeholder{current}@; - if (cur == end) return true; - if (pcur == pend) return x.@\exposid{incremented_}@; - return *cur == *pcur; -} else { - auto cur = x.@\exposid{i_}@.@\placeholder{current}@; - if (cur == end) return true; - if (pcur == pend) return x.@\exposid{incremented_}@; - do { - if (*cur != *pcur) return false; - if (++pcur == pend) return true; - } while (++cur != end); - return false; -} -\end{codeblock} +Initializes \exposid{end_} with \tcode{std::move(s.\exposid{end_})}. \end{itemdescr} -\indexlibrarymember{iter_swap}{lazy_split_view::\exposid{inner-iterator}}% \begin{itemdecl} -friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) - noexcept(noexcept(ranges::iter_swap(x.@\exposid{i_}@.@\placeholdernc{current}@, y.@\exposid{i_}@.@\placeholdernc{current}@))) - requires @\libconcept{indirectly_swappable}@>; +template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to -\tcode{ranges::iter_swap(x.\exposid{i_}.\placeholdernc{current}, y.\exposid{i_}.\placeholdernc{current})}. +Equivalent to: \tcode{return x.\exposid{outer_it_} == y.\exposid{end_};} \end{itemdescr} -\rSec2[range.split]{Split view} +\rSec2[range.lazy.split]{Lazy split view} -\rSec3[range.split.overview]{Overview} +\rSec3[range.lazy.split.overview]{Overview} \pnum -\tcode{split_view} takes a \libconcept{view} and a delimiter, and -splits the \libconcept{view} into \tcode{subrange}s on the delimiter. -The delimiter can be a single element or a \libconcept{view} of elements. +\tcode{lazy_split_view} takes a \libconcept{view} and a delimiter, and splits +the \libconcept{view} into subranges on the delimiter. The delimiter can be +a single element or a \libconcept{view} of elements. \pnum -The name \tcode{views::split} denotes -a range adaptor object\iref{range.adaptor.object}. +\indexlibrarymember{lazy_split}{views}% +The name \tcode{views::lazy_split} denotes a +range adaptor object\iref{range.adaptor.object}. Given subexpressions \tcode{E} and \tcode{F}, -the expression \tcode{views::split(E, F)} is expression-equivalent to -\tcode{split_view(E, F)}. +the expression \tcode{views::lazy_split(E, F)} is expression-equivalent to +\tcode{lazy_split_view(E, F)}. \pnum \begin{example} \begin{codeblock} string str{"the quick brown fox"}; -for (string_view word : split(str, ' ')) { - cout << word << '*'; +for (auto word : str | views::lazy_split(' ')) { + for (char ch : word) + cout << ch; + cout << '*'; } // The above prints: the*quick*brown*fox* \end{codeblock} \end{example} -\rSec3[range.split.view]{Class template \tcode{split_view}} +\rSec3[range.lazy.split.view]{Class template \tcode{lazy_split_view}} +\indexlibraryglobal{lazy_split_view}% +\indexlibrarymember{base}{lazy_split_view}% +\indexlibrarymember{begin}{lazy_split_view}% +\indexlibrarymember{end}{lazy_split_view}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern> + template struct @\exposidnc{require-constant}@; // \expos + + template + concept @\defexposconceptnc{tiny-range}@ = // \expos + @\libconcept{sized_range}@ && + requires { typename @\exposid{require-constant}@::size()>; } && + (remove_reference_t::size() <= 1); + + template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> requires @\libconcept{view}@ && @\libconcept{view}@ && - @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> - class split_view : public view_interface> { + @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> && + (@\libconcept{forward_range}@ || @\exposconcept{tiny-range}@) + class lazy_split_view : public view_interface> { private: - V @\exposid{base_}@ = V(); // \expos - Pattern @\exposid{pattern_}@ = Pattern(); // \expos + V @\exposid{base_}@ = V(); // \expos + Pattern @\exposid{pattern_}@ = Pattern(); // \expos - // \ref{range.split.iterator}, class \tcode{split_view::\exposid{iterator}} - struct @\exposid{iterator}@; // \expos + @\exposidnc{non-propagating-cache}@> @\exposid{current_}@; // \expos, present only + // if \tcode{!\libconcept{forward_range}} - // \ref{range.split.sentinel}, class \tcode{split_view::\exposid{sentinel}} - struct @\exposid{sentinel}@; // \expos + // \ref{range.lazy.split.outer}, class template \tcode{lazy_split_view::\exposid{outer-iterator}} + template struct @\exposidnc{outer-iterator}@; // \expos + + // \ref{range.lazy.split.inner}, class template \tcode{lazy_split_view::\exposid{inner-iterator}} + template struct @\exposidnc{inner-iterator}@; // \expos public: - split_view() + lazy_split_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; - constexpr split_view(V base, Pattern pattern); + constexpr lazy_split_view(V base, Pattern pattern); - template<@\libconcept{forward_range}@ R> + template<@\libconcept{input_range}@ R> requires @\libconcept{constructible_from}@> && @\libconcept{constructible_from}@>> - constexpr split_view(R&& r, range_value_t e); + constexpr lazy_split_view(R&& r, range_value_t e); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } - constexpr @\exposid{iterator}@ begin(); - - constexpr auto end() { - if constexpr (@\libconcept{common_range}@) { - return @\exposid{iterator}@{*this, ranges::end(@\exposid{base_}@), {}}; + constexpr auto begin() { + if constexpr (@\libconcept{forward_range}@) { + return @\exposid{outer-iterator}@<@\exposconcept{simple-view}@ && @\exposconcept{simple-view}@> + {*this, ranges::begin(@\exposid{base_}@)}; } else { - return @\exposid{sentinel}@{*this}; + @\exposid{current_}@ = ranges::begin(@\exposid{base_}@); + return @\exposid{outer-iterator}@{*this}; } } - constexpr subrange> @\exposid{find-next}@(iterator_t); // \expos + constexpr auto begin() const requires @\libconcept{forward_range}@ && @\libconcept{forward_range}@ { + return @\exposid{outer-iterator}@{*this, ranges::begin(@\exposid{base_}@)}; + } + + constexpr auto end() requires @\libconcept{forward_range}@ && @\libconcept{common_range}@ { + return @\exposid{outer-iterator}@<@\exposconcept{simple-view}@ && @\exposconcept{simple-view}@> + {*this, ranges::end(@\exposid{base_}@)}; + } + + constexpr auto end() const { + if constexpr (@\libconcept{forward_range}@ && @\libconcept{forward_range}@ && @\libconcept{common_range}@) + return @\exposid{outer-iterator}@{*this, ranges::end(@\exposid{base_}@)}; + else + return default_sentinel; + } }; template - split_view(R&&, P&&) -> split_view, views::all_t

>; + lazy_split_view(R&&, P&&) -> lazy_split_view, views::all_t

>; - template<@\libconcept{forward_range}@ R> - split_view(R&&, range_value_t) - -> split_view, single_view>>; -} + template<@\libconcept{input_range}@ R> + lazy_split_view(R&&, range_value_t) + -> lazy_split_view, single_view>>; +} \end{codeblock} +\indexlibraryctor{lazy_split_view}% \begin{itemdecl} -constexpr split_view(V base, Pattern pattern); +constexpr lazy_split_view(V base, Pattern pattern); \end{itemdecl} \begin{itemdescr} @@ -6457,12 +6818,12 @@ \exposid{pattern_} with \tcode{std::move(pattern)}. \end{itemdescr} -\indexlibraryctor{split_view}% +\indexlibraryctor{lazy_split_view}% \begin{itemdecl} -template<@\libconcept{forward_range}@ R> +template<@\libconcept{input_range}@ R> requires @\libconcept{constructible_from}@> && @\libconcept{constructible_from}@>> -constexpr split_view(R&& r, range_value_t e); +constexpr lazy_split_view(R&& r, range_value_t e); \end{itemdecl} \begin{itemdescr} @@ -6472,97 +6833,111 @@ \exposid{pattern_} with \tcode{views::\linebreak single(std::move(e))}. \end{itemdescr} -\begin{itemdecl} -constexpr @\exposid{iterator}@ begin(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{\{*this, ranges::begin(\exposid{base_}), \exposid{find-next}(ranges::begin(\exposid{base_}))\}}. - -\pnum -\remarks -In order to provide the amortized constant time complexity -required by the \libconcept{range} concept, -this function caches the result within the \tcode{split_view} -for use on subsequent calls. -\end{itemdescr} - -\begin{itemdecl} -constexpr subrange> @\exposid{find-next}@(iterator_t it); // \expos -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -auto [b, e] = ranges::search(subrange(it, ranges::end(@\exposid{base_}@)), @\exposid{pattern_}@); -if (b != ranges::end(@\exposid{base_}@) && ranges::empty(@\exposid{pattern_}@)) { - ++b; - ++e; -} -return {b, e}; -\end{codeblock} -\end{itemdescr} - -\rSec3[range.split.iterator]{Class \tcode{split_view::\exposid{iterator}}} +\rSec3[range.lazy.split.outer]{Class template \tcode{lazy_split_view::\exposid{outer-iterator}}} +\indexlibraryglobal{lazy_split_view::\exposid{outer-iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern> + template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> requires @\libconcept{view}@ && @\libconcept{view}@ && - @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> - class split_view::@\exposid{iterator}@ { + @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> && + (@\libconcept{forward_range}@ || @\exposconcept{tiny-range}@) + template + struct lazy_split_view::@\exposid{outer-iterator}@ { private: - split_view* @\exposid{parent_}@ = nullptr; // \expos - iterator_t @\exposid{cur_}@ = iterator_t(); // \expos - subrange> @\exposid{next_}@ = subrange>(); // \expos - bool @\exposid{trailing_empty_}@ = false; // \expos + using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + + iterator_t<@\exposidnc{Base}@> @\exposid{current_}@ = iterator_t<@\exposidnc{Base}@>(); // \expos, present only + // if \tcode{V} models \libconcept{forward_range} + + bool @\exposid{trailing_empty_}@ = false; // \expos public: - using iterator_concept = forward_iterator_tag; - using iterator_category = input_iterator_tag; - using value_type = subrange>; - using difference_type = range_difference_t; + using iterator_concept = + conditional_t<@\libconcept{forward_range}@<@\exposid{Base}@>, forward_iterator_tag, input_iterator_tag>; - @\exposid{iterator}@() = default; - constexpr @\exposid{iterator}@(split_view& parent, iterator_t current, subrange> next); + using iterator_category = input_iterator_tag; // present only if \exposid{Base} + // models \libconcept{forward_range} + + // \ref{range.lazy.split.outer.value}, class \tcode{lazy_split_view::\exposid{outer-iterator}::value_type} + struct value_type; + using difference_type = range_difference_t<@\exposid{Base}@>; + + @\exposid{outer-iterator}@() = default; + constexpr explicit @\exposid{outer-iterator}@(@\exposid{Parent}@& parent) + requires (!@\libconcept{forward_range}@<@\exposid{Base}@>); + constexpr @\exposid{outer-iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current) + requires @\libconcept{forward_range}@<@\exposid{Base}@>; + constexpr @\exposid{outer-iterator}@(@\exposid{outer-iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; - constexpr iterator_t base() const; constexpr value_type operator*() const; - constexpr @\exposid{iterator}@& operator++(); - constexpr @\exposid{iterator}@ operator++(int); + constexpr @\exposid{outer-iterator}@& operator++(); + constexpr decltype(auto) operator++(int) { + if constexpr (@\libconcept{forward_range}@<@\exposid{Base}@>) { + auto tmp = *this; + ++*this; + return tmp; + } else + ++*this; + } - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, const @\exposid{outer-iterator}@& y) + requires @\libconcept{forward_range}@<@\exposid{Base}@>; + + friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); }; } \end{codeblock} +\pnum +Many of the specifications in \ref{range.lazy.split} refer to the notional member +\placeholder{current} of \exposid{outer-iterator}. +\placeholder{current} is equivalent to \exposid{current_} if \tcode{V} +models \libconcept{forward_range}, and \tcode{*\exposid{parent_}->\exposid{current_}} otherwise. + +\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(split_view& parent, iterator_t current, subrange> next); +constexpr explicit @\exposid{outer-iterator}@(@\exposid{Parent}@& parent) + requires (!@\libconcept{forward_range}@<@\exposid{Base}@>); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{addressof(parent)}, -\exposid{cur_} with \tcode{std::move(current)}, and -\exposid{next_} with \tcode{std::move(next)}. +Initializes \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} +\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -constexpr iterator_t base() const; +constexpr @\exposid{outer-iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> current) + requires @\libconcept{forward_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to \tcode{return \exposid{cur_};} +Initializes \exposid{parent_} with \tcode{addressof(parent)} +and \exposid{current_} with \tcode{std::move(current)}. +\end{itemdescr} + +\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}}% +\begin{itemdecl} +constexpr @\exposid{outer-iterator}@(@\exposid{outer-iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and +\exposid{current_} with \tcode{std::move(i.\exposid{current_})}. \end{itemdescr} +\indexlibrarymember{operator*}{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} constexpr value_type operator*() const; \end{itemdecl} @@ -6570,11 +6945,12 @@ \begin{itemdescr} \pnum \effects -Equivalent to \tcode{return \{\exposid{cur_}, \exposid{next_}.begin()\};} +Equivalent to: \tcode{return value_type\{*this\};} \end{itemdescr} +\indexlibrarymember{operator++}{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator++(); +constexpr @\exposid{outer-iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} @@ -6582,24 +6958,40 @@ \effects Equivalent to: \begin{codeblock} -@\exposid{cur_}@ = @\exposid{next_}@.begin(); -if (@\exposid{cur_}@ != ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { - @\exposid{cur_}@ = @\exposid{next_}@.end(); - if (@\exposid{cur_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { - @\exposid{trailing_empty_}@ = true; - @\exposid{next_}@ = {@\exposid{cur_}@, @\exposid{cur_}@}; - } else { - @\exposid{next_}@ = @\exposid{parent_}@->@\exposid{find-next}@(@\exposid{cur_}@); - } -} else { +const auto end = ranges::end(@\exposid{parent_}@->@\exposid{base_}@); +if (@\placeholder{current}@ == end) { @\exposid{trailing_empty_}@ = false; + return *this; +} +const auto [pbegin, pend] = subrange{@\exposid{parent_}@->@\exposid{pattern_}@}; +if (pbegin == pend) ++@\placeholder{current}@; +else if constexpr (@\exposconcept{tiny-range}@) { + @\placeholder{current}@ = ranges::find(std::move(@\placeholder{current}@), end, *pbegin); + if (@\placeholder{current}@ != end) { + ++@\placeholder{current}@; + if (@\placeholder{current}@ == end) + @\exposid{trailing_empty_}@ = true; + } +} +else { + do { + auto [b, p] = ranges::mismatch(@\placeholder{current}@, end, pbegin, pend); + if (p == pend) { + @\placeholder{current}@ = b; + if (@\placeholder{current}@ == end) + @\exposid{trailing_empty_}@ = true; + break; // The pattern matched; skip it + } + } while (++@\placeholder{current}@ != end); } return *this; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator==}{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int); +friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, const @\exposid{outer-iterator}@& y) + requires @\libconcept{forward_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -6607,14 +6999,13 @@ \effects Equivalent to: \begin{codeblock} -auto tmp = *this; -++*this; -return tmp; +return x.@\exposid{current_}@ == y.@\exposid{current_}@ && x.@\exposid{trailing_empty_}@ == y.@\exposid{trailing_empty_}@; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator==}{lazy_split_view::\exposid{outer-iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); \end{itemdecl} \begin{itemdescr} @@ -6622,202 +7013,2873 @@ \effects Equivalent to: \begin{codeblock} -return x.@\exposid{cur_}@ == y.@\exposid{cur_}@ && x.@\exposid{trailing_empty_}@ == y.@\exposid{trailing_empty_}@; +return x.@\placeholdernc{current}@ == ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) && !x.@\exposid{trailing_empty_}@; \end{codeblock} \end{itemdescr} -\rSec3[range.split.sentinel]{Class \tcode{split_view::\exposid{sentinel}}} +\rSec3[range.lazy.split.outer.value]{Class \tcode{lazy_split_view::\exposid{outer-iterator}::value_type}} +\indexlibraryglobal{lazy_split_view::\exposid{outer-iterator}::value_type}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern> + template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> requires @\libconcept{view}@ && @\libconcept{view}@ && - @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> - struct split_view::@\exposid{sentinel}@ { + @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> && + (@\libconcept{forward_range}@ || @\exposconcept{tiny-range}@) + template + struct lazy_split_view::@\exposid{outer-iterator}@::value_type + : view_interface { private: - sentinel_t @\exposid{end_}@ = sentinel_t(); // \expos - + @\exposid{outer-iterator}@ @\exposid{i_}@ = @\exposid{outer-iterator}@(); // \expos public: - @\exposid{sentinel}@() = default; - constexpr explicit @\exposid{sentinel}@(split_view& parent); + value_type() = default; + constexpr explicit value_type(@\exposid{outer-iterator}@ i); - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + constexpr @\exposid{inner-iterator}@ begin() const; + constexpr default_sentinel_t end() const noexcept; }; } \end{codeblock} +\indexlibraryctor{lazy_split_view::\exposid{outer-iterator}::value_type}% \begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(split_view& parent); +constexpr explicit value_type(@\exposid{outer-iterator}@ i); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}. +Initializes \exposid{i_} with \tcode{std::move(i)}. \end{itemdescr} +\indexlibrarymember{begin}{lazy_split_view::\exposid{outer-iterator}::value_type}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +constexpr @\exposid{inner-iterator}@ begin() const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{cur_} == y.\exposid{end_} \&\& !x.\exposid{trailing_empty_};} +Equivalent to: \tcode{return \exposid{inner-iterator}\{\exposid{i_}\};} \end{itemdescr} -\rSec2[range.counted]{Counted view} +\indexlibrarymember{end}{lazy_split_view::\exposid{outer-iterator}::value_type}% +\begin{itemdecl} +constexpr default_sentinel_t end() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\indextext{range!counted}% -A counted view presents a \libconcept{view} of the elements -of the counted range\iref{iterator.requirements.general} \countedrange{i}{n} -for an iterator \tcode{i} and non-negative integer \tcode{n}. +\effects +Equivalent to: \tcode{return default_sentinel;} +\end{itemdescr} -\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: +\rSec3[range.lazy.split.inner]{Class template \tcode{lazy_split_view::\exposid{inner-iterator}}} -\begin{itemize} -\item -If \tcode{T} models \libconcept{contiguous_iterator}, -then \tcode{span(to_address(E), static_cast(static_-\linebreak{}cast(F)))}. +\indexlibraryglobal{lazy_split_view::\exposid{inner-iterator}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> + requires @\libconcept{view}@ && @\libconcept{view}@ && + @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> && + (@\libconcept{forward_range}@ || @\exposconcept{tiny-range}@) + template + struct lazy_split_view::@\exposid{inner-iterator}@ { + private: + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + @\exposidnc{outer-iterator}@ @\exposid{i_}@ = @\exposidnc{outer-iterator}@(); // \expos + bool @\exposid{incremented_}@ = false; // \expos -\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. + public: + using iterator_concept = typename @\exposid{outer-iterator}@::iterator_concept; + + using iterator_category = @\seebelownc@; // present only if \exposid{Base} + // models \libconcept{forward_range} + using value_type = range_value_t<@\exposid{Base}@>; + using difference_type = range_difference_t<@\exposid{Base}@>; + + @\exposid{inner-iterator}@() = default; + constexpr explicit @\exposid{inner-iterator}@(@\exposid{outer-iterator}@ i); + + constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; + constexpr iterator_t<@\exposid{Base}@> base() && requires @\libconcept{forward_range}@; + + constexpr decltype(auto) operator*() const { return *@\exposid{i_}@.@\placeholder{current}@; } + + constexpr @\exposid{inner-iterator}@& operator++(); + constexpr decltype(auto) operator++(int) { + if constexpr (@\libconcept{forward_range}@<@\exposid{Base}@>) { + auto tmp = *this; + ++*this; + return tmp; + } else + ++*this; + } + + friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) + requires @\libconcept{forward_range}@<@\exposid{Base}@>; + + friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); + + friend constexpr decltype(auto) iter_move(const @\exposid{inner-iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{i_}@.@\placeholdernc{current}@))) { + return ranges::iter_move(i.@\exposid{i_}@.@\placeholdernc{current}@); + } + + friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) + noexcept(noexcept(ranges::iter_swap(x.@\exposid{i_}@.@\placeholdernc{current}@, y.@\exposid{i_}@.@\placeholdernc{current}@))) + requires @\libconcept{indirectly_swappable}@>; + }; +} +\end{codeblock} +\pnum +If \exposid{Base} does not model \libconcept{forward_range} +there is no member \tcode{iterator_category}. +Otherwise, the \grammarterm{typedef-name} \tcode{iterator_category} denotes: +\begin{itemize} \item -Otherwise, -\tcode{subrange(counted_iterator(E, F), default_sentinel)}. +\tcode{forward_iterator_tag} if +\tcode{iterator_traits>::iterator_category} models \linebreak +\tcode{\libconcept{derived_from}}; +\item otherwise, \tcode{iterator_traits>::iterator_category}. \end{itemize} -\rSec2[range.common]{Common view} +\indexlibraryctor{lazy_split_view::\exposid{inner-iterator}}% +\begin{itemdecl} +constexpr explicit @\exposid{inner-iterator}@(@\exposid{outer-iterator}@ i); +\end{itemdecl} -\rSec3[range.common.overview]{Overview} +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{i_} with \tcode{std::move(i)}. +\end{itemdescr} + +\indexlibrarymember{base}{lazy_split_view::\exposid{inner-iterator}}% +\begin{itemdecl} +constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\tcode{common_view} takes a \libconcept{view} which has different types for -its iterator and sentinel and turns it into a \libconcept{view} of the same -elements with an iterator and sentinel of the same type. +\effects +Equivalent to: \tcode{return \exposid{i_}.\placeholder{current};} +\end{itemdescr} + +\indexlibrarymember{base}{lazy_split_view::\exposid{inner-iterator}}% +\begin{itemdecl} +constexpr iterator_t<@\exposid{Base}@> base() && requires @\libconcept{forward_range}@; +\end{itemdecl} +\begin{itemdescr} \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} +\effects +Equivalent to: \tcode{return std::move(\exposid{i_}.\placeholder{current});} +\end{itemdescr} + +\indexlibrarymember{operator++}{lazy_split_view::\exposid{inner-iterator}}% +\begin{itemdecl} +constexpr @\exposid{inner-iterator}@& operator++(); +\end{itemdecl} +\begin{itemdescr} \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. +\effects +Equivalent to: +\begin{codeblock} +@\exposid{incremented_}@ = true; +if constexpr (!@\libconcept{forward_range}@<@\exposid{Base}@>) { + if constexpr (Pattern::size() == 0) { + return *this; + } +} +++@\exposid{i_}@.@\placeholder{current}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator==}{lazy_split_view::\exposid{inner-iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) + requires @\libconcept{forward_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{i_}.\placeholder{current} == y.\exposid{i_}.\placeholder{current};} +\end{itemdescr} + +\indexlibrarymember{operator==}{lazy_split_view::\exposid{inner-iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto [pcur, pend] = subrange{x.@\exposid{i_}@.@\exposid{parent_}@->@\exposid{pattern_}@}; +auto end = ranges::end(x.@\exposid{i_}@.@\exposid{parent_}@->@\exposid{base_}@); +if constexpr (@\exposconcept{tiny-range}@) { + const auto & cur = x.@\exposid{i_}@.@\placeholder{current}@; + if (cur == end) return true; + if (pcur == pend) return x.@\exposid{incremented_}@; + return *cur == *pcur; +} else { + auto cur = x.@\exposid{i_}@.@\placeholder{current}@; + if (cur == end) return true; + if (pcur == pend) return x.@\exposid{incremented_}@; + do { + if (*cur != *pcur) return false; + if (++pcur == pend) return true; + } while (++cur != end); + return false; +} +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{iter_swap}{lazy_split_view::\exposid{inner-iterator}}% +\begin{itemdecl} +friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) + noexcept(noexcept(ranges::iter_swap(x.@\exposid{i_}@.@\placeholdernc{current}@, y.@\exposid{i_}@.@\placeholdernc{current}@))) + requires @\libconcept{indirectly_swappable}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to +\tcode{ranges::iter_swap(x.\exposid{i_}.\placeholdernc{current}, y.\exposid{i_}.\placeholdernc{current})}. +\end{itemdescr} + +\rSec2[range.split]{Split view} + +\rSec3[range.split.overview]{Overview} + +\pnum +\tcode{split_view} takes a \libconcept{view} and a delimiter, and +splits the \libconcept{view} into \tcode{subrange}s on the delimiter. +The delimiter can be a single element or a \libconcept{view} of elements. + +\pnum +The name \tcode{views::split} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{F}, +the expression \tcode{views::split(E, F)} is expression-equivalent to +\tcode{split_view(E, F)}. + +\pnum +\begin{example} +\begin{codeblock} +string str{"the quick brown fox"}; +for (string_view word : split(str, ' ')) { + cout << word << '*'; +} +// The above prints: the*quick*brown*fox* +\end{codeblock} +\end{example} + +\rSec3[range.split.view]{Class template \tcode{split_view}} + +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern> + requires @\libconcept{view}@ && @\libconcept{view}@ && + @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> + class split_view : public view_interface> { + private: + V @\exposid{base_}@ = V(); // \expos + Pattern @\exposid{pattern_}@ = Pattern(); // \expos + + // \ref{range.split.iterator}, class \tcode{split_view::\exposid{iterator}} + struct @\exposid{iterator}@; // \expos + + // \ref{range.split.sentinel}, class \tcode{split_view::\exposid{sentinel}} + struct @\exposid{sentinel}@; // \expos + + public: + split_view() + requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; + constexpr split_view(V base, Pattern pattern); + + template<@\libconcept{forward_range}@ R> + requires @\libconcept{constructible_from}@> && + @\libconcept{constructible_from}@>> + constexpr split_view(R&& r, range_value_t e); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr @\exposid{iterator}@ begin(); + + constexpr auto end() { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@{*this, ranges::end(@\exposid{base_}@), {}}; + } else { + return @\exposid{sentinel}@{*this}; + } + } + + constexpr subrange> @\exposid{find-next}@(iterator_t); // \expos + }; + + template + split_view(R&&, P&&) -> split_view, views::all_t

>; + + template<@\libconcept{forward_range}@ R> + split_view(R&&, range_value_t) + -> split_view, single_view>>; +} +\end{codeblock} + +\begin{itemdecl} +constexpr split_view(V base, Pattern pattern); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}, and +\exposid{pattern_} with \tcode{std::move(pattern)}. +\end{itemdescr} + +\indexlibraryctor{split_view}% +\begin{itemdecl} +template<@\libconcept{forward_range}@ R> + requires @\libconcept{constructible_from}@> && + @\libconcept{constructible_from}@>> +constexpr split_view(R&& r, range_value_t e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{views::all(std::forward(r))}, and +\exposid{pattern_} with \tcode{views::\linebreak single(std::move(e))}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ begin(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\{*this, ranges::begin(\exposid{base_}), \exposid{find-next}(ranges::begin(\exposid{base_}))\}}. + +\pnum +\remarks +In order to provide the amortized constant time complexity +required by the \libconcept{range} concept, +this function caches the result within the \tcode{split_view} +for use on subsequent calls. +\end{itemdescr} + +\begin{itemdecl} +constexpr subrange> @\exposid{find-next}@(iterator_t it); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto [b, e] = ranges::search(subrange(it, ranges::end(@\exposid{base_}@)), @\exposid{pattern_}@); +if (b != ranges::end(@\exposid{base_}@) && ranges::empty(@\exposid{pattern_}@)) { + ++b; + ++e; +} +return {b, e}; +\end{codeblock} +\end{itemdescr} + +\rSec3[range.split.iterator]{Class \tcode{split_view::\exposid{iterator}}} + +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern> + requires @\libconcept{view}@ && @\libconcept{view}@ && + @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> + class split_view::@\exposid{iterator}@ { + private: + split_view* @\exposid{parent_}@ = nullptr; // \expos + iterator_t @\exposid{cur_}@ = iterator_t(); // \expos + subrange> @\exposid{next_}@ = subrange>(); // \expos + bool @\exposid{trailing_empty_}@ = false; // \expos + + public: + using iterator_concept = forward_iterator_tag; + using iterator_category = input_iterator_tag; + using value_type = subrange>; + using difference_type = range_difference_t; + + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(split_view& parent, iterator_t current, subrange> next); + + constexpr iterator_t base() const; + constexpr value_type operator*() const; + + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(split_view& parent, iterator_t current, subrange> next); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{addressof(parent)}, +\exposid{cur_} with \tcode{std::move(current)}, and +\exposid{next_} with \tcode{std::move(next)}. +\end{itemdescr} + +\begin{itemdecl} +constexpr iterator_t base() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{return \exposid{cur_};} +\end{itemdescr} + +\begin{itemdecl} +constexpr value_type operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{return \{\exposid{cur_}, \exposid{next_}.begin()\};} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{cur_}@ = @\exposid{next_}@.begin(); +if (@\exposid{cur_}@ != ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { + @\exposid{cur_}@ = @\exposid{next_}@.end(); + if (@\exposid{cur_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { + @\exposid{trailing_empty_}@ = true; + @\exposid{next_}@ = {@\exposid{cur_}@, @\exposid{cur_}@}; + } else { + @\exposid{next_}@ = @\exposid{parent_}@->@\exposid{find-next}@(@\exposid{cur_}@); + } +} else { + @\exposid{trailing_empty_}@ = false; +} +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return x.@\exposid{cur_}@ == y.@\exposid{cur_}@ && x.@\exposid{trailing_empty_}@ == y.@\exposid{trailing_empty_}@; +\end{codeblock} +\end{itemdescr} + +\rSec3[range.split.sentinel]{Class \tcode{split_view::\exposid{sentinel}}} + +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern> + requires @\libconcept{view}@ && @\libconcept{view}@ && + @\libconcept{indirectly_comparable}@, iterator_t, ranges::equal_to> + struct split_view::@\exposid{sentinel}@ { + private: + sentinel_t @\exposid{end_}@ = sentinel_t(); // \expos + + public: + @\exposid{sentinel}@() = default; + constexpr explicit @\exposid{sentinel}@(split_view& parent); + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(split_view& parent); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +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 \libconcept{view} of the elements +of the counted range\iref{iterator.requirements.general} \countedrange{i}{n} +for an iterator \tcode{i} and non-negative integer \tcode{n}. + +\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 \libconcept{view} which has different types for +its iterator and sentinel and turns it into a \libconcept{view} of the same +elements with an iterator and sentinel of the same type. + +\pnum +\begin{note} +\tcode{common_view} is useful for calling legacy algorithms that expect +a range's iterator and sentinel types to be the same. +\end{note} + +\pnum +\indexlibrarymember{common}{views}% +The name \tcode{views::common} denotes a +range adaptor object\iref{range.adaptor.object}. +Given a subexpression \tcode{E}, +the expression \tcode{views::common(E)} is expression-equivalent to: +\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() { + 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() { + if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) + return ranges::begin(@\exposid{base_}@) + ranges::size(@\exposid{base_}@); + else + return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); + } + + constexpr auto end() const requires @\libconcept{range}@ { + if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) + return ranges::begin(@\exposid{base_}@) + ranges::size(@\exposid{base_}@); + else + return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); + } + + constexpr 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 \libconcept{view} and produces +another \libconcept{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: 4 3 2 1 0 +\end{codeblock} +\end{example} + +\rSec3[range.reverse.view]{Class template \tcode{reverse_view}} + +\indexlibraryglobal{reverse_view}% +\indexlibrarymember{base}{reverse_view}% +\indexlibrarymember{size}{reverse_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{bidirectional_range}@ + class reverse_view : public view_interface> { + private: + V @\exposid{base_}@ = V(); // \expos + public: + reverse_view() requires @\libconcept{default_initializable}@ = default; + + constexpr explicit reverse_view(V r); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr reverse_iterator> begin(); + constexpr reverse_iterator> begin() requires @\libconcept{common_range}@; + constexpr auto begin() const requires @\libconcept{common_range}@; + + constexpr reverse_iterator> end(); + constexpr auto end() const requires @\libconcept{common_range}@; + + constexpr auto size() requires @\libconcept{sized_range}@ { + return ranges::size(@\exposid{base_}@); + } + + constexpr auto size() const requires @\libconcept{sized_range}@ { + return ranges::size(@\exposid{base_}@); + } + }; + + template + reverse_view(R&&) -> reverse_view>; +} +\end{codeblock} + +\indexlibraryctor{reverse_view}% +\begin{itemdecl} +constexpr explicit reverse_view(V base); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. +\end{itemdescr} + +\indexlibrarymember{begin}{reverse_view}% +\begin{itemdecl} +constexpr reverse_iterator> begin(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +make_reverse_iterator(ranges::next(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@))) +\end{codeblock} + +\pnum +\remarks +In order to provide the amortized constant time complexity required by +the \libconcept{range} concept, this function caches the result within the +\tcode{reverse_view} for use on subsequent calls. +\end{itemdescr} + +\indexlibrarymember{begin}{reverse_view}% +\begin{itemdecl} +constexpr reverse_iterator> begin() requires @\libconcept{common_range}@; +constexpr auto begin() const requires @\libconcept{common_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return make_reverse_iterator(ranges::end(base_));} +\end{itemdescr} + +\indexlibrarymember{end}{reverse_view}% +\begin{itemdecl} +constexpr reverse_iterator> end(); +constexpr auto end() const requires @\libconcept{common_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return make_reverse_iterator(ranges::begin(base_));} +\end{itemdescr} + +\rSec2[range.elements]{Elements view} + +\rSec3[range.elements.overview]{Overview} + +\pnum +\tcode{elements_view} takes +a \libconcept{view} of tuple-like values and a \tcode{size_t}, and +produces a \libconcept{view} with a value-type of the $N^\text{th}$ element +of the adapted \libconcept{view}'s value-type. + +\pnum +\indexlibrarymember{elements}{views}% +The name \tcode{views::elements} denotes +a range adaptor object\iref{range.adaptor.object}. +Given a subexpression \tcode{E} and constant expression \tcode{N}, +the expression \tcode{views::elements(E)} is expression-equivalent to +\tcode{elements_view, N>\{E\}}. + +\begin{example} +\begin{codeblock} +auto historical_figures = map{ + pair{"Lovelace"sv, 1815}, + {"Turing"sv, 1912}, + {"Babbage"sv, 1791}, + {"Hamilton"sv, 1936} +}; + +auto names = historical_figures | views::elements<0>; +for (auto&& name : names) { + cout << name << ' '; // prints \tcode{Babbage Hamilton Lovelace Turing } +} + +auto birth_years = historical_figures | views::elements<1>; +for (auto&& born : birth_years) { + cout << born << ' '; // prints \tcode{1791 1936 1815 1912 } +} +\end{codeblock} +\end{example} + +\pnum +\tcode{keys_view} is an alias for \tcode{elements_view}, and +is useful for extracting keys from associative containers. + +\begin{example} +\begin{codeblock} +auto names = historical_figures | views::keys; +for (auto&& name : names) { + cout << name << ' '; // prints \tcode{Babbage Hamilton Lovelace Turing } +} +\end{codeblock} +\end{example} + +\pnum +\tcode{values_view} is an alias for \tcode{elements_view}, and +is useful for extracting values from associative containers. + +\begin{example} +\begin{codeblock} +auto is_even = [](const auto x) { return x % 2 == 0; }; +cout << ranges::count_if(historical_figures | views::values, is_even); // prints \tcode{2} +\end{codeblock} +\end{example} + +\rSec3[range.elements.view]{Class template \tcode{elements_view}} + +\indexlibraryglobal{elements_view}% +\indexlibrarymember{base}{elements_view}% +\indexlibrarymember{begin}{elements_view}% +\indexlibrarymember{end}{elements_view}% +\indexlibrarymember{size}{elements_view}% +\begin{codeblock} +namespace std::ranges { + template + concept @\defexposconcept{has-tuple-element}@ = // \expos + requires(T t) { + typename tuple_size::type; + requires N < tuple_size_v; + typename tuple_element_t; + { std::get(t) } -> @\libconcept{convertible_to}@&>; + }; + + template + concept @\defexposconcept{returnable-element}@ = // \expos + is_reference_v || move_constructible>; + + template<@\libconcept{input_range}@ V, size_t N> + requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && + @\exposconcept{has-tuple-element}@>, N> && + @\exposconcept{returnable-element}@, N> + class elements_view : public view_interface> { + public: + elements_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit elements_view(V base); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr auto begin() requires (!@\exposconcept{simple-view}@) + { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@)); } + + constexpr auto begin() const requires @\libconcept{range}@ + { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@)); } + + constexpr auto end() requires (!@\exposconcept{simple-view}@ && !@\libconcept{common_range}@) + { return @\exposid{sentinel}@{ranges::end(@\exposid{base_}@)}; } + + constexpr auto end() requires (!@\exposconcept{simple-view}@ && @\libconcept{common_range}@) + { return @\exposid{iterator}@{ranges::end(@\exposid{base_}@)}; } + + constexpr auto end() const requires @\libconcept{range}@ + { return @\exposid{sentinel}@{ranges::end(@\exposid{base_}@)}; } + + constexpr auto end() const requires @\libconcept{common_range}@ + { return @\exposid{iterator}@{ranges::end(@\exposid{base_}@)}; } + + constexpr auto size() requires @\libconcept{sized_range}@ + { return ranges::size(@\exposid{base_}@); } + + constexpr auto size() const requires @\libconcept{sized_range}@ + { return ranges::size(@\exposid{base_}@); } + + private: + // \ref{range.elements.iterator}, class template \tcode{elements_view::\exposid{iterator}} + template struct @\exposid{iterator}@; // \expos + + // \ref{range.elements.sentinel}, class template \tcode{elements_view::\exposid{sentinel}} + template struct @\exposid{sentinel}@; // \expos + + V @\exposid{base_}@ = V(); // \expos + }; +} +\end{codeblock} + +\indexlibraryctor{elements_view}% +\begin{itemdecl} +constexpr explicit elements_view(V base); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. +\end{itemdescr} + +\rSec3[range.elements.iterator]{Class template \tcode{elements_view::\exposid{iterator}}} + +\indexlibraryglobal{elements_view::iterator}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@ V, size_t N> + requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && + @\exposconcept{has-tuple-element}@>, N> && + @\exposconcept{returnable-element}@, N> + template + class elements_view::@\exposid{iterator}@ { + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + + iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos + + static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i); // \expos + + public: + using iterator_concept = @\seebelow@; + using iterator_category = @\seebelow@; // not always present + using value_type = remove_cvref_t>>; + using difference_type = range_difference_t<@\exposid{Base}@>; + + @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; + constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; + + constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; + constexpr iterator_t<@\exposid{Base}@> base() &&; + + constexpr decltype(auto) operator*() const + { return @\exposid{get-element}@(@\exposid{current_}@); } + + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); + constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; + + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + + constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@> + { return @\exposid{get-element}@(@\exposid{current_}@ + n); } + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@>; + + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@>; + + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + }; +} +\end{codeblock} + +\pnum +The member \grammarterm{typedef-name} \tcode{iterator_concept} +is defined as follows: +\begin{itemize} +\item +If \exposid{Base} models \libconcept{random_access_range}, +then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, if \exposid{Base} models \libconcept{forward_range}, +then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. +\end{itemize} + +\pnum +The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +if and only if \exposid{Base} models \libconcept{forward_range}. +In that case, \tcode{iterator_category} is defined as follows: +Let \tcode{C} denote the type +\tcode{iterator_traits>::iterator_category}. +\begin{itemize} +\item +If \tcode{std::get(*\exposid{current_})} is an rvalue, +\tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\item +Otherwise, if \tcode{C} models \tcode{\libconcept{derived_from}}, +\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, \tcode{iterator_category} denotes \tcode{C}. +\end{itemize} + +\indexlibrarymember{\exposid{get-element}}{elements_view::iterator}% +\begin{itemdecl} +static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if constexpr (is_reference_v>) { + return std::get(*i); +} else { + using E = remove_cv_t>>; + return static_cast(std::get(*i)); +} +\end{codeblock} +\end{itemdescr} + +\indexlibraryctor{elements_view::iterator}% +\begin{itemdecl} +constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(current)}. +\end{itemdescr} + +\indexlibraryctor{elements_view::iterator}% +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +\end{itemdescr} + +\indexlibrarymember{base}{elements_view::iterator}% +\begin{itemdecl} +constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{base}{elements_view::iterator}% +\begin{itemdecl} +constexpr iterator_t<@\exposid{Base}@> base() &&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return std::move(\exposid{current_});} +\end{itemdescr} + +\indexlibrarymember{operator++}{elements_view::iterator}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +++@\exposid{current_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{elements_view::iterator}% +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{++\exposid{current_}}. +\end{itemdescr} + +\indexlibrarymember{operator++}{elements_view::iterator}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = *this; +++@\exposid{current_}@; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{elements_view::iterator}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +--@\exposid{current_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{elements_view::iterator}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = *this; +--@\exposid{current_}@; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+=}{elements_view::iterator}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type n); + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{current_}@ += n; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-=}{elements_view::iterator}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{current_}@ -= n; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator==}{elements_view::iterator}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{operator<}{elements_view::iterator}% +\begin{itemdecl} +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} < y.\exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{operator>}{elements_view::iterator}% +\begin{itemdecl} +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return y < x;} +\end{itemdescr} + +\indexlibrarymember{operator<=}{elements_view::iterator}% +\begin{itemdecl} +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(y < x);} +\end{itemdescr} + +\indexlibrarymember{operator>=}{elements_view::iterator}% +\begin{itemdecl} +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(x < y);} +\end{itemdescr} + +\indexlibrarymember{operator<=>}{elements_view::iterator}% +\begin{itemdecl} +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{operator+}{elements_view::iterator}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return iterator\{x\} += y;} +\end{itemdescr} + +\indexlibrarymember{operator+}{elements_view::iterator}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return y + x;} +\end{itemdescr} + +\indexlibrarymember{operator-}{elements_view::iterator}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return iterator\{x\} -= y;} +\end{itemdescr} + +\indexlibrarymember{operator-}{elements_view::iterator}% +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{current_};} +\end{itemdescr} + +\rSec3[range.elements.sentinel]{Class template \tcode{elements_view::\exposid{sentinel}}} + +\indexlibraryglobal{elements_view::sentinel}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@ V, size_t N> + requires @\libconcept{view}@ && @\placeholder{has-tuple-element}@, N> && + @\placeholder{has-tuple-element}@>, N> && + @\exposconcept{returnable-element}@, N> + template + class elements_view::@\exposid{sentinel}@ { + private: + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + public: + @\exposid{sentinel}@() = default; + constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; + + constexpr sentinel_t<@\exposid{Base}@> base() const; + + template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); + }; +} +\end{codeblock} + +\indexlibraryctor{elements_view::sentinel}% +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{end}. +\end{itemdescr} + +\indexlibraryctor{elements_view::sentinel}% +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}. +\end{itemdescr} + +\indexlibrarymember{base}{elements_view::sentinel}% +\begin{itemdecl} +constexpr sentinel_t<@\exposid{Base}@> base() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{end_};} +\end{itemdescr} + +\indexlibrarymember{operator==}{elements_view::sentinel}% +\begin{itemdecl} +template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};} +\end{itemdescr} + +\indexlibrarymember{operator-}{elements_view::sentinel}% +\begin{itemdecl} +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};} +\end{itemdescr} + +\indexlibrarymember{operator-}{elements_view::sentinel}% +\begin{itemdecl} +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};} +\end{itemdescr} + +\rSec2[range.zip]{Zip view} + +\rSec3[range.zip.overview]{Overview} + +\pnum +\indexlibraryglobal{zip_view}% +\tcode{zip_view} takes any number of \libconcept{view}s and +produces a \libconcept{view} of tuples of references +to the corresponding elements of the constituent views. + +\pnum +\indexlibrarymember{zip}{views}% +The name \tcode{views::zip} denotes +a customization point object\iref{customization.point.object}. +Given a pack of subexpressions \tcode{Es...}, +the expression \tcode{views::zip(Es...)} is expression-equivalent to +\begin{itemize} +\item +\tcode{auto(views::empty>)} +if \tcode{Es} is an empty pack, +\item +otherwise, \tcode{zip_view...>(Es...)}. +\end{itemize} + +\begin{example} +\begin{codeblock} +vector v = {1, 2}; +list l = {'a', 'b', 'c'}; + +auto z = views::zip(v, l); +range_reference_t f = z.front(); // \tcode{f} is a \tcode{pair} + // that refers to the first element of \tcode{v} and \tcode{l} + +for (auto&& [x, y] : z) { + cout << '(' << x << ", " << y << ") "; // prints: (1, a) (2, b) +} +\end{codeblock} +\end{example} + +\rSec3[range.zip.view]{Class template \tcode{zip_view}} + +\indexlibrarymember{begin}{zip_view}% +\indexlibrarymember{end}{zip_view}% +\indexlibrarymember{size}{zip_view}% +\begin{codeblock} +namespace std::ranges { + template + concept @\defexposconcept{zip-is-common}@ = // \expos + (sizeof...(Rs) == 1 && (@\libconcept{common_range}@ && ...)) || + (!(@\libconcept{bidirectional_range}@ && ...) && (@\libconcept{common_range}@ && ...)) || + ((@\libconcept{random_access_range}@ && ...) && (@\libconcept{sized_range}@ && ...)); + + template + using @\exposid{tuple-or-pair}@ = @\seebelow@; // \expos + + template + constexpr auto @\exposid{tuple-transform}@(F&& f, Tuple&& tuple) { // \expos + return apply([&](Ts&&... elements) { + return @\exposid{tuple-or-pair}@...>( + invoke(f, std::forward(elements))... + ); + }, std::forward(tuple)); + } + + template + constexpr void @\exposid{tuple-for-each}@(F&& f, Tuple&& tuple) { // \expos + apply([&](Ts&&... elements) { + (invoke(f, std::forward(elements)), ...); + }, std::forward(tuple)); + } + + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) + class zip_view : public view_interface> { + tuple @\exposid{views_}@; // \expos + + // \ref{range.zip.iterator}, class template \tcode{zip_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos + + // \ref{range.zip.sentinel}, class template \tcode{zip_view::\exposid{sentinel}} + template class @\exposidnc{sentinel}@; // \expos + + public: + zip_view() = default; + constexpr explicit zip_view(Views... views); + + constexpr auto begin() requires (!(@\exposconcept{simple-view}@ && ...)) { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); + } + constexpr auto begin() const requires (@\libconcept{range}@ && ...) { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); + } + + constexpr auto end() requires (!(@\exposconcept{simple-view}@ && ...)) { + if constexpr (!@\exposconcept{zip-is-common}@) { + return @\exposid{sentinel}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } else if constexpr ((@\libconcept{random_access_range}@ && ...)) { + return begin() + iter_difference_t<@\exposid{iterator}@>(size()); + } else { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } + } + + constexpr auto end() const requires (@\libconcept{range}@ && ...) { + if constexpr (!@\exposconcept{zip-is-common}@) { + return @\exposid{sentinel}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } else if constexpr ((@\libconcept{random_access_range}@ && ...)) { + return begin() + iter_difference_t<@\exposid{iterator}@>(size()); + } else { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } + } + + constexpr auto size() requires (@\libconcept{sized_range}@ && ...); + constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); + }; + + template + zip_view(Rs&&...) -> zip_view...>; +} +\end{codeblock} + +\pnum +Given some pack of types \tcode{Ts}, +the alias template \exposid{tuple-or-pair} is defined as follows: +\begin{itemize} +\item +If \tcode{sizeof...(Ts)} is 2, +\tcode{\exposid{tuple-or-pair}} denotes \tcode{pair}. +\item +Otherwise, \tcode{\exposid{tuple-or-pair}} denotes \tcode{tuple}. +\end{itemize} + +\pnum +Two \tcode{zip_view} objects have the same underlying sequence if and only if +the corresponding elements of \exposid{views_} are equal\iref{concepts.equality} +and have the same underlying sequence. +\begin{note} +In particular, comparison of iterators obtained from \tcode{zip_view} objects +that do not have the same underlying sequence +is not required to produce meaningful results\iref{iterator.concept.forward}. +\end{note} + +\begin{itemdecl} +constexpr explicit zip_view(Views... views); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{views_} with \tcode{std::move(views)...}. +\end{itemdescr} + +\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 = @\exposid{make-unsigned-like-t}@>; + return ranges::min({CT(sizes)...}); +}, @\exposid{tuple-transform}@(ranges::size, @\exposid{views_}@)); +\end{codeblock} +\end{itemdescr} + +\rSec3[range.zip.iterator]{Class template \tcode{zip_view::\exposid{iterator}}} + +\indexlibraryglobal{zip_view::iterator}% +\begin{codeblock} +namespace std::ranges { + template + concept @\defexposconceptnc{all-random-access}@ = // \expos + (@\libconcept{random_access_range}@<@\exposid{maybe-const}@> && ...); + template + concept @\defexposconceptnc{all-bidirectional}@ = // \expos + (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@> && ...); + template + concept @\defexposconceptnc{all-forward}@ = // \expos + (@\libconcept{forward_range}@<@\exposid{maybe-const}@> && ...); + + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) + template + class zip_view::@\exposid{iterator}@ { + @\exposid{tuple-or-pair}@>...> @\exposid{current_}@;@\itcorr[-1]@ // \expos + constexpr explicit @\exposidnc{iterator}@(@\exposid{tuple-or-pair}@>...>); + // \expos + public: + using iterator_category = input_iterator_tag; // not always present + using iterator_concept = @\seebelow@; + using value_type = @\exposid{tuple-or-pair}@>...>; + using difference_type = common_type_t>...>; + + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && (@\libconcept{convertible_to}@, + iterator_t<@\exposid{maybe-const}@>> && ...); + + constexpr 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{all-bidirectional}@; + constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@; + + constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\exposconcept{all-random-access}@; + constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\exposconcept{all-random-access}@; + + constexpr auto operator[](difference_type n) const + requires @\exposconcept{all-random-access}@; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{equality_comparable}@>> && ...); + + 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}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\exposconcept{all-random-access}@; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...); + + friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); + + friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires (@\libconcept{indirectly_swappable}@>> && ...); + }; +} +\end{codeblock} + +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If \tcode{\exposconcept{all-random-access}} is modeled, +then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, +if \tcode{\exposconcept{all-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 +\tcode{\exposid{iterator}::iterator_category} is present +if and only if \tcode{\exposconcept{all-forward}} is modeled. + +\pnum +If the invocation of any non-const member function of \exposid{iterator} +exits via an exception, +the iterator acquires a singular value. + +\begin{itemdecl} +constexpr explicit @\exposid{iterator}@(@\exposid{tuple-or-pair}@>...> current); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(current)}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && + (@\libconcept{convertible_to}@, iterator_t<@\exposid{maybe-const}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{tuple-for-each}@([](auto& i) { ++i; }, @\exposid{current_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{++*this}. +\end{itemdescr} + +\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} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{all-bidirectional}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{tuple-for-each}@([](auto& i) { --i; }, @\exposid{current_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{tuple-for-each}@([&](I& i) { i += iter_difference_t(x); }, @\exposid{current_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{tuple-for-each}@([&](I& i) { i -= iter_difference_t(x); }, @\exposid{current_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr auto operator[](difference_type n) const + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([&](I& i) -> decltype(auto) { + return i[iter_difference_t(n)]; +}, @\exposid{current_}@); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{equality_comparable}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{x.\exposid{current_} == y.\exposid{current_}} +if \tcode{\exposconcept{all-bidirectional}} is \tcode{true}. +\item +Otherwise, \tcode{true} +if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$ +such that \tcode{bool(std::\brk{}get<$i$>(x.\exposid{current_}) == +std::get<$i$>(y.\exposid{current_}))} is \tcode{true}. +\begin{note} +This allows \tcode{zip_view} to model \libconcept{common_range} +when all constituent views model \libconcept{common_range}. +\end{note} +\item +Otherwise, \tcode{false}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} < y.\exposid{current_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return y < x;} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(y < x);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(x < y);} +\end{itemdescr} + +\begin{itemdecl} +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 +\returns +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r += n; +return r; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{\exposid{DIST}($i$)} be \tcode{difference_type(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{current_}))}. + +\pnum +\returns +The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)} +for all integers $0 \leq n < \tcode{sizeof...(Views)}$. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@(ranges::iter_move, i.@\exposid{current_}@); +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to: +\begin{codeblock} +(noexcept(ranges::iter_move(declval>&>())) && ...) && +(is_nothrow_move_constructible_v>> && ...) +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires (@\libconcept{indirectly_swappable}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +For every integer $0 \leq i < \tcode{sizeof...(Views)}$, +performs: +\begin{codeblock} +ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@)) +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to +the logical \logop{AND} of the following expressions: +\begin{codeblock} +noexcept(ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@))) +\end{codeblock} +for every integer $0 \leq i < \tcode{sizeof...(Views)}$. +\end{itemdescr} + +\rSec3[range.zip.sentinel]{Class template \tcode{zip_view::\exposid{sentinel}}} + +\indexlibraryglobal{zip_view::sentinel}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) + template + class zip_view::@\exposid{sentinel}@ { + @\exposid{tuple-or-pair}@>...> @\exposid{end_}@;@\itcorr[-1]@ // \expos + constexpr explicit @\exposidnc{sentinel}@(@\exposid{tuple-or-pair}@>...> end); + // \expos + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && + (@\libconcept{convertible_to}@, sentinel_t<@\exposid{maybe-const}@>> && ...); + + template + requires (@\libconcept{sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) + friend constexpr common_type_t>...> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) + friend constexpr common_type_t>...> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(@\exposid{tuple-or-pair}@>...> end); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{end}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && + (@\libconcept{convertible_to}@, sentinel_t<@\exposid{maybe-const}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. +\end{itemdescr} + +\begin{itemdecl} +template + requires (@\libconcept{sentinel_for}@>, + iterator_t>> && ...) +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$ +such that \tcode{bool(std::get<$i$>(x.\brk{}\exposid{current_}) == +std::get<$i$>(y.\exposid{end_}))} is \tcode{true}. +Otherwise, \tcode{false}. +\end{itemdescr} + +\begin{itemdecl} +template + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) +friend constexpr common_type_t>...> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{D} be the return type. +Let \tcode{\exposid{DIST}($i$)} be +\tcode{D(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{end_}))}. + +\pnum +\returns +The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)} +for all integers $0 \leq n < \tcode{sizeof...(Views)}$. +\end{itemdescr} + +\begin{itemdecl} +template + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) +friend constexpr common_type_t>...> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{return -(x - y);} +\end{itemdescr} + +\rSec2[range.zip.transform]{Zip transform view} + +\rSec3[range.zip.transform.overview]{Overview} + +\pnum +\indexlibraryglobal{zip_transform_view}% +\tcode{zip_transform_view} takes an invocable object and +any number of \libconcept{view}s and +produces a \libconcept{view} +whose $M^\text{th}$ element is +the result of applying the invocable object +to the $M^\text{th}$ elements of all views. + +\pnum +\indexlibrarymember{zip_transform}{views}% +The name \tcode{views::zip_transform} denotes +a customization point object\iref{customization.point.object}. +Let \tcode{F} be a subexpression, and +let \tcode{Es...} be a pack of subexpressions. +\begin{itemize} +\item +If \tcode{Es} is an empty pack, +let \tcode{FD} be \tcode{decay_t}. +\begin{itemize} +\item +If \tcode{\libconcept{copy_constructible} \&\& +\libconcept{regular_invocable}} is \tcode{false}, or +if \tcode{decay_t>} is not an object type, +\tcode{views::zip_transform(F, Es...)} is ill-formed. +\item +Otherwise, the expression \tcode{views::zip_transform(F, Es...)} +is expression-equivalent to +\begin{codeblock} +((void)F, auto(views::empty>>)) +\end{codeblock} +\end{itemize} +\item +Otherwise, the expression \tcode{views::zip_transform(F, Es...)} +is expression-equivalent to \tcode{zip_trans\-form_view(F, Es...)}. +\end{itemize} + +\pnum +\begin{example} +\begin{codeblock} +vector v1 = {1, 2}; +vector v2 = {4, 5, 6}; + +for (auto i : views::zip_transform(plus(), v1, v2)) { + cout << i << ' '; // prints: 5 7 +} +\end{codeblock} +\end{example} + +\rSec3[range.zip.transform.view]{Class template \tcode{zip_transform_view}} + +\indexlibrarymember{begin}{zip_transform_view}% +\indexlibrarymember{end}{zip_transform_view}% +\indexlibrarymember{size}{zip_transform_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{copy_constructible}@ F, @\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && + @\libconcept{regular_invocable}@...> && + @\exposconcept{can-reference}@...>> + class zip_transform_view : public view_interface> { + @\exposidnc{copyable-box}@ @\exposid{fun_}@; // \expos + zip_view @\exposid{zip_}@; // \expos + + using @\exposidnc{InnerView}@ = zip_view; // \expos + template + using @\exposidnc{ziperator}@ = iterator_t<@\exposidnc{maybe-const}@>; // \expos + template + using @\exposidnc{zentinel}@ = sentinel_t<@\exposidnc{maybe-const}@>; // \expos + + // \ref{range.zip.transform.iterator}, class template \tcode{zip_transform_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos + + // \ref{range.zip.transform.sentinel}, class template \tcode{zip_transform_view::\exposid{sentinel}} + template class @\exposidnc{sentinel}@; // \expos + + public: + zip_transform_view() = default; + + constexpr explicit zip_transform_view(F fun, Views... views); + + constexpr auto begin() { return @\exposid{iterator}@(*this, @\exposid{zip_}@.begin()); } + + constexpr auto begin() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@...> { + return @\exposid{iterator}@(*this, @\exposid{zip_}@.begin()); + } + + constexpr auto end() { + if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { + return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); + } else { + return @\exposid{sentinel}@(@\exposid{zip_}@.end()); + } + } + + constexpr auto end() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@...> { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); + } else { + return @\exposid{sentinel}@(@\exposid{zip_}@.end()); + } + } + + constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> { + return @\exposid{zip_}@.size(); + } + + constexpr auto size() const requires @\libconcept{sized_range}@ { + return @\exposid{zip_}@.size(); + } + }; + + template + zip_transform_view(F, Rs&&...) -> zip_transform_view...>; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit zip_transform_view(F fun, Views... views); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{fun_} with \tcode{std::move(fun)} and +\exposid{zip_} with \tcode{std::move(views)...}. +\end{itemdescr} + +\rSec3[range.zip.transform.iterator]{Class template \tcode{zip_transform_view::\exposid{iterator}}} + +\indexlibraryglobal{zip_transform_view::iterator}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{copy_constructible}@ F, @\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && + @\libconcept{regular_invocable}@...> && + @\exposconcept{can-reference}@...>> + template + class zip_transform_view::@\exposid{iterator}@ { + using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposid{ziperator}@ @\exposid{inner_}@;@\itcorr[-1]@ // \expos + + constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); // \expos + + public: + using iterator_category = @\seebelownc@; // not always present + using iterator_concept = typename @\exposid{ziperator}@::iterator_concept; + using value_type = + remove_cvref_t&, + range_reference_t<@\exposid{maybe-const}@>...>>; + using difference_type = range_difference_t<@\exposid{Base}@>; + + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; + + constexpr decltype(auto) operator*() const noexcept(@\seebelow@); + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); + constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; + + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + + constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@>; + + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{ziperator}@>; + + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; + }; +} +\end{codeblock} + +\pnum +The member \grammarterm{typedef-name} +\tcode{\exposid{iterator}::iterator_category} +is defined if and only if \exposid{Base} models \libconcept{forward_range}. +In that case, +\tcode{\exposid{iterator}::iterator_category} is defined as follows: +\begin{itemize} +\item +If +\begin{codeblock} +invoke_result_t<@\exposid{maybe-const}@&, range_reference_t<@\exposid{maybe-const}@>...> +\end{codeblock} +is not an lvalue reference, +\tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\item +Otherwise, let \tcode{Cs} denote the pack of types +\tcode{iterator_traits>>::iterator_category...}. +\begin{itemize} +\item +If \tcode{(\libconcept{derived_from} \&\& ...)} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, +if \tcode{(\libconcept{derived_from} \&\& ...)} +is \tcode{true}, +\tcode{itera\-tor_category} denotes \tcode{bidirectional_iterator_tag}. +\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} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{addressof(parent)} and +\exposid{inner_} with \tcode{std::move(inner)}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and +\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr decltype(auto) operator*() const noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply([&](const auto&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); +}, @\exposid{inner_}@.@\exposid{current_}@); +\end{codeblock} + +\pnum +\remarks +Let \tcode{Is} be the pack \tcode{0, 1, \ldots, \tcode{(sizeof...(Views)-1)}}. +The exception specification is equivalent to: +\tcode{noexcept(invoke(*\exposid{parent_}->\exposid{fun_}, *std::get(\exposid{inner_}.\exposid{current_})...))}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +++@\exposid{inner_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{++*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +--@\exposid{inner_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{inner_}@ += x; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{inner_}@ -= x; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply([&](const Is&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[iter_difference_t(n)]...); +}, @\exposid{inner_}@.@\exposid{current_}@); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@>; +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{ziperator}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\effects +Equivalent to: +\tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} + +\rSec3[range.zip.transform.sentinel]{Class template \tcode{zip_transform_view::\exposid{sentinel}}} + +\indexlibraryglobal{zip_transform_view::sentinel}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{copy_constructible}@ F, @\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && + @\libconcept{regular_invocable}@...> && + @\exposconcept{can-reference}@...>> + template + class zip_transform_view::@\exposid{sentinel}@ { + @\exposidnc{zentinel}@ @\exposid{inner_}@; // \expos + constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{zentinel}@ inner); // \expos + + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; + + template + requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(@\exposid{zentinel}@ inner); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{inner_} with \tcode{inner}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} + +\rSec2[range.adjacent]{Adjacent view} + +\rSec3[range.adjacent.overview]{Overview} + +\pnum +\indexlibraryglobal{adjacent_view}% +\tcode{adjacent_view} takes a \libconcept{view} and +produces a \libconcept{view} whose $M^\text{th}$ element is +a tuple of references to +the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements of +the original view. +If the original view has fewer than $N$ elements, the resulting view is empty. -\item Otherwise, \tcode{common_view\{E\}}. +\pnum +\indexlibrarymember{adjacent}{views}% +The name \tcode{views::adjacent} denotes +a range adaptor object\iref{range.adaptor.object}. +Given a subexpression \tcode{E} and a constant expression \tcode{N}, +the expression \tcode{views::adjacent(E)} is expression-equivalent to +\begin{itemize} +\item +\tcode{((void)E, auto(views::empty>))} +if \tcode{N} is equal to \tcode{0}, +\item +otherwise, \tcode{adjacent_view, N>(E)}. \end{itemize} -\pnum \begin{example} \begin{codeblock} -// Legacy algorithm: -template -size_t count(ForwardIterator first, ForwardIterator last); +vector v = {1, 2, 3, 4}; -template<@\libconcept{forward_range}@ R> -void my_algo(R&& r) { - auto&& common = views::common(r); - auto cnt = count(common.begin(), common.end()); - // ... +for (auto i : v | views::adjacent<2>) { + cout << "(" << i.first << ", " << i.second << ") "; // prints: (1, 2) (2, 3) (3, 4) } \end{codeblock} \end{example} -\rSec3[range.common.view]{Class template \tcode{common_view}} +\pnum +Define \tcode{\exposid{REPEAT}(T, N)} as a pack of \tcode{N} types, +each of which denotes the same type as \tcode{T}. -\indexlibraryglobal{common_view}% -\indexlibrarymember{base}{common_view}% -\indexlibrarymember{size}{common_view}% -\indexlibrarymember{begin}{common_view}% -\indexlibrarymember{end}{common_view}% +\rSec3[range.adjacent.view]{Class template \tcode{adjacent_view}} + +\indexlibrarymember{begin}{adjacent_view}% +\indexlibrarymember{end}{adjacent_view}% +\indexlibrarymember{size}{adjacent_view}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{view}@ V> - requires (!@\libconcept{common_range}@ && @\libconcept{copyable}@>) - class common_view : public view_interface> { - private: - V @\exposid{base_}@ = V(); // \expos - public: - common_view() requires @\libconcept{default_initializable}@ = default; + template<@\libconcept{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) + class adjacent_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos - constexpr explicit common_view(V r); + // \ref{range.adjacent.iterator}, class template \tcode{adjacent_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } + // \ref{range.adjacent.sentinel}, class template \tcode{adjacent_view::\exposid{sentinel}} + template class @\exposidnc{sentinel}@; // \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_}@)); + struct @\exposidnc{as-sentinel}@{}; // \expos + + public: + adjacent_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit adjacent_view(V base); + + constexpr auto begin() requires (!@\exposconcept{simple-view}@) { + return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); } constexpr auto begin() const requires @\libconcept{range}@ { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::begin(@\exposid{base_}@)); + return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); } - constexpr auto end() { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@) + ranges::size(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); + constexpr auto end() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + } else { + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + } } constexpr auto end() const requires @\libconcept{range}@ { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@) + ranges::size(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + } else { + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + } } - constexpr auto size() requires @\libconcept{sized_range}@ { - 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>; } \end{codeblock} -\indexlibraryctor{common_view}% \begin{itemdecl} -constexpr explicit common_view(V base); +constexpr explicit adjacent_view(V base); \end{itemdecl} \begin{itemdescr} @@ -6826,407 +9888,273 @@ 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 \libconcept{view} and produces -another \libconcept{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} +\begin{itemdecl} +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; +\end{itemdecl} +\begin{itemdescr} \pnum -\begin{example} +\effects +Equivalent to: \begin{codeblock} -vector is {0,1,2,3,4}; -for (int i : is | views::reverse) - cout << i << ' '; // prints: 4 3 2 1 0 +using ST = decltype(ranges::size(@\exposid{base_}@)); +using CT = common_type_t; +auto sz = static_cast(ranges::size(@\exposid{base_}@)); +sz -= std::min(sz, N - 1); +return static_cast(sz); \end{codeblock} -\end{example} +\end{itemdescr} -\rSec3[range.reverse.view]{Class template \tcode{reverse_view}} +\rSec3[range.adjacent.iterator]{Class template \tcode{adjacent_view::\exposid{iterator}}} -\indexlibraryglobal{reverse_view}% -\indexlibrarymember{base}{reverse_view}% -\indexlibrarymember{size}{reverse_view}% +\indexlibraryglobal{adjacent_view::iterator}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{view}@ V> - requires @\libconcept{bidirectional_range}@ - class reverse_view : public view_interface> { - private: - V @\exposid{base_}@ = V(); // \expos + template<@\libconcept{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) + template + class adjacent_view::@\exposid{iterator}@ { + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + array, N> @\exposid{current_}@ = array, N>(); // \expos + constexpr @\exposidnc{iterator}@(iterator_t<@\exposidnc{Base}@> first, sentinel_t<@\exposidnc{Base}@> last); // \expos + constexpr @\exposidnc{iterator}@(@\exposidnc{as-sentinel}@, iterator_t<@\exposidnc{Base}@> first, iterator_t<@\exposidnc{Base}@> last); + // \expos public: - reverse_view() requires @\libconcept{default_initializable}@ = default; + using iterator_category = input_iterator_tag; + using iterator_concept = @\seebelow@; + using value_type = @\exposid{tuple-or-pair}@<@\exposid{REPEAT}@(range_value_t<@\exposid{Base}@>, N)...>; + using difference_type = range_difference_t<@\exposid{Base}@>; - constexpr explicit reverse_view(V r); + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } + constexpr auto operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); - constexpr reverse_iterator> begin(); - constexpr reverse_iterator> begin() requires @\libconcept{common_range}@; - constexpr auto begin() const requires @\libconcept{common_range}@; + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; - constexpr reverse_iterator> end(); - constexpr auto end() const requires @\libconcept{common_range}@; + constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - constexpr auto size() requires @\libconcept{sized_range}@ { - return ranges::size(@\exposid{base_}@); - } + constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - constexpr auto size() const requires @\libconcept{sized_range}@ { - return ranges::size(@\exposid{base_}@); - } - }; + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && + @\libconcept{three_way_comparable}@>; - template - reverse_view(R&&) -> reverse_view>; + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + + friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); + friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires @\libconcept{indirectly_swappable}@>; + }; } \end{codeblock} -\indexlibraryctor{reverse_view}% +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If \exposid{Base} models \libconcept{random_access_range}, +then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +\end{itemize} + +\pnum +If the invocation of any non-const member function of \exposid{iterator} +exits via an exception, the \exposid{iterator} acquires a singular value. + \begin{itemdecl} -constexpr explicit reverse_view(V base); +constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> first, sentinel_t<@\exposid{Base}@> last); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{base_} with \tcode{std::move(base)}. +\ensures +\tcode{\exposid{current_}[0] == first} is \tcode{true}, and +for every integer $1 \leq i < \tcode{N}$, +\tcode{\exposid{current_}[$i$] == ranges::next(\exposid{current_}[$i$-1], 1, last)} +is \tcode{true}. \end{itemdescr} -\indexlibrarymember{begin}{reverse_view}% \begin{itemdecl} -constexpr reverse_iterator> begin(); +constexpr @\exposid{iterator}@(@\exposid{as-sentinel}@, iterator_t<@\exposid{Base}@> first, iterator_t<@\exposid{Base}@> last); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\begin{codeblock} -make_reverse_iterator(ranges::next(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@))) -\end{codeblock} - -\pnum -\remarks -In order to provide the amortized constant time complexity required by -the \libconcept{range} concept, this function caches the result within the -\tcode{reverse_view} for use on subsequent calls. +\ensures +If \exposid{Base} does not model \libconcept{bidirectional_range}, +each element of \exposid{current_} is equal to \exposid{last}. +Otherwise, \tcode{\exposid{current_}[N-1] == last} is \tcode{true}, and +for every integer $0 \leq i < (\tcode{N} - 1)$, +\tcode{\exposid{current_}[$i$] == ranges::prev(\exposid{current_}[$i$+1], 1, first)} +is \tcode{true}. \end{itemdescr} -\indexlibrarymember{begin}{reverse_view}% \begin{itemdecl} -constexpr reverse_iterator> begin() requires @\libconcept{common_range}@; -constexpr auto begin() const requires @\libconcept{common_range}@; +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return make_reverse_iterator(ranges::end(base_));} +Initializes each element of \exposid{current_} +with the corresponding element of \tcode{i.\exposid{current_}} as an xvalue. \end{itemdescr} -\indexlibrarymember{end}{reverse_view}% \begin{itemdecl} -constexpr reverse_iterator> end(); -constexpr auto end() const requires @\libconcept{common_range}@; +constexpr auto operator*() const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return make_reverse_iterator(ranges::begin(base_));} +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); +\end{codeblock} \end{itemdescr} -\rSec2[range.elements]{Elements view} - -\rSec3[range.elements.overview]{Overview} +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} +\begin{itemdescr} \pnum -\tcode{elements_view} takes -a \libconcept{view} of tuple-like values and a \tcode{size_t}, and -produces a \libconcept{view} with a value-type of the $N^\text{th}$ element -of the adapted \libconcept{view}'s value-type. +\expects +\tcode{\exposid{current_}.back()} is incrementable. \pnum -\indexlibrarymember{elements}{views}% -The name \tcode{views::elements} denotes -a range adaptor object\iref{range.adaptor.object}. -Given a subexpression \tcode{E} and constant expression \tcode{N}, -the expression \tcode{views::elements(E)} is expression-equivalent to -\tcode{elements_view, N>\{E\}}. - -\begin{example} -\begin{codeblock} -auto historical_figures = map{ - pair{"Lovelace"sv, 1815}, - {"Turing"sv, 1912}, - {"Babbage"sv, 1791}, - {"Hamilton"sv, 1936} -}; - -auto names = historical_figures | views::elements<0>; -for (auto&& name : names) { - cout << name << ' '; // prints \tcode{Babbage Hamilton Lovelace Turing } -} - -auto birth_years = historical_figures | views::elements<1>; -for (auto&& born : birth_years) { - cout << born << ' '; // prints \tcode{1791 1936 1815 1912 } -} -\end{codeblock} -\end{example} +\ensures +Each element of \exposid{current_} is equal to \tcode{ranges::next(i)}, +where \tcode{i} is the value of that element before the call. \pnum -\tcode{keys_view} is an alias for \tcode{elements_view}, and -is useful for extracting keys from associative containers. +\returns +\tcode{*this}. +\end{itemdescr} -\begin{example} -\begin{codeblock} -auto names = historical_figures | views::keys; -for (auto&& name : names) { - cout << name << ' '; // prints \tcode{Babbage Hamilton Lovelace Turing } -} -\end{codeblock} -\end{example} +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int); +\end{itemdecl} +\begin{itemdescr} \pnum -\tcode{values_view} is an alias for \tcode{elements_view}, and -is useful for extracting values from associative containers. - -\begin{example} +\expects +Equivalent to: \begin{codeblock} -auto is_even = [](const auto x) { return x % 2 == 0; }; -cout << ranges::count_if(historical_figures | views::values, is_even); // prints \tcode{2} +auto tmp = *this; +++*this; +return tmp; \end{codeblock} -\end{example} - -\rSec3[range.elements.view]{Class template \tcode{elements_view}} - -\indexlibraryglobal{elements_view}% -\indexlibrarymember{base}{elements_view}% -\indexlibrarymember{begin}{elements_view}% -\indexlibrarymember{end}{elements_view}% -\indexlibrarymember{size}{elements_view}% -\begin{codeblock} -namespace std::ranges { - template - concept @\defexposconcept{has-tuple-element}@ = // \expos - requires(T t) { - typename tuple_size::type; - requires N < tuple_size_v; - typename tuple_element_t; - { std::get(t) } -> @\libconcept{convertible_to}@&>; - }; - - template - concept @\defexposconcept{returnable-element}@ = // \expos - is_reference_v || move_constructible>; - - template<@\libconcept{input_range}@ V, size_t N> - requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && - @\exposconcept{has-tuple-element}@>, N> && - @\exposconcept{returnable-element}@, N> - class elements_view : public view_interface> { - public: - elements_view() requires @\libconcept{default_initializable}@ = default; - constexpr explicit elements_view(V base); - - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } - - constexpr auto begin() requires (!@\exposconcept{simple-view}@) - { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@)); } - - constexpr auto begin() const requires @\libconcept{range}@ - { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@)); } - - constexpr auto end() requires (!@\exposconcept{simple-view}@ && !@\libconcept{common_range}@) - { return @\exposid{sentinel}@{ranges::end(@\exposid{base_}@)}; } - - constexpr auto end() requires (!@\exposconcept{simple-view}@ && @\libconcept{common_range}@) - { return @\exposid{iterator}@{ranges::end(@\exposid{base_}@)}; } - - constexpr auto end() const requires @\libconcept{range}@ - { return @\exposid{sentinel}@{ranges::end(@\exposid{base_}@)}; } - - constexpr auto end() const requires @\libconcept{common_range}@ - { return @\exposid{iterator}@{ranges::end(@\exposid{base_}@)}; } - - constexpr auto size() requires @\libconcept{sized_range}@ - { return ranges::size(@\exposid{base_}@); } +\end{itemdescr} - constexpr auto size() const requires @\libconcept{sized_range}@ - { return ranges::size(@\exposid{base_}@); } +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} - private: - // \ref{range.elements.iterator}, class template \tcode{elements_view::\exposid{iterator}} - template struct @\exposid{iterator}@; // \expos +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_}.front()} is decrementable. - // \ref{range.elements.sentinel}, class template \tcode{elements_view::\exposid{sentinel}} - template struct @\exposid{sentinel}@; // \expos +\pnum +\ensures +Each element of \exposid{current_} is equal to \tcode{ranges::prev(i)}, +where \tcode{i} is the value of that element before the call. - V @\exposid{base_}@ = V(); // \expos - }; -} -\end{codeblock} +\pnum +\returns +\tcode{*this}. +\end{itemdescr} -\indexlibraryctor{elements_view}% \begin{itemdecl} -constexpr explicit elements_view(V base); +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{base_} with \tcode{std::move(base)}. -\end{itemdescr} - -\rSec3[range.elements.iterator]{Class template \tcode{elements_view::\exposid{iterator}}} - -\indexlibraryglobal{elements_view::iterator}% +Equivalent to: \begin{codeblock} -namespace std::ranges { - template<@\libconcept{input_range}@ V, size_t N> - requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && - @\exposconcept{has-tuple-element}@>, N> && - @\exposconcept{returnable-element}@, N> - template - class elements_view::@\exposid{iterator}@ { // \expos - using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - - iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos - - static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i); // \expos - - public: - using iterator_concept = @\seebelow@; - using iterator_category = @\seebelow@; // not always present - using value_type = remove_cvref_t>>; - using difference_type = range_difference_t<@\exposid{Base}@>; - - @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; - constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); - constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; - - constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; - constexpr iterator_t<@\exposid{Base}@> base() &&; - - constexpr decltype(auto) operator*() const - { return @\exposid{get-element}@(@\exposid{current_}@); } - - constexpr @\exposid{iterator}@& operator++(); - constexpr void operator++(int); - constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; - - constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} - constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} - constexpr decltype(auto) operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@> - { return @\exposid{get-element}@(@\exposid{current_}@ + n); } +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_}.back() + x} has well-defined behavior. - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@>; +\pnum +\ensures +Each element of \exposid{current_} is equal to \tcode{i + x}, +where \tcode{i} is the value of that element before the call. - friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@>; +\pnum +\returns +\tcode{*this}. +\end{itemdescr} - friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; - }; -} -\end{codeblock} +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} +\begin{itemdescr} \pnum -The member \grammarterm{typedef-name} \tcode{iterator_concept} -is defined as follows: -\begin{itemize} -\item -If \exposid{Base} models \libconcept{random_access_range}, -then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. -\item -Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, -then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. -\item -Otherwise, if \exposid{Base} models \libconcept{forward_range}, -then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. -\item -Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. -\end{itemize} +\expects +\tcode{\exposid{current_}.front() - x} has well-defined behavior. \pnum -The member \grammarterm{typedef-name} \tcode{iterator_category} is defined -if and only if \exposid{Base} models \libconcept{forward_range}. -In that case, \tcode{iterator_category} is defined as follows: -Let \tcode{C} denote the type -\tcode{iterator_traits>::iterator_category}. -\begin{itemize} -\item -If \tcode{std::get(*\exposid{current_})} is an rvalue, -\tcode{iterator_category} denotes \tcode{input_iterator_tag}. -\item -Otherwise, if \tcode{C} models \tcode{\libconcept{derived_from}}, -\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}. -\item -Otherwise, \tcode{iterator_category} denotes \tcode{C}. -\end{itemize} +\ensures +Each element of \exposid{current_} is equal to \tcode{i - x}, +where \tcode{i} is the value of that element before the call. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} -\indexlibrarymember{\exposid{get-element}}{elements_view::iterator}% \begin{itemdecl} -static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i); // \expos +constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -7234,89 +10162,81 @@ \effects Equivalent to: \begin{codeblock} -if constexpr (is_reference_v>) { - return std::get(*i); -} else { - using E = remove_cv_t>>; - return static_cast(std::get(*i)); -} +return @\exposid{tuple-transform}@([&](auto& i) -> decltype(auto) { return i[n]; }, @\exposid{current_}@); \end{codeblock} \end{itemdescr} -\indexlibraryctor{elements_view::iterator}% \begin{itemdecl} -constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{current_} with \tcode{std::move(current)}. +\returns +\tcode{x.\exposid{current_}.back() == y.\exposid{current_}.back()}. \end{itemdescr} -\indexlibraryctor{elements_view::iterator}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +\returns +\tcode{x.\exposid{current_}.back() < y.\exposid{current_}.back()}. \end{itemdescr} -\indexlibrarymember{base}{elements_view::iterator}% \begin{itemdecl} -constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{current_};} +Equivalent to: \tcode{return y < x;} \end{itemdescr} -\indexlibrarymember{base}{elements_view::iterator}% \begin{itemdecl} -constexpr iterator_t<@\exposid{Base}@> base() &&; +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return std::move(\exposid{current_});} +Equivalent to: \tcode{return !(y < x);} \end{itemdescr} -\indexlibrarymember{operator++}{elements_view::iterator}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator++(); +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -++@\exposid{current_}@; -return *this; -\end{codeblock} +Equivalent to: \tcode{return !(x < y);} \end{itemdescr} -\indexlibrarymember{operator++}{elements_view::iterator}% \begin{itemdecl} -constexpr void operator++(int); +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && + @\libconcept{three_way_comparable}@>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{++\exposid{current_}}. +\returns +\tcode{x.\exposid{current_}.back() <=> y.\exposid{current_}.back()}. \end{itemdescr} -\indexlibrarymember{operator++}{elements_view::iterator}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -7324,15 +10244,15 @@ \effects Equivalent to: \begin{codeblock} -auto temp = *this; -++@\exposid{current_}@; -return temp; +auto r = i; +r += n; +return r; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{elements_view::iterator}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -7340,449 +10260,519 @@ \effects Equivalent to: \begin{codeblock} ---@\exposid{current_}@; -return *this; +auto r = i; +r -= n; +return r; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{elements_view::iterator}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum \effects Equivalent to: -\begin{codeblock} -auto temp = *this; ---@\exposid{current_}@; -return temp; -\end{codeblock} +\tcode{return x.\exposid{current_}.back() - y.\exposid{current_}.back();} \end{itemdescr} -\indexlibrarymember{operator+=}{elements_view::iterator}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type n); - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum \effects Equivalent to: +\tcode{return \exposid{tuple-transform}(ranges::iter_move, i.\exposid{current_});} + +\pnum +\remarks +The exception specification is equivalent to: \begin{codeblock} -@\exposid{current_}@ += n; -return *this; +noexcept(ranges::iter_move(declval&>())) && +is_nothrow_move_constructible_v> \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-=}{elements_view::iterator}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires @\libconcept{indirectly_swappable}@>; \end{itemdecl} \begin{itemdescr} +\pnum +\expects +None of the iterators in \tcode{l.\exposid{current_}} is equal to +an iterator in \tcode{r.\exposid{current_}}. + \pnum \effects -Equivalent to: +For every integer $0 \leq i < \tcode{N}$, +performs +\tcode{ranges::iter_swap(l.\exposid{current_}[$i$], r.\exposid{current_}[$i$])}. + +\pnum +\remarks +The exception specification is equivalent to: \begin{codeblock} -@\exposid{current_}@ -= n; -return *this; +noexcept(ranges::iter_swap(declval>(), declval>())) \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator==}{elements_view::iterator}% -\begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@<@\exposid{Base}@>; -\end{itemdecl} +\rSec3[range.adjacent.sentinel]{Class template \tcode{adjacent_view::\exposid{sentinel}}} -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};} -\end{itemdescr} +\indexlibraryglobal{adjacent_view::sentinel}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) + template + class adjacent_view::@\exposid{sentinel}@ { + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); // \expos + + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; + + template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); + }; +} +\end{codeblock} -\indexlibrarymember{operator<}{elements_view::iterator}% \begin{itemdecl} -friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} < y.\exposid{current_};} +Initializes \exposid{end_} with \tcode{end}. \end{itemdescr} -\indexlibrarymember{operator>}{elements_view::iterator}% \begin{itemdecl} -friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return y < x;} +Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. \end{itemdescr} -\indexlibrarymember{operator<=}{elements_view::iterator}% \begin{itemdecl} -friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(y < x);} +Equivalent to: \tcode{return x.\exposid{current_}.back() == y.\exposid{end_};} \end{itemdescr} -\indexlibrarymember{operator>=}{elements_view::iterator}% \begin{itemdecl} -friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(x < y);} +Equivalent to: \tcode{return x.\exposid{current_}.back() - y.\exposid{end_};} \end{itemdescr} -\indexlibrarymember{operator<=>}{elements_view::iterator}% \begin{itemdecl} -friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@>; +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};} +Equivalent to: \tcode{return y.\exposid{end_} - x.\exposid{current_}.back();} \end{itemdescr} -\indexlibrarymember{operator+}{elements_view::iterator}% -\begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} +\rSec2[range.adjacent.transform]{Adjacent transform view} + +\rSec3[range.adjacent.transform.overview]{Overview} -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return iterator\{x\} += y;} -\end{itemdescr} +\indexlibraryglobal{adjacent_transform_view}% +\tcode{adjacent_transform_view} takes an invocable object and +a \libconcept{view} and produces a \libconcept{view} +whose $M^\text{th}$ element is the result of applying the invocable object +to the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements +of the original view. +If the original view has fewer than $N$ elements, the resulting view is empty. -\indexlibrarymember{operator+}{elements_view::iterator}% -\begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} +\pnum +\indexlibrarymember{adjacent_transform}{views}% +The name \tcode{views::adjacent_transform} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{F} and +a constant expression \tcode{N}: +\begin{itemize} +\item +If \tcode{N} is equal to \tcode{0}, +\tcode{views::adjacent_transform(E, F)} is expression-equivalent to +\tcode{((void)E, views::zip_transform(F))}, +except that the evaluations of \tcode{E} and \tcode{F} are +indeterminately sequenced. +\item +Otherwise, +the expression \tcode{views::adjacent_transform(E, F)} is +expression-equivalent to +\tcode{adja\-cent_transform_view, decay_t, N>(E, F)}. +\end{itemize} -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return y + x;} -\end{itemdescr} +\begin{example} +\begin{codeblock} +vector v = {1, 2, 3, 4}; -\indexlibrarymember{operator-}{elements_view::iterator}% -\begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} +for (auto i : v | views::adjacent_transform<2>(std::multiplies())) { + cout << i << ' '; // prints: 2 6 12 +} +\end{codeblock} +\end{example} -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return iterator\{x\} -= y;} -\end{itemdescr} +\rSec3[range.adjacent.transform.view]{Class template \tcode{adjacent_transform_view}} + +\indexlibrarymember{begin}{adjacent_transform_view}% +\indexlibrarymember{end}{adjacent_transform_view}% +\indexlibrarymember{size}{adjacent_transform_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{copy_constructible}@ F, size_t N> + requires @\libconcept{view}@ && (N > 0) && is_object_v && + @\libconcept{regular_invocable}@, N)...> && + @\exposconcept{can-reference}@, N)...>> + class adjacent_transform_view : public view_interface> { + @\exposidnc{copyable-box}@ @\exposid{fun_}@; // \expos + adjacent_view @\exposid{inner_}@; // \expos + + using @\exposidnc{InnerView}@ = adjacent_view; // \expos + template + using @\exposid{inner-iterator}@ = iterator_t<@\exposid{maybe-const}@>; // \expos + template + using @\exposid{inner-sentinel}@ = sentinel_t<@\exposid{maybe-const}@>; // \expos + + // \ref{range.adjacent.transform.iterator}, class template \tcode{adjacent_transform_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos + + // \ref{range.adjacent.transform.sentinel}, class template \tcode{adjacent_transform_view::\exposid{sentinel}} + template class @\exposidnc{sentinel}@; // \expos + + public: + adjacent_transform_view() = default; + constexpr explicit adjacent_transform_view(V base, F fun); + + constexpr auto begin() { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.begin()); + } + + constexpr auto begin() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@, N)...> { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.begin()); + } + + constexpr auto end() { + if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.end()); + } else { + return @\exposid{sentinel}@(@\exposid{inner_}@.end()); + } + } + + constexpr auto end() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@, N)...> { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.end()); + } else { + return @\exposid{sentinel}@(@\exposid{inner_}@.end()); + } + } + + constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> { + return @\exposid{inner_}@.size(); + } + + constexpr auto size() const requires @\libconcept{sized_range}@ { + return @\exposid{inner_}@.size(); + } + }; +} +\end{codeblock} -\indexlibrarymember{operator-}{elements_view::iterator}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +constexpr explicit adjacent_transform_view(V base, F fun); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{current_};} +Initializes \exposid{fun_} with \tcode{std::move(fun)} and +\exposid{inner_} with \tcode{std::move(base)}. \end{itemdescr} -\rSec3[range.elements.sentinel]{Class template \tcode{elements_view::\exposid{sentinel}}} +\rSec3[range.adjacent.transform.iterator]{Class template \tcode{adjacent_transform_view::\exposid{iterator}}} -\indexlibraryglobal{elements_view::sentinel}% +\indexlibraryglobal{adjacent_transform_view::iterator}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{input_range}@ V, size_t N> - requires @\libconcept{view}@ && @\placeholder{has-tuple-element}@, N> && - @\placeholder{has-tuple-element}@>, N> && - @\exposconcept{returnable-element}@, N> + template<@\libconcept{forward_range}@ V, @\libconcept{copy_constructible}@ F, size_t N> + requires @\libconcept{view}@ && (N > 0) && is_object_v && + @\libconcept{regular_invocable}@, N)...> && + @\exposconcept{can-reference}@, N)...>> template - class elements_view::@\exposid{sentinel}@ { // \expos - private: - using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + class adjacent_transform_view::@\exposid{iterator}@ { + using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposidnc{inner-iterator}@ @\exposid{inner_}@; // \expos + + constexpr @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent, @\exposidnc{inner-iterator}@ inner); // \expos + public: - @\exposid{sentinel}@() = default; - constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) - requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; + using iterator_category = @\seebelow@; + using iterator_concept = typename @\exposid{inner-iterator}@::iterator_concept; + using value_type = + remove_cvref_t&, + @\exposid{REPEAT}@(range_reference_t<@\exposid{Base}@>, N)...>>; + using difference_type = range_difference_t<@\exposid{Base}@>; - constexpr sentinel_t<@\exposid{Base}@> base() const; + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; - template - requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + constexpr decltype(auto) operator*() const noexcept(@\seebelow@); + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{inner-iterator}@>; + + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; }; } \end{codeblock} -\indexlibraryctor{elements_view::sentinel}% +\pnum +The member \grammarterm{typedef-name} \tcode{\exposid{iterator}::iterator_category} +is defined as follows: +\begin{itemize} +\item +If \tcode{invoke_result_t<\exposid{maybe-const}\&, +\exposid{REPEAT}(range_reference_t<\exposid{Base}>, N)...>} +is\linebreak not an lvalue reference, +\tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\item +Otherwise, let \tcode{C} denote the type +\tcode{iterator_traits>::iterator_category}. +\begin{itemize} +\item +If \tcode{\libconcept{derived_from}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{ran\-dom_access_iterator_tag}. +\item +Otherwise, +if \tcode{\libconcept{derived_from}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, +if \tcode{\libconcept{derived_from}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\end{itemize} +\end{itemize} + \begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{inner-iterator}@ inner); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{end}. +Initializes \exposid{parent_} with \tcode{addressof(parent)} and +\exposid{inner_} with \tcode{std::move(inner)}. \end{itemdescr} -\indexlibraryctor{elements_view::sentinel}% \begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) - requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}. +Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and +\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. \end{itemdescr} -\indexlibrarymember{base}{elements_view::sentinel}% \begin{itemdecl} -constexpr sentinel_t<@\exposid{Base}@> base() const; +constexpr decltype(auto) operator*() const noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{end_};} +Equivalent to: +\begin{codeblock} +return apply([&](const auto&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); +}, @\exposid{inner_}@.@\exposid{current_}@); +\end{codeblock} + +\pnum +\remarks +Let \tcode{Is} be the pack \tcode{0, 1, \ldots, (N-1)}. +The exception specification is equivalent to: +\begin{codeblock} +noexcept(invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *std::get(@\exposid{inner_}@.@\exposid{current_}@)...)) +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator==}{elements_view::sentinel}% \begin{itemdecl} -template - requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};} +Equivalent to: +\begin{codeblock} +++@\exposid{inner_}@; +return *this; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-}{elements_view::sentinel}% \begin{itemdecl} -template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};} +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-}{elements_view::sentinel}% \begin{itemdecl} -template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};} +Equivalent to: +\begin{codeblock} +--@\exposid{inner_}@; +return *this; +\end{codeblock} \end{itemdescr} -\rSec2[range.zip]{Zip view} - -\rSec3[range.zip.overview]{Overview} - -\pnum -\indexlibraryglobal{zip_view}% -\tcode{zip_view} takes any number of \libconcept{view}s and -produces a \libconcept{view} of tuples of references -to the corresponding elements of the constituent views. +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} +\begin{itemdescr} \pnum -\indexlibrarymember{zip}{views}% -The name \tcode{views::zip} denotes -a customization point object\iref{customization.point.object}. -Given a pack of subexpressions \tcode{Es...}, -the expression \tcode{views::zip(Es...)} is expression-equivalent to -\begin{itemize} -\item -\tcode{auto(views::empty>)} -if \tcode{Es} is an empty pack, -\item -otherwise, \tcode{zip_view...>(Es...)}. -\end{itemize} - -\begin{example} +\effects +Equivalent to: \begin{codeblock} -vector v = {1, 2}; -list l = {'a', 'b', 'c'}; - -auto z = views::zip(v, l); -range_reference_t f = z.front(); // \tcode{f} is a \tcode{pair} - // that refers to the first element of \tcode{v} and \tcode{l} - -for (auto&& [x, y] : z) { - cout << '(' << x << ", " << y << ") "; // prints: (1, a) (2, b) -} +auto tmp = *this; +--*this; +return tmp; \end{codeblock} -\end{example} +\end{itemdescr} -\rSec3[range.zip.view]{Class template \tcode{zip_view}} +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} -\indexlibrarymember{begin}{zip_view}% -\indexlibrarymember{end}{zip_view}% -\indexlibrarymember{size}{zip_view}% +\begin{itemdescr} +\pnum +\effects +Equivalent to: \begin{codeblock} -namespace std::ranges { - template - concept @\defexposconcept{zip-is-common}@ = // \expos - (sizeof...(Rs) == 1 && (@\libconcept{common_range}@ && ...)) || - (!(@\libconcept{bidirectional_range}@ && ...) && (@\libconcept{common_range}@ && ...)) || - ((@\libconcept{random_access_range}@ && ...) && (@\libconcept{sized_range}@ && ...)); - - template - using @\exposid{tuple-or-pair}@ = @\seebelow@; // \expos - - template - constexpr auto @\exposid{tuple-transform}@(F&& f, Tuple&& tuple) { // \expos - return apply([&](Ts&&... elements) { - return @\exposid{tuple-or-pair}@...>( - invoke(f, std::forward(elements))... - ); - }, std::forward(tuple)); - } - - template - constexpr void @\exposid{tuple-for-each}@(F&& f, Tuple&& tuple) { // \expos - apply([&](Ts&&... elements) { - (invoke(f, std::forward(elements)), ...); - }, std::forward(tuple)); - } - - template<@\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) - class zip_view : public view_interface> { - tuple @\exposid{views_}@; // \expos - - // \ref{range.zip.iterator}, class template \tcode{zip_view::\exposid{iterator}} - template class @\exposidnc{iterator}@; // \expos - - // \ref{range.zip.sentinel}, class template \tcode{zip_view::\exposid{sentinel}} - template class @\exposidnc{sentinel}@; // \expos - - public: - zip_view() = default; - constexpr explicit zip_view(Views... views); - - constexpr auto begin() requires (!(@\exposconcept{simple-view}@ && ...)) { - return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); - } - constexpr auto begin() const requires (@\libconcept{range}@ && ...) { - return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); - } - - constexpr auto end() requires (!(@\exposconcept{simple-view}@ && ...)) { - if constexpr (!@\exposconcept{zip-is-common}@) { - return @\exposid{sentinel}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); - } else if constexpr ((@\libconcept{random_access_range}@ && ...)) { - return begin() + iter_difference_t<@\exposid{iterator}@>(size()); - } else { - return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); - } - } - - constexpr auto end() const requires (@\libconcept{range}@ && ...) { - if constexpr (!@\exposconcept{zip-is-common}@) { - return @\exposid{sentinel}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); - } else if constexpr ((@\libconcept{random_access_range}@ && ...)) { - return begin() + iter_difference_t<@\exposid{iterator}@>(size()); - } else { - return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); - } - } - - constexpr auto size() requires (@\libconcept{sized_range}@ && ...); - constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); - }; - - template - zip_view(Rs&&...) -> zip_view...>; -} +@\exposid{inner_}@ += x; +return *this; \end{codeblock} - -\pnum -Given some pack of types \tcode{Ts}, -the alias template \exposid{tuple-or-pair} is defined as follows: -\begin{itemize} -\item -If \tcode{sizeof...(Ts)} is 2, -\tcode{\exposid{tuple-or-pair}} denotes \tcode{pair}. -\item -Otherwise, \tcode{\exposid{tuple-or-pair}} denotes \tcode{tuple}. -\end{itemize} - -\pnum -Two \tcode{zip_view} objects have the same underlying sequence if and only if -the corresponding elements of \exposid{views_} are equal\iref{concepts.equality} -and have the same underlying sequence. -\begin{note} -In particular, comparison of iterators obtained from \tcode{zip_view} objects -that do not have the same underlying sequence -is not required to produce meaningful results\iref{iterator.concept.forward}. -\end{note} +\end{itemdescr} \begin{itemdecl} -constexpr explicit zip_view(Views... views); +constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{views_} with \tcode{std::move(views)...}. +Equivalent to: +\begin{codeblock} +@\exposid{inner_}@ -= x; +return *this; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr auto size() requires (@\libconcept{sized_range}@ && ...); -constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); +constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -7790,183 +10780,259 @@ \effects Equivalent to: \begin{codeblock} -return apply([](auto... sizes) { - using CT = @\exposid{make-unsigned-like-t}@>; - return ranges::min({CT(sizes)...}); -}, @\exposid{tuple-transform}@(ranges::size, @\exposid{views_}@)); +return apply([&](const auto&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[n]...); +}, @\exposid{inner_}@.@\exposid{current_}@); \end{codeblock} \end{itemdescr} -\rSec3[range.zip.iterator]{Class template \tcode{zip_view::\exposid{iterator}}} +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{inner-iterator}@>; +\end{itemdecl} -\indexlibraryglobal{zip_view::iterator}% -\begin{codeblock} -namespace std::ranges { - template - concept @\defexposconceptnc{all-random-access}@ = // \expos - (@\libconcept{random_access_range}@<@\exposid{maybe-const}@> && ...); - template - concept @\defexposconceptnc{all-bidirectional}@ = // \expos - (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@> && ...); - template - concept @\defexposconceptnc{all-forward}@ = // \expos - (@\libconcept{forward_range}@<@\exposid{maybe-const}@> && ...); +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. - template<@\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) - template - class zip_view::@\exposid{iterator}@ { - @\exposid{tuple-or-pair}@>...> @\exposid{current_}@;@\itcorr[-1]@ // \expos - constexpr explicit @\exposidnc{iterator}@(@\exposid{tuple-or-pair}@>...>); - // \expos - public: - using iterator_category = input_iterator_tag; // not always present - using iterator_concept = @\seebelow@; - using value_type = @\exposid{tuple-or-pair}@>...>; - using difference_type = common_type_t>...>; +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} +\end{itemdescr} - @\exposid{iterator}@() = default; - constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && (@\libconcept{convertible_to}@, - iterator_t<@\exposid{maybe-const}@>> && ...); +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} - constexpr auto operator*() const; - constexpr @\exposid{iterator}@& operator++(); - constexpr void operator++(int); - constexpr @\exposid{iterator}@ operator++(int) requires @\exposconcept{all-forward}@; +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} +\end{itemdescr} - constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{all-bidirectional}@; - constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@; +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} - constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\exposconcept{all-random-access}@; - constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\exposconcept{all-random-access}@; +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} +\end{itemdescr} - constexpr auto operator[](difference_type n) const - requires @\exposconcept{all-random-access}@; +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; +\end{itemdecl} - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires (@\libconcept{equality_comparable}@>> && ...); +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} - 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}@>> && ...); +\rSec3[range.adjacent.transform.sentinel]{Class template \tcode{adjacent_transform_view::\exposid{sentinel}}} - friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) - requires @\exposconcept{all-random-access}@; - friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) - requires @\exposconcept{all-random-access}@; - friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\exposconcept{all-random-access}@; - friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...); +\indexlibraryglobal{adjacent_transform_view::sentinel}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{copy_constructible}@ F, size_t N> + requires @\libconcept{view}@ && (N > 0) && is_object_v && + @\libconcept{regular_invocable}@, N)...> && + @\exposconcept{can-reference}@, N)...>> + template + class adjacent_transform_view::@\exposid{sentinel}@ { + @\exposidnc{inner-sentinel}@ @\exposid{inner_}@; // \expos + constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{inner-sentinel}@ inner); // \expos - friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; - friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) - requires (@\libconcept{indirectly_swappable}@>> && ...); + template + requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); }; } \end{codeblock} -\pnum -\tcode{\exposid{iterator}::iterator_concept} is defined as follows: -\begin{itemize} -\item -If \tcode{\exposconcept{all-random-access}} is modeled, -then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. -\item -Otherwise, -if \tcode{\exposconcept{all-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 -\tcode{\exposid{iterator}::iterator_category} is present -if and only if \tcode{\exposconcept{all-forward}} is modeled. +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(@\exposid{inner-sentinel}@ inner); +\end{itemdecl} +\begin{itemdescr} \pnum -If the invocation of any non-const member function of \exposid{iterator} -exits via an exception, -the iterator acquires a singular value. +\effects +Initializes \exposid{inner_} with \tcode{inner}. +\end{itemdescr} \begin{itemdecl} -constexpr explicit @\exposid{iterator}@(@\exposid{tuple-or-pair}@>...> current); +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{current_} with \tcode{std::move(current)}. +Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && - (@\libconcept{convertible_to}@, iterator_t<@\exposid{maybe-const}@>> && ...); +template + requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +Equivalent to \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} \end{itemdescr} \begin{itemdecl} -constexpr auto operator*() const; +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: +Equivalent to \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} + +\rSec2[range.chunk]{Chunk view} + +\rSec3[range.chunk.overview]{Overview} + +\pnum +\tcode{chunk_view} takes a \libconcept{view} and a number \tcode{N} and +produces a range of \libconcept{view}s +that are \tcode{N}-sized non-overlapping successive chunks of +the elements of the original \libconcept{view}, in order. +The last \libconcept{view} in the range can have fewer than \tcode{N} elements. + +\pnum +\indexlibrarymember{chunk}{views}% +The name \tcode{views::chunk} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{N}, +the expression \tcode{views::chunk(E, N)} is expression-equivalent to +\tcode{chunk_view(E, N)}. + +\begin{example} \begin{codeblock} -return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); +vector v = {1, 2, 3, 4, 5}; + +for (auto r : v | views::chunk(2)) { + cout << '['; + auto sep = ""; + for(auto i : r) { + cout << sep << i; + sep = ", "; + } + cout << "] "; +} +\end{codeblock} +The above prints: \tcode{[1, 2] [3, 4] [5]} +\end{example} + +\rSec3[range.chunk.view.input]{\tcode{chunk_view} for input ranges} + +\indexlibrarymember{begin}{chunk_view}% +\indexlibrarymember{end}{chunk_view}% +\indexlibrarymember{size}{chunk_view}% +\begin{codeblock} +namespace std::ranges { + template + constexpr I @\exposidnc{div-ceil}@(I num, I denom) { // \expos + I r = num / denom; + if (num % denom) + ++r; + return r; + } + + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + class chunk_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + range_difference_t @\exposid{n_}@ = 0; // \expos + range_difference_t @\exposid{remainder_}@ = 0; // \expos + + @\exposid{non-propagating-cache}@> @\exposid{current_}@; // \expos + + // \ref{range.chunk.outer.iter}, class \tcode{chunk_view::\exposid{outer-iterator}} + class @\exposid{outer-iterator}@; // \expos + + // \ref{range.chunk.inner.iter}, class \tcode{chunk_view::\exposid{inner-iterator}} + class @\exposid{inner-iterator}@; // \expos + + public: + chunk_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit chunk_view(V base, range_difference_t n); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr @\exposid{outer-iterator}@ begin(); + constexpr default_sentinel_t end() noexcept; + + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; + }; + + template + chunk_view(R&& r, range_difference_t) -> chunk_view>; +} \end{codeblock} -\end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@& operator++(); +constexpr explicit chunk_view(V base, range_difference_t n); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{tuple-for-each}@([](auto& i) { ++i; }, @\exposid{current_}@); -return *this; -\end{codeblock} -\end{itemdescr} - -\begin{itemdecl} -constexpr void operator++(int); -\end{itemdecl} +\expects +\tcode{n > 0} is \tcode{true}. -\begin{itemdescr} \pnum \effects -Equivalent to \tcode{++*this}. +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{n_} with \tcode{n}. \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\exposconcept{all-forward}@; +constexpr @\exposid{outer-iterator}@ begin(); \end{itemdecl} \begin{itemdescr} @@ -7974,28 +11040,25 @@ \effects Equivalent to: \begin{codeblock} -auto tmp = *this; -++*this; -return tmp; +current_ = ranges::begin(base_); +remainder_ = n_; +return @\exposid{outer-iterator}@(*this); \end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{all-bidirectional}@; +constexpr default_sentinel_t end() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{tuple-for-each}@([](auto& i) { --i; }, @\exposid{current_}@); -return *this; -\end{codeblock} +\returns +\tcode{default_sentinel}. \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@; +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; \end{itemdecl} \begin{itemdescr} @@ -8003,529 +11066,484 @@ \effects Equivalent to: \begin{codeblock} -auto tmp = *this; ---*this; -return tmp; +return @\exposid{to-unsigned-like}@(@\exposidnc{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{n_}@)); \end{codeblock} \end{itemdescr} -\begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\exposconcept{all-random-access}@; -\end{itemdecl} +\rSec3[range.chunk.outer.iter]{Class \tcode{chunk_view::\exposid{outer-iterator}}} -\begin{itemdescr} -\pnum -\effects -Equivalent to: +\indexlibraryglobal{chunk_view::outer-iterator}% \begin{codeblock} -@\exposid{tuple-for-each}@([&](I& i) { i += iter_difference_t(x); }, @\exposid{current_}@); -return *this; -\end{codeblock} -\end{itemdescr} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + class chunk_view::@\exposid{outer-iterator}@ { + chunk_view* @\exposid{parent_}@; // \expos -\begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\exposconcept{all-random-access}@; -\end{itemdecl} + constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); // \expos -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{tuple-for-each}@([&](I& i) { i -= iter_difference_t(x); }, @\exposid{current_}@); -return *this; + public: + using iterator_concept = input_iterator_tag; + using difference_type = range_difference_t; + + // \ref{range.chunk.outer.value}, class \tcode{chunk_view::\exposid{outer-iterator}::value_type} + struct value_type; + + @\exposid{outer-iterator}@(@\exposid{outer-iterator}@&&) = default; + @\exposid{outer-iterator}@& operator=(@\exposid{outer-iterator}@&&) = default; + + constexpr value_type operator*() const; + constexpr @\exposid{outer-iterator}@& operator++(); + constexpr void operator++(int); + + friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); + + friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{outer-iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; + friend constexpr difference_type operator-(const @\exposid{outer-iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; + }; +} \end{codeblock} -\end{itemdescr} \begin{itemdecl} -constexpr auto operator[](difference_type n) const - requires @\exposconcept{all-random-access}@; +constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return @\exposid{tuple-transform}@([&](I& i) -> decltype(auto) { - return i[iter_difference_t(n)]; -}, @\exposid{current_}@); -\end{codeblock} +Initializes \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires (@\libconcept{equality_comparable}@>> && ...); +constexpr value_type operator*() const; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\begin{itemize} -\item -\tcode{x.\exposid{current_} == y.\exposid{current_}} -if \tcode{\exposconcept{all-bidirectional}} is \tcode{true}. -\item -Otherwise, \tcode{true} -if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$ -such that \tcode{bool(std::\brk{}get<$i$>(x.\exposid{current_}) == -std::get<$i$>(y.\exposid{current_}))} is \tcode{true}. -\begin{note} -This allows \tcode{zip_view} to model \libconcept{common_range} -when all constituent views model \libconcept{common_range}. -\end{note} -\item -Otherwise, \tcode{false}. -\end{itemize} -\end{itemdescr} - -\begin{itemdecl} -friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposconcept{all-random-access}@; -\end{itemdecl} +\expects +\tcode{*this == default_sentinel} is \tcode{false}. -\begin{itemdescr} \pnum \returns -\tcode{x.\exposid{current_} < y.\exposid{current_}}. +\tcode{value_type(*\exposid{parent_})}. \end{itemdescr} \begin{itemdecl} -friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposconcept{all-random-access}@; +constexpr @\exposid{outer-iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + \pnum \effects -Equivalent to: \tcode{return y < x;} +Equivalent to: +\begin{codeblock} +ranges::advance(*@\exposid{parent_}@->@\exposid{current_}@, @\exposid{parent_}@->@\exposid{remainder_}@, ranges::end(@\exposid{parent_}@->@\exposid{base_}@)); +@\exposid{parent_}@->@\exposid{remainder_}@ = @\exposid{parent_}@->@\exposid{n_}@; +return *this; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposconcept{all-random-access}@; +constexpr void operator++(int); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(y < x);} +Equivalent to \tcode{++*this}. \end{itemdescr} \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{outer-iterator}@& x, default_sentinel_t); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(x < y);} +Equivalent to: +\begin{codeblock} +return *x.@\exposid{parent_}@->@\exposid{current_}@ == ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) && x.@\exposid{parent_}@->@\exposid{remainder_}@ != 0; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposconcept{all-random-access}@ && - (@\libconcept{three_way_comparable}@>> && ...); +friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{outer-iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\effects +Equivalent to: +\begin{codeblock} +const auto dist = ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) - *x.@\exposid{parent_}@->@\exposid{current_}@; +if (dist < x.@\exposid{parent_}@->@\exposid{remainder_}@) { + return dist == 0 ? 0 : 1; +} +return @\exposidnc{div-ceil}@(dist - x.@\exposid{parent_}@->@\exposid{remainder_}@, x.@\exposid{parent_}@->@\exposid{n_}@) + 1; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) - requires @\exposconcept{all-random-access}@; -friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) - requires @\exposconcept{all-random-access}@; +friend constexpr difference_type operator-(const @\exposid{outer-iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: +Equivalent to: \tcode{return -(y - x);} +\end{itemdescr} + +\rSec3[range.chunk.outer.value]{Class \tcode{chunk_view::\exposid{outer-iterator}::value_type}} + +\indexlibraryglobal{chunk_view::outer-iterator::value_type}% \begin{codeblock} -auto r = i; -r += n; -return r; +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + struct chunk_view::@\exposid{outer-iterator}@::value_type : view_interface { + private: + chunk_view* @\exposid{parent_}@; // \expos + + constexpr explicit value_type(chunk_view& parent); // \expos + + public: + constexpr @\exposid{inner-iterator}@ begin() const noexcept; + constexpr default_sentinel_t end() const noexcept; + + constexpr auto size() const + requires @\libconcept{sized_sentinel_for}@, iterator_t>; + }; +} \end{codeblock} -\end{itemdescr} \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\exposconcept{all-random-access}@; +constexpr explicit value_type(chunk_view& parent); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -auto r = i; -r -= n; -return r; -\end{codeblock} +Initializes \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...); +constexpr @\exposid{inner-iterator}@ begin() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{\exposid{DIST}($i$)} be \tcode{difference_type(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{current_}))}. - \pnum \returns -The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)} -for all integers $0 \leq n < \tcode{sizeof...(Views)}$. +\tcode{\exposid{inner-iterator}(*\exposid{parent_})}. \end{itemdescr} \begin{itemdecl} -friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); +constexpr default_sentinel_t end() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return @\exposid{tuple-transform}@(ranges::iter_move, i.@\exposid{current_}@); -\end{codeblock} - -\pnum -\remarks -The exception specification is equivalent to: -\begin{codeblock} -(noexcept(ranges::iter_move(declval>&>())) && ...) && -(is_nothrow_move_constructible_v>> && ...) -\end{codeblock} +\returns +\tcode{default_sentinel}. \end{itemdescr} \begin{itemdecl} -friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) - requires (@\libconcept{indirectly_swappable}@>> && ...); +constexpr auto size() const + requires @\libconcept{sized_sentinel_for}@, iterator_t>; \end{itemdecl} \begin{itemdescr} \pnum \effects -For every integer $0 \leq i < \tcode{sizeof...(Views)}$, -performs: -\begin{codeblock} -ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@)) -\end{codeblock} - -\pnum -\remarks -The exception specification is equivalent to -the logical \logop{AND} of the following expressions: +Equivalent to: \begin{codeblock} -noexcept(ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@))) +return ranges::min(@\exposid{parent_}@->@\exposid{remainder_}@, ranges::end(@\exposid{parent_}@->@\exposid{base_}@) - *@\exposid{parent_}@->@\exposid{current_}@); \end{codeblock} -for every integer $0 \leq i < \tcode{sizeof...(Views)}$. \end{itemdescr} -\rSec3[range.zip.sentinel]{Class template \tcode{zip_view::\exposid{sentinel}}} +\rSec3[range.chunk.inner.iter]{Class \tcode{chunk_view::\exposid{inner-iterator}}} -\indexlibraryglobal{zip_view::sentinel}% +\indexlibraryglobal{chunk_view::inner-iterator}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) - template - class zip_view::@\exposid{sentinel}@ { - @\exposid{tuple-or-pair}@>...> @\exposid{end_}@;@\itcorr[-1]@ // \expos - constexpr explicit @\exposidnc{sentinel}@(@\exposid{tuple-or-pair}@>...> end); - // \expos + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + class chunk_view::@\exposid{inner-iterator}@ { + chunk_view* @\exposid{parent_}@; // \expos + + constexpr explicit @\exposid{inner-iterator}@(chunk_view& parent) noexcept; // \expos + public: - @\exposid{sentinel}@() = default; - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && - (@\libconcept{convertible_to}@, sentinel_t<@\exposid{maybe-const}@>> && ...); + using iterator_concept = input_iterator_tag; + using difference_type = range_difference_t; + using value_type = range_value_t; - template - requires (@\libconcept{sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + @\exposid{inner-iterator}@(@\exposid{inner-iterator}@&&) = default; + @\exposid{inner-iterator}@& operator=(@\exposid{inner-iterator}@&&) = default; - template - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) - friend constexpr common_type_t>...> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + constexpr const iterator_t& base() const &; - template - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) - friend constexpr common_type_t>...> - operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); + constexpr range_reference_t operator*() const; + constexpr @\exposid{inner-iterator}@& operator++(); + constexpr void operator++(int); + + friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); + + friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{inner-iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; + friend constexpr difference_type operator-(const @\exposid{inner-iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; }; } \end{codeblock} \begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(@\exposid{tuple-or-pair}@>...> end); +constexpr explicit @\exposid{inner-iterator}@(chunk_view& parent) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{end}. +Initializes \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && - (@\libconcept{convertible_to}@, sentinel_t<@\exposid{maybe-const}@>> && ...); +constexpr const iterator_t& base() const &; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. +Equivalent to: \tcode{return *\exposid{parent_}->\exposid{current_};} \end{itemdescr} \begin{itemdecl} -template - requires (@\libconcept{sentinel_for}@>, - iterator_t>> && ...) -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +constexpr range_reference_t operator*() const; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{true} if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$ -such that \tcode{bool(std::get<$i$>(x.\brk{}\exposid{current_}) == -std::get<$i$>(y.\exposid{end_}))} is \tcode{true}. -Otherwise, \tcode{false}. +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + +\pnum +\effects +Equivalent to: \tcode{return **\exposid{parent_}->\exposid{current_};} \end{itemdescr} \begin{itemdecl} -template - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) -friend constexpr common_type_t>...> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +constexpr @\exposid{inner-iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{D} be the return type. -Let \tcode{\exposid{DIST}($i$)} be -\tcode{D(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{end_}))}. +\expects +\tcode{*this == default_sentinel} is \tcode{false}. \pnum -\returns -The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)} -for all integers $0 \leq n < \tcode{sizeof...(Views)}$. +\effects +Equivalent to: +\begin{codeblock} +++*@\exposid{parent_}@->@\exposid{current_}@; +if (*@\exposid{parent_}@->@\exposid{current_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) + @\exposid{parent_}@->@\exposid{remainder_}@ = 0; +else + --@\exposid{parent_}@->@\exposid{remainder_}@; +return *this; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -template - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) -friend constexpr common_type_t>...> - operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); +constexpr void operator++(int); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to \tcode{return -(x - y);} +Equivalent to \tcode{++*this}. \end{itemdescr} -\rSec2[range.zip.transform]{Zip transform view} - -\rSec3[range.zip.transform.overview]{Overview} +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); +\end{itemdecl} +\begin{itemdescr} \pnum -\indexlibraryglobal{zip_transform_view}% -\tcode{zip_transform_view} takes an invocable object and -any number of \libconcept{view}s and -produces a \libconcept{view} -whose $M^\text{th}$ element is -the result of applying the invocable object -to the $M^\text{th}$ elements of all views. +\returns +\tcode{x.\exposid{parent_}->\exposid{remainder_} == 0}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{inner-iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; +\end{itemdecl} +\begin{itemdescr} \pnum -\indexlibrarymember{zip_transform}{views}% -The name \tcode{views::zip_transform} denotes -a customization point object\iref{customization.point.object}. -Let \tcode{F} be a subexpression, and -let \tcode{Es...} be a pack of subexpressions. -\begin{itemize} -\item -If \tcode{Es} is an empty pack, -let \tcode{FD} be \tcode{decay_t}. -\begin{itemize} -\item -If \tcode{\libconcept{copy_constructible} \&\& -\libconcept{regular_invocable}} is \tcode{false}, or -if \tcode{decay_t>} is not an object type, -\tcode{views::zip_transform(F, Es...)} is ill-formed. -\item -Otherwise, the expression \tcode{views::zip_transform(F, Es...)} -is expression-equivalent to +\effects +Equivalent to: \begin{codeblock} -((void)F, auto(views::empty>>)) +return ranges::min(x.@\exposid{parent_}@->@\exposid{remainder_}@, + ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) - *x.@\exposid{parent_}@->@\exposid{current_}@); \end{codeblock} -\end{itemize} -\item -Otherwise, the expression \tcode{views::zip_transform(F, Es...)} -is expression-equivalent to \tcode{zip_trans\-form_view(F, Es...)}. -\end{itemize} +\end{itemdescr} -\pnum -\begin{example} -\begin{codeblock} -vector v1 = {1, 2}; -vector v2 = {4, 5, 6}; +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{inner-iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; +\end{itemdecl} -for (auto i : views::zip_transform(plus(), v1, v2)) { - cout << i << ' '; // prints: 5 7 -} -\end{codeblock} -\end{example} +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return -(y - x);} +\end{itemdescr} -\rSec3[range.zip.transform.view]{Class template \tcode{zip_transform_view}} +\rSec3[range.chunk.view.fwd]{\tcode{chunk_view} for forward ranges} -\indexlibrarymember{begin}{zip_transform_view}% -\indexlibrarymember{end}{zip_transform_view}% -\indexlibrarymember{size}{zip_transform_view}% +\indexlibrarymember{begin}{chunk_view}% +\indexlibrarymember{end}{chunk_view}% +\indexlibrarymember{size}{chunk_view}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{copy_constructible}@ F, @\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && - @\libconcept{regular_invocable}@...> && - @\exposconcept{can-reference}@...>> - class zip_transform_view : public view_interface> { - @\exposidnc{copyable-box}@ @\exposid{fun_}@; // \expos - zip_view @\exposid{zip_}@; // \expos - - using @\exposidnc{InnerView}@ = zip_view; // \expos - template - using @\exposidnc{ziperator}@ = iterator_t<@\exposidnc{maybe-const}@>; // \expos - template - using @\exposidnc{zentinel}@ = sentinel_t<@\exposidnc{maybe-const}@>; // \expos - - // \ref{range.zip.transform.iterator}, class template \tcode{zip_transform_view::\exposid{iterator}} - template class @\exposidnc{iterator}@; // \expos + template<@\libconcept{view}@ V> + requires @\libconcept{forward_range}@ + class chunk_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + range_difference_t @\exposid{n_}@ = 0; // \expos - // \ref{range.zip.transform.sentinel}, class template \tcode{zip_transform_view::\exposid{sentinel}} - template class @\exposidnc{sentinel}@; // \expos + // \ref{range.chunk.fwd.iter}, class template \tcode{chunk_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos public: - zip_transform_view() = default; + chunk_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit chunk_view(V base, range_difference_t n); - constexpr explicit zip_transform_view(F fun, Views... views); + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } - constexpr auto begin() { return @\exposid{iterator}@(*this, @\exposid{zip_}@.begin()); } + constexpr auto begin() requires (!@\exposconcept{simple-view}@) { + return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); + } - constexpr auto begin() const - requires @\libconcept{range}@ && - @\libconcept{regular_invocable}@...> { - return @\exposid{iterator}@(*this, @\exposid{zip_}@.begin()); + constexpr auto begin() const requires @\libconcept{forward_range}@ { + return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); } - constexpr auto end() { - if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { - return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); + constexpr auto end() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) { + auto missing = (@\exposid{n_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{n_}@) % @\exposid{n_}@; + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@), missing); + } else if constexpr (@\libconcept{common_range}@ && !@\libconcept{bidirectional_range}@) { + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@)); } else { - return @\exposid{sentinel}@(@\exposid{zip_}@.end()); + return default_sentinel; } } - constexpr auto end() const - requires @\libconcept{range}@ && - @\libconcept{regular_invocable}@...> { - if constexpr (@\libconcept{common_range}@) { - return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); + constexpr auto end() const requires @\libconcept{forward_range}@ { + if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) { + auto missing = (@\exposid{n_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{n_}@) % @\exposid{n_}@; + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@), missing); + } else if constexpr (@\libconcept{common_range}@ && !@\libconcept{bidirectional_range}@) { + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@)); } else { - return @\exposid{sentinel}@(@\exposid{zip_}@.end()); + return default_sentinel; } } - constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> { - return @\exposid{zip_}@.size(); - } - - constexpr auto size() const requires @\libconcept{sized_range}@ { - return @\exposid{zip_}@.size(); - } + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; }; - - template - zip_transform_view(F, Rs&&...) -> zip_transform_view...>; } \end{codeblock} \begin{itemdecl} -constexpr explicit zip_transform_view(F fun, Views... views); +constexpr explicit chunk_view(V base, range_difference_t n); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{n > 0} is \tcode{true}. + \pnum \effects -Initializes \exposid{fun_} with \tcode{std::move(fun)} and -\exposid{zip_} with \tcode{std::move(views)...}. +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{n_} with \tcode{n}. \end{itemdescr} -\rSec3[range.zip.transform.iterator]{Class template \tcode{zip_transform_view::\exposid{iterator}}} +\begin{itemdecl} +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; +\end{itemdecl} -\indexlibraryglobal{zip_transform_view::iterator}% +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{n_}@)); +\end{codeblock} +\end{itemdescr} + +\rSec3[range.chunk.fwd.iter]{Class template \tcode{chunk_view::\exposid{iterator}} for forward ranges} + +\indexlibraryglobal{chunk_view::iterator}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{copy_constructible}@ F, @\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && - @\libconcept{regular_invocable}@...> && - @\exposconcept{can-reference}@...>> + template<@\libconcept{view}@ V> + requires @\libconcept{forward_range}@ template - class zip_transform_view::@\exposid{iterator}@ { - using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos - @\exposid{ziperator}@ @\exposid{inner_}@;@\itcorr[-1]@ // \expos + class chunk_view::@\exposid{iterator}@ { + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); // \expos + iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos + sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + range_difference_t<@\exposid{Base}@> @\exposid{n_}@ = 0; // \expos + range_difference_t<@\exposid{Base}@> @\exposid{missing_}@ = 0; // \expos + + constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, // \expos + range_difference_t<@\exposid{Base}@> missing = 0); public: - using iterator_category = @\seebelownc@; // not always present - using iterator_concept = typename @\exposid{ziperator}@::iterator_concept; - using value_type = - remove_cvref_t&, - range_reference_t<@\exposid{maybe-const}@>...>>; + using iterator_category = input_iterator_tag; + using iterator_concept = @\seebelow@; + using value_type = decltype(views::take(subrange(@\exposid{current_}@, @\exposid{end_}@), @\exposid{n_}@)); using difference_type = range_difference_t<@\exposid{Base}@>; @\exposid{iterator}@() = default; constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> + && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; - constexpr decltype(auto) operator*() const noexcept(@\seebelow@); + constexpr iterator_t<@\exposid{Base}@> base() const; + + constexpr value_type operator*() const; constexpr @\exposid{iterator}@& operator++(); - constexpr void operator++(int); - constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator++(int); constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - constexpr decltype(auto) operator[](difference_type n) const + constexpr value_type operator[](difference_type n) const requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@>; + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -8536,127 +11554,112 @@ friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{ziperator}@>; + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && + @\libconcept{three_way_comparable}@>; - friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + friend constexpr iterator operator+(const @\exposid{iterator}@& i, difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + friend constexpr iterator operator+(difference_type n, const @\exposid{iterator}@& i) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; - }; -} -\end{codeblock} - -\pnum -The member \grammarterm{typedef-name} -\tcode{\exposid{iterator}::iterator_category} -is defined if and only if \exposid{Base} models \libconcept{forward_range}. -In that case, -\tcode{\exposid{iterator}::iterator_category} is defined as follows: -\begin{itemize} -\item -If -\begin{codeblock} -invoke_result_t<@\exposid{maybe-const}@&, range_reference_t<@\exposid{maybe-const}@>...> + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + + friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + }; +} \end{codeblock} -is not an lvalue reference, -\tcode{iterator_category} denotes \tcode{input_iterator_tag}. -\item -Otherwise, let \tcode{Cs} denote the pack of types -\tcode{iterator_traits>>::iterator_category...}. + +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: \begin{itemize} \item -If \tcode{(\libconcept{derived_from} \&\& ...)} -is \tcode{true}, -\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}. -\item -Otherwise, -if \tcode{(\libconcept{derived_from} \&\& ...)} -is \tcode{true}, -\tcode{itera\-tor_category} denotes \tcode{bidirectional_iterator_tag}. +If \exposid{Base} models \libconcept{random_access_range}, +then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. \item -Otherwise, -if \tcode{(\libconcept{derived_from} \&\& ...)} -is \tcode{true}, -\tcode{iterator_cate\-gory} denotes \tcode{forward_iterator_tag}. +Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. \item -Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. -\end{itemize} +Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. \end{itemize} \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); +constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, + range_difference_t<@\exposid{Base}@> missing = 0); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{addressof(parent)} and -\exposid{inner_} with \tcode{std::move(inner)}. +Initializes \exposid{current_} with \tcode{current}, +\exposid{end_} with \tcode{ranges::end(parent->\exposid{base_})}, +\exposid{n_} with \tcode{parent\linebreak ->\exposid{n_}}, and +\exposid{missing_} with \tcode{missing}. \end{itemdescr} \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> + && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and -\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}, +\exposid{end_} with \tcode{std::move(i.\exposid{end_})}, +\exposid{n_} with \tcode{i.\exposid{n_}}, and +\exposid{missing_} with \tcode{i.\exposid{missing_}}. \end{itemdescr} \begin{itemdecl} -constexpr decltype(auto) operator*() const noexcept(@\seebelow@); +constexpr iterator_t<@\exposid{Base}@> base() const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return apply([&](const auto&... iters) -> decltype(auto) { - return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); -}, @\exposid{inner_}@.@\exposid{current_}@); -\end{codeblock} - -\pnum -\remarks -Let \tcode{Is} be the pack \tcode{0, 1, \ldots, \tcode{(sizeof...(Views)-1)}}. -The exception specification is equivalent to: -\tcode{noexcept(invoke(*\exposid{parent_}->\exposid{fun_}, *std::get(\exposid{inner_}.\exposid{current_})...))}. +\returns +\exposid{current_}. \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@& operator++(); +constexpr value_type operator*() const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -++@\exposid{inner_}@; -return *this; -\end{codeblock} +\expects +\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. + +\pnum +\returns +\tcode{views::take(subrange(\exposid{current_}, \exposid{end_}), \exposid{n_})}. \end{itemdescr} \begin{itemdecl} -constexpr void operator++(int); +constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. + \pnum \effects -Equivalent to: \tcode{++*this}. +Equivalent to: +\begin{codeblock} +@\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@, @\exposid{end_}@); +return *this; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} \begin{itemdescr} @@ -8679,7 +11682,8 @@ \effects Equivalent to: \begin{codeblock} ---@\exposid{inner_}@; +ranges::advance(@\exposid{current_}@, @\exposid{missing_}@ - @\exposid{n_}@); +@\exposid{missing_}@ = 0; return *this; \end{codeblock} \end{itemdescr} @@ -8705,11 +11709,25 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\expects +If \tcode{x} is positive, +\tcode{ranges::distance(\exposid{current_}, \exposid{end_}) > \exposid{n_} * (x - 1)} +is \tcode{true}. +\begin{note} +If \tcode{x} is negative, the \Fundescx{Effects} paragraph implies a precondition. +\end{note} + \pnum \effects Equivalent to: \begin{codeblock} -@\exposid{inner_}@ += x; +if (x > 0) { + @\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * x, @\exposid{end_}@); +} else if (x < 0) { + ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * x + @\exposid{missing_}@); + @\exposid{missing_}@ = 0; +} return *this; \end{codeblock} \end{itemdescr} @@ -8722,281 +11740,339 @@ \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -@\exposid{inner_}@ -= x; -return *this; -\end{codeblock} +Equivalent to: \tcode{return *this += -x}; \end{itemdescr} \begin{itemdecl} -constexpr decltype(auto) operator[](difference_type n) const +constexpr value_type operator[](difference_type n) const requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return apply([&](const Is&... iters) -> decltype(auto) { - return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[iter_difference_t(n)]...); -}, @\exposid{inner_}@.@\exposid{current_}@); -\end{codeblock} +\returns +\tcode{*(*this + n)}. \end{itemdescr} \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@>; -friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{ziperator}@>; +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \end{itemdecl} \begin{itemdescr} \pnum -Let \placeholder{op} be the operator. +\returns +\tcode{x.\exposid{current_} == y.\exposid{current_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); +\end{itemdecl} +\begin{itemdescr} \pnum -\effects -Equivalent to: -\tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} +\returns +\tcode{x.\exposid{current_} == x.\exposid{end_}}. \end{itemdescr} \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} +\returns +\tcode{x.\exposid{current_} < y.\exposid{current_}}. \end{itemdescr} \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} +Equivalent to: \tcode{return y < x;} \end{itemdescr} \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +Equivalent to: \tcode{return !(y < x);} \end{itemdescr} -\rSec3[range.zip.transform.sentinel]{Class template \tcode{zip_transform_view::\exposid{sentinel}}} - -\indexlibraryglobal{zip_transform_view::sentinel}% -\begin{codeblock} -namespace std::ranges { - template<@\libconcept{copy_constructible}@ F, @\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && - @\libconcept{regular_invocable}@...> && - @\exposconcept{can-reference}@...>> - template - class zip_transform_view::@\exposid{sentinel}@ { - @\exposidnc{zentinel}@ @\exposid{inner_}@; // \expos - constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{zentinel}@ inner); // \expos - - public: - @\exposid{sentinel}@() = default; - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; +\begin{itemdecl} +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} - template - requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(x < y);} +\end{itemdescr} - template - requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\begin{itemdecl} +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && + @\libconcept{three_way_comparable}@>; +\end{itemdecl} - template - requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); - }; -} -\end{codeblock} +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\end{itemdescr} \begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(@\exposid{zentinel}@ inner); +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{inner_} with \tcode{inner}. +Equivalent to: +\begin{codeblock} +auto r = i; +r += n; +return r; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -template - requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} +\returns +\tcode{(x.\exposid{current_} - y.\exposid{current_} + x.\exposid{missing_} - y.\exposid{missing_}) / x.\exposid{n_}}. \end{itemdescr} \begin{itemdecl} -template - requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); -template - requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); +friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\returns +\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{n_})}. \end{itemdescr} -\rSec2[range.adjacent]{Adjacent view} - -\rSec3[range.adjacent.overview]{Overview} +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} +\begin{itemdescr} \pnum -\indexlibraryglobal{adjacent_view}% -\tcode{adjacent_view} takes a \libconcept{view} and -produces a \libconcept{view} whose $M^\text{th}$ element is -a tuple of references to -the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements of -the original view. -If the original view has fewer than $N$ elements, the resulting view is empty. +\effects +Equivalent to: \tcode{return -(y - x);} +\end{itemdescr} + +\rSec2[range.slide]{Slide view} + +\rSec3[range.slide.overview]{Overview} \pnum -\indexlibrarymember{adjacent}{views}% -The name \tcode{views::adjacent} denotes -a range adaptor object\iref{range.adaptor.object}. -Given a subexpression \tcode{E} and a constant expression \tcode{N}, -the expression \tcode{views::adjacent(E)} is expression-equivalent to -\begin{itemize} -\item -\tcode{((void)E, auto(views::empty>))} -if \tcode{N} is equal to \tcode{0}, -\item -otherwise, \tcode{adjacent_view, N>(E)}. -\end{itemize} +\tcode{slide_view} takes a \libconcept{view} and a number \tcode{N} and +produces a \libconcept{view} +whose $\tcode{M}^\text{th}$ element is a \libconcept{view} over +the $\tcode{M}^\text{th}$ through +$(\tcode{M} + \tcode{N} - 1)^\text{th}$ elements +of the original \libconcept{view}. +If the original \libconcept{view} has fewer than \tcode{N} elements, +the resulting \libconcept{view} is empty. +\pnum +\indexlibrarymember{slide}{views}% +The name \tcode{views::slide} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{N}, +the expression \tcode{views::slide(E, N)} is expression-equivalent to +\tcode{slide_view(E, N)}. \begin{example} \begin{codeblock} vector v = {1, 2, 3, 4}; -for (auto i : v | views::adjacent<2>) { - cout << '(' << i.first << ', ' << i.second << ") "; // prints: (1, 2) (2, 3) (3, 4) +for (auto i : v | views::slide(2)) { + cout << '[' << i[0] << ", " << i[1] << "] "; // prints: [1, 2] [2, 3] [3, 4] } \end{codeblock} \end{example} -\pnum -Define \tcode{\exposid{REPEAT}(T, N)} as a pack of \tcode{N} types, -each of which denotes the same type as \tcode{T}. - -\rSec3[range.adjacent.view]{Class template \tcode{adjacent_view}} +\rSec3[range.slide.view]{Class template \tcode{slide_view}} -\indexlibrarymember{begin}{adjacent_view}% -\indexlibrarymember{end}{adjacent_view}% -\indexlibrarymember{size}{adjacent_view}% +\indexlibrarymember{begin}{slide_view}% +\indexlibrarymember{end}{slide_view}% +\indexlibrarymember{size}{slide_view}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V, size_t N> - requires @\libconcept{view}@ && (N > 0) - class adjacent_view : public view_interface> { - V @\exposid{base_}@ = V(); // \expos + template + concept @\defexposconcept{slide-caches-nothing}@ = @\libconcept{random_access_range}@ && @\libconcept{sized_range}@; // \expos - // \ref{range.adjacent.iterator}, class template \tcode{adjacent_view::\exposid{iterator}} - template class @\exposidnc{iterator}@; // \expos + template + concept @\defexposconcept{slide-caches-last}@ = // \expos + !@\exposconcept{slide-caches-nothing}@ && @\libconcept{bidirectional_range}@ && @\libconcept{common_range}@; - // \ref{range.adjacent.sentinel}, class template \tcode{adjacent_view::\exposid{sentinel}} - template class @\exposidnc{sentinel}@; // \expos + template + concept @\defexposconcept{slide-caches-first}@ = // \expos + !@\exposconcept{slide-caches-nothing}@ && !@\exposconcept{slide-caches-last}@; - struct @\exposidnc{as-sentinel}@{}; // \expos + template<@\libconcept{forward_range}@ V> + requires @\libconcept{view}@ + class slide_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + range_difference_t @\exposid{n_}@ = 0; // \expos - public: - adjacent_view() requires @\libconcept{default_initializable}@ = default; - constexpr explicit adjacent_view(V base); + // \ref{range.slide.iterator}, class template \tcode{slide_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos - constexpr auto begin() requires (!@\exposconcept{simple-view}@) { - return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); - } + // \ref{range.slide.sentinel}, class \tcode{slide_view::\exposid{sentinel}} + class @\exposid{sentinel}@; // \expos - constexpr auto begin() const requires @\libconcept{range}@ { - return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); - } + public: + slide_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit slide_view(V base, range_difference_t n); - constexpr auto end() requires (!@\exposconcept{simple-view}@) { - if constexpr (@\libconcept{common_range}@) { - return @\exposid{iterator}@(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); - } else { - return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); - } - } + constexpr auto begin() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); + constexpr auto begin() const requires @\exposconcept{slide-caches-nothing}@; - constexpr auto end() const requires @\libconcept{range}@ { - if constexpr (@\libconcept{common_range}@) { - return @\exposid{iterator}@(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); - } else { - return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); - } - } + constexpr auto end() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); + constexpr auto end() const requires @\exposconcept{slide-caches-nothing}@; constexpr auto size() requires @\libconcept{sized_range}@; constexpr auto size() const requires @\libconcept{sized_range}@; }; + + template + slide_view(R&& r, range_difference_t) -> slide_view>; } \end{codeblock} \begin{itemdecl} -constexpr explicit adjacent_view(V base); +constexpr explicit slide_view(V base, range_difference_t n); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{base_} with \tcode{std::move(base)}. +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{n_} with \tcode{n}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto begin() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +If \tcode{V} models \exposconcept{slide-caches-first}, +\begin{codeblock} +@\exposid{iterator}@(ranges::begin(@\exposid{base_}@), + ranges::next(ranges::begin(@\exposid{base_}@), @\exposid{n_}@ - 1, ranges::end(@\exposid{base_}@)), @\exposid{n_}@) +\end{codeblock} +\item +Otherwise, \tcode{\exposid{iterator}(ranges::begin(\exposid{base_}), \exposid{n_})}. +\end{itemize} + +\pnum +\remarks +In order to provide the amortized constant-time complexity +required by the \libconcept{range} concept, +this function caches the result within the \tcode{slide_view} +for use on subsequent calls +when \tcode{V} models \exposconcept{slide-caches-first}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto begin() const requires @\exposconcept{slide-caches-nothing}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{iterator}(ranges::begin(\exposid{base_}), \exposid{n_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto end() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +If \tcode{V} models \exposconcept{slide-caches-nothing}, +\begin{codeblock} +@\exposid{iterator}@(ranges::begin(@\exposid{base_}@) + range_difference_t(size()), @\exposid{n_}@) +\end{codeblock} +\item +Otherwise, if \tcode{V} models \exposconcept{slide-caches-last}, +\begin{codeblock} +@\exposid{iterator}@(ranges::prev(ranges::end(@\exposid{base_}@), @\exposid{n_}@ - 1, ranges::begin(@\exposid{base_}@)), @\exposid{n_}@) +\end{codeblock} +\item +Otherwise, if \tcode{V} models \libconcept{common_range}, +\begin{codeblock} +@\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::end(@\exposid{base_}@), @\exposid{n_}@) +\end{codeblock} +\item +Otherwise, \tcode{\exposid{sentinel}(ranges::end(\exposid{base_}))}. +\end{itemize} + +\pnum +\remarks +In order to provide the amortized constant-time complexity +required by the \libconcept{range} concept, +this function caches the result within the \tcode{slide_view} +for use on subsequent calls +when \tcode{V} models \exposconcept{slide-caches-last}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto end() const requires @\exposconcept{slide-caches-nothing}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{begin() + range_difference_t(size())}. \end{itemdescr} \begin{itemdecl} @@ -9005,35 +12081,42 @@ \end{itemdecl} \begin{itemdescr} +\pnum \effects Equivalent to: \begin{codeblock} -using ST = decltype(ranges::size(@\exposid{base_}@)); -using CT = common_type_t; -auto sz = static_cast(ranges::size(@\exposid{base_}@)); -sz -= std::min(sz, N - 1); -return static_cast(sz); +auto sz = ranges::distance(@\exposid{base_}@) - @\exposid{n_}@ + 1; +if (sz < 0) sz = 0; +return @\exposid{to-unsigned-like}@(sz); \end{codeblock} \end{itemdescr} -\rSec3[range.adjacent.iterator]{Class template \tcode{adjacent_view::\exposid{iterator}}} +\rSec3[range.slide.iterator]{Class template \tcode{slide_view::\exposid{iterator}}} -\indexlibraryglobal{adjacent_view::iterator}% +\indexlibraryglobal{slide_view::iterator}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V, size_t N> - requires @\libconcept{view}@ && (N > 0) + template<@\libconcept{forward_range}@ V> + requires @\libconcept{view}@ template - class adjacent_view::@\exposid{iterator}@ { - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - array, N> @\exposid{current_}@ = array, N>(); // \expos - constexpr @\exposidnc{iterator}@(iterator_t<@\exposidnc{Base}@> first, sentinel_t<@\exposidnc{Base}@> last); // \expos - constexpr @\exposidnc{iterator}@(@\exposidnc{as-sentinel}@, iterator_t<@\exposidnc{Base}@> first, iterator_t<@\exposidnc{Base}@> last); - // \expos + class slide_view::@\exposid{iterator}@ { + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos + iterator_t<@\exposid{Base}@> @\exposid{last_ele_}@ = iterator_t<@\exposid{Base}@>(); // \expos, + // present only if \tcode{\exposid{Base}} models \tcode{\exposconcept{slide-caches-first}} + range_difference_t<@\exposid{Base}@> @\exposid{n_}@ = 0; // \expos + + constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, range_difference_t<@\exposid{Base}@> n) // \expos + requires (!@\exposconcept{slide-caches-first}@<@\exposid{Base}@>); + + constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, iterator_t<@\exposid{Base}@> last_ele, // \expos + range_difference_t<@\exposid{Base}@> n) + requires @\exposconcept{slide-caches-first}@<@\exposid{Base}@>; + public: using iterator_category = input_iterator_tag; - using iterator_concept = @\seebelow@; - using value_type = @\exposid{tuple-or-pair}@<@\exposid{REPEAT}@(range_value_t<@\exposid{Base}@>, N)...>; + using iterator_concept = @\seebelow@; + using value_type = decltype(views::counted(@\exposid{current_}@, @\exposid{n_}@)); using difference_type = range_difference_t<@\exposid{Base}@>; @\exposid{iterator}@() = default; @@ -9056,6 +12139,7 @@ requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) @@ -9076,10 +12160,6 @@ requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; - - friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); - friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) - requires @\libconcept{indirectly_swappable}@>; }; } \end{codeblock} @@ -9102,31 +12182,29 @@ exits via an exception, the \exposid{iterator} acquires a singular value. \begin{itemdecl} -constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> first, sentinel_t<@\exposid{Base}@> last); +constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, range_difference_t<@\exposid{Base}@> n) + requires (!@\exposconcept{slide-caches-first}@<@\exposid{Base}@>); \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{\exposid{current_}[0] == first} is \tcode{true}, and -for every integer $1 \leq i < \tcode{N}$, -\tcode{\exposid{current_}[$i$] == ranges::next(\exposid{current_}[$i$-1], 1, last)} -is \tcode{true}. +\effects +Initializes \exposid{current_} with \tcode{current} and +\exposid{n_} with \tcode{n}. \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{as-sentinel}@, iterator_t<@\exposid{Base}@> first, iterator_t<@\exposid{Base}@> last); +constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, iterator_t<@\exposid{Base}@> last_ele, + range_difference_t<@\exposid{Base}@> n) + requires @\exposconcept{slide-caches-first}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -If \exposid{Base} does not model \libconcept{bidirectional_range}, -each element of \exposid{current_} is equal to \exposid{last}. -Otherwise, \tcode{\exposid{current_}[N-1] == last} is \tcode{true}, and -for every integer $0 \leq i < (\tcode{N} - 1)$, -\tcode{\exposid{current_}[$i$] == ranges::prev(\exposid{current_}[$i$+1], 1, first)} -is \tcode{true}. +\effects +Initializes \exposid{current_} with \tcode{current}, +\exposid{last_ele_} with \tcode{last_ele}, and +\exposid{n_} with \tcode{n}. \end{itemdescr} \begin{itemdecl} @@ -9137,8 +12215,13 @@ \begin{itemdescr} \pnum \effects -Initializes each element of \exposid{current_} -with the corresponding element of \tcode{i.\exposid{current_}} as an xvalue. +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})} and +\exposid{n_} with \tcode{i.\exposid{n_}}. +\begin{note} +\tcode{\exposid{iterator}} can only be formed +when \exposid{Base} models \exposconcept{slide-caches-nothing}, +in which case \exposid{last_ele_} is not present. +\end{note} \end{itemdescr} \begin{itemdecl} @@ -9147,11 +12230,8 @@ \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); -\end{codeblock} +\returns +\tcode{views::counted(\exposid{current_}, \exposid{n_})}. \end{itemdescr} \begin{itemdecl} @@ -9161,12 +12241,13 @@ \begin{itemdescr} \pnum \expects -\tcode{\exposid{current_}.back()} is incrementable. +\exposid{current_} and \exposid{last_ele_} (if present) are incrementable. \pnum \ensures -Each element of \exposid{current_} is equal to \tcode{ranges::next(i)}, -where \tcode{i} is the value of that element before the call. +\exposid{current_} and \exposid{last_ele_} (if present) are +each equal to \tcode{ranges::next(i)}, +where \tcode{i} is the value of that data member before the call. \pnum \returns @@ -9179,7 +12260,7 @@ \begin{itemdescr} \pnum -\expects +\effects Equivalent to: \begin{codeblock} auto tmp = *this; @@ -9195,12 +12276,13 @@ \begin{itemdescr} \pnum \expects -\tcode{\exposid{current_}.front()} is decrementable. +\exposid{current_} and \exposid{last_ele_} (if present) are decrementable. \pnum \ensures -Each element of \exposid{current_} is equal to \tcode{ranges::prev(i)}, -where \tcode{i} is the value of that element before the call. +\exposid{current_} and \exposid{last_ele_} (if present) are +each equal to \tcode{ranges::prev(i)}, +where \tcode{i} is the value of that data member before the call. \pnum \returns @@ -9223,19 +12305,21 @@ \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type x) +constexpr iterator& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{\exposid{current_}.back() + x} has well-defined behavior. +\tcode{\exposid{current_} + x} and \tcode{\exposid{last_ele_} + x} (if \exposid{last_ele_} is present) +have well-defined behavior. \pnum \ensures -Each element of \exposid{current_} is equal to \tcode{i + x}, -where \tcode{i} is the value of that element before the call. +\exposid{current_} and \exposid{last_ele_} (if present) are +each equal to \tcode{i + x}, +where \tcode{i} is the value of that data member before the call. \pnum \returns @@ -9250,12 +12334,14 @@ \begin{itemdescr} \pnum \expects -\tcode{\exposid{current_}.front() - x} has well-defined behavior. +\tcode{\exposid{current_} - x} and \tcode{\exposid{last_ele_} - x} (if \exposid{last_ele_} is present) +have well-defined behavior. \pnum \ensures -Each element of \exposid{current_} is equal to \tcode{i - x}, -where \tcode{i} is the value of that element before the call. +\exposid{current_} and \exposid{last_ele_} (if present) are +each equal to \tcode{i - x}, +where \tcode{i} is the value of that data member before the call. \pnum \returns @@ -9270,10 +12356,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return @\exposid{tuple-transform}@([&](auto& i) -> decltype(auto) { return i[n]; }, @\exposid{current_}@); -\end{codeblock} +Equivalent to: \tcode{return views::counted(\exposid{current_} + n, \exposid{n_});} \end{itemdescr} \begin{itemdecl} @@ -9283,7 +12366,9 @@ \begin{itemdescr} \pnum \returns -\tcode{x.\exposid{current_}.back() == y.\exposid{current_}.back()}. +If \exposid{last_ele_} is present, +\tcode{x.\exposid{last_ele_} == y.\exposid{last_ele_}}; +otherwise, \tcode{x.\exposid{current_} == y.\exposid{cur\-rent_}}. \end{itemdescr} \begin{itemdecl} @@ -9294,7 +12379,7 @@ \begin{itemdescr} \pnum \returns -\tcode{x.\exposid{current_}.back() < y.\exposid{current_}.back()}. +\tcode{x.\exposid{current_} < y.\exposid{current_}}. \end{itemdescr} \begin{itemdecl} @@ -9339,7 +12424,7 @@ \begin{itemdescr} \pnum \returns -\tcode{x.\exposid{current_}.back() <=> y.\exposid{current_}.back()}. +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. \end{itemdescr} \begin{itemdecl} @@ -9383,419 +12468,203 @@ \begin{itemdescr} \pnum -\effects -Equivalent to: -\tcode{return x.\exposid{current_}.back() - y.\exposid{current_}.back();} -\end{itemdescr} - -\begin{itemdecl} -friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\tcode{return \exposid{tuple-transform}(ranges::iter_move, i.\exposid{current_});} - -\pnum -\remarks -The exception specification is equivalent to: -\begin{codeblock} -noexcept(ranges::iter_move(declval&>())) && -is_nothrow_move_constructible_v> -\end{codeblock} -\end{itemdescr} - -\begin{itemdecl} -friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) - requires @\libconcept{indirectly_swappable}@>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -None of the iterators in \tcode{l.\exposid{current_}} is equal to -an iterator in \tcode{r.\exposid{current_}}. - -\pnum -\effects -For every integer $0 \leq i < \tcode{N}$, -performs -\tcode{ranges::iter_swap(l.\exposid{current_}[$i$], r.\exposid{current_}[$i$])}. - -\pnum -\remarks -The exception specification is equivalent to: -\begin{codeblock} -noexcept(ranges::iter_swap(declval>(), declval>())) -\end{codeblock} +\returns +If \exposid{last_ele_} is present, +\tcode{x.\exposid{last_ele_} - y.\exposid{last_ele_}}; +otherwise, \tcode{x.\exposid{current_} - y.\exposid{cur\-rent_}}. \end{itemdescr} -\rSec3[range.adjacent.sentinel]{Class template \tcode{adjacent_view::\exposid{sentinel}}} +\rSec3[range.slide.sentinel]{Class \tcode{slide_view::\exposid{sentinel}}} -\indexlibraryglobal{adjacent_view::sentinel}% +\indexlibraryglobal{chunk_view::sentinel}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V, size_t N> - requires @\libconcept{view}@ && (N > 0) - template - class adjacent_view::@\exposid{sentinel}@ { - using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos - constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); // \expos + template<@\libconcept{forward_range}@ V> + requires @\libconcept{view}@ + class slide_view::@\exposid{sentinel}@ { + sentinel_t @\exposid{end_}@ = sentinel_t(); // \expos + constexpr explicit @\exposid{sentinel}@(sentinel_t end); // \expos public: @\exposid{sentinel}@() = default; - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; - template - requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); - template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + friend constexpr range_difference_t + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; - template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); + friend constexpr range_difference_t + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; }; } \end{codeblock} -\begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); -\end{itemdecl} - -\begin{itemdescr} \pnum -\effects -Initializes \exposid{end_} with \tcode{end}. -\end{itemdescr} +\begin{note} +\exposid{sentinel} is used +only when \tcode{\exposconcept{slide-caches-first}} is \tcode{true}. +\end{note} \begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +constexpr explicit @\exposid{sentinel}@(sentinel_t end); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. +Initializes \exposid{end_} with \tcode{end}. \end{itemdescr} \begin{itemdecl} -template - requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{current_}.back() == y.\exposid{end_};} +\returns +\tcode{x.\exposid{last_ele_} == y.\exposid{end_}}. \end{itemdescr} \begin{itemdecl} -template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +friend constexpr range_difference_t + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{current_}.back() - y.\exposid{end_};} +\returns +\tcode{x.\exposid{last_ele_} - y.\exposid{end_}}. \end{itemdescr} \begin{itemdecl} -template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); +friend constexpr range_difference_t + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return y.\exposid{end_} - x.\exposid{current_}.back();} +\returns +\tcode{y.\exposid{end_} - x.\exposid{last_ele_}}. \end{itemdescr} -\rSec2[range.adjacent.transform]{Adjacent transform view} +\rSec2[range.chunk.by]{Chunk by view} -\rSec3[range.adjacent.transform.overview]{Overview} +\rSec3[range.chunk.by.overview]{Overview} \pnum -\indexlibraryglobal{adjacent_transform_view}% -\tcode{adjacent_transform_view} takes an invocable object and -a \libconcept{view} and produces a \libconcept{view} -whose $M^\text{th}$ element is the result of applying the invocable object -to the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements -of the original view. -If the original view has fewer than $N$ elements, the resulting view is empty. +\tcode{chunk_by_view} takes a \libconcept{view} and a predicate, and +splits the \libconcept{view} into \tcode{subrange}s +between each pair of adjacent elements +for which the predicate returns \tcode{false}. \pnum -\indexlibrarymember{adjacent_transform}{views}% -The name \tcode{views::adjacent_transform} denotes +\indexlibrarymember{chunk_by}{views}% +The name \tcode{views::chunk_by} denotes a range adaptor object\iref{range.adaptor.object}. -Given subexpressions \tcode{E} and \tcode{F} and -a constant expression \tcode{N}: -\begin{itemize} -\item -If \tcode{N} is equal to \tcode{0}, -\tcode{views::adjacent_transform(E, F)} is expression-equivalent to -\tcode{((void)E, views::zip_transform(F))}, -except that the evaluations of \tcode{E} and \tcode{F} are -indeterminately sequenced. -\item -Otherwise, -the expression \tcode{views::adjacent_transform(E, F)} is -expression-equivalent to -\tcode{adja\-cent_transform_view, decay_t, N>(E, F)}. -\end{itemize} - -\pnum +Given subexpressions \tcode{E} and \tcode{F}, +the expression \tcode{views::chunk_by(E, F)} is expression-equivalent to +\tcode{chunk_by_view(E, F)}. \begin{example} \begin{codeblock} -vector v = {1, 2, 3, 4}; +vector v = {1, 2, 2, 3, 0, 4, 5, 2}; -for (auto i : v | views::adjacent_transform<2>(std::multiplies())) { - cout << i << ' '; // prints: 2 6 12 +for (auto r : v | views::chunk_by(ranges::less_equal{})) { + cout << '['; + auto sep = ""; + for(auto i : r) { + cout << sep << i; + sep = ", "; + } + cout << "] "; } \end{codeblock} +The above prints: \tcode{[1, 2, 2, 3] [0, 4, 5] [2]} \end{example} -\rSec3[range.adjacent.transform.view]{Class template \tcode{adjacent_transform_view}} - -\indexlibrarymember{begin}{adjacent_transform_view}% -\indexlibrarymember{end}{adjacent_transform_view}% -\indexlibrarymember{size}{adjacent_transform_view}% -\begin{codeblock} -namespace std::ranges { - template<@\libconcept{forward_range}@ V, @\libconcept{copy_constructible}@ F, size_t N> - requires @\libconcept{view}@ && (N > 0) && is_object_v && - @\libconcept{regular_invocable}@, N)...> && - @\exposconcept{can-reference}@, N)...>> - class adjacent_transform_view : public view_interface> { - @\exposidnc{copyable-box}@ @\exposid{fun_}@; // \expos - adjacent_view @\exposid{inner_}@; // \expos - - using @\exposidnc{InnerView}@ = adjacent_view; // \expos - template - using @\exposid{inner-iterator}@ = iterator_t<@\exposid{maybe-const}@>; // \expos - template - using @\exposid{inner-sentinel}@ = sentinel_t<@\exposid{maybe-const}@>; // \expos - - // \ref{range.adjacent.transform.iterator}, class template \tcode{adjacent_transform_view::\exposid{iterator}} - template class @\exposidnc{iterator}@; // \expos - - // \ref{range.adjacent.transform.sentinel}, class template \tcode{adjacent_transform_view::\exposid{sentinel}} - template class @\exposidnc{sentinel}@; // \expos - - public: - adjacent_transform_view() = default; - constexpr explicit adjacent_transform_view(V base, F fun); - - constexpr auto begin() { - return @\exposid{iterator}@(*this, @\exposid{inner_}@.begin()); - } - - constexpr auto begin() const - requires @\libconcept{range}@ && - @\libconcept{regular_invocable}@, N)...> { - return @\exposid{iterator}@(*this, @\exposid{inner_}@.begin()); - } - - constexpr auto end() { - if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { - return @\exposid{iterator}@(*this, @\exposid{inner_}@.end()); - } else { - return @\exposid{sentinel}@(@\exposid{inner_}@.end()); - } - } - - constexpr auto end() const - requires @\libconcept{range}@ && - @\libconcept{regular_invocable}@, N)...> { - if constexpr (@\libconcept{common_range}@) { - return @\exposid{iterator}@(*this, @\exposid{inner_}@.end()); - } else { - return @\exposid{sentinel}@(@\exposid{inner_}@.end()); - } - } - - constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> { - return @\exposid{inner_}@.size(); - } - - constexpr auto size() const requires @\libconcept{sized_range}@ { - return @\exposid{inner_}@.size(); - } - }; -} -\end{codeblock} - -\begin{itemdecl} -constexpr explicit adjacent_transform_view(V base, F fun); -\end{itemdecl} +\rSec3[range.chunk.by.view]{Class template \tcode{chunk_by_view}} -\begin{itemdescr} -\pnum -\effects -Initializes \exposid{fun_} with \tcode{std::move(fun)} and -\exposid{inner_} with \tcode{std::move(base)}. -\end{itemdescr} - -\rSec3[range.adjacent.transform.iterator]{Class template \tcode{adjacent_transform_view::\exposid{iterator}}} - -\indexlibraryglobal{adjacent_transform_view::iterator}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V, @\libconcept{copy_constructible}@ F, size_t N> - requires @\libconcept{view}@ && (N > 0) && is_object_v && - @\libconcept{regular_invocable}@, N)...> && - @\exposconcept{can-reference}@, N)...>> - template - class adjacent_transform_view::@\exposid{iterator}@ { - using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos - @\exposidnc{inner-iterator}@ @\exposid{inner_}@; // \expos + template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@, iterator_t> Pred> + requires @\libconcept{view}@ && is_object_v + class chunk_by_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + @\exposid{copyable-box}@ @\exposid{pred_}@ = Pred(); // \expos - constexpr @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent, @\exposidnc{inner-iterator}@ inner); // \expos + // \ref{range.chunk.by.iter}, class \tcode{chunk_by_view::\exposid{iterator}} + class @\exposid{iterator}@; // \expos public: - using iterator_category = @\seebelow@; - using iterator_concept = typename @\exposid{inner-iterator}@::iterator_concept; - using value_type = - remove_cvref_t&, - @\exposid{REPEAT}@(range_reference_t<@\exposid{Base}@>, N)...>>; - using difference_type = range_difference_t<@\exposid{Base}@>; - - @\exposid{iterator}@() = default; - constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; + chunk_by_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; + constexpr explicit chunk_by_view(V base, Pred pred); - constexpr decltype(auto) operator*() const noexcept(@\seebelow@); - constexpr @\exposid{iterator}@& operator++(); - constexpr @\exposid{iterator}@ operator++(int); - constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } - constexpr decltype(auto) operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr const Pred& pred() const; - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); - friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires random_access_range; - friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{inner-iterator}@>; + constexpr @\exposid{iterator}@ begin(); + constexpr auto end(); - friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; + constexpr iterator_t @\exposid{find-next}@(iterator_t); // \expos + constexpr iterator_t @\exposid{find-prev}@(iterator_t) // \expos + requires @\libconcept{bidirectional_range}@; }; -} -\end{codeblock} -\pnum -The member \grammarterm{typedef-name} \tcode{\exposid{iterator}::iterator_category} -is defined as follows: -\begin{itemize} -\item -If \tcode{invoke_result_t<\exposid{maybe-const}\&, -\exposid{REPEAT}(range_reference_t<\exposid{Base}>, N)...>} -is\linebreak not an lvalue reference, -\tcode{iterator_category} denotes \tcode{input_iterator_tag}. -\item -Otherwise, let \tcode{C} denote the type -\tcode{iterator_traits>::iterator_category}. -\begin{itemize} -\item -If \tcode{\libconcept{derived_from}} -is \tcode{true}, -\tcode{iterator_category} denotes \tcode{ran\-dom_access_iterator_tag}. -\item -Otherwise, -if \tcode{\libconcept{derived_from}} -is \tcode{true}, -\tcode{iterator_category} denotes \tcode{bidirectional_iterator_tag}. -\item -Otherwise, -if \tcode{\libconcept{derived_from}} -is \tcode{true}, -\tcode{iterator_category} denotes \tcode{forward_iterator_tag}. -\item -Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. -\end{itemize} -\end{itemize} + template + chunk_by_view(R&&, Pred) -> chunk_by_view, Pred>; +} +\end{codeblock} \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{inner-iterator}@ inner); +constexpr explicit chunk_by_view(V base, Pred pred); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{addressof(parent)} and -\exposid{inner_} with \tcode{std::move(inner)}. +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{pred_} with \tcode{std::move(pred)}. \end{itemdescr} +\indexlibrarymember{pred}{chunk_by_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; +constexpr const Pred& pred() const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and -\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +Equivalent to: \tcode{return *\exposid{pred_};} \end{itemdescr} \begin{itemdecl} -constexpr decltype(auto) operator*() const noexcept(@\seebelow@); +constexpr @\exposid{iterator}@ begin(); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return apply([&](const auto&... iters) -> decltype(auto) { - return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); -}, @\exposid{inner_}@.@\exposid{current_}@); -\end{codeblock} +\expects +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. + +\pnum +\returns +\tcode{\exposid{iterator}(*this, ranges::begin(\exposid{base_}), \exposid{find-next}(ranges::begin(\exposid{base_})))}. \pnum \remarks -Let \tcode{Is} be the pack \tcode{0, 1, \ldots, (N-1)}. -The exception specification is equivalent to: -\begin{codeblock} -noexcept(invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *std::get(@\exposid{inner_}@.@\exposid{current_}@)...)) -\end{codeblock} +In order to provide +the amortized constant-time complexity required by the \libconcept{range} concept, +this function caches the result within the \tcode{chunk_by_view} +for use on subsequent calls. \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@& operator++(); +constexpr auto end(); \end{itemdecl} \begin{itemdescr} @@ -9803,240 +12672,210 @@ \effects Equivalent to: \begin{codeblock} -++@\exposid{inner_}@; -return *this; +if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(*this, ranges::end(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); +} else { + return default_sentinel; +} \end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int); +constexpr iterator_t @\exposid{find-next}@(iterator_t current); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto tmp = *this; -++*this; -return tmp; -\end{codeblock} -\end{itemdescr} - -\begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; -\end{itemdecl} +\expects +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. -\begin{itemdescr} \pnum -\effects -Equivalent to: +\returns \begin{codeblock} ---@\exposid{inner_}@; -return *this; +ranges::next(ranges::adjacent_find(current, ranges::end(@\exposid{base_}@), not_fn(ref(*@\exposid{pred_}@))), + 1, ranges::end(@\exposid{base_}@)) \end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr iterator_t @\exposid{find-prev}@(iterator_t current) requires @\libconcept{bidirectional_range}@; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto tmp = *this; ---*this; -return tmp; -\end{codeblock} -\end{itemdescr} - -\begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} +\expects +\begin{itemize} +\item +\tcode{current} is not equal to \tcode{ranges::begin(\exposid{base_})}. +\item +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. +\end{itemize} -\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{inner_}@ += x; -return *this; -\end{codeblock} +\returns +An iterator \tcode{i} +in the range \range{ranges::begin(\exposid{base_})}{current} such that: +\begin{itemize} +\item +\tcode{ranges::adjacent_find(i, current, not_fn(ref(*\exposid{pred_})))} is equal to \tcode{current}; and +\item +if \tcode{i} is not equal to \tcode{ranges::begin(\exposid{base_})}, +then \tcode{bool(invoke(*\exposid{pred_}, *ranges::prev(i), *i))} +is \tcode{false}. +\end{itemize} \end{itemdescr} -\begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} +\rSec3[range.chunk.by.iter]{Class \tcode{chunk_by_view::\exposid{iterator}}} -\begin{itemdescr} -\pnum -\effects -Equivalent to: \begin{codeblock} -@\exposid{inner_}@ -= x; -return *this; +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@, iterator_t> Pred> + requires @\libconcept{view}@ && is_object_v + class chunk_by_view::@\exposid{iterator}@ { + chunk_by_view* @\exposid{parent_}@ = nullptr; // \expos + iterator_t @\exposid{current_}@ = iterator_t(); // \expos + iterator_t @\exposid{next_}@ = iterator_t(); // \expos + + constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, // \expos + iterator_t next); + + public: + using value_type = subrange>; + using difference_type = range_difference_t; + using iterator_category = input_iterator_tag; + using iterator_concept = @\seebelow@; + + @\exposid{iterator}@() = default; + + constexpr value_type operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); + + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); + }; +} \end{codeblock} -\end{itemdescr} + +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If \tcode{V} models \libconcept{bidirectional_range}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +\end{itemize} \begin{itemdecl} -constexpr decltype(auto) operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, iterator_t next); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return apply([&](const auto&... iters) -> decltype(auto) { - return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[n]...); -}, @\exposid{inner_}@.@\exposid{current_}@); -\end{codeblock} +Initializes \exposid{parent_} with \tcode{addressof(parent)}, +\exposid{current_} with \tcode{current}, and +\exposid{next_} with \tcode{next}. \end{itemdescr} \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); -friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{inner-iterator}@>; +constexpr value_type operator*() const; \end{itemdecl} \begin{itemdescr} \pnum -Let \placeholder{op} be the operator. +\expects +\exposid{current_} is not equal to \exposid{next_}. \pnum -\effects -Equivalent to: \tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} +\returns +\tcode{subrange(\exposid{current_}, \exposid{next_})}. \end{itemdescr} \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} -\end{itemdescr} - -\begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} +\expects +\exposid{current_} is not equal to \exposid{next_}. -\begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} +Equivalent to: +\begin{codeblock} +@\exposid{current_}@ = @\exposid{next_}@; +@\exposid{next_}@ = @\exposid{parent_}@->@\exposid{find-next}@(@\exposid{current_}@); +return *this; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; +constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} -\end{itemdescr} - -\rSec3[range.adjacent.transform.sentinel]{Class template \tcode{adjacent_transform_view::\exposid{sentinel}}} - -\indexlibraryglobal{adjacent_transform_view::sentinel}% +Equivalent to: \begin{codeblock} -namespace std::ranges { - template<@\libconcept{forward_range}@ V, @\libconcept{copy_constructible}@ F, size_t N> - requires @\libconcept{view}@ && (N > 0) && is_object_v && - @\libconcept{regular_invocable}@, N)...> && - @\exposconcept{can-reference}@, N)...>> - template - class adjacent_transform_view::@\exposid{sentinel}@ { - @\exposidnc{inner-sentinel}@ @\exposid{inner_}@; // \expos - constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{inner-sentinel}@ inner); // \expos - - public: - @\exposid{sentinel}@() = default; - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; - - template - requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); - - template - requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); - - template - requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); - }; -} +auto tmp = *this; +++*this; +return tmp; \end{codeblock} +\end{itemdescr} \begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(@\exposid{inner-sentinel}@ inner); +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{inner_} with \tcode{inner}. +Equivalent to: +\begin{codeblock} +@\exposid{next_}@ = @\exposid{current_}@; +@\exposid{current_}@ = @\exposid{parent_}@->@\exposid{find-prev}@(@\exposid{next_}@); +return *this; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} \end{itemdescr} \begin{itemdecl} -template - requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} +\returns +\tcode{x.\exposid{current_} == y.\exposid{current_}}. \end{itemdescr} \begin{itemdecl} -template - requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); - -template - requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); +friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\returns +\tcode{x.\exposid{current_} == x.\exposid{next_}}. \end{itemdescr} diff --git a/source/regex.tex b/source/regex.tex index d69c440ed5..5ee8aa28ed 100644 --- a/source/regex.tex +++ b/source/regex.tex @@ -63,130 +63,283 @@ \indextext{requirements!regular expression traits}% \indextext{regular expression!requirements}% \indextext{locale}% -In \tref{re.req} \tcode{X} denotes a traits class -defining types and functions for the character container -type \tcode{charT}; \tcode{u} is an object of -type \tcode{X}; \tcode{v} is an object of type \tcode{const -X}; \tcode{p} is a value of type \tcode{const charT*}; \tcode{I1} -and \tcode{I2} are input iterators\iref{input.iterators}; +In the following requirements, +\begin{itemize} +\item +\tcode{X} denotes a traits class defining types and functions +for the character container type \tcode{charT}; +\item +\tcode{u} is an object of type \tcode{X}; +\item +\tcode{v} is an object of type \tcode{const X}; +\item +\tcode{p} is a value of type \tcode{const charT*}; +\item +\tcode{I1} and \tcode{I2} are input iterators\iref{input.iterators}; +\item \tcode{F1} and \tcode{F2} are forward iterators\iref{forward.iterators}; +\item \tcode{c} is a value of type \tcode{const charT}; +\item \tcode{s} is an object of type \tcode{X::string_type}; +\item \tcode{cs} is an object of type \tcode{const X::string_type}; +\item \tcode{b} is a value of type \tcode{bool}; +\item \tcode{I} is a value of type \tcode{int}; -\tcode{cl} is an object of type \tcode{X::char_class_type}, -and \tcode{loc} is an object of type \tcode{X::locale_type}. - -\begin{libreqtab3} - {Regular expression traits class requirements} - {re.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \rhdr{Assertion/note pre-/post-condition } \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \rhdr{Assertion/note pre-/post-condition } \\ \capsep -\endhead -%% +\item +\tcode{cl} is an object of type \tcode{X::char_class_type}; and +\item +\tcode{loc} is an object of type \tcode{X::locale_type}. +\end{itemize} + +\pnum +A traits class \tcode{X} meets the regular expression traits requirements +if the following types and expressions are well-formed and have the specified +semantics. + +\begin{itemdecl} +typename X::char_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{charT}, +the character container type used in the implementation of class +template \tcode{basic_regex}. +\end{itemdescr} + +\begin{itemdecl} +typename X::string_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{basic_string} +\end{itemdescr} + +\begin{itemdecl} +typename X::locale_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A copy constructible type +that represents the locale used by the traits class. +\end{itemdescr} + +\begin{itemdecl} +typename X::char_class_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A bitmask type\iref{bitmask.types} +representing a particular character classification. +\end{itemdescr} + +\begin{itemdecl} +X::length(p) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_t} + +\pnum +\returns +The smallest \tcode{i} such that \tcode{p[i] == 0}. + +\pnum +\complexity +Linear in \tcode{i}. +\end{itemdescr} + +\begin{itemdecl} +v.translate(c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result \tcode{X::char_type} - & \tcode{charT} - & The character container type used in the implementation of class - template \tcode{basic_regex}. - \\ \rowsep + +\pnum +\returns +A character such that for any character \tcode{d} +that is to be considered equivalent to \tcode{c} +then \tcode{v.translate(c) == v.translate(d)}. +\end{itemdescr} + +\begin{itemdecl} +v.translate_nocase(c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::char_type} + +\pnum +\returns +For all characters \tcode{C} that are to be considered equivalent to \tcode{c} +when comparisons are to be performed without regard to case, +then \tcode{v.translate_nocase(c) == v.translate_nocase(C)}. +\end{itemdescr} + +\begin{itemdecl} +v.transform(F1, F2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result \tcode{X::string_type} - & \tcode{basic_string} - & - \\ \rowsep -\tcode{X::locale_type} - & A copy constructible type - & A type that represents the locale used by the traits class. \indextext{locale} - \\ \rowsep + +\pnum +\returns +A sort key for the character sequence designated by +the iterator range \range{F1}{F2} such that +if the character sequence \range{G1}{G2} sorts before +the character sequence \range{H1}{H2} +then \tcode{v.transform(G1, G2) < v.transform(H1, H2)}. +\end{itemdescr} + +\begin{itemdecl} +v.transform_primary(F1, F2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\indextext{regular expression traits!\idxcode{transform_primary}}% +\indextext{transform_primary@\tcode{transform_primary}!regular expression traits}% +\result +\tcode{X::string_type} + +\pnum +\returns +A sort key for the character sequence designated by +the iterator range \range{F1}{F2} such that +if the character sequence \range{G1}{G2} sorts before +the character sequence \range{H1}{H2} +when character case is not considered +then \tcode{v.transform_primary(G1, G2) < v.transform_primary(H1, H2)}. +\end{itemdescr} + +\begin{itemdecl} +v.lookup_collatename(F1, F2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::string_type} + +\pnum +\returns +A sequence of characters that represents the collating element +consisting of the character sequence designated by +the iterator range \range{F1}{F2}. +Returns an empty string +if the character sequence is not a valid collating element. +\end{itemdescr} + +\begin{itemdecl} +v.lookup_classname(F1, F2, b) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result \tcode{X::char_class_type} - & A bitmask type\iref{bitmask.types}. - & A bitmask type representing a particular character classification. - \\ \rowsep -\tcode{X::length(p)} - & \tcode{size_t} - & Yields the smallest \tcode{i} such that \tcode{p[i] == 0}. Complexity is - linear in \tcode{i}. - \\ \rowsep -\tcode{v.translate(c)} - & \tcode{X::char_type} - & Returns a character such that for any character \tcode{d} that is to - be considered equivalent to \tcode{c} then \tcode{v.translate(c) == v.translate(d)}. - \\ \rowsep -\tcode{v.translate_nocase(c)} - & \tcode{X::char_type} - & For all characters \tcode{C} that are to be considered equivalent - to \tcode{c} when comparisons are to be performed without regard to - case, then \tcode{v.translate_nocase(c) == v.translate_nocase(C)}. - \\ \rowsep -\tcode{v.transform(F1, F2)} - & \tcode{X::string_type} - & Returns a sort key for the character sequence designated by the - iterator range \range{F1}{F2} such that if the character sequence - \range{G1}{G2} sorts before the character sequence \range{H1}{H2} - then \tcode{v.transform(G1, G2) < v.transform(H1, H2)}. - \\ \rowsep -\tcode{v.transform_primary(F1, F2)} - & \tcode{X::string_type} - & Returns a sort key for the character sequence designated by the - iterator range \range{F1}{F2} such that if the character sequence - \range{G1}{G2} sorts before the character sequence \range{H1}{H2} - when character case is not considered - then \tcode{v.transform_primary(G1, G2) < v.transform_primary(H1, H2)}. - \indextext{regular expression traits!\idxcode{transform_primary}}% - \indextext{transform_primary@\tcode{transform_primary}!regular expression traits}% - \\ \rowsep -\tcode{v.lookup_collatename(F1, F2)} - & \tcode{X::string_type} - & Returns a sequence of characters that represents the collating element - consisting of the character sequence designated by the iterator range - \range{F1}{F2}. Returns an empty string if the character sequence is not - a valid collating element. - \\ \rowsep -\tcode{v.lookup_classname(F1, F2, b)} - & \tcode{X::char_class_type} - & Converts the character sequence designated by the iterator range - \range{F1}{F2} into a value of a bitmask type that can - subsequently be passed to \tcode{isctype}. Values returned from - \tcode{lookup_classname} can be bitwise \logop{OR}'ed together; the - resulting value represents membership in either of the - corresponding character classes. - If \tcode{b} is \tcode{true}, the returned bitmask is suitable for - matching characters without regard to their case. - Returns \tcode{0} if the character - sequence is not the name of a character class recognized by - \tcode{X}. The value returned shall be independent of the case of - the characters in the sequence. - \\ \rowsep -\tcode{v.isctype(c, cl)} - & \tcode{bool} - & Returns \tcode{true} if character \tcode{c} is a member of - one of the character classes designated by \tcode{cl}, - \tcode{false} otherwise. - \\ \rowsep -\tcode{v.value(c, I)} - & \tcode{int} - & Returns the value represented by the digit \textit{c} in base - \textit{I} if the character \textit{c} is a valid digit in base \textit{I}; - otherwise returns \tcode{-1}. -\begin{tailnote} -The value of \textit{I} will only - be 8, 10, or 16. -\end{tailnote} - \\ \rowsep -\tcode{u.imbue(loc)} - & \tcode{X::locale_type} - & Imbues \tcode{u} with the locale \tcode{loc} and returns the previous locale - used by \tcode{u} if any. \indextext{locale}% - \\ \rowsep -\tcode{v.getloc()} - & \tcode{X::locale_type} - & Returns the current locale used by \tcode{v}, if any. \indextext{locale}% - \\ -\end{libreqtab3} + +\pnum +\returns +Converts the character sequence designated by the iterator range +\range{F1}{F2} into a value of a bitmask type that can +subsequently be passed to \tcode{isctype}. +Values returned from \tcode{lookup_classname} can be bitwise \logop{OR}'ed together; +the resulting value represents membership +in either of the corresponding character classes. +If \tcode{b} is \tcode{true}, the returned bitmask is suitable for +matching characters without regard to their case. +Returns \tcode{0} +if the character sequence is not the name of +a character class recognized by \tcode{X}. +The value returned shall be independent of +the case of the characters in the sequence. +\end{itemdescr} + +\begin{itemdecl} +v.isctype(c, cl) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\returns +Returns \tcode{true} if character \tcode{c} is a member of +one of the character classes designated by \tcode{cl}, +\tcode{false} otherwise. +\end{itemdescr} + +\begin{itemdecl} +v.value(c, I) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{int} + +\pnum +\returns +Returns the value represented by the digit \textit{c} in base +\textit{I} if the character \textit{c} is a valid digit in base \textit{I}; +otherwise returns \tcode{-1}. +\begin{note} +The value of \textit{I} will only be 8, 10, or 16. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +u.imbue(loc) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::locale_type} + +\indextext{locale}% +\pnum +\effects +Imbues \tcode{u} with the locale \tcode{loc} and +returns the previous locale used by \tcode{u} if any. +\end{itemdescr} + +\begin{itemdecl} +v.getloc() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::locale_type} + +\pnum +\returns +Returns the current locale used by \tcode{v}, if any. \indextext{locale}% +\end{itemdescr} \pnum \begin{note} @@ -810,11 +963,13 @@ \rSec1[re.badexp]{Class \tcode{regex_error}} \indexlibraryglobal{regex_error}% \begin{codeblock} -class regex_error : public runtime_error { -public: - explicit regex_error(regex_constants::error_type ecode); - regex_constants::error_type code() const; -}; +namespace std { + class regex_error : public runtime_error { + public: + explicit regex_error(regex_constants::error_type ecode); + regex_constants::error_type code() const; + }; +} \end{codeblock} \pnum @@ -1949,8 +2104,8 @@ \indextext{requirements!container}% \indextext{requirements!sequence}% The class template \tcode{match_results} meets the requirements of an -allocator-aware container and of a sequence container -(\ref{container.requirements.general}, \ref{sequence.reqmts}) +allocator-aware container and of +a sequence container\iref{container.requirements.general,sequence.reqmts} except that only copy assignment, move assignment, and @@ -3235,7 +3390,7 @@ \pnum \begin{note} -This means that a compiler can call an +This means that an implementation can call an implementation-specific search function, in which case a program-defined specialization of \tcode{regex_search} will not be called. diff --git a/source/statements.tex b/source/statements.tex index 6c2ffed294..65b4534ee1 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -231,7 +231,7 @@ has a block scope\iref{basic.scope.block}. \end{note} -\rSec2[stmt.if]{The \tcode{if} statement}% +\rSec2[stmt.if]{The \keyword{if} statement}% \indextext{statement!\idxcode{if}} \pnum @@ -376,7 +376,7 @@ \keyword{if} \keyword{consteval} statement$_2$ \keyword{else} compound-statement$_1$ \end{ncsimplebnf} -\rSec2[stmt.switch]{The \tcode{switch} statement}% +\rSec2[stmt.switch]{The \keyword{switch} statement}% \indextext{statement!\idxcode{switch}} \pnum @@ -518,7 +518,7 @@ Thus after the \keyword{while} statement, \tcode{i} is no longer in scope. \end{example} -\rSec2[stmt.while]{The \tcode{while} statement}% +\rSec2[stmt.while]{The \keyword{while} statement}% \indextext{statement!\idxcode{while}} \pnum @@ -562,7 +562,7 @@ \end{example} \end{note} -\rSec2[stmt.do]{The \tcode{do} statement}% +\rSec2[stmt.do]{The \keyword{do} statement}% \indextext{statement!\idxcode{do}} \pnum @@ -614,7 +614,7 @@ makes the implied \keyword{while} clause equivalent to \tcode{while(true)}. -\rSec2[stmt.ranged]{The range-based \tcode{for} statement}% +\rSec2[stmt.ranged]{The range-based \keyword{for} statement}% \indextext{statement!range based for@range based \tcode{for}} \pnum @@ -736,7 +736,7 @@ A suspension of a coroutine\iref{expr.await} is not considered to be an exit from a scope. \end{note} -\rSec2[stmt.break]{The \tcode{break} statement}% +\rSec2[stmt.break]{The \keyword{break} statement}% \indextext{statement!\idxcode{break}} \pnum @@ -748,7 +748,7 @@ \keyword{switch} statement; control passes to the statement following the terminated statement, if any. -\rSec2[stmt.cont]{The \tcode{continue} statement}% +\rSec2[stmt.cont]{The \keyword{continue} statement}% \indextext{statement!\idxcode{continue}} \pnum @@ -795,7 +795,7 @@ a \keyword{continue} not contained in an enclosed iteration statement is equivalent to \tcode{goto} \exposid{contin}. -\rSec2[stmt.return]{The \tcode{return} statement}% +\rSec2[stmt.return]{The \keyword{return} statement}% \indextext{\idxcode{return}}% \indextext{function return|see{\tcode{return}}}% @@ -811,15 +811,18 @@ \indextext{\idxcode{return}!constructor and}% \indextext{\idxcode{return}!constructor and}% A \tcode{return} statement with an operand of type \keyword{void} shall be used only -in a function whose return type is \cv{}~\keyword{void}. +in a function that has a \cv{}~\keyword{void} return type. A \tcode{return} statement with any other operand shall be used only -in a function whose return type is not \cv{}~\keyword{void}; +in a function that has a return type other than \cv{}~\keyword{void}; \indextext{conversion!return type}% the \tcode{return} statement initializes the returned reference or prvalue result object of the (explicit or implicit) function call by copy-initialization\iref{dcl.init} from the operand. \begin{note} +A constructor or destructor does not have a return type. +\end{note} +\begin{note} A \tcode{return} statement can involve an invocation of a constructor to perform a copy or move of the operand if it is not a prvalue or if its type differs from the return type of the function. @@ -829,7 +832,7 @@ \pnum The destructor for the result object -is potentially invoked~(\ref{class.dtor}, \ref{except.ctor}). +is potentially invoked\iref{class.dtor,except.ctor}. \begin{example} \begin{codeblock} class A { @@ -846,7 +849,7 @@ a non-coroutine function with a \cv{}~\keyword{void} return type is equivalent to a \tcode{return} with no operand. Otherwise, flowing off the end of a function -other than \tcode{main}\iref{basic.start.main} or a coroutine\iref{dcl.fct.def.coroutine} +that is neither \tcode{main}\iref{basic.start.main} nor a coroutine\iref{dcl.fct.def.coroutine} results in undefined behavior. \pnum @@ -856,7 +859,7 @@ before the destruction of local variables\iref{stmt.jump} of the block enclosing the \tcode{return} statement. -\rSec2[stmt.return.coroutine]{The \tcode{co_return} statement}% +\rSec2[stmt.return.coroutine]{The \keyword{co_return} statement}% \indextext{\idxcode{co_return}}% \indextext{coroutine return|see{\tcode{co_return}}}% @@ -907,7 +910,7 @@ otherwise flowing off the end of a coroutine's \grammarterm{function-body} results in undefined behavior. -\rSec2[stmt.goto]{The \tcode{goto} statement}% +\rSec2[stmt.goto]{The \keyword{goto} statement}% \indextext{statement!\idxcode{goto}} \pnum diff --git a/source/std.tex b/source/std.tex index 5b4a97f572..040decb135 100644 --- a/source/std.tex +++ b/source/std.tex @@ -47,6 +47,7 @@ \usepackage[active,header=false,handles=false,copydocumentclass=false,generate=std-gram.ext,extract-cmdline={gramSec},extract-env={bnf,simplebnf}]{extract} % Grammar extraction \usepackage{expl3} \usepackage{xparse} +\usepackage{xstring} \pdfminorversion=5 \pdfcompresslevel=9 @@ -118,6 +119,8 @@ \include{support} \include{concepts} \include{diagnostics} +\include{memory} +\include{meta} \include{utilities} \include{strings} \include{containers} @@ -129,7 +132,6 @@ \include{locales} \include{iostreams} \include{regex} -\include{atomics} \include{threads} %%-------------------------------------------------- diff --git a/source/strings.tex b/source/strings.tex index b65235b7c3..d163c25419 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -5,7 +5,7 @@ \pnum This Clause describes components for manipulating sequences of -any non-array trivial standard-layout\iref{basic.types} type. +any non-array trivial standard-layout\iref{term.standard.layout.type} type. Such types are called \defnx{char-like types}{char-like type}, and objects of char-like types are called \defnx{char-like objects}{char-like object} or @@ -19,8 +19,8 @@ \begin{libsumtab}[x{2.1in}]{Strings library summary}{strings.summary} \ref{char.traits} & Character traits & \tcode{} \\ -\ref{string.classes} & String classes & \\ \rowsep \ref{string.view} & String view classes & \tcode{} \\ \rowsep +\ref{string.classes} & String classes & \\ \rowsep \ref{c.strings} & Null-terminated sequence utilities & \tcode{}, \tcode{}, \tcode{}, \tcode{}, \tcode{}, \tcode{} \\ @@ -134,31 +134,31 @@ \tcode{X::state_type} & & (described in~\ref{char.traits.typedefs}) & compile-time \\ \rowsep \tcode{X::eq(c,d)} & \tcode{bool} & -\returns + \returns whether \tcode{c} is to be treated as equal to \tcode{d}. & constant \\ \rowsep \tcode{X::lt(c,d)} & \tcode{bool} & -\returns + \returns whether \tcode{c} is to be treated as less than \tcode{d}. & constant \\ \rowsep \tcode{X::compare(p,q,n)} & \tcode{int} & -\returns + \returns \tcode{0} if for each \tcode{i} in \tcode{[0,n)}, \tcode{X::eq(p[i],q[i])} is \tcode{true}; else, a negative value if, for some \tcode{j} in \tcode{[0,n)}, \tcode{X::lt(p[j],q[j])} is \tcode{true} and for each \tcode{i} in \tcode{[0,j)} \tcode{X::eq(p[i],q[i])} is \tcode{true}; else a positive value. & linear \\ \rowsep \tcode{X::length(p)} & \tcode{size_t} & -\returns + \returns the smallest \tcode{i} such that \tcode{X::eq(p[i],charT())} is \tcode{true}. & linear \\ \rowsep \tcode{X::find(p,n,c)} & \tcode{const X::char_type*} & -\returns + \returns the smallest \tcode{q} in \tcode{[p,p+n)} such that \tcode{X::eq(*q,c)} is \tcode{true}, zero otherwise. & linear \\ \rowsep \tcode{X::move(s,p,n)} & \tcode{X::char_type*} & for each \tcode{i} in \tcode{[0,n)}, performs \tcode{X::assign(s[i],p[i])}. Copies correctly even where the ranges \tcode{[p,p+n)} and \tcode{[s,s+n)} overlap.\br \returns \tcode{s}. & linear \\ \rowsep \tcode{X::copy(s,p,n)} & \tcode{X::char_type*} & -\expects + \expects \tcode{p} not in \tcode{[s,s+n)}.\par -\returns + \returns \tcode{s}.\br for each \tcode{i} in \tcode{[0,n)}, performs \tcode{X::assign(s[i],p[i])}. & linear \\ \rowsep @@ -167,30 +167,30 @@ \tcode{X::assign\-(s,n,c)} & \tcode{X::char_type*} & for each \tcode{i} in \tcode{[0,n)}, performs \tcode{X::assign(s[i],c)}.\br -\returns + \returns \tcode{s}. & linear \\ \rowsep \tcode{X::not_eof(e)} & \tcode{int_type} & -\returns + \returns \tcode{e} if \tcode{X::eq_int_type(e,X::eof())} is \tcode{false}, otherwise a value \tcode{f} such that \tcode{X::eq_int_type(f,X::eof())} is \tcode{false}. & constant \\ \rowsep \tcode{X::to_char_type\-(e)} & \tcode{X::char_type} & -\returns + \returns if for some \tcode{c}, \tcode{X::eq_int_type(e,X::to_int_type(c))} is \tcode{true}, \tcode{c}; else some unspecified value. & constant \\ \rowsep \tcode{X::to_int_type\-(c)} & \tcode{X::int_type} & -\returns + \returns some value \tcode{e}, constrained by the definitions of \tcode{to_char_type} and \tcode{eq_int_type}. & constant \\ \rowsep \tcode{X::eq_int_type\-(e,f)} & \tcode{bool} & -\returns + \returns for all \tcode{c} and \tcode{d}, \tcode{X::eq(c,d)} is equal to \tcode{X::eq_int_type(X::to_int_type(c), X::to_int_type(d))}; otherwise, yields \tcode{true} if \tcode{e} and \tcode{f} are both copies of \tcode{X::eof()}; otherwise, yields \tcode{false} if one of \tcode{e} and \tcode{f} is a copy of \tcode{X::eof()} and the other is not; otherwise the value is unspecified. & constant \\ \rowsep \tcode{X::eof()} & \tcode{X::int_type} & -\returns + \returns a value \tcode{e} such that \tcode{X::eq_int_type(e,X::to_int_type(c))} is \tcode{false} for all values \tcode{c}. & constant \\ \end{libreqtab4d} @@ -515,1816 +515,1986 @@ returns \tcode{WEOF}. -\rSec1[string.classes]{String classes} +\rSec1[string.view]{String view classes} -\rSec2[string.classes.general]{General} +\rSec2[string.view.general]{General} \pnum -The header \tcode{} defines the -\tcode{basic_string} class template for manipulating -varying-length sequences of char-like objects and five -\grammarterm{typedef-name}{s}, \tcode{string}, -\tcode{u8string}, -\tcode{u16string}, -\tcode{u32string}, -and \tcode{wstring}, that name -the specializations -\tcode{basic_string}, -\tcode{basic_string}, -\tcode{basic_string}, -\tcode{basic_string}, -and -\tcode{basic_string<\brk{}wchar_t>}, respectively. +The class template \tcode{basic_string_view} describes an object that can refer to a constant contiguous sequence of char-like\iref{strings.general} objects with the first element of the sequence at position zero. +In the rest of \ref{string.view}, the type of the char-like objects held in a \tcode{basic_string_view} object is designated by \tcode{charT}. -\rSec2[string.syn]{Header \tcode{} synopsis} -\indexheader{string}% +\pnum +\begin{note} +The library provides implicit conversions from \tcode{const charT*} and \tcode{std::basic_string} to \tcode{std::basic_string_view} so that user code can accept just \tcode{std::basic_string_view} as a non-templated parameter wherever a sequence of characters is expected. +User-defined types can define their own implicit conversions to \tcode{std::basic_string_view} in order to interoperate with these functions. +\end{note} + +\rSec2[string.view.synop]{Header \tcode{} synopsis} +\indexheader{string_view}% \begin{codeblock} #include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} namespace std { - // \ref{char.traits}, character traits - template struct char_traits; - template<> struct char_traits; - template<> struct char_traits; - template<> struct char_traits; - template<> struct char_traits; - template<> struct char_traits; - - // \ref{basic.string}, \tcode{basic_string} - template, class Allocator = allocator> - class basic_string; - - template - constexpr basic_string - operator+(const basic_string& lhs, - const basic_string& rhs); - template - constexpr basic_string - operator+(basic_string&& lhs, - const basic_string& rhs); - template - constexpr basic_string - operator+(const basic_string& lhs, - basic_string&& rhs); - template - constexpr basic_string - operator+(basic_string&& lhs, - basic_string&& rhs); - template - constexpr basic_string - operator+(const charT* lhs, - const basic_string& rhs); - template - constexpr basic_string - operator+(const charT* lhs, - basic_string&& rhs); - template - constexpr basic_string - operator+(charT lhs, - const basic_string& rhs); - template - constexpr basic_string - operator+(charT lhs, - basic_string&& rhs); - template - constexpr basic_string - operator+(const basic_string& lhs, - const charT* rhs); - template - constexpr basic_string - operator+(basic_string&& lhs, - const charT* rhs); - template - constexpr basic_string - operator+(const basic_string& lhs, - charT rhs); - template - constexpr basic_string - operator+(basic_string&& lhs, - charT rhs); + // \ref{string.view.template}, class template \tcode{basic_string_view} + template> + class basic_string_view; - template - constexpr bool - operator==(const basic_string& lhs, - const basic_string& rhs) noexcept; - template - constexpr bool operator==(const basic_string& lhs, - const charT* rhs); + template + inline constexpr bool ranges::enable_view> = true; + template + inline constexpr bool ranges::enable_borrowed_range> = true; - template - constexpr @\seebelow@ operator<=>(const basic_string& lhs, - @\itcorr@ const basic_string& rhs) noexcept; - template - constexpr @\seebelow@ operator<=>(const basic_string& lhs, - @\itcorr@ const charT* rhs); + // \ref{string.view.comparison}, non-member comparison functions + template + constexpr bool operator==(basic_string_view x, + basic_string_view y) noexcept; + template + constexpr @\seebelow@ operator<=>(basic_string_view x, + @\itcorr@ basic_string_view y) noexcept; - // \ref{string.special}, swap - template - constexpr void - swap(basic_string& lhs, - basic_string& rhs) - noexcept(noexcept(lhs.swap(rhs))); + // see \ref{string.view.comparison}, sufficient additional overloads of comparison functions - // \ref{string.io}, inserters and extractors - template - basic_istream& - operator>>(basic_istream& is, - basic_string& str); - template + // \ref{string.view.io}, inserters and extractors + template basic_ostream& operator<<(basic_ostream& os, - const basic_string& str); - template - basic_istream& - getline(basic_istream& is, - basic_string& str, - charT delim); - template - basic_istream& - getline(basic_istream&& is, - basic_string& str, - charT delim); - template - basic_istream& - getline(basic_istream& is, - basic_string& str); - template - basic_istream& - getline(basic_istream&& is, - basic_string& str); + basic_string_view str); - // \ref{string.erasure}, erasure - template - constexpr typename basic_string::size_type - erase(basic_string& c, const U& value); - template - constexpr typename basic_string::size_type - erase_if(basic_string& c, Predicate pred); + // \tcode{basic_string_view} \grammarterm{typedef-name}s + using string_view = basic_string_view; + using u8string_view = basic_string_view; + using u16string_view = basic_string_view; + using u32string_view = basic_string_view; + using wstring_view = basic_string_view; - // \tcode{basic_string} \grammarterm{typedef-name}s - using @\libglobal{string}@ = basic_string; - using @\libglobal{u8string}@ = basic_string; - using @\libglobal{u16string}@ = basic_string; - using @\libglobal{u32string}@ = basic_string; - using @\libglobal{wstring}@ = basic_string; + // \ref{string.view.hash}, hash support + template struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; - // \ref{string.conversions}, numeric conversions - int stoi(const string& str, size_t* idx = nullptr, int base = 10); - long stol(const string& str, size_t* idx = nullptr, int base = 10); - unsigned long stoul(const string& str, size_t* idx = nullptr, int base = 10); - long long stoll(const string& str, size_t* idx = nullptr, int base = 10); - unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10); - float stof(const string& str, size_t* idx = nullptr); - double stod(const string& str, size_t* idx = nullptr); - long double stold(const string& str, size_t* idx = nullptr); - string to_string(int val); - string to_string(unsigned val); - string to_string(long val); - string to_string(unsigned long val); - string to_string(long long val); - string to_string(unsigned long long val); - string to_string(float val); - string to_string(double val); - string to_string(long double val); + 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; + } + } +} +\end{codeblock} - int stoi(const wstring& str, size_t* idx = nullptr, int base = 10); - long stol(const wstring& str, size_t* idx = nullptr, int base = 10); - unsigned long stoul(const wstring& str, size_t* idx = nullptr, int base = 10); - long long stoll(const wstring& str, size_t* idx = nullptr, int base = 10); - unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10); - float stof(const wstring& str, size_t* idx = nullptr); - double stod(const wstring& str, size_t* idx = nullptr); - long double stold(const wstring& str, size_t* idx = nullptr); - wstring to_wstring(int val); - wstring to_wstring(unsigned val); - wstring to_wstring(long val); - wstring to_wstring(unsigned long val); - wstring to_wstring(long long val); - wstring to_wstring(unsigned long long val); - wstring to_wstring(float val); - wstring to_wstring(double val); - wstring to_wstring(long double val); +\pnum +The function templates defined in \ref{utility.swap} and \ref{iterator.range} +are available when \tcode{} is included. - namespace pmr { - template> - using basic_string = std::basic_string>; +\rSec2[string.view.template]{Class template \tcode{basic_string_view}} - using string = basic_string; - using u8string = basic_string; - using u16string = basic_string; - using u32string = basic_string; - using wstring = basic_string; - } +\rSec3[string.view.template.general]{General} - // \ref{basic.string.hash}, hash support - template struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - - 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); - } - } -} -\end{codeblock} - -\rSec2[basic.string]{Class template \tcode{basic_string}} - -\rSec3[basic.string.general]{General} - -\pnum -\indexlibraryglobal{basic_string}% -The -class template -\tcode{basic_string} -describes objects that can store a sequence consisting of a varying number of -arbitrary char-like objects with the first element of the sequence at position zero. -Such a sequence is also called a ``string'' if the type of the -char-like objects that it holds -is clear from context. -In the rest of \ref{basic.string}, -the type of the char-like objects held in a \tcode{basic_string} object -is designated by \tcode{charT}. - -\pnum -A specialization of \tcode{basic_string} is a contiguous container\iref{container.requirements.general}. - -\pnum -In all cases, -\crange{data()}{data() + size()} is a valid range, -\tcode{data() + size()} points at an object with value \tcode{charT()} -(a ``null terminator''\indextext{string!null terminator}), -and \tcode{size() <= capacity()} is \tcode{true}. - - -\indexlibraryglobal{basic_string}% -\indexlibrarymember{traits_type}{basic_string}% -\indexlibrarymember{value_type}{basic_string}% -\indexlibrarymember{allocator_type}{basic_string}% -\indexlibrarymember{size_type}{basic_string}% -\indexlibrarymember{difference_type}{basic_string}% -\indexlibrarymember{pointer}{basic_string}% -\indexlibrarymember{const_pointer}{basic_string}% -\indexlibrarymember{reference}{basic_string}% -\indexlibrarymember{const_reference}{basic_string}% -\indexlibrarymember{iterator}{basic_string}% -\indexlibrarymember{const_iterator}{basic_string}% -\indexlibrarymember{reverse_iterator}{basic_string}% -\indexlibrarymember{const_reverse_iterator}{basic_string}% +\indexlibraryglobal{basic_string_view}% +\indexlibrarymember{traits_type}{basic_string_view}% +\indexlibrarymember{value_type}{basic_string_view}% +\indexlibrarymember{pointer}{basic_string_view}% +\indexlibrarymember{const_pointer}{basic_string_view}% +\indexlibrarymember{reference}{basic_string_view}% +\indexlibrarymember{const_reference}{basic_string_view}% +\indexlibrarymember{const_iterator}{basic_string_view}% +\indexlibrarymember{iterator}{basic_string_view}% +\indexlibrarymember{const_reverse_iterator}{basic_string_view}% +\indexlibrarymember{reverse_iterator}{basic_string_view}% +\indexlibrarymember{size_type}{basic_string_view}% +\indexlibrarymember{difference_type}{basic_string_view}% \begin{codeblock} namespace std { - template, - class Allocator = allocator> - class basic_string { + template> + class basic_string_view { public: // types using traits_type = traits; using value_type = charT; - using allocator_type = Allocator; - using size_type = typename allocator_traits::size_type; - using difference_type = typename allocator_traits::difference_type; - using pointer = typename allocator_traits::pointer; - using const_pointer = typename allocator_traits::const_pointer; + using pointer = value_type*; + using const_pointer = const value_type*; using reference = value_type&; using const_reference = const value_type&; - - using iterator = @\impdefx{type of \tcode{basic_string::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{basic_string::const_iterator}}@; // see \ref{container.requirements} - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; + using const_iterator = @\impdefx{type of \tcode{basic_string_view::const_iterator}}@; // see \ref{string.view.iterators} + using iterator = const_iterator;@ +\begin{footnote} +Because \tcode{basic_string_view} refers to a constant sequence, \tcode{iterator} and \tcode{const_iterator} are the same type. +\end{footnote}@ + using const_reverse_iterator = reverse_iterator; + using reverse_iterator = const_reverse_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; static constexpr size_type npos = size_type(-1); - // \ref{string.cons}, construct/copy/destroy - constexpr basic_string() noexcept(noexcept(Allocator())) : basic_string(Allocator()) { } - constexpr explicit basic_string(const Allocator& a) noexcept; - constexpr basic_string(const basic_string& str); - constexpr basic_string(basic_string&& str) noexcept; - constexpr basic_string(const basic_string& str, size_type pos, - const Allocator& a = Allocator()); - constexpr basic_string(const basic_string& str, size_type pos, size_type n, - const Allocator& a = Allocator()); - template - constexpr basic_string(const T& t, size_type pos, size_type n, - const Allocator& a = Allocator()); - template - constexpr explicit basic_string(const T& t, const Allocator& a = Allocator()); - constexpr basic_string(const charT* s, size_type n, const Allocator& a = Allocator()); - constexpr basic_string(const charT* s, const Allocator& a = Allocator()); - basic_string(nullptr_t) = delete; - constexpr basic_string(size_type n, charT c, const Allocator& a = Allocator()); - template - constexpr basic_string(InputIterator begin, InputIterator end, - const Allocator& a = Allocator()); - constexpr basic_string(initializer_list, const Allocator& = Allocator()); - constexpr basic_string(const basic_string&, const Allocator&); - constexpr basic_string(basic_string&&, const Allocator&); - constexpr ~basic_string(); - - constexpr basic_string& operator=(const basic_string& str); - constexpr basic_string& operator=(basic_string&& str) - noexcept(allocator_traits::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); - template - constexpr basic_string& operator=(const T& t); - constexpr basic_string& operator=(const charT* s); - basic_string& operator=(nullptr_t) = delete; - constexpr basic_string& operator=(charT c); - constexpr basic_string& operator=(initializer_list); + // \ref{string.view.cons}, construction and assignment + constexpr basic_string_view() noexcept; + constexpr basic_string_view(const basic_string_view&) noexcept = default; + constexpr basic_string_view& operator=(const basic_string_view&) noexcept = default; + constexpr basic_string_view(const charT* str); + basic_string_view(nullptr_t) = delete; + constexpr basic_string_view(const charT* str, size_type len); + template + constexpr basic_string_view(It begin, End end); + template + constexpr basic_string_view(R&& r); - // \ref{string.iterators}, iterators - constexpr iterator begin() noexcept; + // \ref{string.view.iterators}, iterator support constexpr const_iterator begin() const noexcept; - constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; - - constexpr reverse_iterator rbegin() noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator rbegin() const noexcept; - constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; - - constexpr const_iterator cbegin() const noexcept; - constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; - // \ref{string.capacity}, capacity + // \ref{string.view.capacity}, capacity constexpr size_type size() const noexcept; constexpr size_type length() const noexcept; constexpr size_type max_size() const noexcept; - constexpr void resize(size_type n, charT c); - constexpr void resize(size_type n); - template constexpr void resize_and_overwrite(size_type n, Operation op); - constexpr size_type capacity() const noexcept; - constexpr void reserve(size_type res_arg); - constexpr void shrink_to_fit(); - constexpr void clear() noexcept; [[nodiscard]] constexpr bool empty() const noexcept; - // \ref{string.access}, element access + // \ref{string.view.access}, element access constexpr const_reference operator[](size_type pos) const; - constexpr reference operator[](size_type pos); - constexpr const_reference at(size_type n) const; - constexpr reference at(size_type n); - - constexpr const charT& front() const; - constexpr charT& front(); - constexpr const charT& back() const; - constexpr charT& back(); + constexpr const_reference at(size_type pos) const; + constexpr const_reference front() const; + constexpr const_reference back() const; + constexpr const_pointer data() const noexcept; - // \ref{string.modifiers}, modifiers - constexpr basic_string& operator+=(const basic_string& str); - template - constexpr basic_string& operator+=(const T& t); - constexpr basic_string& operator+=(const charT* s); - constexpr basic_string& operator+=(charT c); - constexpr basic_string& operator+=(initializer_list); - constexpr basic_string& append(const basic_string& str); - constexpr basic_string& append(const basic_string& str, size_type pos, size_type n = npos); - template - constexpr basic_string& append(const T& t); - template - constexpr basic_string& append(const T& t, size_type pos, size_type n = npos); - constexpr basic_string& append(const charT* s, size_type n); - constexpr basic_string& append(const charT* s); - constexpr basic_string& append(size_type n, charT c); - template - constexpr basic_string& append(InputIterator first, InputIterator last); - constexpr basic_string& append(initializer_list); + // \ref{string.view.modifiers}, modifiers + constexpr void remove_prefix(size_type n); + constexpr void remove_suffix(size_type n); + constexpr void swap(basic_string_view& s) noexcept; - constexpr void push_back(charT c); + // \ref{string.view.ops}, string operations + constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; - constexpr basic_string& assign(const basic_string& str); - constexpr basic_string& assign(basic_string&& str) - noexcept(allocator_traits::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); - constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos); - template - constexpr basic_string& assign(const T& t); - template - constexpr basic_string& assign(const T& t, size_type pos, size_type n = npos); - constexpr basic_string& assign(const charT* s, size_type n); - constexpr basic_string& assign(const charT* s); - constexpr basic_string& assign(size_type n, charT c); - template - constexpr basic_string& assign(InputIterator first, InputIterator last); - constexpr basic_string& assign(initializer_list); + constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; - constexpr basic_string& insert(size_type pos, const basic_string& str); - constexpr basic_string& insert(size_type pos1, const basic_string& str, - size_type pos2, size_type n = npos); - template - constexpr basic_string& insert(size_type pos, const T& t); - template - constexpr basic_string& insert(size_type pos1, const T& t, - size_type pos2, size_type n = npos); - constexpr basic_string& insert(size_type pos, const charT* s, size_type n); - constexpr basic_string& insert(size_type pos, const charT* s); - constexpr basic_string& insert(size_type pos, size_type n, charT c); - constexpr iterator insert(const_iterator p, charT c); - constexpr iterator insert(const_iterator p, size_type n, charT c); - template - constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); - constexpr iterator insert(const_iterator p, initializer_list); + constexpr int compare(basic_string_view s) const noexcept; + constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const; + constexpr int compare(size_type pos1, size_type n1, basic_string_view s, + size_type pos2, size_type n2) const; + constexpr int compare(const charT* s) const; + constexpr int compare(size_type pos1, size_type n1, const charT* s) const; + constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; - constexpr basic_string& erase(size_type pos = 0, size_type n = npos); - constexpr iterator erase(const_iterator p); - constexpr iterator erase(const_iterator first, const_iterator last); - - constexpr void pop_back(); - - constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str); - constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str, - size_type pos2, size_type n2 = npos); - template - constexpr basic_string& replace(size_type pos1, size_type n1, const T& t); - template - constexpr basic_string& replace(size_type pos1, size_type n1, const T& t, - size_type pos2, size_type n2 = npos); - constexpr basic_string& replace(size_type pos, size_type n1, const charT* s, size_type n2); - constexpr basic_string& replace(size_type pos, size_type n1, const charT* s); - constexpr basic_string& replace(size_type pos, size_type n1, size_type n2, charT c); - constexpr basic_string& replace(const_iterator i1, const_iterator i2, - const basic_string& str); - template - constexpr basic_string& replace(const_iterator i1, const_iterator i2, const T& t); - constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s, - size_type n); - constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s); - constexpr basic_string& replace(const_iterator i1, const_iterator i2, size_type n, charT c); - template - constexpr basic_string& replace(const_iterator i1, const_iterator i2, - InputIterator j1, InputIterator j2); - constexpr basic_string& replace(const_iterator, const_iterator, initializer_list); - - constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; - - constexpr void swap(basic_string& str) - noexcept(allocator_traits::propagate_on_container_swap::value || - allocator_traits::is_always_equal::value); + constexpr bool starts_with(basic_string_view x) const noexcept; + constexpr bool starts_with(charT x) const noexcept; + constexpr bool starts_with(const charT* x) const; + constexpr bool ends_with(basic_string_view x) const noexcept; + constexpr bool ends_with(charT x) const noexcept; + constexpr bool ends_with(const charT* x) const; - // \ref{string.ops}, string operations - constexpr const charT* c_str() const noexcept; - constexpr const charT* data() const noexcept; - constexpr charT* data() noexcept; - constexpr operator basic_string_view() const noexcept; - constexpr allocator_type get_allocator() const noexcept; + constexpr bool contains(basic_string_view x) const noexcept; + constexpr bool contains(charT x) const noexcept; + constexpr bool contains(const charT* x) const; - template - constexpr size_type find(const T& t, size_type pos = 0) const noexcept(@\seebelow@); - constexpr size_type find(const basic_string& str, size_type pos = 0) const noexcept; + // \ref{string.view.find}, searching + constexpr size_type find(basic_string_view s, size_type pos = 0) const noexcept; + constexpr size_type find(charT c, size_type pos = 0) const noexcept; constexpr size_type find(const charT* s, size_type pos, size_type n) const; constexpr size_type find(const charT* s, size_type pos = 0) const; - constexpr size_type find(charT c, size_type pos = 0) const noexcept; - template - constexpr size_type rfind(const T& t, size_type pos = npos) const noexcept(@\seebelow@); - constexpr size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; + constexpr size_type rfind(basic_string_view s, size_type pos = npos) const noexcept; + constexpr size_type rfind(charT c, size_type pos = npos) const noexcept; constexpr size_type rfind(const charT* s, size_type pos, size_type n) const; constexpr size_type rfind(const charT* s, size_type pos = npos) const; - constexpr size_type rfind(charT c, size_type pos = npos) const noexcept; - template - constexpr size_type find_first_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@); - constexpr size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; + constexpr size_type find_first_of(basic_string_view s, size_type pos = 0) const noexcept; + constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept; constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const; constexpr size_type find_first_of(const charT* s, size_type pos = 0) const; - constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept; - template - constexpr size_type find_last_of(const T& t, - size_type pos = npos) const noexcept(@\seebelow@); - constexpr size_type find_last_of(const basic_string& str, - size_type pos = npos) const noexcept; + constexpr size_type find_last_of(basic_string_view s, size_type pos = npos) const noexcept; + constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept; constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const; constexpr size_type find_last_of(const charT* s, size_type pos = npos) const; - constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept; - - template - constexpr size_type find_first_not_of(const T& t, - size_type pos = 0) const noexcept(@\seebelow@); - constexpr size_type find_first_not_of(const basic_string& str, - size_type pos = 0) const noexcept; - constexpr size_type find_first_not_of(const charT* s, size_type pos, size_type n) const; - constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const; + constexpr size_type find_first_not_of(basic_string_view s, size_type pos = 0) const noexcept; constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept; - template - constexpr size_type find_last_not_of(const T& t, - size_type pos = npos) const noexcept(@\seebelow@); - constexpr size_type find_last_not_of(const basic_string& str, + constexpr size_type find_first_not_of(const charT* s, size_type pos, + size_type n) const; + constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const; + constexpr size_type find_last_not_of(basic_string_view s, size_type pos = npos) const noexcept; - constexpr size_type find_last_not_of(const charT* s, size_type pos, size_type n) const; - constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const; constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept; + constexpr size_type find_last_not_of(const charT* s, size_type pos, + size_type n) const; + constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const; - constexpr basic_string substr(size_type pos = 0, size_type n = npos) const; - - template - constexpr int compare(const T& t) const noexcept(@\seebelow@); - template - constexpr int compare(size_type pos1, size_type n1, const T& t) const; - template - constexpr int compare(size_type pos1, size_type n1, const T& t, - size_type pos2, size_type n2 = npos) const; - constexpr int compare(const basic_string& str) const noexcept; - constexpr int compare(size_type pos1, size_type n1, const basic_string& str) const; - constexpr int compare(size_type pos1, size_type n1, const basic_string& str, - size_type pos2, size_type n2 = npos) const; - constexpr int compare(const charT* s) const; - constexpr int compare(size_type pos1, size_type n1, const charT* s) const; - constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; - - constexpr bool starts_with(basic_string_view x) const noexcept; - constexpr bool starts_with(charT x) const noexcept; - constexpr bool starts_with(const charT* x) const; - constexpr bool ends_with(basic_string_view x) const noexcept; - constexpr bool ends_with(charT x) const noexcept; - constexpr bool ends_with(const charT* x) const; - - constexpr bool contains(basic_string_view x) const noexcept; - constexpr bool contains(charT x) const noexcept; - constexpr bool contains(const charT* x) const; + private: + const_pointer data_; // \expos + size_type size_; // \expos }; - template::value_type>> - basic_string(InputIterator, InputIterator, Allocator = Allocator()) - -> basic_string::value_type, - char_traits::value_type>, - Allocator>; - - template> - explicit basic_string(basic_string_view, const Allocator& = Allocator()) - -> basic_string; - - template> - basic_string(basic_string_view, - typename @\seebelow@::size_type, typename @\seebelow@::size_type, - const Allocator& = Allocator()) - -> basic_string; + // \ref{string.view.deduct}, deduction guides + template + basic_string_view(It, End) -> basic_string_view>; + template + basic_string_view(R&&) -> basic_string_view>; } \end{codeblock} \pnum -A \tcode{size_type} parameter type in -a \tcode{basic_string} deduction guide -refers to the \tcode{size_type} member type of -the type deduced by the deduction guide. - -\rSec3[string.require]{General requirements} - -\pnum -If any operation would cause \tcode{size()} to -exceed \tcode{max_size()}, that operation throws an -exception object of type \tcode{length_error}. - -\pnum -If any member function or operator of \tcode{basic_string} throws an exception, that -function or operator has no other effect on the \tcode{basic_string} object. - -\pnum -In every specialization \tcode{basic_string}, -the type \tcode{allocator_traits::value_type} shall name the same type -as \tcode{charT}. Every object of type -\tcode{basic_string} uses an object of type -\tcode{Allocator} to allocate and free storage for the contained \tcode{charT} -objects as needed. The \tcode{Allocator} object used is -obtained as described in \ref{container.requirements.general}. -In every specialization \tcode{basic_string}, -the type \tcode{traits} shall meet -the character traits requirements\iref{char.traits}. -\begin{note} -Every specialization \tcode{basic_string} is -an allocator-aware container, -but does not use the allocator's \tcode{construct} and \tcode{destroy} -member functions\iref{container.requirements.general}. -\end{note} +In every specialization \tcode{basic_string_view}, the type \tcode{traits} shall meet the character traits requirements\iref{char.traits}. \begin{note} -The program is ill-formed if \tcode{traits::char_type} -is not the same type as \tcode{charT}. +The program is ill-formed if \tcode{traits::char_type} is not the same type as \tcode{charT}. \end{note} \pnum -References, pointers, and iterators referring to the elements of a -\tcode{basic_string} sequence may be -invalidated by the following uses of that \tcode{basic_string} object: +For a \tcode{basic_string_view str}, +any operation that invalidates a pointer +in the range +\begin{codeblock} +@\range{str.data()}{\brk{}str.data() + str.size()}@ +\end{codeblock} +invalidates pointers, iterators, and references +returned from \tcode{str}'s member functions. -\begin{itemize} -\item Passing as an argument to any standard library function taking a reference to non-const -\tcode{basic_string} as an argument. -\begin{footnote} -For example, as an argument to non-member -functions \tcode{swap()}\iref{string.special}, -\tcode{operator>{}>()}\iref{string.io}, and \tcode{getline()}\iref{string.io}, or as -an argument to \tcode{basic_string::swap()}. -\end{footnote} +\pnum +The complexity of \tcode{basic_string_view} member functions is \bigoh{1} +unless otherwise specified. -\item Calling non-const member functions, except -\tcode{operator[]}, -\tcode{at}, -\tcode{data}, -\tcode{front}, -\tcode{back}, -\tcode{begin}, -\tcode{rbegin}, -\tcode{end}, -and -\tcode{rend}. -\end{itemize} +\pnum +\tcode{basic_string_view} is +a trivially copyable type\iref{term.trivially.copyable.type}. -\rSec3[string.cons]{Constructors and assignment operators} +\rSec3[string.view.cons]{Construction and assignment} -\indexlibraryctor{basic_string}% +\indexlibraryctor{basic_string_view}% \begin{itemdecl} -constexpr explicit basic_string(const Allocator& a) noexcept; +constexpr basic_string_view() noexcept; \end{itemdecl} \begin{itemdescr} - \pnum \ensures -\tcode{size()} is equal to \tcode{0}. +\tcode{size_ == 0} and \tcode{data_ == nullptr}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibraryctor{basic_string_view}% \begin{itemdecl} -constexpr basic_string(const basic_string& str); -constexpr basic_string(basic_string&& str) noexcept; +constexpr basic_string_view(const charT* str); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\range{str}{str + traits::length(str)} is a valid range. + \pnum \effects -Constructs an object whose -value is that of \tcode{str} prior to this call. +Constructs a \tcode{basic_string_view}, initializing \tcode{data_} with \tcode{str} +and initializing \tcode{size_} with \tcode{traits::length(str)}. \pnum -\remarks -In the second form, \tcode{str} is left in a valid but unspecified state. +\complexity +\bigoh{\tcode{traits::length(str)}}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibraryctor{basic_string_view}% \begin{itemdecl} -constexpr basic_string(const basic_string& str, size_type pos, - const Allocator& a = Allocator()); -constexpr basic_string(const basic_string& str, size_type pos, size_type n, - const Allocator& a = Allocator()); +constexpr basic_string_view(const charT* str, size_type len); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\range{str}{str + len} is a valid range. + \pnum \effects -Let \tcode{n} be \tcode{npos} for the first overload. Equivalent to: -\begin{codeblock} -basic_string(basic_string_view(str).substr(pos, n), a) -\end{codeblock} +Constructs a \tcode{basic_string_view}, initializing \tcode{data_} with \tcode{str} +and initializing \tcode{size_} with \tcode{len}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibraryctor{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); +template + constexpr basic_string_view(It begin, End end); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_convertible_v>} -is \tcode{true}. +\begin{itemize} +\item \tcode{It} satisfies \libconcept{contiguous_iterator}. +\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}}. +\item \tcode{is_same_v, charT>} is \tcode{true}. +\item \tcode{is_convertible_v} is \tcode{false}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item \range{begin}{end} is a valid range. +\item \tcode{It} models \libconcept{contiguous_iterator}. +\item \tcode{End} models \tcode{\libconcept{sized_sentinel_for}}. +\end{itemize} \pnum \effects -Creates a variable, \tcode{sv}, -as if by \tcode{basic_string_view sv = t;} -and then behaves the same as: -\begin{codeblock} -basic_string(sv.substr(pos, n), a); -\end{codeblock} +Initializes \tcode{data_} with \tcode{to_address(begin)} and +initializes \tcode{size_} with \tcode{end - begin}. + +\pnum +\throws +When and what \tcode{end - begin} throws. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibraryctor{basic_string_view}% \begin{itemdecl} -template - constexpr explicit basic_string(const T& t, const Allocator& a = Allocator()); +template + constexpr basic_string_view(R&& r); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{d} be an lvalue of type \tcode{remove_cvref_t}. + \pnum \constraints \begin{itemize} \item -\tcode{is_convertible_v>} is -\tcode{true} and +\tcode{remove_cvref_t} is not the same type as \tcode{basic_string_view}, \item -\tcode{is_convertible_v} is -\tcode{false}. +\tcode{R} models +\tcode{ranges::\libconcept{contiguous_range}} and \tcode{ranges::\libconcept{sized_range}}, +\item +\tcode{is_same_v, charT>} is \tcode{true}, +\item +\tcode{is_convertible_v} is \tcode{false}, +\item +\tcode{d.operator ::std::basic_string_view()} +is not a valid expression, and +\item +if the \grammarterm{qualified-id} \tcode{remove_reference_t::traits_type} +is valid and denotes a type, +\tcode{is_same_v::traits_type, traits>} is \tcode{true}. \end{itemize} \pnum \effects -Creates a variable, \tcode{sv}, as if by -\tcode{basic_string_view sv = t;} and -then behaves the same as \tcode{basic_string(sv.data(), sv.size(), a)}. +Initializes \tcode{data_} with \tcode{ranges::data(r)} and +\tcode{size_} with \tcode{ranges::size(r)}. + +\pnum +\throws +Any exception thrown by \tcode{ranges::data(r)} and \tcode{ranges::size(r)}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\rSec3[string.view.iterators]{Iterator support} + +\indexlibrarymember{const_iterator}{basic_string_view}% \begin{itemdecl} -constexpr basic_string(const charT* s, size_type n, const Allocator& a = Allocator()); +using const_iterator = @\impdefx{type of \tcode{basic_string_view::const_iterator}}@; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\range{s}{s + n} is a valid range. - -\pnum -\effects -Constructs an object whose initial value is the range \range{s}{s + n}. +A type that meets the requirements +of a constant +\oldconcept{RandomAccessIterator}\iref{random.access.iterators}, +models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}, and +meets the constexpr iterator requirements\iref{iterator.requirements.general}, +whose \tcode{value_type} is the template parameter \tcode{charT}. \pnum -\ensures -\tcode{size()} is equal to \tcode{n}, and -\tcode{traits::compare(data(), s, n)} is equal to \tcode{0}. +All requirements on container iterators\iref{container.requirements} apply to \tcode{basic_string_view::const_iterator} as well. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibrarymember{begin}{basic_string_view}% +\indexlibrarymember{cbegin}{basic_string_view}% \begin{itemdecl} -constexpr basic_string(const charT* s, const Allocator& a = Allocator()); +constexpr const_iterator begin() const noexcept; +constexpr const_iterator cbegin() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{Allocator} is a type -that qualifies as an allocator\iref{container.requirements.general}. -\begin{note} -This affects class template argument deduction. -\end{note} - -\pnum -\effects -Equivalent to: \tcode{basic_string(s, traits::length(s), a)}. +\returns +An iterator such that +\begin{itemize} +\item if \tcode{!empty()}, \tcode{addressof(*begin()) == data_}, +\item otherwise, an unspecified value such that \range{begin()}{end()} is a valid range. +\end{itemize} \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibrarymember{end}{basic_string_view}% +\indexlibrarymember{cend}{basic_string_view}% \begin{itemdecl} -constexpr basic_string(size_type n, charT c, const Allocator& a = Allocator()); +constexpr const_iterator end() const noexcept; +constexpr const_iterator cend() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{Allocator} is a type -that qualifies as an allocator\iref{container.requirements.general}. -\begin{note} -This affects class template argument deduction. -\end{note} - -\pnum -\effects -Constructs an object whose value consists of \tcode{n} copies of \tcode{c}. +\returns +\tcode{begin() + size()}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibrarymember{rbegin}{basic_string_view}% +\indexlibrarymember{crbegin}{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator()); +constexpr const_reverse_iterator rbegin() const noexcept; +constexpr const_reverse_iterator crbegin() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. - -\pnum -\effects -Constructs a string from the values in the range \range{begin}{end}, -as indicated in \tref{container.seq.req}. +\returns +\tcode{const_reverse_iterator(end())}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibrarymember{rend}{basic_string_view}% +\indexlibrarymember{crend}{basic_string_view}% \begin{itemdecl} -constexpr basic_string(initializer_list il, const Allocator& a = Allocator()); +constexpr const_reverse_iterator rend() const noexcept; +constexpr const_reverse_iterator crend() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{basic_string(il.begin(), il.end(), a)}. +\returns +\tcode{const_reverse_iterator(begin())}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\rSec3[string.view.capacity]{Capacity} + +\indexlibrarymember{size}{basic_string_view}% +\indexlibrarymember{length}{basic_string_view}% \begin{itemdecl} -constexpr basic_string(const basic_string& str, const Allocator& alloc); -constexpr basic_string(basic_string&& str, const Allocator& alloc); +constexpr size_type size() const noexcept; +constexpr size_type length() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Constructs an object whose value is -that of \tcode{str} prior to this call. -The stored allocator is constructed from \tcode{alloc}. -In the second form, \tcode{str} is left in a valid but unspecified state. - -\pnum -\throws -The second form throws nothing if \tcode{alloc == str.get_allocator()}. +\returns +\tcode{size_}. \end{itemdescr} + +\indexlibrarymember{max_size}{basic_string_view}% \begin{itemdecl} -template::value_type>> - basic_string(InputIterator, InputIterator, Allocator = Allocator()) - -> basic_string::value_type, - char_traits::value_type>, - Allocator>; +constexpr size_type max_size() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{InputIterator} is a type that qualifies as an input iterator, -and \tcode{Allocator} is a type that qualifies as an allocator\iref{container.requirements.general}. +\returns +The largest possible number of char-like objects that can be referred to by a \tcode{basic_string_view}. \end{itemdescr} +\indexlibrarymember{empty}{basic_string_view}% \begin{itemdecl} -template> - explicit basic_string(basic_string_view, const Allocator& = Allocator()) - -> basic_string; - -template> - basic_string(basic_string_view, - typename @\seebelow@::size_type, typename @\seebelow@::size_type, - const Allocator& = Allocator()) - -> basic_string; +[[nodiscard]] constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{Allocator} is a type that qualifies as -an allocator\iref{container.requirements.general}. +\returns +\tcode{size_ == 0}. \end{itemdescr} -\indexlibrarymember{operator=}{basic_string}% +\rSec3[string.view.access]{Element access} + +\indexlibrarymember{operator[]}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator=(const basic_string& str); +constexpr const_reference operator[](size_type pos) const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -If \tcode{*this} and \tcode{str} are the same object, has no effect. -Otherwise, replaces the value of \tcode{*this} with a copy of \tcode{str}. +\expects +\tcode{pos < size()}. \pnum \returns -\tcode{*this}. +\tcode{data_[pos]}. + +\pnum +\throws +Nothing. + +\pnum +\begin{note} +Unlike \tcode{basic_string::operator[]}, +\tcode{basic_string_view::operator[](size())} has undefined behavior instead of returning \tcode{charT()}. +\end{note} \end{itemdescr} -\indexlibrarymember{operator=}{basic_string}% +\indexlibrarymember{at}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator=(basic_string&& str) - noexcept(allocator_traits::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); +constexpr const_reference at(size_type pos) const; \end{itemdecl} \begin{itemdescr} -\pnum -\effects -Move assigns as a sequence container\iref{container.requirements}, -except that iterators, pointers and references may be invalidated. - \pnum \returns -\tcode{*this}. +\tcode{data_[pos]}. + +\pnum +\throws +\tcode{out_of_range} if \tcode{pos >= size()}. \end{itemdescr} -\indexlibrarymember{operator=}{basic_string}% +\indexlibrarymember{front}{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string& operator=(const T& t); +constexpr const_reference front() const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item \tcode{is_convertible_v>} -is \tcode{true} and -\item \tcode{is_convertible_v} -is \tcode{false}. -\end{itemize} +\expects +\tcode{!empty()}. \pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return assign(sv); -\end{codeblock} +\returns +\tcode{data_[0]}. + +\pnum +\throws +Nothing. \end{itemdescr} -\indexlibrarymember{operator=}{basic_string}% +\indexlibrarymember{back}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator=(const charT* s); +constexpr const_reference back() const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\tcode{return *this = basic_string_view(s);} +\expects +\tcode{!empty()}. + +\pnum +\returns +\tcode{data_[size() - 1]}. + +\pnum +\throws +Nothing. \end{itemdescr} -\indexlibrarymember{operator=}{basic_string}% +\indexlibrarymember{data}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator=(charT c); +constexpr const_pointer data() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return *this = basic_string_view(addressof(c), 1); -\end{codeblock} +\returns +\tcode{data_}. + +\pnum +\begin{note} +Unlike \tcode{basic_string::data()} and \grammarterm{string-literal}s, +\tcode{data()} can return a pointer to a buffer that is not null-terminated. +Therefore it is typically a mistake to pass \tcode{data()} to a function that takes just a \tcode{const charT*} and expects a null-terminated string. +\end{note} \end{itemdescr} -\indexlibrarymember{operator=}{basic_string}% +\rSec3[string.view.modifiers]{Modifiers} + +\indexlibrarymember{remove_prefix}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator=(initializer_list il); +constexpr void remove_prefix(size_type n); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{n <= size()}. + \pnum \effects -Equivalent to: -\begin{codeblock} -return *this = basic_string_view(il.begin(), il.size()); -\end{codeblock} +Equivalent to: \tcode{data_ += n; size_ -= n;} \end{itemdescr} -\rSec3[string.iterators]{Iterator support} - -\indexlibrarymember{begin}{basic_string}% -\indexlibrarymember{cbegin}{basic_string}% +\indexlibrarymember{remove_suffix}{basic_string_view}% \begin{itemdecl} -constexpr iterator begin() noexcept; -constexpr const_iterator begin() const noexcept; -constexpr const_iterator cbegin() const noexcept; +constexpr void remove_suffix(size_type n); \end{itemdecl} \begin{itemdescr} \pnum -\returns -An iterator referring to the first character in the string. +\expects +\tcode{n <= size()}. + +\pnum +\effects +Equivalent to: \tcode{size_ -= n;} \end{itemdescr} -\indexlibrarymember{end}{basic_string}% -\indexlibrarymember{cend}{basic_string}% +\indexlibrarymember{swap}{basic_string_view}% \begin{itemdecl} -constexpr iterator end() noexcept; -constexpr const_iterator end() const noexcept; -constexpr const_iterator cend() const noexcept; +constexpr void swap(basic_string_view& s) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -An iterator which is the past-the-end value. +\effects +Exchanges the values of \tcode{*this} and \tcode{s}. \end{itemdescr} -\indexlibrarymember{rbegin}{basic_string}% -\indexlibrarymember{crbegin}{basic_string}% +\rSec3[string.view.ops]{String operations} + +\indexlibrarymember{copy}{basic_string_view}% \begin{itemdecl} -constexpr reverse_iterator rbegin() noexcept; -constexpr const_reverse_iterator rbegin() const noexcept; -constexpr const_reverse_iterator crbegin() const noexcept; +constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{rlen} be the smaller of \tcode{n} and \tcode{size() - pos}. + +\pnum +\expects +\range{s}{s + rlen} is a valid range. + +\pnum +\effects +Equivalent to \tcode{traits::copy(s, data() + pos, rlen)}. + \pnum \returns -An iterator which is semantically equivalent to -\tcode{reverse_iterator(end())}. +\tcode{rlen}. + +\pnum +\throws +\tcode{out_of_range} if \tcode{pos > size()}. + +\pnum +\complexity +\bigoh{\tcode{rlen}}. \end{itemdescr} -\indexlibrarymember{rend}{basic_string}% -\indexlibrarymember{crend}{basic_string}% +\indexlibrarymember{substr}{basic_string_view}% \begin{itemdecl} -constexpr reverse_iterator rend() noexcept; -constexpr const_reverse_iterator rend() const noexcept; -constexpr const_reverse_iterator crend() const noexcept; +constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{rlen} be the smaller of \tcode{n} and \tcode{size() - pos}. + +\pnum +\effects +Determines \tcode{rlen}, the effective length of the string to reference. + \pnum \returns -An iterator which is semantically equivalent to -\tcode{reverse_iterator(begin())}. -\end{itemdescr} +\tcode{basic_string_view(data() + pos, rlen)}. -\rSec3[string.capacity]{Capacity} +\pnum +\throws +\tcode{out_of_range} if \tcode{pos > size()}. +\end{itemdescr} -\indexlibrarymember{size}{basic_string}% -\indexlibrarymember{length}{basic_string}% +\indexlibrarymember{compare}{basic_string_view}% \begin{itemdecl} -constexpr size_type size() const noexcept; -constexpr size_type length() const noexcept; +constexpr int compare(basic_string_view str) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{rlen} be the smaller of \tcode{size()} and \tcode{str.size()}. + +\pnum +\effects +Determines \tcode{rlen}, the effective length of the strings to compare. +The function then compares the two strings by calling \tcode{traits::compare(data(), str.data(), rlen)}. + \pnum \returns -A count of the number of char-like objects currently in the string. +The nonzero result if the result of the comparison is nonzero. +Otherwise, returns a value as indicated in \tref{string.view.compare}. +\begin{libtab2}{\tcode{compare()} results}{string.view.compare}{cc}{Condition}{Return Value} +\tcode{size() < str.size()} & \tcode{< 0}\\ +\tcode{size() == str.size()} & \tcode{ \ 0}\\ +\tcode{size() > str.size()} & \tcode{> 0}\\ +\end{libtab2} \pnum \complexity -Constant time. +\bigoh{\tcode{rlen}}. \end{itemdescr} -\indexlibrarymember{max_size}{basic_string}% +\indexlibrarymember{compare}{basic_string_view}% \begin{itemdecl} -constexpr size_type max_size() const noexcept; +constexpr int compare(size_type pos1, size_type n1, basic_string_view str) const; \end{itemdecl} \begin{itemdescr} \pnum -\returns -The largest possible number of char-like objects that can be stored in a -\tcode{basic_string}. - -\pnum -\complexity -Constant time. +\effects +Equivalent to: \tcode{return substr(pos1, n1).compare(str);} \end{itemdescr} -\indexlibrarymember{resize}{basic_string}% +\indexlibrarymember{compare}{basic_string_view}% \begin{itemdecl} -constexpr void resize(size_type n, charT c); +constexpr int compare(size_type pos1, size_type n1, basic_string_view str, + size_type pos2, size_type n2) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Alters the value of -\tcode{*this} -as follows: -\begin{itemize} -\item -If -\tcode{n <= size()}, -erases the last \tcode{size() - n} elements. -\item -If -\tcode{n > size()}, -appends \tcode{n - size()} copies of \tcode{c}. -\end{itemize} +Equivalent to: \tcode{return substr(pos1, n1).compare(str.substr(pos2, n2));} \end{itemdescr} -\indexlibrarymember{resize}{basic_string}% +\indexlibrarymember{compare}{basic_string_view}% \begin{itemdecl} -constexpr void resize(size_type n); +constexpr int compare(const charT* s) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to \tcode{resize(n, charT())}. +Equivalent to: \tcode{return compare(basic_string_view(s));} \end{itemdescr} -\indexlibrarymember{resize_and_overwrite}{basic_string}% +\indexlibrarymember{compare}{basic_string_view}% \begin{itemdecl} -template constexpr void resize_and_overwrite(size_type n, Operation op); +constexpr int compare(size_type pos1, size_type n1, const charT* s) const; \end{itemdecl} \begin{itemdescr} \pnum -Let -\begin{itemize} -\item -\tcode{o = size()} before the call to \tcode{resize_and_overwrite}. -\item -\tcode{k} be \tcode{min(o, n)}. -\item -\tcode{p} be a \tcode{charT*}, -such that the range \crange{p}{p + n} is valid and -\tcode{this->compare(0, k, p, k) == 0} is \tcode{true} before the call. -The values in the range \crange{p + k}{p + n} may be indeterminate\iref{basic.indet}. -\item -$OP$ be the expression \tcode{std::move(op)(p, n)}. -\item -\tcode{r} = $OP$. -\end{itemize} - -\pnum -\mandates -$OP$ has an integer-like type\iref{iterator.concept.winc}. - -\pnum -\expects -\begin{itemize} -\item -$OP$ does not throw an exception or modify \tcode{p} or \tcode{n}. -\item -$\tcode{r} \geq 0$. -\item -$\tcode{r} \leq \tcode{n}$. -\item -After evaluating $OP$ -there are no indeterminate values in the range \range{p}{p + r}. -\end{itemize} +\effects +Equivalent to: \tcode{return substr(pos1, n1).compare(basic_string_view(s));} +\end{itemdescr} + +\indexlibrarymember{compare}{basic_string_view}% +\begin{itemdecl} +constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; +\end{itemdecl} +\begin{itemdescr} \pnum \effects -Evaluates $OP$, -replaces the contents of \tcode{*this} with \range{p}{p + r}, and -invalidates all pointers and references to the range \crange{p}{p + n}. - -\pnum -\recommended -Implementations should avoid unnecessary copies and allocations -by, for example, making \tcode{p} a pointer into internal storage and -by restoring \tcode{*(p + r)} to \tcode{charT()} after evaluating $OP$. +Equivalent to: \tcode{return substr(pos1, n1).compare(basic_string_view(s, n2));} \end{itemdescr} -\indexlibrarymember{capacity}{basic_string}% +\indexlibrarymember{starts_with}{basic_string_view}% \begin{itemdecl} -constexpr size_type capacity() const noexcept; +constexpr bool starts_with(basic_string_view x) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -The size of the allocated storage in the string. - -\pnum -\complexity -Constant time. +\effects +Equivalent to: \tcode{return substr(0, x.size()) == x;} \end{itemdescr} -\indexlibrarymember{reserve}{basic_string}% +\indexlibrarymember{starts_with}{basic_string_view}% \begin{itemdecl} -constexpr void reserve(size_type res_arg); +constexpr bool starts_with(charT x) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -A directive that informs a \tcode{basic_string} of a planned change in size, -so that the storage allocation can be managed accordingly. -After -\tcode{reserve()}, -\tcode{capacity()} -is greater or equal to the argument of -\tcode{reserve} -if reallocation happens; and -equal to the previous value of -\tcode{capacity()} -otherwise. -Reallocation happens at this point if and only if -the current capacity is less than the argument of \tcode{reserve()}. - -\pnum -\throws -\tcode{length_error} -if -\tcode{res_arg > max_size()} or any exceptions thrown by -\tcode{allocator_traits} \tcode{::allocate}. +Equivalent to: \tcode{return !empty() \&\& traits::eq(front(), x);} \end{itemdescr} -\indexlibrarymember{shrink_to_fit}{basic_string}% +\indexlibrarymember{starts_with}{basic_string_view}% \begin{itemdecl} -constexpr void shrink_to_fit(); +constexpr bool starts_with(const charT* x) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -\tcode{shrink_to_fit} is a non-binding request to reduce -\tcode{capacity()} to \tcode{size()}. -\begin{note} -The request is non-binding to -allow latitude for implementation-specific optimizations. -\end{note} -It does not increase \tcode{capacity()}, but may reduce \tcode{capacity()} -by causing reallocation. +Equivalent to: \tcode{return starts_with(basic_string_view(x));} +\end{itemdescr} -\pnum -\complexity -If the size is not equal to the old capacity, -linear in the size of the sequence; -otherwise constant. +\indexlibrarymember{ends_with}{basic_string_view}% +\begin{itemdecl} +constexpr bool ends_with(basic_string_view x) const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\remarks -Reallocation invalidates all the references, pointers, and iterators -referring to the elements in the sequence, as well as the past-the-end iterator. -\begin{note} -If no reallocation happens, they remain valid. -\end{note} +\effects +Equivalent to: +\begin{codeblock} +return size() >= x.size() && compare(size() - x.size(), npos, x) == 0; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{clear}{basic_string}% +\indexlibrarymember{ends_with}{basic_string_view}% \begin{itemdecl} -constexpr void clear() noexcept; +constexpr bool ends_with(charT x) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{erase(begin(), end());} +Equivalent to: \tcode{return !empty() \&\& traits::eq(back(), x);} \end{itemdescr} -\indexlibrarymember{empty}{basic_string}% +\indexlibrarymember{ends_with}{basic_string_view}% \begin{itemdecl} -[[nodiscard]] constexpr bool empty() const noexcept; +constexpr bool ends_with(const charT* x) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return size() == 0;} +Equivalent to: \tcode{return ends_with(basic_string_view(x));} \end{itemdescr} -\rSec3[string.access]{Element access} - -\indexlibrarymember{operator[]}{basic_string}% +\indexlibrarymember{contains}{basic_string_view}% \begin{itemdecl} -constexpr const_reference operator[](size_type pos) const; -constexpr reference operator[](size_type pos); +constexpr bool contains(basic_string_view x) const noexcept; +constexpr bool contains(charT x) const noexcept; +constexpr bool contains(const charT* x) const; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{pos <= size()}. +\effects +Equivalent to: \tcode{return find(x) != npos;} +\end{itemdescr} -\pnum -\returns -\tcode{*(begin() + pos)} if \tcode{pos < size()}. Otherwise, -returns a reference to an object of type \tcode{charT} with value -\tcode{charT()}, where modifying the object to any value other than -\tcode{charT()} leads to undefined behavior. +\rSec3[string.view.find]{Searching} \pnum -\throws -Nothing. +Member functions in this subclause have complexity \bigoh{\tcode{size() * str.size()}} at worst, +although implementations should do better. \pnum -\complexity -Constant time. -\end{itemdescr} +Let \placeholder{F} be one of +\tcode{find}, +\tcode{rfind}, +\tcode{find_first_of}, +\tcode{find_last_of}, +\tcode{find_first_not_of}, +and +\tcode{find_last_not_of}. +\begin{itemize} +\item +Each member function of the form +\begin{codeblock} +constexpr @\placeholder{return-type}@ @\placeholder{F}@(const charT* s, size_type pos) const; +\end{codeblock} +has effects equivalent to: \tcode{return \placeholder{F}(basic_string_view(s), pos);} -\indexlibrarymember{at}{basic_string}% +\item +Each member function of the form +\begin{codeblock} +constexpr @\placeholder{return-type}@ @\placeholder{F}@(const charT* s, size_type pos, size_type n) const; +\end{codeblock} +has effects equivalent to: \tcode{return \placeholder{F}(basic_string_view(s, n), pos);} + +\item +Each member function of the form +\begin{codeblock} +constexpr @\placeholder{return-type}@ @\placeholder{F}@(charT c, size_type pos) const noexcept; +\end{codeblock} +has effects equivalent to: \tcode{return \placeholder{F}(basic_string_view(addressof(c), 1), pos);} +\end{itemize} + +\indexlibrarymember{find}{basic_string_view}% \begin{itemdecl} -constexpr const_reference at(size_type pos) const; -constexpr reference at(size_type pos); +constexpr size_type find(basic_string_view str, size_type pos = 0) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{operator[](pos)}. +Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold: +\begin{itemize} +\item +\tcode{pos <= xpos} +\item +\tcode{xpos + str.size() <= size()} +\item +\tcode{traits::eq(at(xpos + I), str.at(I))} for all elements \tcode{I} of the string referenced by \tcode{str}. +\end{itemize} \pnum -\throws -\tcode{out_of_range} -if -\tcode{pos >= size()}. +\effects +Determines \tcode{xpos}. + +\pnum +\returns +\tcode{xpos} if the function can determine such a value for \tcode{xpos}. +Otherwise, returns \tcode{npos}. \end{itemdescr} -\indexlibrarymember{front}{basic_string}% +\indexlibrarymember{rfind}{basic_string_view}% \begin{itemdecl} -constexpr const charT& front() const; -constexpr charT& front(); +constexpr size_type rfind(basic_string_view str, size_type pos = npos) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +Let \tcode{xpos} be the highest position, if possible, such that the following conditions hold: +\begin{itemize} +\item +\tcode{xpos <= pos} +\item +\tcode{xpos + str.size() <= size()} +\item +\tcode{traits::eq(at(xpos + I), str.at(I))} for all elements \tcode{I} of the string referenced by \tcode{str}. +\end{itemize} \pnum \effects -Equivalent to: \tcode{return operator[](0);} +Determines \tcode{xpos}. + +\pnum +\returns +\tcode{xpos} if the function can determine such a value for \tcode{xpos}. +Otherwise, returns \tcode{npos}. \end{itemdescr} -\indexlibrarymember{back}{basic_string}% +\indexlibrarymember{find_first_of}{basic_string_view}% \begin{itemdecl} -constexpr const charT& back() const; -constexpr charT& back(); +constexpr size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold: +\begin{itemize} +\item +\tcode{pos <= xpos} +\item +\tcode{xpos < size()} +\item +\tcode{traits::eq(at(xpos), str.at(I))} for some element \tcode{I} of the string referenced by \tcode{str}. +\end{itemize} \pnum \effects -Equivalent to: \tcode{return operator[](size() - 1);} -\end{itemdescr} - -\rSec3[string.modifiers]{Modifiers} +Determines \tcode{xpos}. -\rSec4[string.op.append]{\tcode{basic_string::operator+=}} +\pnum +\returns +\tcode{xpos} if the function can determine such a value for \tcode{xpos}. +Otherwise, returns \tcode{npos}. +\end{itemdescr} -\indexlibrarymember{operator+=}{basic_string}% +\indexlibrarymember{find_last_of}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator+=(const basic_string& str); +constexpr size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(str);} - - +Let \tcode{xpos} be the highest position, if possible, such that the following conditions hold: +\begin{itemize} +\item +\tcode{xpos <= pos} +\item +\tcode{xpos < size()} +\item +\tcode{traits::eq(at(xpos), str.at(I))} for some element \tcode{I} of the string referenced by \tcode{str}. +\end{itemize} + +\pnum +\effects +Determines \tcode{xpos}. + +\pnum +\returns +\tcode{xpos} if the function can determine such a value for \tcode{xpos}. +Otherwise, returns \tcode{npos}. \end{itemdescr} -\indexlibrarymember{operator+=}{basic_string}% +\indexlibrarymember{find_first_not_of}{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string& operator+=(const T& t); +constexpr size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints +Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold: \begin{itemize} \item -\tcode{is_convertible_v>} is -\tcode{true} and +\tcode{pos <= xpos} \item -\tcode{is_convertible_v} is -\tcode{false}. +\tcode{xpos < size()} +\item +\tcode{traits::eq(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum \effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return append(sv); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{operator+=}{basic_string}% -\begin{itemdecl} -constexpr basic_string& operator+=(const charT* s); -\end{itemdecl} +Determines \tcode{xpos}. -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(s);} +\returns +\tcode{xpos} if the function can determine such a value for \tcode{xpos}. Otherwise, returns \tcode{npos}. \end{itemdescr} -\indexlibrarymember{operator+=}{basic_string}% +\indexlibrarymember{find_last_not_of}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator+=(charT c); +constexpr size_type find_last_not_of(basic_string_view str, size_type pos = npos) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{xpos} be the highest position, if possible, such that the following conditions hold: +\begin{itemize} +\item +\tcode{xpos <= pos} +\item +\tcode{xpos < size()} +\item +\tcode{traits::eq(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. +\end{itemize} + \pnum \effects -Equivalent to: \tcode{return append(size_type\{1\}, c);} +Determines \tcode{xpos}. + +\pnum +\returns +\tcode{xpos} if the function can determine such a value for \tcode{xpos}. +Otherwise, returns \tcode{npos}. \end{itemdescr} -\indexlibrarymember{operator+=}{basic_string}% +\rSec2[string.view.deduct]{Deduction guides} + \begin{itemdecl} -constexpr basic_string& operator+=(initializer_list il); +template + basic_string_view(It, End) -> basic_string_view>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(il);} +\constraints +\begin{itemize} +\item \tcode{It} satisfies \libconcept{contiguous_iterator}. +\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}}. +\end{itemize} \end{itemdescr} - -\rSec4[string.append]{\tcode{basic_string::append}} - -\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -constexpr basic_string& append(const basic_string& str); +template + basic_string_view(R&&) -> basic_string_view>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(str.data(), str.size());} +\constraints +\tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}}. \end{itemdescr} -\indexlibrarymember{append}{basic_string}% -\begin{itemdecl} -constexpr basic_string& append(const basic_string& str, size_type pos, size_type n = npos); -\end{itemdecl} +\rSec2[string.view.comparison]{Non-member comparison functions} -\begin{itemdescr} \pnum -\effects -Equivalent to: +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} -return append(basic_string_view(str).substr(pos, n)); +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{itemdescr} +\end{example} -\indexlibrarymember{append}{basic_string}% +\indexlibrarymember{operator==}{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string& append(const T& t); +template + constexpr bool operator==(basic_string_view lhs, + basic_string_view rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} - -\pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return append(sv.data(), sv.size()); -\end{codeblock} +\returns +\tcode{lhs.compare(rhs) == 0}. \end{itemdescr} -\indexlibrarymember{append}{basic_string}% +\indexlibrarymember{operator<=>}{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string& append(const T& t, size_type pos, size_type n = npos); +template + constexpr @\seebelow@ operator<=>(basic_string_view lhs, + @\itcorr@ basic_string_view rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} +Let \tcode{R} denote the type \tcode{traits::comparison_category} if +that \grammarterm{qualified-id} is valid and denotes a type\iref{temp.deduct}, +otherwise \tcode{R} is \tcode{weak_ordering}. \pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return append(sv.substr(pos, n)); -\end{codeblock} +\mandates +\tcode{R} denotes a comparison category type\iref{cmp.categories}. + +\pnum +\returns +\tcode{static_cast(lhs.compare(rhs) <=> 0)}. \end{itemdescr} -\indexlibrarymember{append}{basic_string}% +\rSec2[string.view.io]{Inserters and extractors} + +\indexlibrarymember{operator<<}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& append(const charT* s, size_type n); +template + basic_ostream& + operator<<(basic_ostream& os, basic_string_view str); \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\range{s}{s + n} is a valid range. - \pnum \effects -Appends a copy of the range \range{s}{s + n} to the string. +Behaves as a formatted output +function\iref{ostream.formatted.reqmts} of \tcode{os}. Forms a character sequence +\tcode{seq}, initially consisting of the elements defined by the range +\range{str.begin()}{str.end()}. Determines padding for \tcode{seq} +as described in~\ref{ostream.formatted.reqmts}. +Then inserts \tcode{seq} as if by calling +\tcode{os.rdbuf()->sputn(\brk{}seq, n)}, where \tcode{n} is the larger +of \tcode{os.width()} and \tcode{str.size()}; +then calls \tcode{os.\brk{}width(0)}. \pnum \returns -\tcode{*this}. +\tcode{os} \end{itemdescr} -\indexlibrarymember{append}{basic_string}% +\rSec2[string.view.hash]{Hash support} + +\indexlibrarymember{hash}{string_view}% +\indexlibrarymember{hash}{u8string_view}% +\indexlibrarymember{hash}{u16string_view}% +\indexlibrarymember{hash}{u32string_view}% +\indexlibrarymember{hash}{wstring_view}% \begin{itemdecl} -constexpr basic_string& append(const charT* s); +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(s, traits::length(s));} +The specialization is enabled\iref{unord.hash}. +\begin{note} +The hash value of a string view object is equal to the hash value of +the corresponding string object\iref{basic.string.hash}. +\end{note} \end{itemdescr} -\indexlibrarymember{append}{basic_string}% +\rSec2[string.view.literals]{Suffix for \tcode{basic_string_view} literals} + +\indexlibrarymember{operator""""sv}{string_view}% \begin{itemdecl} -constexpr basic_string& append(size_type n, charT c); +constexpr string_view operator""sv(const char* str, size_t len) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\effects -Appends \tcode{n} copies of \tcode{c} to the string. - \pnum \returns -\tcode{*this}. +\tcode{string_view\{str, len\}}. \end{itemdescr} -\indexlibrarymember{append}{basic_string}% +\indexlibrarymember{operator""""sv}{u8string_view}% \begin{itemdecl} -template - constexpr basic_string& append(InputIterator first, InputIterator last); +constexpr u8string_view operator""sv(const char8_t* str, size_t len) noexcept; \end{itemdecl} - \begin{itemdescr} \pnum -\constraints -\tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. - -\pnum -\effects -Equivalent to: \tcode{return append(basic_string(first, last, get_allocator()));} +\returns +\tcode{u8string_view\{str, len\}}. \end{itemdescr} -\indexlibrarymember{append}{basic_string}% +\indexlibrarymember{operator""""sv}{u16string_view}% \begin{itemdecl} -constexpr basic_string& append(initializer_list il); +constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept; \end{itemdecl} - \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(il.begin(), il.size());} +\returns +\tcode{u16string_view\{str, len\}}. \end{itemdescr} -\indexlibrarymember{push_back}{basic_string}% +\indexlibrarymember{operator""""sv}{u32string_view}% \begin{itemdecl} -constexpr void push_back(charT c); +constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept; \end{itemdecl} - \begin{itemdescr} \pnum -\effects -Equivalent to -\tcode{append(size_type\{1\}, c)}. +\returns +\tcode{u32string_view\{str, len\}}. \end{itemdescr} -\rSec4[string.assign]{\tcode{basic_string::assign}} - -\indexlibrarymember{assign}{basic_string}% +\indexlibrarymember{operator""""sv}{wstring_view}% \begin{itemdecl} -constexpr basic_string& assign(const basic_string& str); +constexpr wstring_view operator""sv(const wchar_t* str, size_t len) noexcept; \end{itemdecl} - \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return *this = str;} +\returns +\tcode{wstring_view\{str, len\}}. \end{itemdescr} -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(basic_string&& str) - noexcept(allocator_traits::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); -\end{itemdecl} +\rSec1[string.classes]{String classes} -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return *this = std::move(str);} -\end{itemdescr} +\rSec2[string.classes.general]{General} +\pnum +The header \tcode{} defines the +\tcode{basic_string} class template for manipulating +varying-length sequences of char-like objects and five +\grammarterm{typedef-name}{s}, \tcode{string}, +\tcode{u8string}, +\tcode{u16string}, +\tcode{u32string}, +and \tcode{wstring}, that name +the specializations +\tcode{basic_string}, +\tcode{basic_string}, +\tcode{basic_string}, +\tcode{basic_string}, +and +\tcode{basic_string<\brk{}wchar_t>}, respectively. -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos); -\end{itemdecl} +\rSec2[string.syn]{Header \tcode{} synopsis} +\indexheader{string}% -\begin{itemdescr} -\pnum -\effects -Equivalent to: \begin{codeblock} -return assign(basic_string_view(str).substr(pos, n)); -\end{codeblock} -\end{itemdescr} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -template - constexpr basic_string& assign(const T& t); -\end{itemdecl} +namespace std { + // \ref{char.traits}, character traits + template struct char_traits; + template<> struct char_traits; + template<> struct char_traits; + template<> struct char_traits; + template<> struct char_traits; + template<> struct char_traits; -\begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} + // \ref{basic.string}, \tcode{basic_string} + template, class Allocator = allocator> + class basic_string; -\pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return assign(sv.data(), sv.size()); -\end{codeblock} -\end{itemdescr} + template + constexpr basic_string + operator+(const basic_string& lhs, + const basic_string& rhs); + template + constexpr basic_string + operator+(basic_string&& lhs, + const basic_string& rhs); + template + constexpr basic_string + operator+(const basic_string& lhs, + basic_string&& rhs); + template + constexpr basic_string + operator+(basic_string&& lhs, + basic_string&& rhs); + template + constexpr basic_string + operator+(const charT* lhs, + const basic_string& rhs); + template + constexpr basic_string + operator+(const charT* lhs, + basic_string&& rhs); + template + constexpr basic_string + operator+(charT lhs, + const basic_string& rhs); + template + constexpr basic_string + operator+(charT lhs, + basic_string&& rhs); + template + constexpr basic_string + operator+(const basic_string& lhs, + const charT* rhs); + template + constexpr basic_string + operator+(basic_string&& lhs, + const charT* rhs); + template + constexpr basic_string + operator+(const basic_string& lhs, + charT rhs); + template + constexpr basic_string + operator+(basic_string&& lhs, + charT rhs); -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -template - constexpr basic_string& assign(const T& t, size_type pos, size_type n = npos); -\end{itemdecl} + template + constexpr bool + operator==(const basic_string& lhs, + const basic_string& rhs) noexcept; + template + constexpr bool operator==(const basic_string& lhs, + const charT* rhs); + + template + constexpr @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const basic_string& rhs) noexcept; + template + constexpr @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const charT* rhs); + + // \ref{string.special}, swap + template + constexpr void + swap(basic_string& lhs, + basic_string& rhs) + noexcept(noexcept(lhs.swap(rhs))); + + // \ref{string.io}, inserters and extractors + template + basic_istream& + operator>>(basic_istream& is, + basic_string& str); + template + basic_ostream& + operator<<(basic_ostream& os, + const basic_string& str); + template + basic_istream& + getline(basic_istream& is, + basic_string& str, + charT delim); + template + basic_istream& + getline(basic_istream&& is, + basic_string& str, + charT delim); + template + basic_istream& + getline(basic_istream& is, + basic_string& str); + template + basic_istream& + getline(basic_istream&& is, + basic_string& str); + + // \ref{string.erasure}, erasure + template + constexpr typename basic_string::size_type + erase(basic_string& c, const U& value); + template + constexpr typename basic_string::size_type + erase_if(basic_string& c, Predicate pred); + + // \tcode{basic_string} \grammarterm{typedef-name}s + using @\libglobal{string}@ = basic_string; + using @\libglobal{u8string}@ = basic_string; + using @\libglobal{u16string}@ = basic_string; + using @\libglobal{u32string}@ = basic_string; + using @\libglobal{wstring}@ = basic_string; + + // \ref{string.conversions}, numeric conversions + int stoi(const string& str, size_t* idx = nullptr, int base = 10); + long stol(const string& str, size_t* idx = nullptr, int base = 10); + unsigned long stoul(const string& str, size_t* idx = nullptr, int base = 10); + long long stoll(const string& str, size_t* idx = nullptr, int base = 10); + unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10); + float stof(const string& str, size_t* idx = nullptr); + double stod(const string& str, size_t* idx = nullptr); + long double stold(const string& str, size_t* idx = nullptr); + string to_string(int val); + string to_string(unsigned val); + string to_string(long val); + string to_string(unsigned long val); + string to_string(long long val); + string to_string(unsigned long long val); + string to_string(float val); + string to_string(double val); + string to_string(long double val); + + int stoi(const wstring& str, size_t* idx = nullptr, int base = 10); + long stol(const wstring& str, size_t* idx = nullptr, int base = 10); + unsigned long stoul(const wstring& str, size_t* idx = nullptr, int base = 10); + long long stoll(const wstring& str, size_t* idx = nullptr, int base = 10); + unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10); + float stof(const wstring& str, size_t* idx = nullptr); + double stod(const wstring& str, size_t* idx = nullptr); + long double stold(const wstring& str, size_t* idx = nullptr); + wstring to_wstring(int val); + wstring to_wstring(unsigned val); + wstring to_wstring(long val); + wstring to_wstring(unsigned long val); + wstring to_wstring(long long val); + wstring to_wstring(unsigned long long val); + wstring to_wstring(float val); + wstring to_wstring(double val); + wstring to_wstring(long double val); + + namespace pmr { + template> + using basic_string = std::basic_string>; + + using string = basic_string; + using u8string = basic_string; + using u16string = basic_string; + using u32string = basic_string; + using wstring = basic_string; + } + + // \ref{basic.string.hash}, hash support + template struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + + 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); + } + } +} +\end{codeblock} + +\rSec2[basic.string]{Class template \tcode{basic_string}} + +\rSec3[basic.string.general]{General} + +\pnum +\indexlibraryglobal{basic_string}% +The +class template +\tcode{basic_string} +describes objects that can store a sequence consisting of a varying number of +arbitrary char-like objects with the first element of the sequence at position zero. +Such a sequence is also called a ``string'' if the type of the +char-like objects that it holds +is clear from context. +In the rest of \ref{basic.string}, +the type of the char-like objects held in a \tcode{basic_string} object +is designated by \tcode{charT}. + +\pnum +A specialization of \tcode{basic_string} is a contiguous container\iref{container.requirements.general}. + +\pnum +In all cases, +\crange{data()}{data() + size()} is a valid range, +\tcode{data() + size()} points at an object with value \tcode{charT()} +(a ``null terminator''\indextext{string!null terminator}), +and \tcode{size() <= capacity()} is \tcode{true}. + + +\indexlibraryglobal{basic_string}% +\indexlibrarymember{traits_type}{basic_string}% +\indexlibrarymember{value_type}{basic_string}% +\indexlibrarymember{allocator_type}{basic_string}% +\indexlibrarymember{size_type}{basic_string}% +\indexlibrarymember{difference_type}{basic_string}% +\indexlibrarymember{pointer}{basic_string}% +\indexlibrarymember{const_pointer}{basic_string}% +\indexlibrarymember{reference}{basic_string}% +\indexlibrarymember{const_reference}{basic_string}% +\indexlibrarymember{iterator}{basic_string}% +\indexlibrarymember{const_iterator}{basic_string}% +\indexlibrarymember{reverse_iterator}{basic_string}% +\indexlibrarymember{const_reverse_iterator}{basic_string}% +\begin{codeblock} +namespace std { + template, + class Allocator = allocator> + class basic_string { + public: + // types + using traits_type = traits; + using value_type = charT; + using allocator_type = Allocator; + using size_type = typename allocator_traits::size_type; + using difference_type = typename allocator_traits::difference_type; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + + using iterator = @\impdefx{type of \tcode{basic_string::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{basic_string::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + static constexpr size_type npos = size_type(-1); + + // \ref{string.cons}, construct/copy/destroy + constexpr basic_string() noexcept(noexcept(Allocator())) : basic_string(Allocator()) { } + constexpr explicit basic_string(const Allocator& a) noexcept; + constexpr basic_string(const basic_string& str); + constexpr basic_string(basic_string&& str) noexcept; + constexpr basic_string(const basic_string& str, size_type pos, + const Allocator& a = Allocator()); + constexpr basic_string(const basic_string& str, size_type pos, size_type n, + const Allocator& a = Allocator()); + template + constexpr basic_string(const T& t, size_type pos, size_type n, + const Allocator& a = Allocator()); + template + constexpr explicit basic_string(const T& t, const Allocator& a = Allocator()); + constexpr basic_string(const charT* s, size_type n, const Allocator& a = Allocator()); + constexpr basic_string(const charT* s, const Allocator& a = Allocator()); + basic_string(nullptr_t) = delete; + constexpr basic_string(size_type n, charT c, const Allocator& a = Allocator()); + template + constexpr basic_string(InputIterator begin, InputIterator end, + const Allocator& a = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator()); + constexpr basic_string(initializer_list, const Allocator& = Allocator()); + constexpr basic_string(const basic_string&, const Allocator&); + constexpr basic_string(basic_string&&, const Allocator&); + constexpr ~basic_string(); + + constexpr basic_string& operator=(const basic_string& str); + constexpr basic_string& operator=(basic_string&& str) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); + template + constexpr basic_string& operator=(const T& t); + constexpr basic_string& operator=(const charT* s); + basic_string& operator=(nullptr_t) = delete; + constexpr basic_string& operator=(charT c); + constexpr basic_string& operator=(initializer_list); + + // \ref{string.iterators}, iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; + + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // \ref{string.capacity}, capacity + constexpr size_type size() const noexcept; + constexpr size_type length() const noexcept; + constexpr size_type max_size() const noexcept; + constexpr void resize(size_type n, charT c); + constexpr void resize(size_type n); + template constexpr void resize_and_overwrite(size_type n, Operation op); + constexpr size_type capacity() const noexcept; + constexpr void reserve(size_type res_arg); + constexpr void shrink_to_fit(); + constexpr void clear() noexcept; + [[nodiscard]] constexpr bool empty() const noexcept; + + // \ref{string.access}, element access + constexpr const_reference operator[](size_type pos) const; + constexpr reference operator[](size_type pos); + constexpr const_reference at(size_type n) const; + constexpr reference at(size_type n); + + constexpr const charT& front() const; + constexpr charT& front(); + constexpr const charT& back() const; + constexpr charT& back(); + + // \ref{string.modifiers}, modifiers + constexpr basic_string& operator+=(const basic_string& str); + template + constexpr basic_string& operator+=(const T& t); + constexpr basic_string& operator+=(const charT* s); + constexpr basic_string& operator+=(charT c); + constexpr basic_string& operator+=(initializer_list); + constexpr basic_string& append(const basic_string& str); + constexpr basic_string& append(const basic_string& str, size_type pos, size_type n = npos); + template + constexpr basic_string& append(const T& t); + template + constexpr basic_string& append(const T& t, size_type pos, size_type n = npos); + constexpr basic_string& append(const charT* s, size_type n); + constexpr basic_string& append(const charT* s); + constexpr basic_string& append(size_type n, charT c); + template + constexpr basic_string& append(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& append_range(R&& rg); + constexpr basic_string& append(initializer_list); + + constexpr void push_back(charT c); + + constexpr basic_string& assign(const basic_string& str); + constexpr basic_string& assign(basic_string&& str) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); + constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos); + template + constexpr basic_string& assign(const T& t); + template + constexpr basic_string& assign(const T& t, size_type pos, size_type n = npos); + constexpr basic_string& assign(const charT* s, size_type n); + constexpr basic_string& assign(const charT* s); + constexpr basic_string& assign(size_type n, charT c); + template + constexpr basic_string& assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& assign_range(R&& rg); + constexpr basic_string& assign(initializer_list); + + constexpr basic_string& insert(size_type pos, const basic_string& str); + constexpr basic_string& insert(size_type pos1, const basic_string& str, + size_type pos2, size_type n = npos); + template + constexpr basic_string& insert(size_type pos, const T& t); + template + constexpr basic_string& insert(size_type pos1, const T& t, + size_type pos2, size_type n = npos); + constexpr basic_string& insert(size_type pos, const charT* s, size_type n); + constexpr basic_string& insert(size_type pos, const charT* s); + constexpr basic_string& insert(size_type pos, size_type n, charT c); + constexpr iterator insert(const_iterator p, charT c); + constexpr iterator insert(const_iterator p, size_type n, charT c); + template + constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator p, R&& rg); + constexpr iterator insert(const_iterator p, initializer_list); + + constexpr basic_string& erase(size_type pos = 0, size_type n = npos); + constexpr iterator erase(const_iterator p); + constexpr iterator erase(const_iterator first, const_iterator last); + + constexpr void pop_back(); + + constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str); + constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str, + size_type pos2, size_type n2 = npos); + template + constexpr basic_string& replace(size_type pos1, size_type n1, const T& t); + template + constexpr basic_string& replace(size_type pos1, size_type n1, const T& t, + size_type pos2, size_type n2 = npos); + constexpr basic_string& replace(size_type pos, size_type n1, const charT* s, size_type n2); + constexpr basic_string& replace(size_type pos, size_type n1, const charT* s); + constexpr basic_string& replace(size_type pos, size_type n1, size_type n2, charT c); + constexpr basic_string& replace(const_iterator i1, const_iterator i2, + const basic_string& str); + template + constexpr basic_string& replace(const_iterator i1, const_iterator i2, const T& t); + constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s, + size_type n); + constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s); + constexpr basic_string& replace(const_iterator i1, const_iterator i2, size_type n, charT c); + template + constexpr basic_string& replace(const_iterator i1, const_iterator i2, + InputIterator j1, InputIterator j2); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); + constexpr basic_string& replace(const_iterator, const_iterator, initializer_list); + + constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; + + constexpr void swap(basic_string& str) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); + + // \ref{string.ops}, string operations + constexpr const charT* c_str() const noexcept; + constexpr const charT* data() const noexcept; + constexpr charT* data() noexcept; + constexpr operator basic_string_view() const noexcept; + constexpr allocator_type get_allocator() const noexcept; + + template + constexpr size_type find(const T& t, size_type pos = 0) const noexcept(@\seebelow@); + constexpr size_type find(const basic_string& str, size_type pos = 0) const noexcept; + constexpr size_type find(const charT* s, size_type pos, size_type n) const; + constexpr size_type find(const charT* s, size_type pos = 0) const; + constexpr size_type find(charT c, size_type pos = 0) const noexcept; + template + constexpr size_type rfind(const T& t, size_type pos = npos) const noexcept(@\seebelow@); + constexpr size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; + constexpr size_type rfind(const charT* s, size_type pos, size_type n) const; + constexpr size_type rfind(const charT* s, size_type pos = npos) const; + constexpr size_type rfind(charT c, size_type pos = npos) const noexcept; + + template + constexpr size_type find_first_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@); + constexpr size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; + constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const; + constexpr size_type find_first_of(const charT* s, size_type pos = 0) const; + constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept; + template + constexpr size_type find_last_of(const T& t, + size_type pos = npos) const noexcept(@\seebelow@); + constexpr size_type find_last_of(const basic_string& str, + size_type pos = npos) const noexcept; + constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const; + constexpr size_type find_last_of(const charT* s, size_type pos = npos) const; + constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept; + + template + constexpr size_type find_first_not_of(const T& t, + size_type pos = 0) const noexcept(@\seebelow@); + constexpr size_type find_first_not_of(const basic_string& str, + size_type pos = 0) const noexcept; + constexpr size_type find_first_not_of(const charT* s, size_type pos, size_type n) const; + constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const; + constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept; + template + constexpr size_type find_last_not_of(const T& t, + size_type pos = npos) const noexcept(@\seebelow@); + constexpr size_type find_last_not_of(const basic_string& str, + size_type pos = npos) const noexcept; + constexpr size_type find_last_not_of(const charT* s, size_type pos, size_type n) const; + constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const; + constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept; + + constexpr basic_string substr(size_type pos = 0, size_type n = npos) const; + + template + constexpr int compare(const T& t) const noexcept(@\seebelow@); + template + constexpr int compare(size_type pos1, size_type n1, const T& t) const; + template + constexpr int compare(size_type pos1, size_type n1, const T& t, + size_type pos2, size_type n2 = npos) const; + constexpr int compare(const basic_string& str) const noexcept; + constexpr int compare(size_type pos1, size_type n1, const basic_string& str) const; + constexpr int compare(size_type pos1, size_type n1, const basic_string& str, + size_type pos2, size_type n2 = npos) const; + constexpr int compare(const charT* s) const; + constexpr int compare(size_type pos1, size_type n1, const charT* s) const; + constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; + + constexpr bool starts_with(basic_string_view x) const noexcept; + constexpr bool starts_with(charT x) const noexcept; + constexpr bool starts_with(const charT* x) const; + constexpr bool ends_with(basic_string_view x) const noexcept; + constexpr bool ends_with(charT x) const noexcept; + constexpr bool ends_with(const charT* x) const; + + constexpr bool contains(basic_string_view x) const noexcept; + constexpr bool contains(charT x) const noexcept; + constexpr bool contains(const charT* x) const; + }; + + template::value_type>> + basic_string(InputIterator, InputIterator, Allocator = Allocator()) + -> basic_string::value_type, + char_traits::value_type>, + Allocator>; + + template>> + basic_string(from_range_t, R&&, Allocator = Allocator()) + -> basic_string, char_traits>, + Allocator>; + + template> + explicit basic_string(basic_string_view, const Allocator& = Allocator()) + -> basic_string; + + template> + basic_string(basic_string_view, + typename @\seebelow@::size_type, typename @\seebelow@::size_type, + const Allocator& = Allocator()) + -> basic_string; +} +\end{codeblock} -\begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} +A \tcode{size_type} parameter type in +a \tcode{basic_string} deduction guide +refers to the \tcode{size_type} member type of +the type deduced by the deduction guide. \pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return assign(sv.substr(pos, n)); -\end{codeblock} -\end{itemdescr} +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(const charT* s, size_type n); -\end{itemdecl} +\rSec3[string.require]{General requirements} -\begin{itemdescr} \pnum -\expects -\range{s}{s + n} is a valid range. +If any operation would cause \tcode{size()} to +exceed \tcode{max_size()}, that operation throws an +exception object of type \tcode{length_error}. \pnum -\effects -Replaces the string controlled by \tcode{*this} with -a copy of the range \range{s}{s + n}. +If any member function or operator of \tcode{basic_string} throws an exception, that +function or operator has no other effect on the \tcode{basic_string} object. \pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(const charT* s); -\end{itemdecl} +In every specialization \tcode{basic_string}, +the type \tcode{allocator_traits::value_type} shall name the same type +as \tcode{charT}. Every object of type +\tcode{basic_string} uses an object of type +\tcode{Allocator} to allocate and free storage for the contained \tcode{charT} +objects as needed. The \tcode{Allocator} object used is +obtained as described in \ref{container.requirements.general}. +In every specialization \tcode{basic_string}, +the type \tcode{traits} shall meet +the character traits requirements\iref{char.traits}. +\begin{note} +Every specialization \tcode{basic_string} is +an allocator-aware container, +but does not use the allocator's \tcode{construct} and \tcode{destroy} +member functions\iref{container.requirements.general}. +\end{note} +\begin{note} +The program is ill-formed if \tcode{traits::char_type} +is not the same type as \tcode{charT}. +\end{note} -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return assign(s, traits::length(s));} -\end{itemdescr} - -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(initializer_list il); -\end{itemdecl} +References, pointers, and iterators referring to the elements of a +\tcode{basic_string} sequence may be +invalidated by the following uses of that \tcode{basic_string} object: -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return assign(il.begin(), il.size());} -\end{itemdescr} +\begin{itemize} +\item Passing as an argument to any standard library function taking a reference to non-const +\tcode{basic_string} as an argument. +\begin{footnote} +For example, as an argument to non-member +functions \tcode{swap()}\iref{string.special}, +\tcode{operator>{}>()}\iref{string.io}, and \tcode{getline()}\iref{string.io}, or as +an argument to \tcode{basic_string::swap()}. +\end{footnote} -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(size_type n, charT c); -\end{itemdecl} +\item Calling non-const member functions, except +\tcode{operator[]}, +\tcode{at}, +\tcode{data}, +\tcode{front}, +\tcode{back}, +\tcode{begin}, +\tcode{rbegin}, +\tcode{end}, +and +\tcode{rend}. +\end{itemize} -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -clear(); -resize(n, c); -return *this; -\end{codeblock} -\end{itemdescr} +\rSec3[string.cons]{Constructors and assignment operators} -\indexlibrarymember{assign}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -template - constexpr basic_string& assign(InputIterator first, InputIterator last); +constexpr explicit basic_string(const Allocator& a) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. \pnum -\effects -Equivalent to: \tcode{return assign(basic_string(first, last, get_allocator()));} +\ensures +\tcode{size()} is equal to \tcode{0}. \end{itemdescr} -\rSec4[string.insert]{\tcode{basic_string::insert}} - -\indexlibrarymember{insert}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr basic_string& insert(size_type pos, const basic_string& str); +constexpr basic_string(const basic_string& str); +constexpr basic_string(basic_string&& str) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return insert(pos, str.data(), str.size());} +Constructs an object whose +value is that of \tcode{str} prior to this call. + +\pnum +\remarks +In the second form, \tcode{str} is left in a valid but unspecified state. \end{itemdescr} -\indexlibrarymember{insert}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr basic_string& insert(size_type pos1, const basic_string& str, - size_type pos2, size_type n = npos); +constexpr basic_string(const basic_string& str, size_type pos, + const Allocator& a = Allocator()); +constexpr basic_string(const basic_string& str, size_type pos, size_type n, + const Allocator& a = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: +Let \tcode{n} be \tcode{npos} for the first overload. Equivalent to: \begin{codeblock} -return insert(pos1, basic_string_view(str), pos2, n); +basic_string(basic_string_view(str).substr(pos, n), a) \end{codeblock} \end{itemdescr} -\indexlibrarymember{insert}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} template - constexpr basic_string& insert(size_type pos, const T& t); + constexpr basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} +\tcode{is_convertible_v>} +is \tcode{true}. \pnum \effects -Equivalent to: +Creates a variable, \tcode{sv}, +as if by \tcode{basic_string_view sv = t;} +and then behaves the same as: \begin{codeblock} -basic_string_view sv = t; -return insert(pos, sv.data(), sv.size()); +basic_string(sv.substr(pos, n), a); \end{codeblock} \end{itemdescr} -\indexlibrarymember{insert}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} template - constexpr basic_string& insert(size_type pos1, const T& t, - size_type pos2, size_type n = npos); + constexpr explicit basic_string(const T& t, const Allocator& a = Allocator()); \end{itemdecl} \begin{itemdescr} @@ -2339,125 +2509,75 @@ \tcode{false}. \end{itemize} -\pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return insert(pos1, sv.substr(pos2, n)); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{insert}{basic_string}% -\begin{itemdecl} -constexpr basic_string& insert(size_type pos, const charT* s, size_type n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\range{s}{s + n} is a valid range. - -\pnum -\effects -Inserts a copy of the range \range{s}{s + n} -immediately before the character at position \tcode{pos} if \tcode{pos < size()}, -or otherwise at the end of the string. - -\pnum -\returns -\tcode{*this}. - -\pnum -\throws -\begin{itemize} -\item \tcode{out_of_range} if \tcode{pos > size()}, -\item \tcode{length_error} if \tcode{n > max_size() - size()}, or -\item any exceptions thrown by \tcode{allocator_traits::allocate}. -\end{itemize} -\end{itemdescr} - -\indexlibrarymember{insert}{basic_string}% -\begin{itemdecl} -constexpr basic_string& insert(size_type pos, const charT* s); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return insert(pos, s, traits::length(s));} -\end{itemdescr} - -\indexlibrarymember{insert}{basic_string}% -\begin{itemdecl} -constexpr basic_string& insert(size_type pos, size_type n, charT c); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Inserts \tcode{n} copies of \tcode{c} before the character at position \tcode{pos} -if \tcode{pos < size()}, -or otherwise at the end of the string. - -\pnum -\returns -\tcode{*this} - -\pnum -\throws -\begin{itemize} -\item \tcode{out_of_range} if \tcode{pos > size()}, -\item \tcode{length_error} if \tcode{n > max_size() - size()}, or -\item any exceptions thrown by \tcode{allocator_traits::allocate}. -\end{itemize} +\pnum +\effects +Creates a variable, \tcode{sv}, as if by +\tcode{basic_string_view sv = t;} and +then behaves the same as \tcode{basic_string(sv.data(), sv.size(), a)}. \end{itemdescr} -\indexlibrarymember{insert}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr iterator insert(const_iterator p, charT c); +constexpr basic_string(const charT* s, size_type n, const Allocator& a = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{p} is a valid iterator on -\tcode{*this}. +\range{s}{s + n} is a valid range. \pnum \effects -Inserts a copy of \tcode{c} at the position \tcode{p}. +Constructs an object whose initial value is the range \range{s}{s + n}. \pnum -\returns -An iterator which refers to the inserted character. +\ensures +\tcode{size()} is equal to \tcode{n}, and +\tcode{traits::compare(data(), s, n)} is equal to \tcode{0}. \end{itemdescr} -\indexlibrarymember{insert}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr iterator insert(const_iterator p, size_type n, charT c); +constexpr basic_string(const charT* s, const Allocator& a = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{p} is a valid iterator on -\tcode{*this}. +\constraints +\tcode{Allocator} is a type +that qualifies as an allocator\iref{container.requirements.general}. +\begin{note} +This affects class template argument deduction. +\end{note} \pnum \effects -Inserts \tcode{n} copies of \tcode{c} at the position \tcode{p}. +Equivalent to: \tcode{basic_string(s, traits::length(s), a)}. +\end{itemdescr} + +\indexlibraryctor{basic_string}% +\begin{itemdecl} +constexpr basic_string(size_type n, charT c, const Allocator& a = Allocator()); +\end{itemdecl} +\begin{itemdescr} \pnum -\returns -An iterator which refers to the first inserted character, or -\tcode{p} if \tcode{n == 0}. +\constraints +\tcode{Allocator} is a type +that qualifies as an allocator\iref{container.requirements.general}. +\begin{note} +This affects class template argument deduction. +\end{note} + +\pnum +\effects +Constructs an object whose value consists of \tcode{n} copies of \tcode{c}. \end{itemdescr} -\indexlibrarymember{insert}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} template - constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); + constexpr basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator()); \end{itemdecl} \begin{itemdescr} @@ -2466,437 +2586,496 @@ \tcode{InputIterator} is a type that qualifies as an input iterator\iref{container.requirements.general}. -\pnum -\expects -\tcode{p} is a valid iterator on -\tcode{*this}. - \pnum \effects -Equivalent to -\tcode{insert(p - begin(), basic_string(first, last, get_allocator()))}. - -\pnum -\returns -An iterator which refers to the first inserted character, or -\tcode{p} if \tcode{first == last}. +Constructs a string from the values in the range \range{begin}{end}, +as specified in \ref{sequence.reqmts}. \end{itemdescr} -\indexlibrarymember{insert}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr iterator insert(const_iterator p, initializer_list il); +template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string(from_range_t, R&& rg, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return insert(p, il.begin(), il.end());} +Constructs a string from the values in the range \tcode{rg}, +as specified in \ref{sequence.reqmts}. \end{itemdescr} -\rSec4[string.erase]{\tcode{basic_string::erase}} - -\indexlibrarymember{erase}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr basic_string& erase(size_type pos = 0, size_type n = npos); +constexpr basic_string(initializer_list il, const Allocator& a = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Determines the effective length \tcode{xlen} -of the string to be removed as the smaller of \tcode{n} and -\tcode{size() - pos}. -Removes the characters in the range \range{begin() + pos}{begin() + pos + xlen}. +Equivalent to \tcode{basic_string(il.begin(), il.end(), a)}. +\end{itemdescr} + +\indexlibraryctor{basic_string}% +\begin{itemdecl} +constexpr basic_string(const basic_string& str, const Allocator& alloc); +constexpr basic_string(basic_string&& str, const Allocator& alloc); +\end{itemdecl} +\begin{itemdescr} \pnum -\returns -\tcode{*this}. +\effects +Constructs an object whose value is +that of \tcode{str} prior to this call. +The stored allocator is constructed from \tcode{alloc}. +In the second form, \tcode{str} is left in a valid but unspecified state. \pnum \throws -\tcode{out_of_range} -if \tcode{pos} -\tcode{> size()}. +The second form throws nothing if \tcode{alloc == str.get_allocator()}. \end{itemdescr} -\indexlibrarymember{erase}{basic_string}% \begin{itemdecl} -constexpr iterator erase(const_iterator p); +template::value_type>> + basic_string(InputIterator, InputIterator, Allocator = Allocator()) + -> basic_string::value_type, + char_traits::value_type>, + Allocator>; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{p} is a valid dereferenceable iterator on \tcode{*this}. +\constraints +\tcode{InputIterator} is a type that qualifies as an input iterator, +and \tcode{Allocator} is a type that qualifies as an allocator\iref{container.requirements.general}. +\end{itemdescr} -\pnum -\effects -Removes the character referred to by \tcode{p}. +\begin{itemdecl} +template> + explicit basic_string(basic_string_view, const Allocator& = Allocator()) + -> basic_string; -\pnum -\returns -An iterator which points to the element immediately following \tcode{p} prior to -the element being erased. -If no such element exists, -\tcode{end()} -is returned. +template> + basic_string(basic_string_view, + typename @\seebelow@::size_type, typename @\seebelow@::size_type, + const Allocator& = Allocator()) + -> basic_string; +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -Nothing. +\constraints +\tcode{Allocator} is a type that qualifies as +an allocator\iref{container.requirements.general}. \end{itemdescr} -\indexlibrarymember{erase}{basic_string}% +\indexlibrarymember{operator=}{basic_string}% \begin{itemdecl} -constexpr iterator erase(const_iterator first, const_iterator last); +constexpr basic_string& operator=(const basic_string& str); \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{first} and \tcode{last} are valid iterators on -\tcode{*this}. \range{first}{last} is a valid range. - \pnum \effects -Removes the characters in the range -\tcode{[first, last)}. +If \tcode{*this} and \tcode{str} are the same object, has no effect. +Otherwise, replaces the value of \tcode{*this} with a copy of \tcode{str}. \pnum \returns -An iterator which points to the element pointed to by \tcode{last} prior to -the other elements being erased. -If no such element exists, -\tcode{end()} -is returned. - -\pnum -\throws -Nothing. +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{pop_back}{basic_string}% +\indexlibrarymember{operator=}{basic_string}% \begin{itemdecl} -constexpr void pop_back(); +constexpr basic_string& operator=(basic_string&& str) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{!empty()}. - \pnum \effects -Equivalent to \tcode{erase(end() - 1)}. +Move assigns as a sequence container\iref{container.requirements}, +except that iterators, pointers and references may be invalidated. \pnum -\throws -Nothing. +\returns +\tcode{*this}. \end{itemdescr} -\rSec4[string.replace]{\tcode{basic_string::replace}} - -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{operator=}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str); +template + constexpr basic_string& operator=(const T& t); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{is_convertible_v>} +is \tcode{true} and +\item \tcode{is_convertible_v} +is \tcode{false}. +\end{itemize} + \pnum \effects -Equivalent to: \tcode{return replace(pos1, n1, str.data(), str.size());} +Equivalent to: +\begin{codeblock} +basic_string_view sv = t; +return assign(sv); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{operator=}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str, - size_type pos2, size_type n2 = npos); +constexpr basic_string& operator=(const charT* s); \end{itemdecl} \begin{itemdescr} \pnum \effects Equivalent to: -\begin{codeblock} -return replace(pos1, n1, basic_string_view(str).substr(pos2, n2)); -\end{codeblock} +\tcode{return *this = basic_string_view(s);} \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{operator=}{basic_string}% \begin{itemdecl} -template - constexpr basic_string& replace(size_type pos1, size_type n1, const T& t); +constexpr basic_string& operator=(charT c); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} - \pnum \effects Equivalent to: \begin{codeblock} -basic_string_view sv = t; -return replace(pos1, n1, sv.data(), sv.size()); +return *this = basic_string_view(addressof(c), 1); \end{codeblock} \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{operator=}{basic_string}% \begin{itemdecl} -template - constexpr basic_string& replace(size_type pos1, size_type n1, const T& t, - size_type pos2, size_type n2 = npos); +constexpr basic_string& operator=(initializer_list il); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} - \pnum \effects Equivalent to: \begin{codeblock} -basic_string_view sv = t; -return replace(pos1, n1, sv.substr(pos2, n2)); +return *this = basic_string_view(il.begin(), il.size()); \end{codeblock} \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\rSec3[string.iterators]{Iterator support} + +\indexlibrarymember{begin}{basic_string}% +\indexlibrarymember{cbegin}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(size_type pos1, size_type n1, const charT* s, size_type n2); +constexpr iterator begin() noexcept; +constexpr const_iterator begin() const noexcept; +constexpr const_iterator cbegin() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\range{s}{s + n2} is a valid range. +\returns +An iterator referring to the first character in the string. +\end{itemdescr} -\pnum -\effects -Determines the effective length \tcode{xlen} of the string to be -removed as the smaller of \tcode{n1} and \tcode{size() - pos1}. If -\tcode{size() - xlen >= max_size() - n2} throws \tcode{length_error}. Otherwise, -the function replaces the characters in the range -\range{begin() + pos1}{begin() + pos1 + xlen} -with a copy of the range \range{s}{s + n2}. +\indexlibrarymember{end}{basic_string}% +\indexlibrarymember{cend}{basic_string}% +\begin{itemdecl} +constexpr iterator end() noexcept; +constexpr const_iterator end() const noexcept; +constexpr const_iterator cend() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{*this}. +An iterator which is the past-the-end value. +\end{itemdescr} + +\indexlibrarymember{rbegin}{basic_string}% +\indexlibrarymember{crbegin}{basic_string}% +\begin{itemdecl} +constexpr reverse_iterator rbegin() noexcept; +constexpr const_reverse_iterator rbegin() const noexcept; +constexpr const_reverse_iterator crbegin() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -\begin{itemize} -\item \tcode{out_of_range} if \tcode{pos1 > size()}, -\item \tcode{length_error} if the length of the resulting string -would exceed \tcode{max_size()}, or -\item any exceptions thrown by \tcode{allocator_traits::allocate}. -\end{itemize} +\returns +An iterator which is semantically equivalent to +\tcode{reverse_iterator(end())}. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{rend}{basic_string}% +\indexlibrarymember{crend}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(size_type pos, size_type n, const charT* s); +constexpr reverse_iterator rend() noexcept; +constexpr const_reverse_iterator rend() const noexcept; +constexpr const_reverse_iterator crend() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return replace(pos, n, s, traits::length(s));} +\returns +An iterator which is semantically equivalent to +\tcode{reverse_iterator(begin())}. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\rSec3[string.capacity]{Capacity} + +\indexlibrarymember{size}{basic_string}% +\indexlibrarymember{length}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(size_type pos1, size_type n1, size_type n2, charT c); +constexpr size_type size() const noexcept; +constexpr size_type length() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Determines the effective length \tcode{xlen} of the string to be -removed as the smaller of \tcode{n1} and \tcode{size() - pos1}. If -\tcode{size() - xlen >=} \tcode{max_size() - n2} throws \tcode{length_error}. Otherwise, -the function replaces the characters in the range -\range{begin() + pos1}{begin() + pos1 + xlen} -with \tcode{n2} copies of \tcode{c}. +\returns +A count of the number of char-like objects currently in the string. + +\pnum +\complexity +Constant time. +\end{itemdescr} + +\indexlibrarymember{max_size}{basic_string}% +\begin{itemdecl} +constexpr size_type max_size() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{*this}. +The largest possible number of char-like objects that can be stored in a +\tcode{basic_string}. \pnum -\throws +\complexity +Constant time. +\end{itemdescr} + +\indexlibrarymember{resize}{basic_string}% +\begin{itemdecl} +constexpr void resize(size_type n, charT c); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Alters the value of +\tcode{*this} +as follows: \begin{itemize} -\item \tcode{out_of_range} if \tcode{pos1 > size()}, -\item \tcode{length_error} if the length of the resulting string -would exceed\tcode{max_size()}, or -\item any exceptions thrown by \tcode{allocator_traits::allocate.} +\item +If +\tcode{n <= size()}, +erases the last \tcode{size() - n} elements. +\item +If +\tcode{n > size()}, +appends \tcode{n - size()} copies of \tcode{c}. \end{itemize} \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{resize}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str); +constexpr void resize(size_type n); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return replace(i1, i2, basic_string_view(str));} +Equivalent to \tcode{resize(n, charT())}. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{resize_and_overwrite}{basic_string}% \begin{itemdecl} -template - constexpr basic_string& replace(const_iterator i1, const_iterator i2, const T& t); +template constexpr void resize_and_overwrite(size_type n, Operation op); \end{itemdecl} \begin{itemdescr} \pnum -\constraints +Let \begin{itemize} \item -\tcode{is_convertible_v>} is -\tcode{true} and +\tcode{o = size()} before the call to \tcode{resize_and_overwrite}. \item -\tcode{is_convertible_v} is -\tcode{false}. +\tcode{k} be \tcode{min(o, n)}. +\item +\tcode{p} be a \tcode{charT*}, +such that the range \crange{p}{p + n} is valid and +\tcode{this->compare(0, k, p, k) == 0} is \tcode{true} before the call. +The values in the range \crange{p + k}{p + n} may be indeterminate\iref{basic.indet}. +\item +$OP$ be the expression \tcode{std::move(op)(p, n)}. +\item +\tcode{r} = $OP$. \end{itemize} +\pnum +\mandates +$OP$ has an integer-like type\iref{iterator.concept.winc}. + \pnum \expects -\range{begin()}{i1} and \range{i1}{i2} are valid ranges. +\begin{itemize} +\item +$OP$ does not throw an exception or modify \tcode{p} or \tcode{n}. +\item +$\tcode{r} \geq 0$. +\item +$\tcode{r} \leq \tcode{n}$. +\item +After evaluating $OP$ +there are no indeterminate values in the range \range{p}{p + r}. +\end{itemize} \pnum \effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return replace(i1 - begin(), i2 - i1, sv.data(), sv.size()); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{replace}{basic_string}% -\begin{itemdecl} -constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s, size_type n); -\end{itemdecl} +Evaluates $OP$, +replaces the contents of \tcode{*this} with \range{p}{p + r}, and +invalidates all pointers and references to the range \crange{p}{p + n}. -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return replace(i1, i2, basic_string_view(s, n));} +\recommended +Implementations should avoid unnecessary copies and allocations +by, for example, making \tcode{p} a pointer into internal storage and +by restoring \tcode{*(p + r)} to \tcode{charT()} after evaluating $OP$. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{capacity}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s); +constexpr size_type capacity() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return replace(i1, i2, basic_string_view(s));} +\returns +The size of the allocated storage in the string. + +\pnum +\complexity +Constant time. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{reserve}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(const_iterator i1, const_iterator i2, size_type n, charT c); +constexpr void reserve(size_type res_arg); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\range{begin()}{i1} and \range{i1}{i2} are valid ranges. +\effects +A directive that informs a \tcode{basic_string} of a planned change in size, +so that the storage allocation can be managed accordingly. +After +\tcode{reserve()}, +\tcode{capacity()} +is greater or equal to the argument of +\tcode{reserve} +if reallocation happens; and +equal to the previous value of +\tcode{capacity()} +otherwise. +Reallocation happens at this point if and only if +the current capacity is less than the argument of \tcode{reserve()}. \pnum -\effects -Equivalent to: \tcode{return replace(i1 - begin(), i2 - i1, n, c);} +\throws +\tcode{length_error} +if +\tcode{res_arg > max_size()} or any exceptions thrown by +\tcode{allocator_traits} \tcode{::allocate}. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{shrink_to_fit}{basic_string}% \begin{itemdecl} -template - constexpr basic_string& replace(const_iterator i1, const_iterator i2, - InputIterator j1, InputIterator j2); +constexpr void shrink_to_fit(); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. +\effects +\tcode{shrink_to_fit} is a non-binding request to reduce +\tcode{capacity()} to \tcode{size()}. +\begin{note} +The request is non-binding to +allow latitude for implementation-specific optimizations. +\end{note} +It does not increase \tcode{capacity()}, but may reduce \tcode{capacity()} +by causing reallocation. \pnum -\effects -Equivalent to: \tcode{return replace(i1, i2, basic_string(j1, j2, get_allocator()));} +\complexity +If the size is not equal to the old capacity, +linear in the size of the sequence; +otherwise constant. + +\pnum +\remarks +Reallocation invalidates all the references, pointers, and iterators +referring to the elements in the sequence, as well as the past-the-end iterator. +\begin{note} +If no reallocation happens, they remain valid. +\end{note} \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{clear}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(const_iterator i1, const_iterator i2, initializer_list il); +constexpr void clear() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return replace(i1, i2, il.begin(), il.size());} +Equivalent to: \tcode{erase(begin(), end());} \end{itemdescr} -\rSec4[string.copy]{\tcode{basic_string::copy}} - -\indexlibrarymember{copy}{basic_string}% +\indexlibrarymember{empty}{basic_string}% \begin{itemdecl} -constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; +[[nodiscard]] constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects Equivalent to: -\tcode{return basic_string_view(*this).copy(s, n, pos);} -\begin{note} -This does not terminate \tcode{s} with a null object. -\end{note} +\tcode{return size() == 0;} \end{itemdescr} -\rSec4[string.swap]{\tcode{basic_string::swap}} +\rSec3[string.access]{Element access} -\indexlibrarymember{swap}{basic_string}% +\indexlibrarymember{operator[]}{basic_string}% \begin{itemdecl} -constexpr void swap(basic_string& s) - noexcept(allocator_traits::propagate_on_container_swap::value || - allocator_traits::is_always_equal::value); +constexpr const_reference operator[](size_type pos) const; +constexpr reference operator[](size_type pos); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{allocator_traits::propagate_on_container_swap::value} is \tcode{true} -or -\tcode{get_allocator() == s.get_allocator()}. +\tcode{pos <= size()}. \pnum -\ensures -\tcode{*this} -contains the same sequence of characters that was in \tcode{s}, -\tcode{s} contains the same sequence of characters that was in -\tcode{*this}. +\returns +\tcode{*(begin() + pos)} if \tcode{pos < size()}. Otherwise, +returns a reference to an object of type \tcode{charT} with value +\tcode{charT()}, where modifying the object to any value other than +\tcode{charT()} leads to undefined behavior. \pnum \throws @@ -2907,147 +3086,77 @@ Constant time. \end{itemdescr} -\rSec3[string.ops]{String operations} - -\rSec4[string.accessors]{Accessors} - -\indexlibrarymember{c_str}{basic_string}% -\indexlibrarymember{data}{basic_string}% +\indexlibrarymember{at}{basic_string}% \begin{itemdecl} -constexpr const charT* c_str() const noexcept; -constexpr const charT* data() const noexcept; +constexpr const_reference at(size_type pos) const; +constexpr reference at(size_type pos); \end{itemdecl} \begin{itemdescr} \pnum \returns -A pointer \tcode{p} such that \tcode{p + i == addressof(operator[](i))} for each -\tcode{i} in \crange{0}{size()}. - -\pnum -\complexity -Constant time. +\tcode{operator[](pos)}. \pnum -\remarks -The program shall not modify any of the values stored in the character array; otherwise, the behavior is undefined. +\throws +\tcode{out_of_range} +if +\tcode{pos >= size()}. \end{itemdescr} -\indexlibrarymember{data}{basic_string}% +\indexlibrarymember{front}{basic_string}% \begin{itemdecl} -constexpr charT* data() noexcept; +constexpr const charT& front() const; +constexpr charT& front(); \end{itemdecl} \begin{itemdescr} \pnum -\returns -A pointer \tcode{p} such that \tcode{p + i == addressof(operator[](i))} for each -\tcode{i} in \crange{0}{size()}. - -\pnum -\complexity -Constant time. +\expects +\tcode{!empty()}. \pnum -\remarks -The program shall not modify the value stored at \tcode{p + size()} -to any value other than \tcode{charT()}; otherwise, the behavior is undefined. +\effects +Equivalent to: \tcode{return operator[](0);} \end{itemdescr} -\indexlibrarymember{operator basic_string_view}{basic_string}% +\indexlibrarymember{back}{basic_string}% \begin{itemdecl} -constexpr operator basic_string_view() const noexcept; +constexpr const charT& back() const; +constexpr charT& back(); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{!empty()}. + \pnum \effects -Equivalent to: -\tcode{return basic_string_view(data(), size());} +Equivalent to: \tcode{return operator[](size() - 1);} \end{itemdescr} -\indexlibrarymember{get_allocator}{basic_string}% +\rSec3[string.modifiers]{Modifiers} + +\rSec4[string.op.append]{\tcode{basic_string::operator+=}} + +\indexlibrarymember{operator+=}{basic_string}% \begin{itemdecl} -constexpr allocator_type get_allocator() const noexcept; +constexpr basic_string& operator+=(const basic_string& str); \end{itemdecl} \begin{itemdescr} \pnum -\returns -A copy of the -\tcode{Allocator} -object used to construct the string or, if that allocator has been replaced, a -copy of the most recent replacement. -\end{itemdescr} - -\rSec4[string.find]{Searching} - -\pnum -\indexlibrarymember{find}{basic_string}% -\indexlibrarymember{rfind}{basic_string}% -\indexlibrarymember{find_first_of}{basic_string}% -\indexlibrarymember{find_last_of}{basic_string}% -\indexlibrarymember{find_first_not_of}{basic_string}% -\indexlibrarymember{find_last_not_of}{basic_string}% -Let \placeholder{F} be one of -\tcode{find}, \tcode{rfind}, \tcode{find_first_of}, \tcode{find_last_of}, -\tcode{find_first_not_of}, and \tcode{find_last_not_of}. - -\begin{itemize} -\item -Each member function of the form -\begin{codeblock} -constexpr size_type @\placeholder{F}@(const basic_string& str, size_type pos) const noexcept; -\end{codeblock} -has effects equivalent to: -\tcode{return \placeholder{F}(basic_string_view(str), pos);} - -\item -Each member function of the form -\begin{codeblock} -constexpr size_type @\placeholder{F}@(const charT* s, size_type pos) const; -\end{codeblock} -has effects equivalent to: -\tcode{return \placeholder{F}(basic_string_view(s), pos);} +\effects +Equivalent to: \tcode{return append(str);} -\item -Each member function of the form -\begin{codeblock} -constexpr size_type @\placeholder{F}@(const charT* s, size_type pos, size_type n) const; -\end{codeblock} -has effects equivalent to: -\tcode{return \placeholder{F}(basic_string_view(s, n), pos);} -\item -Each member function of the form -\begin{codeblock} -constexpr size_type @\placeholder{F}@(charT c, size_type pos) const noexcept; -\end{codeblock} -has effects equivalent to: -\begin{codeblock} -return @\placeholder{F}@(basic_string_view(addressof(c), 1), pos); -\end{codeblock} -\end{itemize} +\end{itemdescr} -\indexlibrarymember{find}{basic_string}% -\indexlibrarymember{rfind}{basic_string}% -\indexlibrarymember{find_first_of}{basic_string}% -\indexlibrarymember{find_last_of}{basic_string}% -\indexlibrarymember{find_first_not_of}{basic_string}% -\indexlibrarymember{find_last_not_of}{basic_string}% +\indexlibrarymember{operator+=}{basic_string}% \begin{itemdecl} template - constexpr size_type find(const T& t, size_type pos = 0) const noexcept(@\seebelow@); -template - constexpr size_type rfind(const T& t, size_type pos = npos) const noexcept(@\seebelow@); -template - constexpr size_type find_first_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@); -template - constexpr size_type find_last_of(const T& t, size_type pos = npos) const noexcept(@\seebelow@); -template - constexpr size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@); -template - constexpr size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept(@\seebelow@); + constexpr basic_string& operator+=(const T& t); \end{itemdecl} \begin{itemdescr} @@ -3064,77 +3173,78 @@ \pnum \effects -Let \placeholder{G} be the name of the function. Equivalent to: \begin{codeblock} -basic_string_view s = *this, sv = t; -return s.@\placeholder{G}@(sv, pos); +basic_string_view sv = t; +return append(sv); \end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+=}{basic_string}% +\begin{itemdecl} +constexpr basic_string& operator+=(const charT* s); +\end{itemdecl} +\begin{itemdescr} \pnum -\remarks -The exception specification is equivalent to -\tcode{is_nothrow_convertible_v>}. +\effects +Equivalent to: \tcode{return append(s);} \end{itemdescr} -\rSec4[string.substr]{\tcode{basic_string::substr}} - -\indexlibrarymember{substr}{basic_string}% +\indexlibrarymember{operator+=}{basic_string}% \begin{itemdecl} -constexpr basic_string substr(size_type pos = 0, size_type n = npos) const; +constexpr basic_string& operator+=(charT c); \end{itemdecl} \begin{itemdescr} \pnum \effects -Determines the effective length \tcode{rlen} of the string to copy as the smaller of \tcode{n} and -\tcode{size() - pos}. +Equivalent to: \tcode{return append(size_type\{1\}, c);} +\end{itemdescr} -\pnum -\returns -\tcode{basic_string(data()+pos, rlen)}. +\indexlibrarymember{operator+=}{basic_string}% +\begin{itemdecl} +constexpr basic_string& operator+=(initializer_list il); +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -\tcode{out_of_range} -if -\tcode{pos > size()}. +\effects +Equivalent to: \tcode{return append(il);} \end{itemdescr} -\rSec4[string.compare]{\tcode{basic_string::compare}} -\indexlibrarymember{compare}{basic_string}% +\rSec4[string.append]{\tcode{basic_string::append}} + +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -template - constexpr int compare(const T& t) const noexcept(@\seebelow@); +constexpr basic_string& append(const basic_string& str); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} - \pnum \effects -Equivalent to: \tcode{return basic_string_view(*this).compare(t);} +Equivalent to: \tcode{return append(str.data(), str.size());} +\end{itemdescr} -\pnum -\remarks -The exception specification is equivalent to -\tcode{is_nothrow_convertible_v>}. +\indexlibrarymember{append}{basic_string}% +\begin{itemdecl} +constexpr basic_string& append(const basic_string& str, size_type pos, size_type n = npos); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return append(basic_string_view(str).substr(pos, n)); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} template - constexpr int compare(size_type pos1, size_type n1, const T& t) const; + constexpr basic_string& append(const T& t); \end{itemdecl} \begin{itemdescr} @@ -3153,15 +3263,15 @@ \effects Equivalent to: \begin{codeblock} -return basic_string_view(*this).substr(pos1, n1).compare(t); +basic_string_view sv = t; +return append(sv.data(), sv.size()); \end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} template - constexpr int compare(size_type pos1, size_type n1, const T& t, - size_type pos2, size_type n2 = npos) const; + constexpr basic_string& append(const T& t, size_type pos, size_type n = npos); \end{itemdecl} \begin{itemdescr} @@ -3180,153 +3290,138 @@ \effects Equivalent to: \begin{codeblock} -basic_string_view s = *this, sv = t; -return s.substr(pos1, n1).compare(sv.substr(pos2, n2)); +basic_string_view sv = t; +return append(sv.substr(pos, n)); \end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -constexpr int compare(const basic_string& str) const noexcept; +constexpr basic_string& append(const charT* s, size_type n); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\range{s}{s + n} is a valid range. + \pnum \effects -Equivalent to: -\tcode{return compare(basic_string_view(str));} +Appends a copy of the range \range{s}{s + n} to the string. + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos1, size_type n1, const basic_string& str) const; +constexpr basic_string& append(const charT* s); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return compare(pos1, n1, basic_string_view(str));} +Equivalent to: \tcode{return append(s, traits::length(s));} \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos1, size_type n1, const basic_string& str, - size_type pos2, size_type n2 = npos) const; +constexpr basic_string& append(size_type n, charT c); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return compare(pos1, n1, basic_string_view(str), pos2, n2); -\end{codeblock} +Appends \tcode{n} copies of \tcode{c} to the string. + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -constexpr int compare(const charT* s) const; +template + constexpr basic_string& append(InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{InputIterator} is a type that qualifies as an input +iterator\iref{container.requirements.general}. + \pnum \effects -Equivalent to: -\tcode{return compare(basic_string_view(s));} +Equivalent to: \tcode{return append(basic_string(first, last, get_allocator()));} \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{append_range}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos, size_type n1, const charT* s) const; +template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& append_range(R&& rg); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return compare(pos, n1, basic_string_view(s));} +Equivalent to: \tcode{return append(basic_string(from_range, std::forward(rg), get_allocator()));} \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos, size_type n1, const charT* s, size_type n2) const; +constexpr basic_string& append(initializer_list il); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return compare(pos, n1, basic_string_view(s, n2));} +Equivalent to: \tcode{return append(il.begin(), il.size());} \end{itemdescr} -\rSec4[string.starts.with]{\tcode{basic_string::starts_with}} - -\indexlibrarymember{starts_with}{basic_string}% +\indexlibrarymember{push_back}{basic_string}% \begin{itemdecl} -constexpr bool starts_with(basic_string_view x) const noexcept; -constexpr bool starts_with(charT x) const noexcept; -constexpr bool starts_with(const charT* x) const; +constexpr void push_back(charT c); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return basic_string_view(data(), size()).starts_with(x); -\end{codeblock} +Equivalent to +\tcode{append(size_type\{1\}, c)}. \end{itemdescr} -\rSec4[string.ends.with]{\tcode{basic_string::ends_with}} +\rSec4[string.assign]{\tcode{basic_string::assign}} -\indexlibrarymember{ends_with}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -constexpr bool ends_with(basic_string_view x) const noexcept; -constexpr bool ends_with(charT x) const noexcept; -constexpr bool ends_with(const charT* x) const; +constexpr basic_string& assign(const basic_string& str); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return basic_string_view(data(), size()).ends_with(x); -\end{codeblock} +Equivalent to: \tcode{return *this = str;} \end{itemdescr} -\rSec4[string.contains]{\tcode{basic_string::contains}} - -\indexlibrarymember{contains}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -constexpr bool contains(basic_string_view x) const noexcept; -constexpr bool contains(charT x) const noexcept; -constexpr bool contains(const charT* x) const; +constexpr basic_string& assign(basic_string&& str) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return basic_string_view(data(), size()).contains(x); -\end{codeblock} +Equivalent to: \tcode{return *this = std::move(str);} \end{itemdescr} -\rSec2[string.nonmembers]{Non-member functions} - -\indexlibraryglobal{basic_string} - -\rSec3[string.op.plus]{\tcode{operator+}} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(const basic_string& lhs, - const basic_string& rhs); -template - constexpr basic_string - operator+(const basic_string& lhs, const charT* rhs); +constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos); \end{itemdecl} \begin{itemdescr} @@ -3334,154 +3429,109 @@ \effects Equivalent to: \begin{codeblock} -basic_string r = lhs; -r.append(rhs); -return r; +return assign(basic_string_view(str).substr(pos, n)); \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(basic_string&& lhs, - const basic_string& rhs); -template - constexpr basic_string - operator+(basic_string&& lhs, const charT* rhs); +template + constexpr basic_string& assign(const T& t); \end{itemdecl} \begin{itemdescr} \pnum -\effects -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+(basic_string&& lhs, - basic_string&& rhs); -\end{itemdecl} +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} -\begin{itemdescr} \pnum \effects Equivalent to: \begin{codeblock} -lhs.append(rhs); -return std::move(lhs); +basic_string_view sv = t; +return assign(sv.data(), sv.size()); \end{codeblock} -except that both \tcode{lhs} and \tcode{rhs} -are left in valid but unspecified states. -\begin{note} -If \tcode{lhs} and \tcode{rhs} have equal allocators, -the implementation can move from either. -\end{note} \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(const basic_string& lhs, - basic_string&& rhs); -template - constexpr basic_string - operator+(const charT* lhs, basic_string&& rhs); +template + constexpr basic_string& assign(const T& t, size_type pos, size_type n = npos); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -rhs.insert(0, lhs); -return std::move(rhs); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{operator+}{basic_string}% -\begin{itemdecl} -template - constexpr basic_string - operator+(const charT* lhs, const basic_string& rhs); -\end{itemdecl} +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} -\begin{itemdescr} \pnum \effects Equivalent to: \begin{codeblock} -basic_string r = rhs; -r.insert(0, lhs); -return r; +basic_string_view sv = t; +return assign(sv.substr(pos, n)); \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(charT lhs, const basic_string& rhs); +constexpr basic_string& assign(const charT* s, size_type n); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\range{s}{s + n} is a valid range. + \pnum \effects -Equivalent to: -\begin{codeblock} -basic_string r = rhs; -r.insert(r.begin(), lhs); -return r; -\end{codeblock} +Replaces the string controlled by \tcode{*this} with +a copy of the range \range{s}{s + n}. + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% -\begin{itemdecl} -template - constexpr basic_string - operator+(charT lhs, basic_string&& rhs); +\indexlibrarymember{assign}{basic_string}% +\begin{itemdecl} +constexpr basic_string& assign(const charT* s); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -rhs.insert(rhs.begin(), lhs); -return std::move(rhs); -\end{codeblock} +Equivalent to: \tcode{return assign(s, traits::length(s));} \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(const basic_string& lhs, charT rhs); +constexpr basic_string& assign(initializer_list il); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -basic_string r = lhs; -r.push_back(rhs); -return r; -\end{codeblock} +Equivalent to: \tcode{return assign(il.begin(), il.size());} \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(basic_string&& lhs, charT rhs); +constexpr basic_string& assign(size_type n, charT c); \end{itemdecl} \begin{itemdescr} @@ -3489,1347 +3539,1260 @@ \effects Equivalent to: \begin{codeblock} -lhs.push_back(rhs); -return std::move(lhs); +clear(); +resize(n, c); +return *this; \end{codeblock} \end{itemdescr} -\rSec3[string.cmp]{Non-member comparison operator functions} +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - constexpr bool - operator==(const basic_string& lhs, - const basic_string& rhs) noexcept; -template - constexpr bool operator==(const basic_string& lhs, - const charT* rhs); - -template - constexpr @\seebelow@ operator<=>(const basic_string& lhs, - @\itcorr@ const basic_string& rhs) noexcept; -template - constexpr @\seebelow@ operator<=>(const basic_string& lhs, - @\itcorr@ const charT* rhs); +template + constexpr basic_string& assign(InputIterator first, InputIterator last); \end{itemdecl} + \begin{itemdescr} +\pnum +\constraints +\tcode{InputIterator} is a type that qualifies as an input +iterator\iref{container.requirements.general}. + \pnum \effects -Let \tcode{\placeholder{op}} be the operator. -Equivalent to: -\begin{codeblock} -return basic_string_view(lhs) @\placeholder{op}@ basic_string_view(rhs); -\end{codeblock} +Equivalent to: \tcode{return assign(basic_string(first, last, get_allocator()));} \end{itemdescr} -\rSec3[string.special]{\tcode{swap}} - -\indexlibrarymember{swap}{basic_string}% +\indexlibrarymember{assign_range}{basic_string}% \begin{itemdecl} -template - constexpr void - swap(basic_string& lhs, - basic_string& rhs) - noexcept(noexcept(lhs.swap(rhs))); +template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& assign_range(R&& rg); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to \tcode{lhs.swap(rhs)}. +Equivalent to: \tcode{return assign(basic_string(from_range, std::forward(rg), get_allocator()));} \end{itemdescr} -\rSec3[string.io]{Inserters and extractors} +\rSec4[string.insert]{\tcode{basic_string::insert}} -\indexlibrarymember{operator>>}{basic_string}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -template - basic_istream& - operator>>(basic_istream& is, basic_string& str); +constexpr basic_string& insert(size_type pos, const basic_string& str); \end{itemdecl} \begin{itemdescr} \pnum \effects -Behaves as a formatted input function\iref{istream.formatted.reqmts}. -After constructing a \tcode{sentry} object, -if the \tcode{sentry} object returns \tcode{true} -when converted to a value of type \tcode{bool}, -calls \tcode{str.erase()} -and then extracts characters from \tcode{is} and appends them -to \tcode{str} as if by calling -\tcode{str.append(1, c)}. -If -\tcode{is.width()} -is greater than zero, the maximum -number \tcode{n} of characters appended is -\tcode{is.width()}; -otherwise \tcode{n} is -\tcode{str.max_size()}. -Characters are extracted and appended until any of the following -occurs: -\begin{itemize} -\item -\textit{n} -characters are stored; -\item -end-of-file occurs on the input sequence; -\item -\tcode{isspace(c, is.getloc())} -is \tcode{true} for the next available input character -\textit{c}. -\end{itemize} - -\pnum -After the last character (if any) is extracted, -\tcode{is.width(0)} -is called and the -\tcode{sentry} -object is destroyed. - -\pnum -If the function extracts no characters, it calls -\tcode{is.setstate(ios_base::failbit)}, -which may throw -\tcode{ios_base::fail\-ure}\iref{iostate.flags}. - -\pnum -\returns -\tcode{is}. +Equivalent to: \tcode{return insert(pos, str.data(), str.size());} \end{itemdescr} -\indexlibrarymember{operator<<}{basic_string}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -template - basic_ostream& - operator<<(basic_ostream& os, - const basic_string& str); +constexpr basic_string& insert(size_type pos1, const basic_string& str, + size_type pos2, size_type n = npos); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return os << basic_string_view(str);} +Equivalent to: +\begin{codeblock} +return insert(pos1, basic_string_view(str), pos2, n); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{getline}{basic_string}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -template - basic_istream& - getline(basic_istream& is, - basic_string& str, - charT delim); -template - basic_istream& - getline(basic_istream&& is, - basic_string& str, - charT delim); +template + constexpr basic_string& insert(size_type pos, const T& t); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Behaves as an unformatted input function\iref{istream.unformatted}, -except that it does not affect the value returned by subsequent calls to -\tcode{basic_istream<>::gcount()}. -After constructing a \tcode{sentry} object, -if the \tcode{sentry} object returns \tcode{true} -when converted to a value of type \tcode{bool}, -calls \tcode{str.erase()} -and then extracts characters from \tcode{is} and appends them -to \tcode{str} as if by calling -\tcode{str.append(1, c)} -until any of the following occurs: +\constraints \begin{itemize} \item -end-of-file occurs on the input sequence -(in which case, the -\tcode{getline} -function calls -\tcode{is.setstate(\brk{}ios_base::eofbit)}). -\item -\tcode{traits::eq(c, delim)} -for the next available input character -\textit{c} -(in which case, -\textit{c} -is extracted but not appended)\iref{iostate.flags} +\tcode{is_convertible_v>} is +\tcode{true} and \item -\tcode{str.max_size()} -characters are stored -(in which case, -the function calls -\tcode{is.setstate(ios_base::fail\-bit))}\iref{iostate.flags} +\tcode{is_convertible_v} is +\tcode{false}. \end{itemize} -\pnum -The conditions are tested in the order shown. -In any case, -after the last character is extracted, the -\tcode{sentry} -object is destroyed. - -\pnum -If the function extracts no characters, it calls -\tcode{is.setstate(ios_base::fail\-bit)} -which may throw -\tcode{ios_base::fail\-ure}\iref{iostate.flags}. - -\pnum -\returns -\tcode{is}. -\end{itemdescr} - -\indexlibrarymember{getline}{basic_string}% -\begin{itemdecl} -template - basic_istream& - getline(basic_istream& is, - basic_string& str); -template - basic_istream& - getline(basic_istream&& is, - basic_string& str); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{getline(is, str, is.widen('\textbackslash n'))}. -\end{itemdescr} - -\rSec3[string.erasure]{Erasure} - -\indexlibrarymember{erase}{basic_string}% -\begin{itemdecl} -template - constexpr typename basic_string::size_type - erase(basic_string& c, const U& value); -\end{itemdecl} - -\begin{itemdescr} \pnum \effects Equivalent to: \begin{codeblock} -auto it = remove(c.begin(), c.end(), value); -auto r = distance(it, c.end()); -c.erase(it, c.end()); -return r; +basic_string_view sv = t; +return insert(pos, sv.data(), sv.size()); \end{codeblock} \end{itemdescr} -\indexlibrarymember{erase_if}{basic_string}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -template - constexpr typename basic_string::size_type - erase_if(basic_string& c, Predicate pred); +template + constexpr basic_string& insert(size_type pos1, const T& t, + size_type pos2, size_type n = npos); \end{itemdecl} -\begin{itemdescr} +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} + \pnum \effects Equivalent to: \begin{codeblock} -auto it = remove_if(c.begin(), c.end(), pred); -auto r = distance(it, c.end()); -c.erase(it, c.end()); -return r; +basic_string_view sv = t; +return insert(pos1, sv.substr(pos2, n)); \end{codeblock} \end{itemdescr} -\rSec2[string.conversions]{Numeric conversions} - -\indexlibraryglobal{stoi}% -\indexlibraryglobal{stol}% -\indexlibraryglobal{stoul}% -\indexlibraryglobal{stoll}% -\indexlibraryglobal{stoull}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -int stoi(const string& str, size_t* idx = nullptr, int base = 10); -long stol(const string& str, size_t* idx = nullptr, int base = 10); -unsigned long stoul(const string& str, size_t* idx = nullptr, int base = 10); -long long stoll(const string& str, size_t* idx = nullptr, int base = 10); -unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10); +constexpr basic_string& insert(size_type pos, const charT* s, size_type n); \end{itemdecl} \begin{itemdescr} \pnum -\effects -The first two functions call \tcode{strtol(str.c_str(), ptr, base)}, -and the last three functions call \tcode{strtoul(str.c_str(), ptr, base)}, -\tcode{strtoll(str.c_str(), ptr, base)}, and \tcode{strtoull(\brk{}str.c_str(), ptr, -base)}, respectively. Each function returns the converted result, if any. The -argument \tcode{ptr} designates a pointer to an object internal to the function -that is used to determine what to store at \tcode{*idx}. If the function does -not throw an exception and \tcode{idx != nullptr}, the function stores in \tcode{*idx} -the index of the first unconverted element of \tcode{str}. - -\pnum -\returns -The converted result. - -\pnum -\throws -\tcode{invalid_argument} if \tcode{strtol}, \tcode{strtoul}, -\tcode{strtoll}, or \tcode{strtoull} reports that no conversion can be -performed. Throws \tcode{out_of_range} if \tcode{strtol}, \tcode{strtoul}, -\tcode{strtoll} or \tcode{strtoull} sets \tcode{errno} to \tcode{ERANGE}, -or if the converted value is outside the range of representable values -for the return type. -\end{itemdescr} - -\indexlibraryglobal{stof}% -\indexlibraryglobal{stod}% -\indexlibraryglobal{stold}% -\begin{itemdecl} -float stof(const string& str, size_t* idx = nullptr); -double stod(const string& str, size_t* idx = nullptr); -long double stold(const string& str, size_t* idx = nullptr); -\end{itemdecl} +\expects +\range{s}{s + n} is a valid range. -\begin{itemdescr} \pnum \effects -These functions call -\tcode{strtof(str.c_str(), ptr)}, \tcode{strtod(str.c_str(), ptr)}, and -\tcode{strtold(\brk{}str.c_str(), ptr)}, respectively. Each function returns -the converted result, if any. The argument \tcode{ptr} designates a pointer to -an object internal to the function that is used to determine what to store at -\tcode{*idx}. If the function does not throw an exception and \tcode{idx != nullptr}, -the function stores in \tcode{*idx} the index of the first unconverted element -of \tcode{str}. +Inserts a copy of the range \range{s}{s + n} +immediately before the character at position \tcode{pos} if \tcode{pos < size()}, +or otherwise at the end of the string. \pnum \returns -The converted result. +\tcode{*this}. \pnum \throws -\tcode{invalid_argument} if \tcode{strtof}, \tcode{strtod}, or -\tcode{strtold} reports that no conversion can be performed. Throws -\tcode{out_of_range} if \tcode{strtof}, \tcode{strtod}, or -\tcode{strtold} sets \tcode{errno} to \tcode{ERANGE} -or if the converted value is outside the range of representable -values for the return type. +\begin{itemize} +\item \tcode{out_of_range} if \tcode{pos > size()}, +\item \tcode{length_error} if \tcode{n > max_size() - size()}, or +\item any exceptions thrown by \tcode{allocator_traits::allocate}. +\end{itemize} \end{itemdescr} -\indexlibraryglobal{to_string}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -string to_string(int val); -string to_string(unsigned val); -string to_string(long val); -string to_string(unsigned long val); -string to_string(long long val); -string to_string(unsigned long long val); -string to_string(float val); -string to_string(double val); -string to_string(long double val); +constexpr basic_string& insert(size_type pos, const charT* s); \end{itemdecl} \begin{itemdescr} \pnum -\returns -Each function returns a \tcode{string} object holding the character -representation of the value of its argument that would be generated by calling -\tcode{sprintf(buf, fmt, val)} with a format specifier of -\tcode{"\%d"}, -\tcode{"\%u"}, -\tcode{"\%ld"}, -\tcode{"\%lu"}, -\tcode{"\%lld"}, \tcode{"\%llu"}, -\tcode{"\%f"}, -\tcode{"\%f"}, -or \tcode{"\%Lf"}, respectively, where \tcode{buf} designates an internal -character buffer of sufficient size. +\effects +Equivalent to: \tcode{return insert(pos, s, traits::length(s));} \end{itemdescr} -\indexlibraryglobal{stoi}% -\indexlibraryglobal{stol}% -\indexlibraryglobal{stoul}% -\indexlibraryglobal{stoll}% -\indexlibraryglobal{stoull}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -int stoi(const wstring& str, size_t* idx = nullptr, int base = 10); -long stol(const wstring& str, size_t* idx = nullptr, int base = 10); -unsigned long stoul(const wstring& str, size_t* idx = nullptr, int base = 10); -long long stoll(const wstring& str, size_t* idx = nullptr, int base = 10); -unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10); +constexpr basic_string& insert(size_type pos, size_type n, charT c); \end{itemdecl} \begin{itemdescr} \pnum \effects -The first two functions call \tcode{wcstol(str.c_str(), ptr, base)}, -and the last three functions call \tcode{wcstoul(str.c_str(), ptr, base)}, -\tcode{wcstoll(str.c_str(), ptr, base)}, and \tcode{wcstoull(\brk{}str.c_str(), ptr, -base)}, respectively. Each function returns the converted result, if any. The -argument \tcode{ptr} designates a pointer to an object internal to the function -that is used to determine what to store at \tcode{*idx}. If the function does -not throw an exception and \tcode{idx != nullptr}, the function stores in \tcode{*idx} -the index of the first unconverted element of \tcode{str}. +Inserts \tcode{n} copies of \tcode{c} before the character at position \tcode{pos} +if \tcode{pos < size()}, +or otherwise at the end of the string. \pnum \returns -The converted result. +\tcode{*this} \pnum \throws -\tcode{invalid_argument} if \tcode{wcstol}, \tcode{wcstoul}, \tcode{wcstoll}, or -\tcode{wcstoull} reports that no conversion can be performed. Throws -\tcode{out_of_range} if the converted value is outside the range of representable values -for the return type. +\begin{itemize} +\item \tcode{out_of_range} if \tcode{pos > size()}, +\item \tcode{length_error} if \tcode{n > max_size() - size()}, or +\item any exceptions thrown by \tcode{allocator_traits::allocate}. +\end{itemize} \end{itemdescr} -\indexlibraryglobal{stof}% -\indexlibraryglobal{stod}% -\indexlibraryglobal{stold}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -float stof(const wstring& str, size_t* idx = nullptr); -double stod(const wstring& str, size_t* idx = nullptr); -long double stold(const wstring& str, size_t* idx = nullptr); +constexpr iterator insert(const_iterator p, charT c); \end{itemdecl} \begin{itemdescr} \pnum -\effects -These functions call \tcode{wcstof(str.c_str(), ptr)}, -\tcode{wcstod(str.c_str(), ptr)}, and \tcode{wcstold(\brk{}str.c_str(), ptr)}, -respectively. Each function returns the converted -result, if any. The argument \tcode{ptr} designates a pointer to an object internal to -the function that is used to determine what to store at \tcode{*idx}. If the function -does not throw an exception and \tcode{idx != nullptr}, the function stores in \tcode{*idx} -the index of the first unconverted element of \tcode{str}. +\expects +\tcode{p} is a valid iterator on +\tcode{*this}. \pnum -\returns -The converted result. +\effects +Inserts a copy of \tcode{c} at the position \tcode{p}. \pnum -\throws -\tcode{invalid_argument} if \tcode{wcstof}, \tcode{wcstod}, or \tcode{wcstold} reports that no -conversion can be performed. Throws \tcode{out_of_range} if \tcode{wcstof}, \tcode{wcstod}, or -\tcode{wcstold} sets \tcode{errno} to \tcode{ERANGE}. +\returns +An iterator which refers to the inserted character. \end{itemdescr} -\indexlibraryglobal{to_wstring}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -wstring to_wstring(int val); -wstring to_wstring(unsigned val); -wstring to_wstring(long val); -wstring to_wstring(unsigned long val); -wstring to_wstring(long long val); -wstring to_wstring(unsigned long long val); -wstring to_wstring(float val); -wstring to_wstring(double val); -wstring to_wstring(long double val); +constexpr iterator insert(const_iterator p, size_type n, charT c); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{p} is a valid iterator on +\tcode{*this}. + +\pnum +\effects +Inserts \tcode{n} copies of \tcode{c} at the position \tcode{p}. + \pnum \returns -Each function returns a \tcode{wstring} object holding the character -representation of the value of its argument that would be generated by calling -\tcode{swprintf(buf, buffsz, fmt, val)} with a format specifier of -\tcode{L"\%d"}, -\tcode{L"\%u"}, -\tcode{L"\%ld"}, -\tcode{L"\%lu"}, -\tcode{L"\%lld"}, -\tcode{L"\%llu"}, -\tcode{L"\%f"}, -\tcode{L"\%f"}, -or \tcode{L"\%Lf"}, respectively, where \tcode{buf} designates an -internal character buffer of sufficient size \tcode{buffsz}. +An iterator which refers to the first inserted character, or +\tcode{p} if \tcode{n == 0}. \end{itemdescr} -\rSec2[basic.string.hash]{Hash support} - -\indexlibrarymember{hash}{string}% -\indexlibrarymember{hash}{u16string}% -\indexlibrarymember{hash}{u32string}% -\indexlibrarymember{hash}{wstring}% -\indexlibrarymember{hash}{pmr::string}% -\indexlibrarymember{hash}{pmr::u16string}% -\indexlibrarymember{hash}{pmr::u32string}% -\indexlibrarymember{hash}{pmr::wstring}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; +template + constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} \pnum -If \tcode{S} is one of these string types, -\tcode{SV} is the corresponding string view type, and -\tcode{s} is an object of type \tcode{S}, -then \tcode{hash()(s) == hash()(SV(s))}. -\end{itemdescr} +\constraints +\tcode{InputIterator} is a type that qualifies as an input +iterator\iref{container.requirements.general}. -\rSec2[basic.string.literals]{Suffix for \tcode{basic_string} literals} +\pnum +\expects +\tcode{p} is a valid iterator on +\tcode{*this}. -\indexlibrarymember{operator""""s}{string}% -\begin{itemdecl} -constexpr string operator""s(const char* str, size_t len); -\end{itemdecl} +\pnum +\effects +Equivalent to +\tcode{insert(p - begin(), basic_string(first, last, get_allocator()))}. -\begin{itemdescr} \pnum \returns -\tcode{string\{str, len\}}. +An iterator which refers to the first inserted character, or +\tcode{p} if \tcode{first == last}. \end{itemdescr} -\indexlibrarymember{operator""""s}{u8string}% +\indexlibrarymember{insert_range}{basic_string}% \begin{itemdecl} -constexpr u8string operator""s(const char8_t* str, size_t len); +template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator p, R&& rg); \end{itemdecl} + \begin{itemdescr} +\pnum +\expects +\tcode{p} is a valid iterator on \tcode{*this}. + +\pnum +\effects +Equivalent to +\tcode{insert(p - begin(), basic_string(from_range, std::forward(rg), get_allocator()))}. + \pnum \returns -\tcode{u8string\{str, len\}}. +An iterator which refers to the first inserted character, or +\tcode{p} if \tcode{rg} is empty. \end{itemdescr} -\indexlibrarymember{operator""""s}{u16string}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -constexpr u16string operator""s(const char16_t* str, size_t len); +constexpr iterator insert(const_iterator p, initializer_list il); \end{itemdecl} + \begin{itemdescr} \pnum -\returns -\tcode{u16string\{str, len\}}. +\effects +Equivalent to: \tcode{return insert(p, il.begin(), il.end());} \end{itemdescr} -\indexlibrarymember{operator""""s}{u32string}% +\rSec4[string.erase]{\tcode{basic_string::erase}} + +\indexlibrarymember{erase}{basic_string}% \begin{itemdecl} -constexpr u32string operator""s(const char32_t* str, size_t len); +constexpr basic_string& erase(size_type pos = 0, size_type n = npos); \end{itemdecl} + \begin{itemdescr} +\pnum +\effects +Determines the effective length \tcode{xlen} +of the string to be removed as the smaller of \tcode{n} and +\tcode{size() - pos}. +Removes the characters in the range \range{begin() + pos}{begin() + pos + xlen}. + \pnum \returns -\tcode{u32string\{str, len\}}. +\tcode{*this}. + +\pnum +\throws +\tcode{out_of_range} +if \tcode{pos} +\tcode{> size()}. \end{itemdescr} -\indexlibrarymember{operator""""s}{wstring}% +\indexlibrarymember{erase}{basic_string}% \begin{itemdecl} -constexpr wstring operator""s(const wchar_t* str, size_t len); +constexpr iterator erase(const_iterator p); \end{itemdecl} + \begin{itemdescr} \pnum -\returns -\tcode{wstring\{str, len\}}. -\end{itemdescr} +\expects +\tcode{p} is a valid dereferenceable iterator on \tcode{*this}. \pnum -\begin{note} -The same suffix \tcode{s} is used for \tcode{chrono::duration} literals denoting seconds but there is no conflict, since duration suffixes apply to numbers and string literal suffixes apply to character array literals. -\end{note} - -\rSec1[string.view]{String view classes} - -\rSec2[string.view.general]{General} +\effects +Removes the character referred to by \tcode{p}. \pnum -The class template \tcode{basic_string_view} describes an object that can refer to a constant contiguous sequence of char-like\iref{strings.general} objects with the first element of the sequence at position zero. -In the rest of \ref{string.view}, the type of the char-like objects held in a \tcode{basic_string_view} object is designated by \tcode{charT}. +\returns +An iterator which points to the element immediately following \tcode{p} prior to +the element being erased. +If no such element exists, +\tcode{end()} +is returned. \pnum -\begin{note} -The library provides implicit conversions from \tcode{const charT*} and \tcode{std::basic_string} to \tcode{std::basic_string_view} so that user code can accept just \tcode{std::basic_string_view} as a non-templated parameter wherever a sequence of characters is expected. -User-defined types can define their own implicit conversions to \tcode{std::basic_string_view} in order to interoperate with these functions. -\end{note} - -\rSec2[string.view.synop]{Header \tcode{} synopsis} - -\indexheader{string_view}% -\begin{codeblock} -#include // see \ref{compare.syn} - -namespace std { - // \ref{string.view.template}, class template \tcode{basic_string_view} - template> - class basic_string_view; - - template - inline constexpr bool ranges::enable_view> = true; - template - inline constexpr bool ranges::enable_borrowed_range> = true; - - // \ref{string.view.comparison}, non-member comparison functions - template - constexpr bool operator==(basic_string_view x, - basic_string_view 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 - - // \ref{string.view.io}, inserters and extractors - template - basic_ostream& - operator<<(basic_ostream& os, - basic_string_view str); - - // \tcode{basic_string_view} \grammarterm{typedef-name}s - using string_view = basic_string_view; - using u8string_view = basic_string_view; - using u16string_view = basic_string_view; - using u32string_view = basic_string_view; - using wstring_view = basic_string_view; +\throws +Nothing. +\end{itemdescr} - // \ref{string.view.hash}, hash support - template struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; +\indexlibrarymember{erase}{basic_string}% +\begin{itemdecl} +constexpr iterator erase(const_iterator first, const_iterator last); +\end{itemdecl} - 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; - } - } -} -\end{codeblock} +\begin{itemdescr} +\pnum +\expects +\tcode{first} and \tcode{last} are valid iterators on +\tcode{*this}. \range{first}{last} is a valid range. \pnum -The function templates defined in \ref{utility.swap} and \ref{iterator.range} -are available when \tcode{} is included. +\effects +Removes the characters in the range +\tcode{[first, last)}. -\rSec2[string.view.template]{Class template \tcode{basic_string_view}} +\pnum +\returns +An iterator which points to the element pointed to by \tcode{last} prior to +the other elements being erased. +If no such element exists, +\tcode{end()} +is returned. -\rSec3[string.view.template.general]{General} +\pnum +\throws +Nothing. +\end{itemdescr} -\indexlibraryglobal{basic_string_view}% -\indexlibrarymember{traits_type}{basic_string_view}% -\indexlibrarymember{value_type}{basic_string_view}% -\indexlibrarymember{pointer}{basic_string_view}% -\indexlibrarymember{const_pointer}{basic_string_view}% -\indexlibrarymember{reference}{basic_string_view}% -\indexlibrarymember{const_reference}{basic_string_view}% -\indexlibrarymember{const_iterator}{basic_string_view}% -\indexlibrarymember{iterator}{basic_string_view}% -\indexlibrarymember{const_reverse_iterator}{basic_string_view}% -\indexlibrarymember{reverse_iterator}{basic_string_view}% -\indexlibrarymember{size_type}{basic_string_view}% -\indexlibrarymember{difference_type}{basic_string_view}% -\begin{codeblock} -namespace std { - template> - class basic_string_view { - public: - // types - using traits_type = traits; - using value_type = charT; - using pointer = value_type*; - using const_pointer = const value_type*; - using reference = value_type&; - using const_reference = const value_type&; - using const_iterator = @\impdefx{type of \tcode{basic_string_view::const_iterator}}@; // see \ref{string.view.iterators} - using iterator = const_iterator;@ -\begin{footnote} -Because \tcode{basic_string_view} refers to a constant sequence, \tcode{iterator} and \tcode{const_iterator} are the same type. -\end{footnote}@ - using const_reverse_iterator = reverse_iterator; - using reverse_iterator = const_reverse_iterator; - using size_type = size_t; - using difference_type = ptrdiff_t; - static constexpr size_type npos = size_type(-1); +\indexlibrarymember{pop_back}{basic_string}% +\begin{itemdecl} +constexpr void pop_back(); +\end{itemdecl} - // \ref{string.view.cons}, construction and assignment - constexpr basic_string_view() noexcept; - constexpr basic_string_view(const basic_string_view&) noexcept = default; - constexpr basic_string_view& operator=(const basic_string_view&) noexcept = default; - constexpr basic_string_view(const charT* str); - basic_string_view(nullptr_t) = delete; - constexpr basic_string_view(const charT* str, size_type len); - template - constexpr basic_string_view(It begin, End end); - template - constexpr basic_string_view(R&& r); +\begin{itemdescr} +\pnum +\expects +\tcode{!empty()}. - // \ref{string.view.iterators}, iterator support - constexpr const_iterator begin() const noexcept; - constexpr const_iterator end() const noexcept; - constexpr const_iterator cbegin() const noexcept; - constexpr const_iterator cend() const noexcept; - constexpr const_reverse_iterator rbegin() const noexcept; - constexpr const_reverse_iterator rend() const noexcept; - constexpr const_reverse_iterator crbegin() const noexcept; - constexpr const_reverse_iterator crend() const noexcept; +\pnum +\effects +Equivalent to \tcode{erase(end() - 1)}. - // \ref{string.view.capacity}, capacity - constexpr size_type size() const noexcept; - constexpr size_type length() const noexcept; - constexpr size_type max_size() const noexcept; - [[nodiscard]] constexpr bool empty() const noexcept; +\pnum +\throws +Nothing. +\end{itemdescr} - // \ref{string.view.access}, element access - constexpr const_reference operator[](size_type pos) const; - constexpr const_reference at(size_type pos) const; - constexpr const_reference front() const; - constexpr const_reference back() const; - constexpr const_pointer data() const noexcept; +\rSec4[string.replace]{\tcode{basic_string::replace}} - // \ref{string.view.modifiers}, modifiers - constexpr void remove_prefix(size_type n); - constexpr void remove_suffix(size_type n); - constexpr void swap(basic_string_view& s) noexcept; +\indexlibrarymember{replace}{basic_string}% +\begin{itemdecl} +constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str); +\end{itemdecl} - // \ref{string.view.ops}, string operations - constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return replace(pos1, n1, str.data(), str.size());} +\end{itemdescr} - constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; +\indexlibrarymember{replace}{basic_string}% +\begin{itemdecl} +constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str, + size_type pos2, size_type n2 = npos); +\end{itemdecl} - constexpr int compare(basic_string_view s) const noexcept; - constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const; - constexpr int compare(size_type pos1, size_type n1, basic_string_view s, - size_type pos2, size_type n2) const; - constexpr int compare(const charT* s) const; - constexpr int compare(size_type pos1, size_type n1, const charT* s) const; - constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return replace(pos1, n1, basic_string_view(str).substr(pos2, n2)); +\end{codeblock} +\end{itemdescr} - constexpr bool starts_with(basic_string_view x) const noexcept; - constexpr bool starts_with(charT x) const noexcept; - constexpr bool starts_with(const charT* x) const; - constexpr bool ends_with(basic_string_view x) const noexcept; - constexpr bool ends_with(charT x) const noexcept; - constexpr bool ends_with(const charT* x) const; +\indexlibrarymember{replace}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string& replace(size_type pos1, size_type n1, const T& t); +\end{itemdecl} - constexpr bool contains(basic_string_view x) const noexcept; - constexpr bool contains(charT x) const noexcept; - constexpr bool contains(const charT* x) const; +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} - // \ref{string.view.find}, searching - constexpr size_type find(basic_string_view s, size_type pos = 0) const noexcept; - constexpr size_type find(charT c, size_type pos = 0) const noexcept; - constexpr size_type find(const charT* s, size_type pos, size_type n) const; - constexpr size_type find(const charT* s, size_type pos = 0) const; - constexpr size_type rfind(basic_string_view s, size_type pos = npos) const noexcept; - constexpr size_type rfind(charT c, size_type pos = npos) const noexcept; - constexpr size_type rfind(const charT* s, size_type pos, size_type n) const; - constexpr size_type rfind(const charT* s, size_type pos = npos) const; +\pnum +\effects +Equivalent to: +\begin{codeblock} +basic_string_view sv = t; +return replace(pos1, n1, sv.data(), sv.size()); +\end{codeblock} +\end{itemdescr} - constexpr size_type find_first_of(basic_string_view s, size_type pos = 0) const noexcept; - constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept; - constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const; - constexpr size_type find_first_of(const charT* s, size_type pos = 0) const; - constexpr size_type find_last_of(basic_string_view s, size_type pos = npos) const noexcept; - constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept; - constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const; - constexpr size_type find_last_of(const charT* s, size_type pos = npos) const; - constexpr size_type find_first_not_of(basic_string_view s, size_type pos = 0) const noexcept; - constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept; - constexpr size_type find_first_not_of(const charT* s, size_type pos, - size_type n) const; - constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const; - constexpr size_type find_last_not_of(basic_string_view s, - size_type pos = npos) const noexcept; - constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept; - constexpr size_type find_last_not_of(const charT* s, size_type pos, - size_type n) const; - constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const; +\indexlibrarymember{replace}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string& replace(size_type pos1, size_type n1, const T& t, + size_type pos2, size_type n2 = npos); +\end{itemdecl} - private: - const_pointer data_; // \expos - size_type size_; // \expos - }; +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} - // \ref{string.view.deduct}, deduction guides - template - basic_string_view(It, End) -> basic_string_view>; - template - basic_string_view(R&&) -> basic_string_view>; -} +\pnum +\effects +Equivalent to: +\begin{codeblock} +basic_string_view sv = t; +return replace(pos1, n1, sv.substr(pos2, n2)); \end{codeblock} +\end{itemdescr} -\pnum -In every specialization \tcode{basic_string_view}, the type \tcode{traits} shall meet the character traits requirements\iref{char.traits}. -\begin{note} -The program is ill-formed if \tcode{traits::char_type} is not the same type as \tcode{charT}. -\end{note} +\indexlibrarymember{replace}{basic_string}% +\begin{itemdecl} +constexpr basic_string& replace(size_type pos1, size_type n1, const charT* s, size_type n2); +\end{itemdecl} +\begin{itemdescr} \pnum -For a \tcode{basic_string_view str}, -any operation that invalidates a pointer -in the range \range{str.data()}{\brk{}str.data() + str.size()} -invalidates pointers, iterators, and references -returned from \tcode{str}'s member functions. +\expects +\range{s}{s + n2} is a valid range. \pnum -The complexity of \tcode{basic_string_view} member functions is \bigoh{1} -unless otherwise specified. +\effects +Determines the effective length \tcode{xlen} of the string to be +removed as the smaller of \tcode{n1} and \tcode{size() - pos1}. If +\tcode{size() - xlen >= max_size() - n2} throws \tcode{length_error}. Otherwise, +the function replaces the characters in the range +\range{begin() + pos1}{begin() + pos1 + xlen} +with a copy of the range \range{s}{s + n2}. \pnum -\tcode{basic_string_view} is a trivially copyable type\iref{basic.types.general}. +\returns +\tcode{*this}. -\rSec3[string.view.cons]{Construction and assignment} +\pnum +\throws +\begin{itemize} +\item \tcode{out_of_range} if \tcode{pos1 > size()}, +\item \tcode{length_error} if the length of the resulting string +would exceed \tcode{max_size()}, or +\item any exceptions thrown by \tcode{allocator_traits::allocate}. +\end{itemize} +\end{itemdescr} -\indexlibraryctor{basic_string_view}% +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -constexpr basic_string_view() noexcept; +constexpr basic_string& replace(size_type pos, size_type n, const charT* s); \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{size_ == 0} and \tcode{data_ == nullptr}. +\effects +Equivalent to: \tcode{return replace(pos, n, s, traits::length(s));} \end{itemdescr} -\indexlibraryctor{basic_string_view}% +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -constexpr basic_string_view(const charT* str); +constexpr basic_string& replace(size_type pos1, size_type n1, size_type n2, charT c); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\range{str}{str + traits::length(str)} is a valid range. +\effects +Determines the effective length \tcode{xlen} of the string to be +removed as the smaller of \tcode{n1} and \tcode{size() - pos1}. If +\tcode{size() - xlen >=} \tcode{max_size() - n2} throws \tcode{length_error}. Otherwise, +the function replaces the characters in the range +\range{begin() + pos1}{begin() + pos1 + xlen} +with \tcode{n2} copies of \tcode{c}. \pnum -\effects -Constructs a \tcode{basic_string_view}, initializing \tcode{data_} with \tcode{str} -and initializing \tcode{size_} with \tcode{traits::length(str)}. +\returns +\tcode{*this}. \pnum -\complexity -\bigoh{\tcode{traits::length(str)}}. +\throws +\begin{itemize} +\item \tcode{out_of_range} if \tcode{pos1 > size()}, +\item \tcode{length_error} if the length of the resulting string +would exceed\tcode{max_size()}, or +\item any exceptions thrown by \tcode{allocator_traits::allocate.} +\end{itemize} \end{itemdescr} -\indexlibraryctor{basic_string_view}% +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -constexpr basic_string_view(const charT* str, size_type len); +constexpr basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str); \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\range{str}{str + len} is a valid range. - \pnum \effects -Constructs a \tcode{basic_string_view}, initializing \tcode{data_} with \tcode{str} -and initializing \tcode{size_} with \tcode{len}. +Equivalent to: \tcode{return replace(i1, i2, basic_string_view(str));} \end{itemdescr} -\indexlibraryctor{basic_string_view}% +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -template - constexpr basic_string_view(It begin, End end); +template + constexpr basic_string& replace(const_iterator i1, const_iterator i2, const T& t); \end{itemdecl} \begin{itemdescr} \pnum \constraints \begin{itemize} -\item \tcode{It} satisfies \libconcept{contiguous_iterator}. -\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}}. -\item \tcode{is_same_v, charT>} is \tcode{true}. -\item \tcode{is_convertible_v} is \tcode{false}. +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. \end{itemize} \pnum \expects -\begin{itemize} -\item \range{begin}{end} is a valid range. -\item \tcode{It} models \libconcept{contiguous_iterator}. -\item \tcode{End} models \tcode{\libconcept{sized_sentinel_for}}. -\end{itemize} +\range{begin()}{i1} and \range{i1}{i2} are valid ranges. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +basic_string_view sv = t; +return replace(i1 - begin(), i2 - i1, sv.data(), sv.size()); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{replace}{basic_string}% +\begin{itemdecl} +constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s, size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return replace(i1, i2, basic_string_view(s, n));} +\end{itemdescr} + +\indexlibrarymember{replace}{basic_string}% +\begin{itemdecl} +constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return replace(i1, i2, basic_string_view(s));} +\end{itemdescr} + +\indexlibrarymember{replace}{basic_string}% +\begin{itemdecl} +constexpr basic_string& replace(const_iterator i1, const_iterator i2, size_type n, charT c); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\range{begin()}{i1} and \range{i1}{i2} are valid ranges. \pnum \effects -Initializes \tcode{data_} with \tcode{to_address(begin)} and -initializes \tcode{size_} with \tcode{end - begin}. - -\pnum -\throws -When and what \tcode{end - begin} throws. +Equivalent to: \tcode{return replace(i1 - begin(), i2 - i1, n, c);} \end{itemdescr} -\indexlibraryctor{basic_string_view}% +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -template - constexpr basic_string_view(R&& r); +template + constexpr basic_string& replace(const_iterator i1, const_iterator i2, + InputIterator j1, InputIterator j2); \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{d} be an lvalue of type \tcode{remove_cvref_t}. - \pnum \constraints -\begin{itemize} -\item -\tcode{remove_cvref_t} is not the same type as \tcode{basic_string_view}, -\item -\tcode{R} models -\tcode{ranges::\libconcept{contiguous_range}} and \tcode{ranges::\libconcept{sized_range}}, -\item -\tcode{is_same_v, charT>} is \tcode{true}, -\item -\tcode{is_convertible_v} is \tcode{false}, -\item -\tcode{d.operator ::std::basic_string_view()} -is not a valid expression, and -\item -if the \grammarterm{qualified-id} \tcode{remove_reference_t::traits_type} -is valid and denotes a type, -\tcode{is_same_v::traits_type, traits>} is \tcode{true}. -\end{itemize} +\tcode{InputIterator} is a type that qualifies as an input +iterator\iref{container.requirements.general}. \pnum \effects -Initializes \tcode{data_} with \tcode{ranges::data(r)} and -\tcode{size_} with \tcode{ranges::size(r)}. - -\pnum -\throws -Any exception thrown by \tcode{ranges::data(r)} and \tcode{ranges::size(r)}. +Equivalent to: \tcode{return replace(i1, i2, basic_string(j1, j2, get_allocator()));} \end{itemdescr} -\rSec3[string.view.iterators]{Iterator support} - -\indexlibrarymember{const_iterator}{basic_string_view}% +\indexlibrarymember{replace_with_range}{basic_string}% \begin{itemdecl} -using const_iterator = @\impdefx{type of \tcode{basic_string_view::const_iterator}}@; +template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); \end{itemdecl} \begin{itemdescr} \pnum -A type that meets the requirements -of a constant -\oldconcept{RandomAccessIterator}\iref{random.access.iterators}, -models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}, and -meets the constexpr iterator requirements\iref{iterator.requirements.general}, -whose \tcode{value_type} is the template parameter \tcode{charT}. - -\pnum -All requirements on container iterators\iref{container.requirements} apply to \tcode{basic_string_view::const_iterator} as well. +\effects +Equivalent to: +\begin{codeblock} +return replace(i1, i2, basic_string(from_range, std::forward(rg), get_allocator())); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{begin}{basic_string_view}% -\indexlibrarymember{cbegin}{basic_string_view}% +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -constexpr const_iterator begin() const noexcept; -constexpr const_iterator cbegin() const noexcept; +constexpr basic_string& replace(const_iterator i1, const_iterator i2, initializer_list il); \end{itemdecl} \begin{itemdescr} \pnum -\returns -An iterator such that -\begin{itemize} -\item if \tcode{!empty()}, \tcode{addressof(*begin()) == data_}, -\item otherwise, an unspecified value such that \range{begin()}{end()} is a valid range. -\end{itemize} +\effects +Equivalent to: \tcode{return replace(i1, i2, il.begin(), il.size());} \end{itemdescr} -\indexlibrarymember{end}{basic_string_view}% -\indexlibrarymember{cend}{basic_string_view}% +\rSec4[string.copy]{\tcode{basic_string::copy}} + +\indexlibrarymember{copy}{basic_string}% \begin{itemdecl} -constexpr const_iterator end() const noexcept; -constexpr const_iterator cend() const noexcept; +constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{begin() + size()}. +\effects +Equivalent to: +\tcode{return basic_string_view(*this).copy(s, n, pos);} +\begin{note} +This does not terminate \tcode{s} with a null object. +\end{note} \end{itemdescr} -\indexlibrarymember{rbegin}{basic_string_view}% -\indexlibrarymember{crbegin}{basic_string_view}% +\rSec4[string.swap]{\tcode{basic_string::swap}} + +\indexlibrarymember{swap}{basic_string}% \begin{itemdecl} -constexpr const_reverse_iterator rbegin() const noexcept; -constexpr const_reverse_iterator crbegin() const noexcept; +constexpr void swap(basic_string& s) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{const_reverse_iterator(end())}. +\expects +\tcode{allocator_traits::propagate_on_container_swap::value} is \tcode{true} +or +\tcode{get_allocator() == s.get_allocator()}. + +\pnum +\ensures +\tcode{*this} +contains the same sequence of characters that was in \tcode{s}, +\tcode{s} contains the same sequence of characters that was in +\tcode{*this}. + +\pnum +\throws +Nothing. + +\pnum +\complexity +Constant time. \end{itemdescr} -\indexlibrarymember{rend}{basic_string_view}% -\indexlibrarymember{crend}{basic_string_view}% +\rSec3[string.ops]{String operations} + +\rSec4[string.accessors]{Accessors} + +\indexlibrarymember{c_str}{basic_string}% +\indexlibrarymember{data}{basic_string}% \begin{itemdecl} -constexpr const_reverse_iterator rend() const noexcept; -constexpr const_reverse_iterator crend() const noexcept; +constexpr const charT* c_str() const noexcept; +constexpr const charT* data() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{const_reverse_iterator(begin())}. -\end{itemdescr} +A pointer \tcode{p} such that \tcode{p + i == addressof(operator[](i))} for each +\tcode{i} in \crange{0}{size()}. -\rSec3[string.view.capacity]{Capacity} +\pnum +\complexity +Constant time. -\indexlibrarymember{size}{basic_string_view}% -\indexlibrarymember{length}{basic_string_view}% +\pnum +\remarks +The program shall not modify any of the values stored in the character array; otherwise, the behavior is undefined. +\end{itemdescr} + +\indexlibrarymember{data}{basic_string}% \begin{itemdecl} -constexpr size_type size() const noexcept; -constexpr size_type length() const noexcept; +constexpr charT* data() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{size_}. -\end{itemdescr} +A pointer \tcode{p} such that \tcode{p + i == addressof(operator[](i))} for each +\tcode{i} in \crange{0}{size()}. + +\pnum +\complexity +Constant time. +\pnum +\remarks +The program shall not modify the value stored at \tcode{p + size()} +to any value other than \tcode{charT()}; otherwise, the behavior is undefined. +\end{itemdescr} -\indexlibrarymember{max_size}{basic_string_view}% +\indexlibrarymember{operator basic_string_view}{basic_string}% \begin{itemdecl} -constexpr size_type max_size() const noexcept; +constexpr operator basic_string_view() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -The largest possible number of char-like objects that can be referred to by a \tcode{basic_string_view}. +\effects +Equivalent to: +\tcode{return basic_string_view(data(), size());} \end{itemdescr} -\indexlibrarymember{empty}{basic_string_view}% +\indexlibrarymember{get_allocator}{basic_string}% \begin{itemdecl} -[[nodiscard]] constexpr bool empty() const noexcept; +constexpr allocator_type get_allocator() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{size_ == 0}. +A copy of the +\tcode{Allocator} +object used to construct the string or, if that allocator has been replaced, a +copy of the most recent replacement. \end{itemdescr} -\rSec3[string.view.access]{Element access} +\rSec4[string.find]{Searching} -\indexlibrarymember{operator[]}{basic_string_view}% +\pnum +\indexlibrarymember{find}{basic_string}% +\indexlibrarymember{rfind}{basic_string}% +\indexlibrarymember{find_first_of}{basic_string}% +\indexlibrarymember{find_last_of}{basic_string}% +\indexlibrarymember{find_first_not_of}{basic_string}% +\indexlibrarymember{find_last_not_of}{basic_string}% +Let \placeholder{F} be one of +\tcode{find}, \tcode{rfind}, \tcode{find_first_of}, \tcode{find_last_of}, +\tcode{find_first_not_of}, and \tcode{find_last_not_of}. + +\begin{itemize} +\item +Each member function of the form +\begin{codeblock} +constexpr size_type @\placeholder{F}@(const basic_string& str, size_type pos) const noexcept; +\end{codeblock} +has effects equivalent to: +\tcode{return \placeholder{F}(basic_string_view(str), pos);} + +\item +Each member function of the form +\begin{codeblock} +constexpr size_type @\placeholder{F}@(const charT* s, size_type pos) const; +\end{codeblock} +has effects equivalent to: +\tcode{return \placeholder{F}(basic_string_view(s), pos);} + +\item +Each member function of the form +\begin{codeblock} +constexpr size_type @\placeholder{F}@(const charT* s, size_type pos, size_type n) const; +\end{codeblock} +has effects equivalent to: +\tcode{return \placeholder{F}(basic_string_view(s, n), pos);} + +\item +Each member function of the form +\begin{codeblock} +constexpr size_type @\placeholder{F}@(charT c, size_type pos) const noexcept; +\end{codeblock} +has effects equivalent to: +\begin{codeblock} +return @\placeholder{F}@(basic_string_view(addressof(c), 1), pos); +\end{codeblock} +\end{itemize} + +\indexlibrarymember{find}{basic_string}% +\indexlibrarymember{rfind}{basic_string}% +\indexlibrarymember{find_first_of}{basic_string}% +\indexlibrarymember{find_last_of}{basic_string}% +\indexlibrarymember{find_first_not_of}{basic_string}% +\indexlibrarymember{find_last_not_of}{basic_string}% \begin{itemdecl} -constexpr const_reference operator[](size_type pos) const; +template + constexpr size_type find(const T& t, size_type pos = 0) const noexcept(@\seebelow@); +template + constexpr size_type rfind(const T& t, size_type pos = npos) const noexcept(@\seebelow@); +template + constexpr size_type find_first_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@); +template + constexpr size_type find_last_of(const T& t, size_type pos = npos) const noexcept(@\seebelow@); +template + constexpr size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@); +template + constexpr size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{pos < size()}. - -\pnum -\returns -\tcode{data_[pos]}. +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} \pnum -\throws -Nothing. +\effects +Let \placeholder{G} be the name of the function. +Equivalent to: +\begin{codeblock} +basic_string_view s = *this, sv = t; +return s.@\placeholder{G}@(sv, pos); +\end{codeblock} \pnum -\begin{note} -Unlike \tcode{basic_string::operator[]}, -\tcode{basic_string_view::operator[](size())} has undefined behavior instead of returning \tcode{charT()}. -\end{note} +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_convertible_v>}. \end{itemdescr} -\indexlibrarymember{at}{basic_string_view}% +\rSec4[string.substr]{\tcode{basic_string::substr}} + +\indexlibrarymember{substr}{basic_string}% \begin{itemdecl} -constexpr const_reference at(size_type pos) const; +constexpr basic_string substr(size_type pos = 0, size_type n = npos) const; \end{itemdecl} \begin{itemdescr} +\pnum +\effects +Determines the effective length \tcode{rlen} of the string to copy as the smaller of \tcode{n} and +\tcode{size() - pos}. + \pnum \returns -\tcode{data_[pos]}. +\tcode{basic_string(data()+pos, rlen)}. \pnum \throws -\tcode{out_of_range} if \tcode{pos >= size()}. +\tcode{out_of_range} +if +\tcode{pos > size()}. \end{itemdescr} -\indexlibrarymember{front}{basic_string_view}% +\rSec4[string.compare]{\tcode{basic_string::compare}} + +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr const_reference front() const; +template + constexpr int compare(const T& t) const noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} \pnum -\returns -\tcode{data_[0]}. +\effects +Equivalent to: \tcode{return basic_string_view(*this).compare(t);} \pnum -\throws -Nothing. +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_convertible_v>}. \end{itemdescr} -\indexlibrarymember{back}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr const_reference back() const; +template + constexpr int compare(size_type pos1, size_type n1, const T& t) const; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. - -\pnum -\returns -\tcode{data_[size() - 1]}. +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} \pnum -\throws -Nothing. +\effects +Equivalent to: +\begin{codeblock} +return basic_string_view(*this).substr(pos1, n1).compare(t); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{data}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr const_pointer data() const noexcept; +template + constexpr int compare(size_type pos1, size_type n1, const T& t, + size_type pos2, size_type n2 = npos) const; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{data_}. +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} \pnum -\begin{note} -Unlike \tcode{basic_string::data()} and \grammarterm{string-literal}s, -\tcode{data()} can return a pointer to a buffer that is not null-terminated. -Therefore it is typically a mistake to pass \tcode{data()} to a function that takes just a \tcode{const charT*} and expects a null-terminated string. -\end{note} +\effects +Equivalent to: +\begin{codeblock} +basic_string_view s = *this, sv = t; +return s.substr(pos1, n1).compare(sv.substr(pos2, n2)); +\end{codeblock} \end{itemdescr} -\rSec3[string.view.modifiers]{Modifiers} - -\indexlibrarymember{remove_prefix}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr void remove_prefix(size_type n); +constexpr int compare(const basic_string& str) const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{n <= size()}. - \pnum \effects -Equivalent to: \tcode{data_ += n; size_ -= n;} +Equivalent to: +\tcode{return compare(basic_string_view(str));} \end{itemdescr} -\indexlibrarymember{remove_suffix}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr void remove_suffix(size_type n); +constexpr int compare(size_type pos1, size_type n1, const basic_string& str) const; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{n <= size()}. - \pnum \effects -Equivalent to: \tcode{size_ -= n;} +Equivalent to: +\tcode{return compare(pos1, n1, basic_string_view(str));} \end{itemdescr} -\indexlibrarymember{swap}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr void swap(basic_string_view& s) noexcept; +constexpr int compare(size_type pos1, size_type n1, const basic_string& str, + size_type pos2, size_type n2 = npos) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Exchanges the values of \tcode{*this} and \tcode{s}. +Equivalent to: +\begin{codeblock} +return compare(pos1, n1, basic_string_view(str), pos2, n2); +\end{codeblock} \end{itemdescr} -\rSec3[string.view.ops]{String operations} - -\indexlibrarymember{copy}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; +constexpr int compare(const charT* s) const; \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{rlen} be the smaller of \tcode{n} and \tcode{size() - pos}. - -\pnum -\expects -\range{s}{s + rlen} is a valid range. - \pnum \effects -Equivalent to \tcode{traits::copy(s, data() + pos, rlen)}. - -\pnum -\returns -\tcode{rlen}. - -\pnum -\throws -\tcode{out_of_range} if \tcode{pos > size()}. - -\pnum -\complexity -\bigoh{\tcode{rlen}}. +Equivalent to: +\tcode{return compare(basic_string_view(s));} \end{itemdescr} -\indexlibrarymember{substr}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; +constexpr int compare(size_type pos, size_type n1, const charT* s) const; \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{rlen} be the smaller of \tcode{n} and \tcode{size() - pos}. - \pnum \effects -Determines \tcode{rlen}, the effective length of the string to reference. - -\pnum -\returns -\tcode{basic_string_view(data() + pos, rlen)}. - -\pnum -\throws -\tcode{out_of_range} if \tcode{pos > size()}. +Equivalent to: \tcode{return compare(pos, n1, basic_string_view(s));} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr int compare(basic_string_view str) const noexcept; +constexpr int compare(size_type pos, size_type n1, const charT* s, size_type n2) const; \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{rlen} be the smaller of \tcode{size()} and \tcode{str.size()}. - \pnum \effects -Determines \tcode{rlen}, the effective length of the strings to compare. -The function then compares the two strings by calling \tcode{traits::compare(data(), str.data(), rlen)}. +Equivalent to: \tcode{return compare(pos, n1, basic_string_view(s, n2));} +\end{itemdescr} -\pnum -\returns -The nonzero result if the result of the comparison is nonzero. -Otherwise, returns a value as indicated in \tref{string.view.compare}. -\begin{libtab2}{\tcode{compare()} results}{string.view.compare}{cc}{Condition}{Return Value} -\tcode{size() < str.size()} & \tcode{< 0}\\ -\tcode{size() == str.size()} & \tcode{ \ 0}\\ -\tcode{size() > str.size()} & \tcode{> 0}\\ -\end{libtab2} +\rSec4[string.starts.with]{\tcode{basic_string::starts_with}} + +\indexlibrarymember{starts_with}{basic_string}% +\begin{itemdecl} +constexpr bool starts_with(basic_string_view x) const noexcept; +constexpr bool starts_with(charT x) const noexcept; +constexpr bool starts_with(const charT* x) const; +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -\bigoh{\tcode{rlen}}. +\effects +Equivalent to: +\begin{codeblock} +return basic_string_view(data(), size()).starts_with(x); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\rSec4[string.ends.with]{\tcode{basic_string::ends_with}} + +\indexlibrarymember{ends_with}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos1, size_type n1, basic_string_view str) const; +constexpr bool ends_with(basic_string_view x) const noexcept; +constexpr bool ends_with(charT x) const noexcept; +constexpr bool ends_with(const charT* x) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return substr(pos1, n1).compare(str);} +Equivalent to: +\begin{codeblock} +return basic_string_view(data(), size()).ends_with(x); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\rSec4[string.contains]{\tcode{basic_string::contains}} + +\indexlibrarymember{contains}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos1, size_type n1, basic_string_view str, - size_type pos2, size_type n2) const; +constexpr bool contains(basic_string_view x) const noexcept; +constexpr bool contains(charT x) const noexcept; +constexpr bool contains(const charT* x) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return substr(pos1, n1).compare(str.substr(pos2, n2));} +Equivalent to: +\begin{codeblock} +return basic_string_view(data(), size()).contains(x); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\rSec2[string.nonmembers]{Non-member functions} + +\indexlibraryglobal{basic_string} + +\rSec3[string.op.plus]{\tcode{operator+}} + +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr int compare(const charT* s) const; +template + constexpr basic_string + operator+(const basic_string& lhs, + const basic_string& rhs); +template + constexpr basic_string + operator+(const basic_string& lhs, const charT* rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return compare(basic_string_view(s));} +Equivalent to: +\begin{codeblock} +basic_string r = lhs; +r.append(rhs); +return r; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos1, size_type n1, const charT* s) const; +template + constexpr basic_string + operator+(basic_string&& lhs, + const basic_string& rhs); +template + constexpr basic_string + operator+(basic_string&& lhs, const charT* rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return substr(pos1, n1).compare(basic_string_view(s));} +Equivalent to: +\begin{codeblock} +lhs.append(rhs); +return std::move(lhs); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; +template + constexpr basic_string + operator+(basic_string&& lhs, + basic_string&& rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return substr(pos1, n1).compare(basic_string_view(s, n2));} +Equivalent to: +\begin{codeblock} +lhs.append(rhs); +return std::move(lhs); +\end{codeblock} +except that both \tcode{lhs} and \tcode{rhs} +are left in valid but unspecified states. +\begin{note} +If \tcode{lhs} and \tcode{rhs} have equal allocators, +the implementation can move from either. +\end{note} \end{itemdescr} -\indexlibrarymember{starts_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool starts_with(basic_string_view x) const noexcept; +template + constexpr basic_string + operator+(const basic_string& lhs, + basic_string&& rhs); +template + constexpr basic_string + operator+(const charT* lhs, basic_string&& rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return substr(0, x.size()) == x;} +Equivalent to: +\begin{codeblock} +rhs.insert(0, lhs); +return std::move(rhs); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{starts_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool starts_with(charT x) const noexcept; +template + constexpr basic_string + operator+(const charT* lhs, const basic_string& rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !empty() \&\& traits::eq(front(), x);} +Equivalent to: +\begin{codeblock} +basic_string r = rhs; +r.insert(0, lhs); +return r; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{starts_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool starts_with(const charT* x) const; +template + constexpr basic_string + operator+(charT lhs, const basic_string& rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return starts_with(basic_string_view(x));} +Equivalent to: +\begin{codeblock} +basic_string r = rhs; +r.insert(r.begin(), lhs); +return r; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{ends_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool ends_with(basic_string_view x) const noexcept; +template + constexpr basic_string + operator+(charT lhs, basic_string&& rhs); \end{itemdecl} \begin{itemdescr} @@ -4837,448 +4800,582 @@ \effects Equivalent to: \begin{codeblock} -return size() >= x.size() && compare(size() - x.size(), npos, x) == 0; +rhs.insert(rhs.begin(), lhs); +return std::move(rhs); \end{codeblock} \end{itemdescr} -\indexlibrarymember{ends_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool ends_with(charT x) const noexcept; +template + constexpr basic_string + operator+(const basic_string& lhs, charT rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !empty() \&\& traits::eq(back(), x);} +Equivalent to: +\begin{codeblock} +basic_string r = lhs; +r.push_back(rhs); +return r; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{ends_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool ends_with(const charT* x) const; +template + constexpr basic_string + operator+(basic_string&& lhs, charT rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return ends_with(basic_string_view(x));} +Equivalent to: +\begin{codeblock} +lhs.push_back(rhs); +return std::move(lhs); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{contains}{basic_string_view}% +\rSec3[string.cmp]{Non-member comparison operator functions} \begin{itemdecl} -constexpr bool contains(basic_string_view x) const noexcept; -constexpr bool contains(charT x) const noexcept; -constexpr bool contains(const charT* x) const; -\end{itemdecl} +template + constexpr bool + operator==(const basic_string& lhs, + const basic_string& rhs) noexcept; +template + constexpr bool operator==(const basic_string& lhs, + const charT* rhs); +template + constexpr @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const basic_string& rhs) noexcept; +template + constexpr @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const charT* rhs); +\end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return find(x) != npos;} +Let \tcode{\placeholder{op}} be the operator. +Equivalent to: +\begin{codeblock} +return basic_string_view(lhs) @\placeholder{op}@ basic_string_view(rhs); +\end{codeblock} \end{itemdescr} -\rSec3[string.view.find]{Searching} +\rSec3[string.special]{\tcode{swap}} -\pnum -Member functions in this subclause have complexity \bigoh{\tcode{size() * str.size()}} at worst, -although implementations should do better. +\indexlibrarymember{swap}{basic_string}% +\begin{itemdecl} +template + constexpr void + swap(basic_string& lhs, + basic_string& rhs) + noexcept(noexcept(lhs.swap(rhs))); +\end{itemdecl} +\begin{itemdescr} \pnum -Let \placeholder{F} be one of -\tcode{find}, -\tcode{rfind}, -\tcode{find_first_of}, -\tcode{find_last_of}, -\tcode{find_first_not_of}, -and -\tcode{find_last_not_of}. -\begin{itemize} -\item -Each member function of the form -\begin{codeblock} -constexpr @\placeholder{return-type}@ @\placeholder{F}@(const charT* s, size_type pos) const; -\end{codeblock} -has effects equivalent to: \tcode{return \placeholder{F}(basic_string_view(s), pos);} - -\item -Each member function of the form -\begin{codeblock} -constexpr @\placeholder{return-type}@ @\placeholder{F}@(const charT* s, size_type pos, size_type n) const; -\end{codeblock} -has effects equivalent to: \tcode{return \placeholder{F}(basic_string_view(s, n), pos);} +\effects +Equivalent to \tcode{lhs.swap(rhs)}. +\end{itemdescr} -\item -Each member function of the form -\begin{codeblock} -constexpr @\placeholder{return-type}@ @\placeholder{F}@(charT c, size_type pos) const noexcept; -\end{codeblock} -has effects equivalent to: \tcode{return \placeholder{F}(basic_string_view(addressof(c), 1), pos);} -\end{itemize} +\rSec3[string.io]{Inserters and extractors} -\indexlibrarymember{find}{basic_string_view}% +\indexlibrarymember{operator>>}{basic_string}% \begin{itemdecl} -constexpr size_type find(basic_string_view str, size_type pos = 0) const noexcept; +template + basic_istream& + operator>>(basic_istream& is, basic_string& str); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold: +\effects +Behaves as a formatted input function\iref{istream.formatted.reqmts}. +After constructing a \tcode{sentry} object, +if the \tcode{sentry} object returns \tcode{true} +when converted to a value of type \tcode{bool}, +calls \tcode{str.erase()} +and then extracts characters from \tcode{is} and appends them +to \tcode{str} as if by calling +\tcode{str.append(1, c)}. +If +\tcode{is.width()} +is greater than zero, the maximum +number \tcode{n} of characters appended is +\tcode{is.width()}; +otherwise \tcode{n} is +\tcode{str.max_size()}. +Characters are extracted and appended until any of the following +occurs: \begin{itemize} \item -\tcode{pos <= xpos} +\textit{n} +characters are stored; \item -\tcode{xpos + str.size() <= size()} +end-of-file occurs on the input sequence; \item -\tcode{traits::eq(at(xpos + I), str.at(I))} for all elements \tcode{I} of the string referenced by \tcode{str}. +\tcode{isspace(c, is.getloc())} +is \tcode{true} for the next available input character +\textit{c}. \end{itemize} \pnum -\effects -Determines \tcode{xpos}. +After the last character (if any) is extracted, +\tcode{is.width(0)} +is called and the +\tcode{sentry} +object is destroyed. + +\pnum +If the function extracts no characters, it calls +\tcode{is.setstate(ios_base::failbit)}, +which may throw +\tcode{ios_base::fail\-ure}\iref{iostate.flags}. \pnum \returns -\tcode{xpos} if the function can determine such a value for \tcode{xpos}. -Otherwise, returns \tcode{npos}. +\tcode{is}. \end{itemdescr} -\indexlibrarymember{rfind}{basic_string_view}% +\indexlibrarymember{operator<<}{basic_string}% \begin{itemdecl} -constexpr size_type rfind(basic_string_view str, size_type pos = npos) const noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, + const basic_string& str); \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{xpos} be the highest position, if possible, such that the following conditions hold: -\begin{itemize} -\item -\tcode{xpos <= pos} -\item -\tcode{xpos + str.size() <= size()} -\item -\tcode{traits::eq(at(xpos + I), str.at(I))} for all elements \tcode{I} of the string referenced by \tcode{str}. -\end{itemize} - \pnum \effects -Determines \tcode{xpos}. - -\pnum -\returns -\tcode{xpos} if the function can determine such a value for \tcode{xpos}. -Otherwise, returns \tcode{npos}. +Equivalent to: \tcode{return os << basic_string_view(str);} \end{itemdescr} -\indexlibrarymember{find_first_of}{basic_string_view}% +\indexlibrarymember{getline}{basic_string}% \begin{itemdecl} -constexpr size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept; +template + basic_istream& + getline(basic_istream& is, + basic_string& str, + charT delim); +template + basic_istream& + getline(basic_istream&& is, + basic_string& str, + charT delim); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold: +\effects +Behaves as an unformatted input function\iref{istream.unformatted}, +except that it does not affect the value returned by subsequent calls to +\tcode{basic_istream<>::gcount()}. +After constructing a \tcode{sentry} object, +if the \tcode{sentry} object returns \tcode{true} +when converted to a value of type \tcode{bool}, +calls \tcode{str.erase()} +and then extracts characters from \tcode{is} and appends them +to \tcode{str} as if by calling +\tcode{str.append(1, c)} +until any of the following occurs: \begin{itemize} \item -\tcode{pos <= xpos} +end-of-file occurs on the input sequence +(in which case, the +\tcode{getline} +function calls +\tcode{is.setstate(\brk{}ios_base::eofbit)}). \item -\tcode{xpos < size()} +\tcode{traits::eq(c, delim)} +for the next available input character +\textit{c} +(in which case, +\textit{c} +is extracted but not appended)\iref{iostate.flags} \item -\tcode{traits::eq(at(xpos), str.at(I))} for some element \tcode{I} of the string referenced by \tcode{str}. +\tcode{str.max_size()} +characters are stored +(in which case, +the function calls +\tcode{is.setstate(ios_base::fail\-bit))}\iref{iostate.flags} \end{itemize} \pnum -\effects -Determines \tcode{xpos}. +The conditions are tested in the order shown. +In any case, +after the last character is extracted, the +\tcode{sentry} +object is destroyed. + +\pnum +If the function extracts no characters, it calls +\tcode{is.setstate(ios_base::fail\-bit)} +which may throw +\tcode{ios_base::fail\-ure}\iref{iostate.flags}. \pnum \returns -\tcode{xpos} if the function can determine such a value for \tcode{xpos}. -Otherwise, returns \tcode{npos}. +\tcode{is}. \end{itemdescr} -\indexlibrarymember{find_last_of}{basic_string_view}% +\indexlibrarymember{getline}{basic_string}% \begin{itemdecl} -constexpr size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept; +template + basic_istream& + getline(basic_istream& is, + basic_string& str); +template + basic_istream& + getline(basic_istream&& is, + basic_string& str); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{xpos} be the highest position, if possible, such that the following conditions hold: -\begin{itemize} -\item -\tcode{xpos <= pos} -\item -\tcode{xpos < size()} -\item -\tcode{traits::eq(at(xpos), str.at(I))} for some element \tcode{I} of the string referenced by \tcode{str}. -\end{itemize} +\returns +\tcode{getline(is, str, is.widen('\textbackslash n'))}. +\end{itemdescr} -\pnum -\effects -Determines \tcode{xpos}. +\rSec3[string.erasure]{Erasure} +\indexlibrarymember{erase}{basic_string}% +\begin{itemdecl} +template + constexpr typename basic_string::size_type + erase(basic_string& c, const U& value); +\end{itemdecl} + +\begin{itemdescr} \pnum -\returns -\tcode{xpos} if the function can determine such a value for \tcode{xpos}. -Otherwise, returns \tcode{npos}. +\effects +Equivalent to: +\begin{codeblock} +auto it = remove(c.begin(), c.end(), value); +auto r = distance(it, c.end()); +c.erase(it, c.end()); +return r; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{find_first_not_of}{basic_string_view}% +\indexlibrarymember{erase_if}{basic_string}% \begin{itemdecl} -constexpr size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept; +template + constexpr typename basic_string::size_type + erase_if(basic_string& c, Predicate pred); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold: -\begin{itemize} -\item -\tcode{pos <= xpos} -\item -\tcode{xpos < size()} -\item -\tcode{traits::eq(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. -\end{itemize} +\effects +Equivalent to: +\begin{codeblock} +auto it = remove_if(c.begin(), c.end(), pred); +auto r = distance(it, c.end()); +c.erase(it, c.end()); +return r; +\end{codeblock} +\end{itemdescr} + +\rSec2[string.conversions]{Numeric conversions} + +\indexlibraryglobal{stoi}% +\indexlibraryglobal{stol}% +\indexlibraryglobal{stoul}% +\indexlibraryglobal{stoll}% +\indexlibraryglobal{stoull}% +\begin{itemdecl} +int stoi(const string& str, size_t* idx = nullptr, int base = 10); +long stol(const string& str, size_t* idx = nullptr, int base = 10); +unsigned long stoul(const string& str, size_t* idx = nullptr, int base = 10); +long long stoll(const string& str, size_t* idx = nullptr, int base = 10); +unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10); +\end{itemdecl} +\begin{itemdescr} \pnum \effects -Determines \tcode{xpos}. +The first two functions call \tcode{strtol(str.c_str(), ptr, base)}, +and the last three functions call \tcode{strtoul(str.c_str(), ptr, base)}, +\tcode{strtoll(str.c_str(), ptr, base)}, and \tcode{strtoull(\brk{}str.c_str(), ptr, +base)}, respectively. Each function returns the converted result, if any. The +argument \tcode{ptr} designates a pointer to an object internal to the function +that is used to determine what to store at \tcode{*idx}. If the function does +not throw an exception and \tcode{idx != nullptr}, the function stores in \tcode{*idx} +the index of the first unconverted element of \tcode{str}. \pnum \returns -\tcode{xpos} if the function can determine such a value for \tcode{xpos}. Otherwise, returns \tcode{npos}. +The converted result. + +\pnum +\throws +\tcode{invalid_argument} if \tcode{strtol}, \tcode{strtoul}, +\tcode{strtoll}, or \tcode{strtoull} reports that no conversion can be +performed. Throws \tcode{out_of_range} if \tcode{strtol}, \tcode{strtoul}, +\tcode{strtoll} or \tcode{strtoull} sets \tcode{errno} to \tcode{ERANGE}, +or if the converted value is outside the range of representable values +for the return type. \end{itemdescr} -\indexlibrarymember{find_last_not_of}{basic_string_view}% +\indexlibraryglobal{stof}% +\indexlibraryglobal{stod}% +\indexlibraryglobal{stold}% \begin{itemdecl} -constexpr size_type find_last_not_of(basic_string_view str, size_type pos = npos) const noexcept; +float stof(const string& str, size_t* idx = nullptr); +double stod(const string& str, size_t* idx = nullptr); +long double stold(const string& str, size_t* idx = nullptr); \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{xpos} be the highest position, if possible, such that the following conditions hold: -\begin{itemize} -\item -\tcode{xpos <= pos} -\item -\tcode{xpos < size()} -\item -\tcode{traits::eq(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. -\end{itemize} - \pnum \effects -Determines \tcode{xpos}. +These functions call +\tcode{strtof(str.c_str(), ptr)}, \tcode{strtod(str.c_str(), ptr)}, and +\tcode{strtold(\brk{}str.c_str(), ptr)}, respectively. Each function returns +the converted result, if any. The argument \tcode{ptr} designates a pointer to +an object internal to the function that is used to determine what to store at +\tcode{*idx}. If the function does not throw an exception and \tcode{idx != nullptr}, +the function stores in \tcode{*idx} the index of the first unconverted element +of \tcode{str}. \pnum \returns -\tcode{xpos} if the function can determine such a value for \tcode{xpos}. -Otherwise, returns \tcode{npos}. -\end{itemdescr} +The converted result. -\rSec2[string.view.deduct]{Deduction guides} +\pnum +\throws +\tcode{invalid_argument} if \tcode{strtof}, \tcode{strtod}, or +\tcode{strtold} reports that no conversion can be performed. Throws +\tcode{out_of_range} if \tcode{strtof}, \tcode{strtod}, or +\tcode{strtold} sets \tcode{errno} to \tcode{ERANGE} +or if the converted value is outside the range of representable +values for the return type. +\end{itemdescr} +\indexlibraryglobal{to_string}% \begin{itemdecl} -template - basic_string_view(It, End) -> basic_string_view>; +string to_string(int val); +string to_string(unsigned val); +string to_string(long val); +string to_string(unsigned long val); +string to_string(long long val); +string to_string(unsigned long long val); +string to_string(float val); +string to_string(double val); +string to_string(long double val); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item \tcode{It} satisfies \libconcept{contiguous_iterator}. -\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}}. -\end{itemize} +\returns +Each function returns a \tcode{string} object holding the character +representation of the value of its argument that would be generated by calling +\tcode{sprintf(buf, fmt, val)} with a format specifier of +\tcode{"\%d"}, +\tcode{"\%u"}, +\tcode{"\%ld"}, +\tcode{"\%lu"}, +\tcode{"\%lld"}, \tcode{"\%llu"}, +\tcode{"\%f"}, +\tcode{"\%f"}, +or \tcode{"\%Lf"}, respectively, where \tcode{buf} designates an internal +character buffer of sufficient size. \end{itemdescr} +\indexlibraryglobal{stoi}% +\indexlibraryglobal{stol}% +\indexlibraryglobal{stoul}% +\indexlibraryglobal{stoll}% +\indexlibraryglobal{stoull}% \begin{itemdecl} -template - basic_string_view(R&&) -> basic_string_view>; +int stoi(const wstring& str, size_t* idx = nullptr, int base = 10); +long stol(const wstring& str, size_t* idx = nullptr, int base = 10); +unsigned long stoul(const wstring& str, size_t* idx = nullptr, int base = 10); +long long stoll(const wstring& str, size_t* idx = nullptr, int base = 10); +unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}}. -\end{itemdescr} - -\rSec2[string.view.comparison]{Non-member comparison functions} +\effects +The first two functions call \tcode{wcstol(str.c_str(), ptr, base)}, +and the last three functions call \tcode{wcstoul(str.c_str(), ptr, base)}, +\tcode{wcstoll(str.c_str(), ptr, base)}, and \tcode{wcstoull(\brk{}str.c_str(), ptr, +base)}, respectively. Each function returns the converted result, if any. The +argument \tcode{ptr} designates a pointer to an object internal to the function +that is used to determine what to store at \tcode{*idx}. If the function does +not throw an exception and \tcode{idx != nullptr}, the function stores in \tcode{*idx} +the index of the first unconverted element of \tcode{str}. \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; -\end{itemdecl} +\returns +The converted result. -\begin{itemdescr} \pnum -\returns -\tcode{lhs.compare(rhs) == 0}. +\throws +\tcode{invalid_argument} if \tcode{wcstol}, \tcode{wcstoul}, \tcode{wcstoll}, or +\tcode{wcstoull} reports that no conversion can be performed. Throws +\tcode{out_of_range} if the converted value is outside the range of representable values +for the return type. \end{itemdescr} -\indexlibrarymember{operator<=>}{basic_string_view}% +\indexlibraryglobal{stof}% +\indexlibraryglobal{stod}% +\indexlibraryglobal{stold}% \begin{itemdecl} -template - constexpr @\seebelow@ operator<=>(basic_string_view lhs, - @\itcorr@ basic_string_view rhs) noexcept; +float stof(const wstring& str, size_t* idx = nullptr); +double stod(const wstring& str, size_t* idx = nullptr); +long double stold(const wstring& str, size_t* idx = nullptr); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{R} denote the type \tcode{traits::comparison_category} if -that \grammarterm{qualified-id} is valid and denotes a type\iref{temp.deduct}, -otherwise \tcode{R} is \tcode{weak_ordering}. +\effects +These functions call \tcode{wcstof(str.c_str(), ptr)}, +\tcode{wcstod(str.c_str(), ptr)}, and \tcode{wcstold(\brk{}str.c_str(), ptr)}, +respectively. Each function returns the converted +result, if any. The argument \tcode{ptr} designates a pointer to an object internal to +the function that is used to determine what to store at \tcode{*idx}. If the function +does not throw an exception and \tcode{idx != nullptr}, the function stores in \tcode{*idx} +the index of the first unconverted element of \tcode{str}. \pnum -\mandates -\tcode{R} denotes a comparison category type\iref{cmp.categories}. +\returns +The converted result. \pnum -\returns -\tcode{static_cast(lhs.compare(rhs) <=> 0)}. +\throws +\tcode{invalid_argument} if \tcode{wcstof}, \tcode{wcstod}, or \tcode{wcstold} reports that no +conversion can be performed. Throws \tcode{out_of_range} if \tcode{wcstof}, \tcode{wcstod}, or +\tcode{wcstold} sets \tcode{errno} to \tcode{ERANGE}. \end{itemdescr} -\rSec2[string.view.io]{Inserters and extractors} - -\indexlibrarymember{operator<<}{basic_string_view}% +\indexlibraryglobal{to_wstring}% \begin{itemdecl} -template - basic_ostream& - operator<<(basic_ostream& os, basic_string_view str); +wstring to_wstring(int val); +wstring to_wstring(unsigned val); +wstring to_wstring(long val); +wstring to_wstring(unsigned long val); +wstring to_wstring(long long val); +wstring to_wstring(unsigned long long val); +wstring to_wstring(float val); +wstring to_wstring(double val); +wstring to_wstring(long double val); \end{itemdecl} \begin{itemdescr} -\pnum -\effects -Behaves as a formatted output -function\iref{ostream.formatted.reqmts} of \tcode{os}. Forms a character sequence -\tcode{seq}, initially consisting of the elements defined by the range -\range{str.begin()}{str.end()}. Determines padding for \tcode{seq} -as described in~\ref{ostream.formatted.reqmts}. -Then inserts \tcode{seq} as if by calling -\tcode{os.rdbuf()->sputn(\brk{}seq, n)}, where \tcode{n} is the larger -of \tcode{os.width()} and \tcode{str.size()}; -then calls \tcode{os.\brk{}width(0)}. - \pnum \returns -\tcode{os} +Each function returns a \tcode{wstring} object holding the character +representation of the value of its argument that would be generated by calling +\tcode{swprintf(buf, buffsz, fmt, val)} with a format specifier of +\tcode{L"\%d"}, +\tcode{L"\%u"}, +\tcode{L"\%ld"}, +\tcode{L"\%lu"}, +\tcode{L"\%lld"}, +\tcode{L"\%llu"}, +\tcode{L"\%f"}, +\tcode{L"\%f"}, +or \tcode{L"\%Lf"}, respectively, where \tcode{buf} designates an +internal character buffer of sufficient size \tcode{buffsz}. \end{itemdescr} -\rSec2[string.view.hash]{Hash support} +\rSec2[basic.string.hash]{Hash support} -\indexlibrarymember{hash}{string_view}% -\indexlibrarymember{hash}{u8string_view}% -\indexlibrarymember{hash}{u16string_view}% -\indexlibrarymember{hash}{u32string_view}% -\indexlibrarymember{hash}{wstring_view}% +\indexlibrarymember{hash}{string}% +\indexlibrarymember{hash}{u16string}% +\indexlibrarymember{hash}{u32string}% +\indexlibrarymember{hash}{wstring}% +\indexlibrarymember{hash}{pmr::string}% +\indexlibrarymember{hash}{pmr::u16string}% +\indexlibrarymember{hash}{pmr::u32string}% +\indexlibrarymember{hash}{pmr::wstring}% \begin{itemdecl} -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; \end{itemdecl} \begin{itemdescr} \pnum -The specialization is enabled\iref{unord.hash}. -\begin{note} -The hash value of a string view object is equal to the hash value of -the corresponding string object\iref{basic.string.hash}. -\end{note} +If \tcode{S} is one of these string types, +\tcode{SV} is the corresponding string view type, and +\tcode{s} is an object of type \tcode{S}, +then \tcode{hash()(s) == hash()(SV(s))}. \end{itemdescr} -\rSec2[string.view.literals]{Suffix for \tcode{basic_string_view} literals} +\rSec2[basic.string.literals]{Suffix for \tcode{basic_string} literals} -\indexlibrarymember{operator""""sv}{string_view}% +\indexlibrarymember{operator""""s}{string}% \begin{itemdecl} -constexpr string_view operator""sv(const char* str, size_t len) noexcept; +constexpr string operator""s(const char* str, size_t len); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{string_view\{str, len\}}. +\tcode{string\{str, len\}}. \end{itemdescr} -\indexlibrarymember{operator""""sv}{u8string_view}% +\indexlibrarymember{operator""""s}{u8string}% \begin{itemdecl} -constexpr u8string_view operator""sv(const char8_t* str, size_t len) noexcept; +constexpr u8string operator""s(const char8_t* str, size_t len); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{u8string_view\{str, len\}}. +\tcode{u8string\{str, len\}}. \end{itemdescr} -\indexlibrarymember{operator""""sv}{u16string_view}% +\indexlibrarymember{operator""""s}{u16string}% \begin{itemdecl} -constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept; +constexpr u16string operator""s(const char16_t* str, size_t len); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{u16string_view\{str, len\}}. +\tcode{u16string\{str, len\}}. \end{itemdescr} -\indexlibrarymember{operator""""sv}{u32string_view}% +\indexlibrarymember{operator""""s}{u32string}% \begin{itemdecl} -constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept; +constexpr u32string operator""s(const char32_t* str, size_t len); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{u32string_view\{str, len\}}. +\tcode{u32string\{str, len\}}. \end{itemdescr} -\indexlibrarymember{operator""""sv}{wstring_view}% +\indexlibrarymember{operator""""s}{wstring}% \begin{itemdecl} -constexpr wstring_view operator""sv(const wchar_t* str, size_t len) noexcept; +constexpr wstring operator""s(const wchar_t* str, size_t len); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{wstring_view\{str, len\}}. +\tcode{wstring\{str, len\}}. \end{itemdescr} +\pnum +\begin{note} +The same suffix \tcode{s} is used for \tcode{chrono::duration} literals denoting seconds but there is no conflict, since duration suffixes apply to numbers and string literal suffixes apply to character array literals. +\end{note} \rSec1[c.strings]{Null-terminated sequence utilities} @@ -5772,7 +5869,7 @@ Subsequent calls will store successive UTF-8 code units without consuming any additional input until all the code units have been stored. -If the corresponding Unicode character is U+0000, +If the corresponding Unicode character is \unicode{0000}{null}, the resulting state described is the initial conversion state. \pnum @@ -5781,13 +5878,13 @@ \begin{itemize} \item \tcode{0}, if the next \tcode{n} or fewer bytes complete the multibyte character -that corresponds to the U+0000 Unicode character +that corresponds to the \unicode{0000}{null} Unicode character (which is the value stored). \item between \tcode{1} and \tcode{n} (inclusive), if the next n or fewer bytes complete a valid multibyte character -(which is the value stored); +(whose first (or only) code unit is stored); the value returned is the number of bytes that complete the multibyte character. -\item \tcode{(size_t)(-3)}, if the next character +\item \tcode{(size_t)(-3)}, if the next code unit resulting from a previous call has been stored (no bytes from the input have been consumed by this call). \item \tcode{(size_t)(-2)}, if the next \tcode{n} bytes diff --git a/source/support.tex b/source/support.tex index d3f888b167..40ceef1aae 100644 --- a/source/support.tex +++ b/source/support.tex @@ -219,21 +219,21 @@ void srand(unsigned int seed); // \ref{c.math.abs}, absolute values - int abs(int j); - long int abs(long int j); - long long int abs(long long int j); - float abs(float j); - double abs(double j); - long double abs(long double j); - - long int labs(long int j); - long long int llabs(long long int j); - - div_t div(int numer, int denom); - ldiv_t div(long int numer, long int denom); // see \ref{library.c} - lldiv_t div(long long int numer, long long int denom); // see \ref{library.c} - ldiv_t ldiv(long int numer, long int denom); - lldiv_t lldiv(long long int numer, long long int denom); + constexpr int abs(int j); + constexpr long int abs(long int j); + constexpr long long int abs(long long int j); + constexpr float abs(float j); + constexpr double abs(double j); + constexpr long double abs(long double j); + + constexpr long int labs(long int j); + constexpr long long int llabs(long long int j); + + constexpr div_t div(int numer, int denom); + constexpr ldiv_t div(long int numer, long int denom); // see \ref{library.c} + constexpr lldiv_t div(long long int numer, long long int denom); // see \ref{library.c} + constexpr ldiv_t ldiv(long int numer, long int denom); + constexpr lldiv_t lldiv(long long int numer, long long int denom); } \end{codeblock} @@ -573,6 +573,7 @@ #define @\defnlibxname{cpp_lib_atomic_value_initialization}@ 201911L // also in \libheader{atomic}, \libheader{memory} #define @\defnlibxname{cpp_lib_atomic_wait}@ 201907L // also in \libheader{atomic} #define @\defnlibxname{cpp_lib_barrier}@ 201907L // also in \libheader{barrier} +#define @\defnlibxname{cpp_lib_bind_back}@ 202202L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_bind_front}@ 201907L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_bit_cast}@ 201806L // also in \libheader{bit} #define @\defnlibxname{cpp_lib_bitops}@ 201907L // also in \libheader{bit} @@ -589,11 +590,12 @@ #define @\defnlibxname{cpp_lib_complex_udls}@ 201309L // also in \libheader{complex} #define @\defnlibxname{cpp_lib_concepts}@ 202002L // also in \libheader{concepts} #define @\defnlibxname{cpp_lib_constexpr_algorithms}@ 201806L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_constexpr_cmath}@ 202202L // also in \libheader{cmath}, \libheader{cstdlib} #define @\defnlibxname{cpp_lib_constexpr_complex}@ 201711L // also in \libheader{complex} #define @\defnlibxname{cpp_lib_constexpr_dynamic_alloc}@ 201907L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_constexpr_functional}@ 201907L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_constexpr_iterator}@ 201811L // also in \libheader{iterator} -#define @\defnlibxname{cpp_lib_constexpr_memory}@ 201811L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_constexpr_memory}@ 202202L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_constexpr_numeric}@ 201911L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_constexpr_string}@ 201907L // also in \libheader{string} #define @\defnlibxname{cpp_lib_constexpr_string_view}@ 201811L // also in \libheader{string_view} @@ -601,6 +603,9 @@ #define @\defnlibxname{cpp_lib_constexpr_typeinfo}@ 202106L // also in \libheader{typeinfo} #define @\defnlibxname{cpp_lib_constexpr_utility}@ 201811L // also in \libheader{utility} #define @\defnlibxname{cpp_lib_constexpr_vector}@ 201907L // also in \libheader{vector} +#define @\defnlibxname{cpp_lib_containers_ranges}@ 202202L + // also in \libheader{vector}, \libheader{list}, \libheader{forward_list}, \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set}, + // \libheader{deque}, \libheader{queue}, \libheader{stack}, \libheader{string} #define @\defnlibxname{cpp_lib_coroutine}@ 201902L // also in \libheader{coroutine} #define @\defnlibxname{cpp_lib_destroying_delete}@ 201806L // also in \libheader{new} #define @\defnlibxname{cpp_lib_enable_shared_from_this}@ 201603L // also in \libheader{memory} @@ -610,6 +615,7 @@ // \libheader{unordered_set} #define @\defnlibxname{cpp_lib_exchange_function}@ 201304L // also in \libheader{utility} #define @\defnlibxname{cpp_lib_execution}@ 201902L // also in \libheader{execution} +#define @\defnlibxname{cpp_lib_expected}@ 202202L // also in \libheader{expected} #define @\defnlibxname{cpp_lib_filesystem}@ 201703L // also in \libheader{filesystem} #define @\defnlibxname{cpp_lib_format}@ 202110L // also in \libheader{format} #define @\defnlibxname{cpp_lib_gcd_lcm}@ 201606L // also in \libheader{numeric} @@ -650,7 +656,6 @@ #define @\defnlibxname{cpp_lib_math_constants}@ 201907L // also in \libheader{numbers} #define @\defnlibxname{cpp_lib_math_special_functions}@ 201603L // also in \libheader{cmath} #define @\defnlibxname{cpp_lib_memory_resource}@ 201603L // also in \libheader{memory_resource} -#define @\defnlibxname{cpp_lib_monadic_optional}@ 202110L // also in \libheader{optional} #define @\defnlibxname{cpp_lib_move_only_function}@ 202110L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_node_extract}@ 201606L // also in \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set} @@ -659,16 +664,23 @@ // \libheader{unordered_map}, \libheader{unordered_set}, \libheader{vector} #define @\defnlibxname{cpp_lib_not_fn}@ 201603L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_null_iterators}@ 201304L // also in \libheader{iterator} -#define @\defnlibxname{cpp_lib_optional}@ 202106L // also in \libheader{optional} +#define @\defnlibxname{cpp_lib_optional}@ 202110L // also in \libheader{optional} #define @\defnlibxname{cpp_lib_out_ptr}@ 202106L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_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_quoted_string_io}@ 201304L // also in \libheader{iomanip} -#define @\defnlibxname{cpp_lib_ranges}@ 202110L +#define @\defnlibxname{cpp_lib_ranges}@ 202202L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_chunk}@ 202202L // also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_chunk_by}@ 202202L // also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_iota}@ 202202L // also in \libheader{numeric} +#define @\defnlibxname{cpp_lib_ranges_join_with}@ 202202L // also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_slide}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_starts_ends_with}@ 202106L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // also in \libheader{ranges}, \libheader{tuple}, \libheader{utility} #define @\defnlibxname{cpp_lib_raw_memory_algorithms}@ 201606L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_reference_from_temporary}@ 202202L // also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_remove_cvref}@ 201711L // also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_result_of_sfinae}@ 201210L // also in \libheader{functional}, \libheader{type_traits} #define @\defnlibxname{cpp_lib_robust_nonmodifying_seq_ops}@ 201304L // also in \libheader{algorithm} @@ -679,7 +691,7 @@ #define @\defnlibxname{cpp_lib_shared_ptr_arrays}@ 201707L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_shared_ptr_weak_type}@ 201606L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_shared_timed_mutex}@ 201402L // also in \libheader{shared_mutex} -#define @\defnlibxname{cpp_lib_shift}@ 201806L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_shift}@ 202202L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_smart_ptr_for_overwrite}@ 202002L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_source_location}@ 201907L // also in \libheader{source_location} #define @\defnlibxname{cpp_lib_span}@ 202002L // also in \libheader{span} @@ -706,6 +718,7 @@ #define @\defnlibxname{cpp_lib_type_trait_variable_templates}@ 201510L // also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_uncaught_exceptions}@ 201411L // also in \libheader{exception} #define @\defnlibxname{cpp_lib_unordered_map_try_emplace}@ 201411L // also in \libheader{unordered_map} +#define @\defnlibxname{cpp_lib_unreachable}@ 202202L // also in \libheader{utility} #define @\defnlibxname{cpp_lib_unwrap_ref}@ 201811L // also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_variant}@ 202106L // also in \libheader{variant} #define @\defnlibxname{cpp_lib_void_t}@ 201411L // also in \libheader{type_traits} @@ -3212,7 +3225,7 @@ \remarks The message may be a null-terminated multibyte string\iref{multibyte.strings}, suitable for conversion and display as a -\tcode{wstring}~(\ref{string.classes}, \ref{locale.codecvt}). +\tcode{wstring}\iref{string.classes,locale.codecvt}. \end{itemdescr} \rSec2[bad.cast]{Class \tcode{bad_cast}} @@ -3622,7 +3635,7 @@ \remarks The message may be a null-terminated multibyte string\iref{multibyte.strings}, suitable for conversion and display as a -\tcode{wstring}~(\ref{string.classes}, \ref{locale.codecvt}). +\tcode{wstring}\iref{string.classes,locale.codecvt}. The return value remains valid until the exception object from which it is obtained is destroyed or a non-\keyword{const} member function of the exception object is called. @@ -4264,7 +4277,8 @@ \pnum The \tcode{partial_ordering} type is typically used as the result type of a three-way comparison operator\iref{expr.spaceship} -that (a) admits all of the six two-way comparison operators (\ref{expr.rel}, \ref{expr.eq}), +that (a) admits all of the six +two-way comparison operators\iref{expr.rel,expr.eq}, (b) does not imply substitutability, and (c) permits two values to be incomparable. \begin{footnote} @@ -4381,7 +4395,8 @@ \pnum The \tcode{weak_ordering} type is typically used as the result type of a three-way comparison operator\iref{expr.spaceship} -that (a) admits all of the six two-way comparison operators (\ref{expr.rel}, \ref{expr.eq}), +that (a) admits all of the six +two-way comparison operators\iref{expr.rel,expr.eq}, and (b) does not imply substitutability. \indexlibraryglobal{weak_ordering}% @@ -4505,7 +4520,8 @@ \pnum The \tcode{strong_ordering} type is typically used as the result type of a three-way comparison operator\iref{expr.spaceship} -that (a) admits all of the six two-way comparison operators (\ref{expr.rel}, \ref{expr.eq}), +that (a) admits all of the six +two-way comparison operators\iref{expr.rel,expr.eq}, and (b) does imply substitutability. \indexlibraryglobal{strong_ordering}% @@ -4835,7 +4851,7 @@ a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and \tcode{F}, the expression \tcode{strong_order(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to the following: +is expression-equivalent\iref{defns.expression.equivalent} to the following: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, @@ -4873,7 +4889,7 @@ a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and \tcode{F}, the expression \tcode{weak_order(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to the following: +is expression-equivalent\iref{defns.expression.equivalent} to the following: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, @@ -4925,7 +4941,7 @@ a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and \tcode{F}, the expression \tcode{partial_order(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to the following: +is expression-equivalent\iref{defns.expression.equivalent} to the following: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, @@ -4957,7 +4973,7 @@ denotes a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and {F}, the expression \tcode{compare_strong_order_fallback(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to: +is expression-equivalent\iref{defns.expression.equivalent} to: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, @@ -4989,7 +5005,7 @@ a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and \tcode{F}, the expression \tcode{compare_weak_order_fallback(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to: +is expression-equivalent\iref{defns.expression.equivalent} to: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, @@ -5021,7 +5037,7 @@ a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and \tcode{F}, the expression \tcode{compare_partial_order_fallback(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to: +is expression-equivalent\iref{defns.expression.equivalent} to: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, @@ -5856,7 +5872,7 @@ \item initialization of a variable with static storage duration -requiring dynamic initialization~(\ref{basic.start.dynamic}, \ref{stmt.dcl}) +requiring dynamic initialization\iref{basic.start.dynamic,stmt.dcl} \begin{footnote} Such initialization can occur because it is the first odr-use\iref{term.odr.use} of that variable. \end{footnote} diff --git a/source/templates.tex b/source/templates.tex index c34d77a66a..dce8fc693d 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -428,8 +428,8 @@ &i; // error: address of non-reference template-parameter &a; // OK int& ri = i; // error: attempt to bind non-const reference to temporary - const int& cri = i; // OK: const reference binds to temporary - const A& ra = a; // OK: const reference binds to a template parameter object + const int& cri = i; // OK, const reference binds to temporary + const A& ra = a; // OK, const reference binds to a template parameter object } \end{codeblock} \end{example} @@ -558,17 +558,6 @@ \end{codeblock} \end{example} -\pnum -A \grammarterm{template-parameter} -shall not be given default arguments by two different declarations -if one is reachable from the other. -\begin{example} -\begin{codeblock} -template class X; -template class X { @\commentellip@ }; // error -\end{codeblock} -\end{example} - \indextext{\idxcode{<}!template and}% \pnum When parsing a @@ -733,9 +722,9 @@ }; template void f(T* p) { T* p1 = p->alloc<200>(); // error: \tcode{<} means less than - T* p2 = p->template alloc<200>(); // OK: \tcode{<} starts template argument list + T* p2 = p->template alloc<200>(); // OK, \tcode{<} starts template argument list T::adjust<100>(); // error: \tcode{<} means less than - T::template adjust<100>(); // OK: \tcode{<} starts template argument list + T::template adjust<100>(); // OK, \tcode{<} starts template argument list } \end{codeblock} \end{example} @@ -812,7 +801,7 @@ template void f(T t) { A a; - a.template f<>(t); // OK: calls template + a.template f<>(t); // OK, calls template a.template f(t); // error: not a \grammarterm{template-id} } @@ -1031,9 +1020,9 @@ class Y { private: struct S { @\commentellip@ }; - X x; // OK: \tcode{S} is accessible + X x; // OK, \tcode{S} is accessible // \tcode{X} has a static member of type \tcode{Y::S} - // OK: even though \tcode{Y::S} is private + // OK, even though \tcode{Y::S} is private }; X y; // error: \tcode{S} not accessible @@ -1072,10 +1061,10 @@ \begin{example} \begin{codeblock} template class String; -String<>* p; // OK: \tcode{String} +String<>* p; // OK, \tcode{String} String* q; // syntax error template class Tuple; -Tuple<>* t; // OK: \tcode{Elements} is empty +Tuple<>* t; // OK, \tcode{Elements} is empty Tuple* u; // syntax error \end{codeblock} \end{example} @@ -1090,8 +1079,8 @@ ~A(); }; void f(A* p, A* q) { - p->A::~A(); // OK: destructor call - q->A::~A(); // OK: destructor call + p->A::~A(); // OK, destructor call + q->A::~A(); // OK, destructor call } \end{codeblock} \end{example} @@ -1168,7 +1157,7 @@ \end{codeblock} \end{example} \begin{note} -A template type argument can be an incomplete type\iref{basic.types}. +A template type argument can be an incomplete type\iref{term.incomplete.type}. \end{note} \rSec2[temp.arg.nontype]{Template non-type arguments} @@ -1387,8 +1376,8 @@ template struct D; template struct E; -eval> eA; // OK: matches partial specialization of \tcode{eval} -eval> eB; // OK: matches partial specialization of \tcode{eval} +eval> eA; // OK, matches partial specialization of \tcode{eval} +eval> eB; // OK, matches partial specialization of \tcode{eval} eval> eC; // error: \tcode{C} does not match \tcode{TT} in partial specialization eval> eD; // error: \tcode{D} does not match \tcode{TT} in partial specialization eval> eE; // error: \tcode{E} does not match \tcode{TT} in partial specialization @@ -1539,7 +1528,7 @@ void f(int); -f('a'); // OK: calls \tcode{f(int)} +f('a'); // OK, calls \tcode{f(int)} \end{codeblock} In the satisfaction of the associated constraints\iref{temp.constr.decl} of \tcode{f}, the constraint \tcode{sizeof(char) > 1} is not satisfied; @@ -1650,9 +1639,11 @@ } \end{codeblock} \end{example} -This similarity includes the situation where a program is ill-formed, no diagnostic required, -when the meaning of the program depends on whether two constructs are equivalent, -and they are functionally equivalent but not equivalent. +As specified in \ref{temp.over.link}, +if the validity or meaning of the program depends on +whether two constructs are equivalent, and +they are functionally equivalent but not equivalent, +the program is ill-formed, no diagnostic required. \begin{example} \begin{codeblock} template void f2() @@ -2285,7 +2276,7 @@ template struct Inner; }; -template void S::f() { } // OK: \grammarterm{template-head}{s} match +template void S::f() { } // OK, \grammarterm{template-head}{s} match template void S::g() { } // error: no matching declaration for \tcode{S} template requires C // ill-formed, no diagnostic required: \grammarterm{template-head}{s} are @@ -2444,9 +2435,9 @@ template struct A { class B; }; -A::B* b1; // OK: requires \tcode{A} to be defined but not \tcode{A::B} +A::B* b1; // OK, requires \tcode{A} to be defined but not \tcode{A::B} template class A::B { }; -A::B b2; // OK: requires \tcode{A::B} to be defined +A::B b2; // OK, requires \tcode{A::B} to be defined \end{codeblock} \end{note} @@ -2483,7 +2474,7 @@ static int i[]; }; template int A::i[4]; // 4 elements -template <> int A::i[] = { 1 }; // OK: 1 element +template <> int A::i[] = { 1 }; // OK, 1 element \end{codeblock} \end{example} @@ -2789,11 +2780,11 @@ // error: different number of arguments specified for \tcode{Args1} and \tcode{Args2} template - void g(Args ... args) { // OK: \tcode{Args} is expanded by the function parameter pack \tcode{args} - f(const_cast(&args)...); // OK: ``\tcode{Args}'' and ``\tcode{args}'' are expanded + void g(Args ... args) { // OK, \tcode{Args} is expanded by the function parameter pack \tcode{args} + f(const_cast(&args)...); // OK, ``\tcode{Args}'' and ``\tcode{args}'' are expanded f(5 ...); // error: pattern does not contain any packs f(args); // error: pack ``\tcode{args}'' is not expanded - f(h(args ...) + args ...); // OK: first ``\tcode{args}'' expanded within \tcode{h}, + f(h(args ...) + args ...); // OK, first ``\tcode{args}'' expanded within \tcode{h}, // second ``\tcode{args}'' expanded within \tcode{f} } \end{codeblock} @@ -2925,7 +2916,7 @@ X x(values...); } -template void f<>(); // OK: \tcode{X<>} has no base classes +template void f<>(); // OK, \tcode{X<>} has no base classes // \tcode{x} is a variable of type \tcode{X<>} that is value-initialized \end{codeblock} \end{example} @@ -3189,7 +3180,7 @@ \pnum A partial specialization may be declared in any scope in which the corresponding primary template -may be defined~(\ref{dcl.meaning}, \ref{class.mem}, \ref{temp.mem}). +may be defined\iref{dcl.meaning,class.mem,temp.mem}. \begin{example} \begin{codeblock} template struct A { @@ -3499,7 +3490,7 @@ If a member template of a class template is partially specialized, the member template partial specializations are member templates of the enclosing class template; -if the enclosing class template is instantiated~(\ref{temp.inst}, \ref{temp.explicit}), +if the enclosing class template is instantiated\iref{temp.inst,temp.explicit}, a declaration for every member template partial specialization is also instantiated as part of creating the members of the class template specialization. @@ -3609,7 +3600,7 @@ \begin{codeblock} template void f(); -template void f(); // OK: overloads the first template +template void f(); // OK, overloads the first template // distinguishable with an explicit template argument list \end{codeblock} \end{note} @@ -3655,7 +3646,7 @@ would satisfy the one-definition rule, except that the tokens used to name types and declarations may differ as long as they name the same entities, and -the tokens used to form \grammarterm{concept-id}s may differ +the tokens used to form concept-ids\iref{temp.names} may differ as long as the two \grammarterm{template-id}{s} are the same\iref{temp.type}. \begin{note} For instance, \tcode{A<42>} and \tcode{A<40+2>} name the same type. @@ -3799,7 +3790,7 @@ when a placement operator delete that is a function template specialization -is selected to match a placement operator new~(\ref{basic.stc.dynamic.deallocation}, \ref{expr.new}); +is selected to match a placement operator new\iref{basic.stc.dynamic.deallocation,expr.new}; \item when a friend function declaration\iref{temp.friend}, an explicit instantiation\iref{temp.explicit} or an explicit specialization\iref{temp.expl.spec} refers to @@ -3959,8 +3950,8 @@ template void g(T); // \#4 void h(int i) { - f(&i); // OK: calls \#2 - g(&i); // OK: calls \#3 + f(&i); // OK, calls \#2 + g(&i); // OK, calls \#3 } \end{codeblock} \end{example} @@ -4030,7 +4021,7 @@ template void f(Q &, C auto &); void g(struct A *ap, struct B *bp) { - f(*ap, *bp); // OK: Can use different methods to produce template parameters + f(*ap, *bp); // OK, can use different methods to produce template parameters } template struct X {}; @@ -4039,7 +4030,7 @@ template bool operator==(T, X); void h() { - X{} == 0; // OK: Correspondence of [\tcode{T}, \tcode{U}, \tcode{V}] and [\tcode{U}, \tcode{V}, \tcode{T}] + X{} == 0; // OK, correspondence of [\tcode{T}, \tcode{U}, \tcode{V}] and [\tcode{U}, \tcode{V}, \tcode{T}] } \end{codeblock} \end{example} @@ -4083,7 +4074,7 @@ template class TT> void g(TT>); -g(v); // OK: \tcode{TT} = \tcode{vector} +g(v); // OK, \tcode{TT} = \tcode{vector} \end{codeblock} \end{example} @@ -4200,7 +4191,8 @@ \pnum A name that appears in a declaration $D$ of a template $T$ is looked up from where it appears -in an unspecified declaration of $T$ that is or is reachable from $D$ and +in an unspecified declaration of $T$ +that either is $D$ itself or is reachable from $D$ and from which no other declaration of $T$ that contains the usage of the name is reachable. If the name is dependent (as specified in \ref{temp.dep}), @@ -4209,8 +4201,8 @@ \begin{note} Some dependent names are also looked up during parsing to determine that they are dependent or to interpret following \tcode{<} tokens. -Uses of other names might be type-dependent or value-dependent -(\ref{temp.dep.expr}, \ref{temp.dep.constexpr}). +Uses of other names might be type-dependent or +value-dependent\iref{temp.dep.expr,temp.dep.constexpr}. A \grammarterm{using-declarator} is never dependent in a specialization and is therefore replaced during lookup for that specialization\iref{basic.lookup}. \end{note} @@ -4221,7 +4213,7 @@ struct D : B { T get() { return operator T(); } // \grammarterm{conversion-function-id} is dependent }; -int f(D d) { return d.get(); } // OK: lookup finds A::operator int +int f(D d) { return d.get(); } // OK, lookup finds A::operator int \end{codeblock} \end{example} \begin{example} @@ -4313,7 +4305,7 @@ void foo() { A a; B b; - f(b); // OK: \tcode{T::X} refers to \tcode{B::X} + f(b); // OK, \tcode{T::X} refers to \tcode{B::X} f(a); // error: \tcode{T::X} refers to the data member \tcode{A::X} not the struct \tcode{A::X} } \end{codeblock} @@ -4446,6 +4438,7 @@ is different from the interpretation of the corresponding construct in any actual instantiation of the template. +\end{itemize} \begin{note} This can happen in situations including the following: \begin{itemize} @@ -4478,7 +4471,6 @@ specialization that was not declared when the template was defined. \end{itemize} \end{note} -\end{itemize} Otherwise, no diagnostic shall be issued for a template for which a valid specialization can be generated. @@ -4536,7 +4528,9 @@ class template itself. Otherwise, it is a \grammarterm{type-name} equivalent to the \grammarterm{template-name} -followed by the \grammarterm{template-parameter}{s} of the class template +followed by +the template argument list\iref{temp.decls.general,temp.arg.general} +of the class template enclosed in \tcode{<>}. \pnum @@ -4578,7 +4572,7 @@ }; template class U = T::Base> struct Third { }; -Third > t; // OK: default argument uses injected-class-name as a template +Third > t; // OK, default argument uses injected-class-name as a template \end{codeblock} \end{example} @@ -4631,7 +4625,7 @@ void f() { char T; // error: \grammarterm{template-parameter} hidden } - friend void T(); // OK: no name bound + friend void T(); // OK, no name bound }; template class X; // error: hidden by \grammarterm{template-parameter} @@ -4646,8 +4640,7 @@ the \grammarterm{template-parameter-list}). \begin{note} The scope of a class template, -including its non-dependent base classes -(\ref{temp.dep.type}, \ref{class.member.lookup}), +including its non-dependent base classes\iref{temp.dep.type,class.member.lookup}, is searched before its template parameter scope. \end{note} \begin{example} @@ -4709,7 +4702,7 @@ \begin{itemize} \item any of the expressions in the \grammarterm{expression-list} is a pack -expansion\iref{temp.variadic}, +expansion\iref{temp.variadic}, or \item any of the expressions or \grammarterm{braced-init-list}{s} @@ -4974,8 +4967,8 @@ }; 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} +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} \end{codeblock} \end{example} @@ -5451,7 +5444,7 @@ export module M; import F; void g(X x) { - f(x); // OK: instantiates \tcode{f} from \tcode{F}, + f(x); // OK, instantiates \tcode{f} from \tcode{F}, // \tcode{operator+} is visible in instantiation context } \end{codeblocktu} @@ -5731,7 +5724,7 @@ If the template selected for the specialization\iref{temp.spec.partial.match} has been declared, but not defined, at the point of instantiation\iref{temp.point}, -the instantiation yields an incomplete class type\iref{basic.types}. +the instantiation yields an incomplete class type\iref{term.incomplete.type}. \begin{example} \begin{codeblock} template class X; @@ -5795,7 +5788,7 @@ struct Outer { template struct Inner; template struct Inner; // \#1a - template struct Inner { }; // \#1b; OK: valid redeclaration of \#1a + template struct Inner { }; // \#1b; OK, valid redeclaration of \#1a template struct Inner { }; // \#2 }; @@ -6244,7 +6237,7 @@ the translation unit containing the explicit instantiation, provided that the associated constraints, if any, of that member are satisfied by the template arguments of the explicit -instantiation~(\ref{temp.constr.decl}, \ref{temp.constr.constr}), +instantiation\iref{temp.constr.decl,temp.constr.constr}, except as described below. \begin{note} In addition, it will typically be an explicit instantiation of certain @@ -6363,7 +6356,7 @@ \pnum An explicit specialization may be declared in any scope in which the corresponding primary template -may be defined~(\ref{dcl.meaning}, \ref{class.mem}, \ref{temp.mem}). +may be defined\iref{dcl.meaning,class.mem,temp.mem}. \pnum An explicit specialization does not introduce a name\iref{basic.scope.scope}. @@ -6383,7 +6376,7 @@ template class X; -template<> class X { @\commentellip@ }; // OK: \tcode{X} is a template +template<> class X { @\commentellip@ }; // OK, \tcode{X} is a template \end{codeblock} \end{example} @@ -6488,7 +6481,7 @@ } template<> void sort(Array& v); // error: specialization after use of primary template -template<> void sort<>(Array& v); // OK: \tcode{sort} not yet used +template<> void sort<>(Array& v); // OK, \tcode{sort} not yet used template struct A { enum E : T; enum class S : T; @@ -6538,7 +6531,7 @@ template class X; // \tcode{X} is a class template template<> class X; -X* p; // OK: pointer to declared class \tcode{X} +X* p; // OK, pointer to declared class \tcode{X} X x; // error: object of incomplete class \tcode{X} \end{codeblock} \end{example} @@ -6587,8 +6580,8 @@ template void f(T) { @\commentellip@ } template inline T g(T) { @\commentellip@ } -template<> inline void f<>(int) { @\commentellip@ } // OK: inline -template<> int g<>(int) { @\commentellip@ } // OK: not inline +template<> inline void f<>(int) { @\commentellip@ } // OK, inline +template<> int g<>(int) { @\commentellip@ } // OK, not inline \end{codeblock} \end{example} @@ -6806,7 +6799,7 @@ \pnum Template arguments shall not be specified when referring to a specialization of -a constructor template~(\ref{class.ctor}, \ref{class.qual}). +a constructor template\iref{class.ctor,class.qual}. \pnum A template argument list may be specified when referring to a specialization @@ -8150,8 +8143,8 @@ void g(A a, B b) { f(a,b); // error: \tcode{T} deduced as both \tcode{A} and \tcode{B} f(b,a); // error: \tcode{T} deduced as both \tcode{A} and \tcode{B} - f(a,a); // OK: \tcode{T} is \tcode{A} - f(b,b); // OK: \tcode{T} is \tcode{B} + f(a,a); // OK, \tcode{T} is \tcode{A} + f(b,b); // OK, \tcode{T} is \tcode{B} } \end{codeblock} @@ -8168,7 +8161,7 @@ int g3( int, char, float); void r() { - f(g1); // OK: \tcode{T} is \tcode{int} and \tcode{U} is \tcode{float} + f(g1); // OK, \tcode{T} is \tcode{int} and \tcode{U} is \tcode{float} f(g2); // error: \tcode{T} deduced as both \tcode{char} and \tcode{int} f(g3); // error: \tcode{U} deduced as both \tcode{char} and \tcode{float} } @@ -8430,7 +8423,7 @@ template void f(int (&a)[i]); int v[10]; void g() { - f(v); // OK: \tcode{T} is \tcode{std::size_t} + f(v); // OK, \tcode{T} is \tcode{std::size_t} } \end{codeblock} \end{example} @@ -8446,11 +8439,11 @@ void g() { int v[10][20]; - f1(v); // OK: \tcode{i} deduced as \tcode{20} + f1(v); // OK, \tcode{i} deduced as \tcode{20} f1<20>(v); // OK f2(v); // error: cannot deduce template-argument \tcode{i} f2<10>(v); // OK - f3(v); // OK: \tcode{i} deduced as \tcode{10} + f3(v); // OK, \tcode{i} deduced as \tcode{10} } \end{codeblock} \end{note} @@ -8530,7 +8523,7 @@ template void g(B); void k2() { B<1> b; - g(b); // OK: cv-qualifiers are ignored on template parameter types + g(b); // OK, cv-qualifiers are ignored on template parameter types } \end{codeblock} \end{example} @@ -8552,7 +8545,7 @@ void h(char,int); int m() { f(&g); // error: ambiguous - f(&h); // OK: void \tcode{h(char,int)} is a unique match + f(&h); // OK, void \tcode{h(char,int)} is a unique match f(&foo); // error: type deduction fails because \tcode{foo} is a template } \end{codeblock} @@ -8566,9 +8559,9 @@ \begin{codeblock} template void f(T = 5, T = 7); void g() { - f(1); // OK: call \tcode{f(1,7)} + f(1); // OK, calls \tcode{f(1,7)} f(); // error: cannot deduce \tcode{T} - f(); // OK: call \tcode{f(5,7)} + f(); // OK, calls \tcode{f(5,7)} } \end{codeblock} \end{example} @@ -8626,7 +8619,7 @@ for explicit instantiations\iref{temp.explicit}, explicit specializations\iref{temp.expl.spec}, and certain friend declarations\iref{temp.friend}. This is also done to determine whether a deallocation function template specialization matches a placement -\tcode{operator new}~(\ref{basic.stc.dynamic.deallocation}, \ref{expr.new}). +\tcode{operator new}\iref{basic.stc.dynamic.deallocation,expr.new}. In all these cases, \tcode{P} is the type of the function template being considered as a potential match and \tcode{A} is either the function type from the declaration diff --git a/source/threads.tex b/source/threads.tex index 4476674e95..b2a90ea8d3 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -1,5 +1,5 @@ %!TEX root = std.tex -\rSec0[thread]{Thread support library} +\rSec0[thread]{Concurrency support library} \rSec1[thread.general]{General} @@ -13,6 +13,8 @@ \ref{thread.req} & Requirements & \\ \rowsep \ref{thread.stoptoken}& Stop tokens & \tcode{} \\ \rowsep \ref{thread.threads} & Threads & \tcode{} \\ \rowsep +\ref{atomics} & Atomic operations & + \tcode{} \tcode{} \tcode{} \\ \rowsep \ref{thread.mutex} & Mutual exclusion & \tcode{}, \tcode{} \\ \rowsep \ref{thread.condition}& Condition variables & \tcode{} \\ \rowsep @@ -2032,6 +2034,3841 @@ Timeout-related exceptions\iref{thread.req.timing}. \end{itemdescr} +\rSec1[atomics]{Atomic operations} + +\rSec2[atomics.general]{General} + +\pnum +Subclause \ref{atomics} describes components for fine-grained atomic access. +This access is provided via operations on atomic objects. + +\rSec2[atomics.syn]{Header \tcode{} synopsis} + +\indexheader{atomic}% +\begin{codeblock} +namespace std { + // \ref{atomics.order}, order and consistency + enum class memory_order : @\unspec@; + template + T kill_dependency(T y) noexcept; +} + +// \ref{atomics.lockfree}, lock-free property +#define ATOMIC_BOOL_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR8_T_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR16_T_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR32_T_LOCK_FREE @\unspec@ +#define ATOMIC_WCHAR_T_LOCK_FREE @\unspec@ +#define ATOMIC_SHORT_LOCK_FREE @\unspec@ +#define ATOMIC_INT_LOCK_FREE @\unspec@ +#define ATOMIC_LONG_LOCK_FREE @\unspec@ +#define ATOMIC_LLONG_LOCK_FREE @\unspec@ +#define ATOMIC_POINTER_LOCK_FREE @\unspec@ + +namespace std { + // \ref{atomics.ref.generic}, class template \tcode{atomic_ref} + template struct atomic_ref; + // \ref{atomics.ref.pointer}, partial specialization for pointers + template struct atomic_ref; + + // \ref{atomics.types.generic}, class template \tcode{atomic} + template struct atomic; + // \ref{atomics.types.pointer}, partial specialization for pointers + template struct atomic; + + // \ref{atomics.nonmembers}, non-member functions + template + bool atomic_is_lock_free(const volatile atomic*) noexcept; + template + bool atomic_is_lock_free(const atomic*) noexcept; + template + void atomic_store(volatile atomic*, typename atomic::value_type) noexcept; + template + void atomic_store(atomic*, typename atomic::value_type) noexcept; + template + void atomic_store_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; + template + void atomic_store_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_load(const volatile atomic*) noexcept; + template + T atomic_load(const atomic*) noexcept; + template + T atomic_load_explicit(const volatile atomic*, memory_order) noexcept; + template + T atomic_load_explicit(const atomic*, memory_order) noexcept; + template + T atomic_exchange(volatile atomic*, typename atomic::value_type) noexcept; + template + T atomic_exchange(atomic*, typename atomic::value_type) noexcept; + template + T atomic_exchange_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_exchange_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; + template + bool atomic_compare_exchange_weak(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; + template + bool atomic_compare_exchange_weak(atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; + template + bool atomic_compare_exchange_strong(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; + template + bool atomic_compare_exchange_strong(atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; + template + bool atomic_compare_exchange_weak_explicit(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; + template + bool atomic_compare_exchange_weak_explicit(atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; + template + bool atomic_compare_exchange_strong_explicit(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; + template + bool atomic_compare_exchange_strong_explicit(atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; + + template + T atomic_fetch_add(volatile atomic*, typename atomic::difference_type) noexcept; + template + T atomic_fetch_add(atomic*, typename atomic::difference_type) noexcept; + template + T atomic_fetch_add_explicit(volatile atomic*, typename atomic::difference_type, + memory_order) noexcept; + template + T atomic_fetch_add_explicit(atomic*, typename atomic::difference_type, + memory_order) noexcept; + template + T atomic_fetch_sub(volatile atomic*, typename atomic::difference_type) noexcept; + template + T atomic_fetch_sub(atomic*, typename atomic::difference_type) noexcept; + template + T atomic_fetch_sub_explicit(volatile atomic*, typename atomic::difference_type, + memory_order) noexcept; + template + T atomic_fetch_sub_explicit(atomic*, typename atomic::difference_type, + memory_order) noexcept; + template + T atomic_fetch_and(volatile atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_and(atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_and_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_and_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_or(volatile atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_or(atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_or_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_or_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_xor(volatile atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_xor(atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_xor_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_xor_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; + + template + void atomic_wait(const volatile atomic*, typename atomic::value_type); + template + void atomic_wait(const atomic*, typename atomic::value_type); + template + void atomic_wait_explicit(const volatile atomic*, typename atomic::value_type, + memory_order); + template + void atomic_wait_explicit(const atomic*, typename atomic::value_type, + memory_order); + template + void atomic_notify_one(volatile atomic*); + template + void atomic_notify_one(atomic*); + template + void atomic_notify_all(volatile atomic*); + template + void atomic_notify_all(atomic*); + + // \ref{atomics.alias}, type aliases + using atomic_bool = atomic; + using atomic_char = atomic; + using atomic_schar = atomic; + using atomic_uchar = atomic; + using atomic_short = atomic; + using atomic_ushort = atomic; + using atomic_int = atomic; + using atomic_uint = atomic; + using atomic_long = atomic; + using atomic_ulong = atomic; + using atomic_llong = atomic; + using atomic_ullong = atomic; + using atomic_char8_t = atomic; + using atomic_char16_t = atomic; + using atomic_char32_t = atomic; + using atomic_wchar_t = atomic; + + using atomic_int8_t = atomic; + using atomic_uint8_t = atomic; + using atomic_int16_t = atomic; + using atomic_uint16_t = atomic; + using atomic_int32_t = atomic; + using atomic_uint32_t = atomic; + using atomic_int64_t = atomic; + using atomic_uint64_t = atomic; + + using atomic_int_least8_t = atomic; + using atomic_uint_least8_t = atomic; + using atomic_int_least16_t = atomic; + using atomic_uint_least16_t = atomic; + using atomic_int_least32_t = atomic; + using atomic_uint_least32_t = atomic; + using atomic_int_least64_t = atomic; + using atomic_uint_least64_t = atomic; + + using atomic_int_fast8_t = atomic; + using atomic_uint_fast8_t = atomic; + using atomic_int_fast16_t = atomic; + using atomic_uint_fast16_t = atomic; + using atomic_int_fast32_t = atomic; + using atomic_uint_fast32_t = atomic; + using atomic_int_fast64_t = atomic; + using atomic_uint_fast64_t = atomic; + + using atomic_intptr_t = atomic; + using atomic_uintptr_t = atomic; + using atomic_size_t = atomic; + using atomic_ptrdiff_t = atomic; + using atomic_intmax_t = atomic; + using atomic_uintmax_t = atomic; + + using atomic_signed_lock_free = @\seebelow@; + using atomic_unsigned_lock_free = @\seebelow@; + + // \ref{atomics.flag}, flag type and operations + struct atomic_flag; + + bool atomic_flag_test(const volatile atomic_flag*) noexcept; + bool atomic_flag_test(const atomic_flag*) noexcept; + bool atomic_flag_test_explicit(const volatile atomic_flag*, memory_order) noexcept; + bool atomic_flag_test_explicit(const atomic_flag*, memory_order) noexcept; + bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept; + bool atomic_flag_test_and_set(atomic_flag*) noexcept; + bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order) noexcept; + bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept; + void atomic_flag_clear(volatile atomic_flag*) noexcept; + void atomic_flag_clear(atomic_flag*) noexcept; + void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept; + void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; + + void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept; + void atomic_flag_wait(const atomic_flag*, bool) noexcept; + void atomic_flag_wait_explicit(const volatile atomic_flag*, + bool, memory_order) noexcept; + void atomic_flag_wait_explicit(const atomic_flag*, + bool, memory_order) noexcept; + void atomic_flag_notify_one(volatile atomic_flag*) noexcept; + void atomic_flag_notify_one(atomic_flag*) noexcept; + void atomic_flag_notify_all(volatile atomic_flag*) noexcept; + void atomic_flag_notify_all(atomic_flag*) noexcept; + + // \ref{atomics.fences}, fences + extern "C" void atomic_thread_fence(memory_order) noexcept; + extern "C" void atomic_signal_fence(memory_order) noexcept; +} +\end{codeblock} + +\rSec2[atomics.alias]{Type aliases} +\indexlibraryglobal{atomic_bool}% +\indexlibraryglobal{atomic_char}% +\indexlibraryglobal{atomic_schar}% +\indexlibraryglobal{atomic_uchar}% +\indexlibraryglobal{atomic_short}% +\indexlibraryglobal{atomic_ushort}% +\indexlibraryglobal{atomic_int}% +\indexlibraryglobal{atomic_uint}% +\indexlibraryglobal{atomic_long}% +\indexlibraryglobal{atomic_ulong}% +\indexlibraryglobal{atomic_llong}% +\indexlibraryglobal{atomic_ullong}% +\indexlibraryglobal{atomic_char8_t}% +\indexlibraryglobal{atomic_char16_t}% +\indexlibraryglobal{atomic_char32_t}% +\indexlibraryglobal{atomic_wchar_t}% +\indexlibraryglobal{atomic_int8_t}% +\indexlibraryglobal{atomic_uint8_t}% +\indexlibraryglobal{atomic_int16_t}% +\indexlibraryglobal{atomic_uint16_t}% +\indexlibraryglobal{atomic_int32_t}% +\indexlibraryglobal{atomic_uint32_t}% +\indexlibraryglobal{atomic_int64_t}% +\indexlibraryglobal{atomic_uint64_t}% +\indexlibraryglobal{atomic_int_least8_t}% +\indexlibraryglobal{atomic_uint_least8_t}% +\indexlibraryglobal{atomic_int_least16_t}% +\indexlibraryglobal{atomic_uint_least16_t}% +\indexlibraryglobal{atomic_int_least32_t}% +\indexlibraryglobal{atomic_uint_least32_t}% +\indexlibraryglobal{atomic_int_least64_t}% +\indexlibraryglobal{atomic_uint_least64_t}% +\indexlibraryglobal{atomic_int_fast8_t}% +\indexlibraryglobal{atomic_uint_fast8_t}% +\indexlibraryglobal{atomic_int_fast16_t}% +\indexlibraryglobal{atomic_uint_fast16_t}% +\indexlibraryglobal{atomic_int_fast32_t}% +\indexlibraryglobal{atomic_uint_fast32_t}% +\indexlibraryglobal{atomic_int_fast64_t}% +\indexlibraryglobal{atomic_uint_fast64_t}% +\indexlibraryglobal{atomic_intptr_t}% +\indexlibraryglobal{atomic_uintptr_t}% +\indexlibraryglobal{atomic_size_t}% +\indexlibraryglobal{atomic_ptrdiff_t}% +\indexlibraryglobal{atomic_intmax_t}% +\indexlibraryglobal{atomic_uintmax_t}% +\pnum +The type aliases \tcode{atomic_int$N$_t}, \tcode{atomic_uint$N$_t}, +\tcode{atomic_intptr_t}, and \tcode{atomic_uintptr_t} +are defined if and only if +\tcode{int$N$_t}, \tcode{uint$N$_t}, +\tcode{intptr_t}, and \tcode{uintptr_t} +are defined, respectively. + +\pnum +\indexlibraryglobal{atomic_signed_lock_free}% +\indexlibraryglobal{atomic_unsigned_lock_free}% +The type aliases +\tcode{atomic_signed_lock_free} and \tcode{atomic_unsigned_lock_free} +name specializations of \tcode{atomic} +whose template arguments are integral types, respectively signed and unsigned, +and whose \tcode{is_always_lock_free} property is \tcode{true}. +\begin{note} +\indextext{implementation!freestanding}% +These aliases are optional in freestanding implementations\iref{compliance}. +\end{note} +Implementations should choose for these aliases +the integral specializations of \tcode{atomic} +for which the atomic waiting and notifying operations\iref{atomics.wait} +are most efficient. + +\rSec2[atomics.order]{Order and consistency} +\indexlibraryglobal{memory_order}% +\indexlibrarymember{relaxed}{memory_order}% +\indexlibrarymember{consume}{memory_order}% +\indexlibrarymember{acquire}{memory_order}% +\indexlibrarymember{release}{memory_order}% +\indexlibrarymember{acq_rel}{memory_order}% +\indexlibrarymember{seq_cst}{memory_order}% +\indexlibraryglobal{memory_order_relaxed}% +\indexlibraryglobal{memory_order_consume}% +\indexlibraryglobal{memory_order_acquire}% +\indexlibraryglobal{memory_order_release}% +\indexlibraryglobal{memory_order_acq_rel}% +\indexlibraryglobal{memory_order_seq_cst}% + +\begin{codeblock} +namespace std { + enum class memory_order : @\unspec@ { + relaxed, consume, acquire, release, acq_rel, seq_cst + }; + inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; + inline constexpr memory_order memory_order_consume = memory_order::consume; + inline constexpr memory_order memory_order_acquire = memory_order::acquire; + inline constexpr memory_order memory_order_release = memory_order::release; + inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; + inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; +} +\end{codeblock} + +\pnum +The enumeration \tcode{memory_order} specifies the detailed regular +(non-atomic) memory synchronization order as defined in +\ref{intro.multithread} and may provide for operation ordering. Its +enumerated values and their meanings are as follows: + +\begin{itemize} +\item \tcode{memory_order::relaxed}: no operation orders memory. + +\item \tcode{memory_order::release}, \tcode{memory_order::acq_rel}, and +\tcode{memory_order::seq_cst}: a store operation performs a release operation on the +affected memory location. + +\item \tcode{memory_order::consume}: a load operation performs a consume operation on the +affected memory location. +\begin{note} +Prefer \tcode{memory_order::acquire}, which provides stronger guarantees +than \tcode{memory_order::consume}. Implementations have found it infeasible +to provide performance better than that of \tcode{memory_order::acquire}. +Specification revisions are under consideration. +\end{note} + +\item \tcode{memory_order::acquire}, \tcode{memory_order::acq_rel}, and +\tcode{memory_order::seq_cst}: a load operation performs an acquire operation on the +affected memory location. +\end{itemize} + +\begin{note} +Atomic operations specifying \tcode{memory_order::relaxed} are relaxed +with respect to memory ordering. Implementations must still guarantee that any +given atomic access to a particular atomic object be indivisible with respect +to all other atomic accesses to that object. +\end{note} + +\pnum +An atomic operation $A$ that performs a release operation on an atomic +object $M$ synchronizes with an atomic operation $B$ that performs +an acquire operation on $M$ and takes its value from any side effect in the +release sequence headed by $A$. + +\pnum +An atomic operation $A$ on some atomic object $M$ is +\defn{coherence-ordered before} +another atomic operation $B$ on $M$ if +\begin{itemize} +\item $A$ is a modification, and +$B$ reads the value stored by $A$, or +\item $A$ precedes $B$ +in the modification order of $M$, or +\item $A$ and $B$ are not +the same atomic read-modify-write operation, and +there exists an atomic modification $X$ of $M$ +such that $A$ reads the value stored by $X$ and +$X$ precedes $B$ +in the modification order of $M$, or +\item there exists an atomic modification $X$ of $M$ +such that $A$ is coherence-ordered before $X$ and +$X$ is coherence-ordered before $B$. +\end{itemize} + +\pnum +There is a single total order $S$ +on all \tcode{memory_order::seq_cst} operations, including fences, +that satisfies the following constraints. +First, if $A$ and $B$ are +\tcode{memory_order::seq_cst} operations and +$A$ strongly happens before $B$, +then $A$ precedes $B$ in $S$. +Second, for every pair of atomic operations $A$ and +$B$ on an object $M$, +where $A$ is coherence-ordered before $B$, +the following four conditions are required to be satisfied by $S$: +\begin{itemize} +\item if $A$ and $B$ are both +\tcode{memory_order::seq_cst} operations, +then $A$ precedes $B$ in $S$; and +\item if $A$ is a \tcode{memory_order::seq_cst} operation and +$B$ happens before +a \tcode{memory_order::seq_cst} fence $Y$, +then $A$ precedes $Y$ in $S$; and +\item if a \tcode{memory_order::seq_cst} fence $X$ +happens before $A$ and +$B$ is a \tcode{memory_order::seq_cst} operation, +then $X$ precedes $B$ in $S$; and +\item if a \tcode{memory_order::seq_cst} fence $X$ +happens before $A$ and +$B$ happens before +a \tcode{memory_order::seq_cst} fence $Y$, +then $X$ precedes $Y$ in $S$. +\end{itemize} + +\pnum +\begin{note} +This definition ensures that $S$ is consistent with +the modification order of any atomic object $M$. +It also ensures that +a \tcode{memory_order::seq_cst} load $A$ of $M$ +gets its value either from the last modification of $M$ +that precedes $A$ in $S$ or +from some non-\tcode{memory_order::seq_cst} modification of $M$ +that does not happen before any modification of $M$ +that precedes $A$ in $S$. +\end{note} + +\pnum +\begin{note} +We do not require that $S$ be consistent with +``happens before''\iref{intro.races}. +This allows more efficient implementation +of \tcode{memory_order::acquire} and \tcode{memory_order::release} +on some machine architectures. +It can produce surprising results +when these are mixed with \tcode{memory_order::seq_cst} accesses. +\end{note} + +\pnum +\begin{note} +\tcode{memory_order::seq_cst} ensures sequential consistency only +for a program that is free of data races and +uses exclusively \tcode{memory_order::seq_cst} atomic operations. +Any use of weaker ordering will invalidate this guarantee +unless extreme care is used. +In many cases, \tcode{memory_order::seq_cst} atomic operations are reorderable +with respect to other atomic operations performed by the same thread. +\end{note} + +\pnum +Implementations should ensure that no ``out-of-thin-air'' values are computed that +circularly depend on their own computation. + +\begin{note} +For example, with \tcode{x} and \tcode{y} initially zero, +\begin{codeblock} +// Thread 1: +r1 = y.load(memory_order::relaxed); +x.store(r1, memory_order::relaxed); +\end{codeblock} + +\begin{codeblock} +// Thread 2: +r2 = x.load(memory_order::relaxed); +y.store(r2, memory_order::relaxed); +\end{codeblock} +this recommendation discourages producing \tcode{r1 == r2 == 42}, since the store of 42 to \tcode{y} is only +possible if the store to \tcode{x} stores \tcode{42}, which circularly depends on the +store to \tcode{y} storing \tcode{42}. Note that without this restriction, such an +execution is possible. +\end{note} + +\pnum +\begin{note} +The recommendation similarly disallows \tcode{r1 == r2 == 42} in the +following example, with \tcode{x} and \tcode{y} again initially zero: + +\begin{codeblock} +// Thread 1: +r1 = x.load(memory_order::relaxed); +if (r1 == 42) y.store(42, memory_order::relaxed); +\end{codeblock} + +\begin{codeblock} +// Thread 2: +r2 = y.load(memory_order::relaxed); +if (r2 == 42) x.store(42, memory_order::relaxed); +\end{codeblock} +\end{note} + +\pnum +Atomic read-modify-write operations shall always read the last value +(in the modification order) written before the write associated with +the read-modify-write operation. + +\pnum +Implementations should make atomic stores visible to atomic loads within a reasonable +amount of time. + +\indexlibraryglobal{kill_dependency}% +\begin{itemdecl} +template + T kill_dependency(T y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +The argument does not carry a dependency to the return +value\iref{intro.multithread}. + +\pnum +\returns +\tcode{y}. +\end{itemdescr} + + +\rSec2[atomics.lockfree]{Lock-free property} + +\indexlibraryglobal{ATOMIC_BOOL_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_CHAR_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_CHAR8_T_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_CHAR16_T_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_CHAR32_T_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_WCHAR_T_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_SHORT_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_INT_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_LONG_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_LLONG_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_POINTER_LOCK_FREE}% +\indeximpldef{values of various \tcode{ATOMIC_..._LOCK_FREE} macros} +\begin{codeblock} +#define ATOMIC_BOOL_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR8_T_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR16_T_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR32_T_LOCK_FREE @\unspec@ +#define ATOMIC_WCHAR_T_LOCK_FREE @\unspec@ +#define ATOMIC_SHORT_LOCK_FREE @\unspec@ +#define ATOMIC_INT_LOCK_FREE @\unspec@ +#define ATOMIC_LONG_LOCK_FREE @\unspec@ +#define ATOMIC_LLONG_LOCK_FREE @\unspec@ +#define ATOMIC_POINTER_LOCK_FREE @\unspec@ +\end{codeblock} + +\pnum +The \tcode{ATOMIC_..._LOCK_FREE} macros indicate the lock-free property of the +corresponding atomic types, with the signed and unsigned variants grouped +together. The properties also apply to the corresponding (partial) specializations of the +\tcode{atomic} template. A value of 0 indicates that the types are never +lock-free. A value of 1 indicates that the types are sometimes lock-free. A +value of 2 indicates that the types are always lock-free. + +\pnum +At least one signed integral specialization of the \tcode{atomic} template, +along with the specialization +for the corresponding unsigned type\iref{basic.fundamental}, +is always lock-free. +\begin{note} +\indextext{implementation!freestanding}% +This requirement is optional in freestanding implementations\iref{compliance}. +\end{note} + +\pnum +The functions \tcode{atomic::is_lock_free} and +\tcode{atomic_is_lock_free}\iref{atomics.types.operations} +indicate whether the object is lock-free. In any given program execution, the +result of the lock-free query +is the same for all atomic objects of the same type. + +\pnum +Atomic operations that are not lock-free are considered to potentially +block\iref{intro.progress}. + +\pnum +\recommended +Operations that are lock-free should also be address-free. +\begin{footnote} +That is, +atomic operations on the same memory location via two different addresses will +communicate atomically. +\end{footnote} +The implementation of these operations should not depend on any per-process state. +\begin{note} +This restriction enables communication by memory that is +mapped into a process more than once and by memory that is shared between two +processes. +\end{note} + +\rSec2[atomics.wait]{Waiting and notifying} + +\pnum +\defnx{Atomic waiting operations}{atomic!waiting operation} +and \defnx{atomic notifying operations}{atomic!notifying operation} +provide a mechanism to wait for the value of an atomic object to change +more efficiently than can be achieved with polling. +An atomic waiting operation may block until it is unblocked +by an atomic notifying operation, according to each function's effects. +\begin{note} +Programs are not guaranteed to observe transient atomic values, +an issue known as the A-B-A problem, +resulting in continued blocking if a condition is only temporarily met. +\end{note} + +\pnum +\begin{note} +The following functions are atomic waiting operations: +\begin{itemize} +\item \tcode{atomic::wait}, +\item \tcode{atomic_flag::wait}, +\item \tcode{atomic_wait} and \tcode{atomic_wait_explicit}, +\item \tcode{atomic_flag_wait} and \tcode{atomic_flag_wait_explicit}, and +\item \tcode{atomic_ref::wait}. +\end{itemize} +\end{note} + +\pnum +\begin{note} +The following functions are atomic notifying operations: +\begin{itemize} +\item \tcode{atomic::notify_one} and \tcode{atomic::notify_all}, +\item \tcode{atomic_flag::notify_one} and \tcode{atomic_flag::notify_all}, +\item \tcode{atomic_notify_one} and \tcode{atomic_notify_all}, +\item \tcode{atomic_flag_notify_one} and \tcode{atomic_flag_notify_all}, and +\item \tcode{atomic_ref::notify_one} and \tcode{atomic_ref::notify_all}. +\end{itemize} +\end{note} + +\indextext{atomic!waiting operation!eligible to be unblocked}% +\pnum +A call to an atomic waiting operation on an atomic object \tcode{M} +is \defn{eligible to be unblocked} +by a call to an atomic notifying operation on \tcode{M} +if there exist side effects \tcode{X} and \tcode{Y} on \tcode{M} such that: +\begin{itemize} +\item the atomic waiting operation has blocked after observing the result of \tcode{X}, +\item \tcode{X} precedes \tcode{Y} in the modification order of \tcode{M}, and +\item \tcode{Y} happens before the call to the atomic notifying operation. +\end{itemize} + +\rSec2[atomics.ref.generic]{Class template \tcode{atomic_ref}} + +\rSec3[atomics.ref.generic.general]{General} + +\indexlibraryglobal{atomic_ref}% +\indexlibrarymember{value_type}{atomic_ref}% +\begin{codeblock} +namespace std { + template struct atomic_ref { + private: + T* ptr; // \expos + public: + using value_type = T; + static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + explicit atomic_ref(T&); + atomic_ref(const atomic_ref&) noexcept; + atomic_ref& operator=(const atomic_ref&) = delete; + + void store(T, memory_order = memory_order::seq_cst) const noexcept; + T operator=(T) const noexcept; + T load(memory_order = memory_order::seq_cst) const noexcept; + operator T() const noexcept; + + T exchange(T, memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_weak(T&, T, + memory_order, memory_order) const noexcept; + bool compare_exchange_strong(T&, T, + memory_order, memory_order) const noexcept; + bool compare_exchange_weak(T&, T, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_strong(T&, T, + memory_order = memory_order::seq_cst) const noexcept; + + void wait(T, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() const noexcept; + void notify_all() const noexcept; + }; +} +\end{codeblock} + +\pnum +An \tcode{atomic_ref} object applies atomic operations\iref{atomics.general} to +the object referenced by \tcode{*ptr} such that, +for the lifetime\iref{basic.life} of the \tcode{atomic_ref} object, +the object referenced by \tcode{*ptr} is an atomic object\iref{intro.races}. + +\pnum +The program is ill-formed if \tcode{is_trivially_copyable_v} is \tcode{false}. + +\pnum +The lifetime\iref{basic.life} of an object referenced by \tcode{*ptr} +shall exceed the lifetime of all \tcode{atomic_ref}s that reference the object. +While any \tcode{atomic_ref} instances exist +that reference the \tcode{*ptr} object, +all accesses to that object shall exclusively occur +through those \tcode{atomic_ref} instances. +No subobject of the object referenced by \tcode{atomic_ref} +shall be concurrently referenced by any other \tcode{atomic_ref} object. + +\pnum +Atomic operations applied to an object +through a referencing \tcode{atomic_ref} are atomic with respect to +atomic operations applied through any other \tcode{atomic_ref} +referencing the same object. +\begin{note} +Atomic operations or the \tcode{atomic_ref} constructor can acquire +a shared resource, such as a lock associated with the referenced object, +to enable atomic operations to be applied to the referenced object. +\end{note} + +\rSec3[atomics.ref.ops]{Operations} + +\indexlibrarymember{required_alignment}{atomic_ref}% +\indexlibrarymember{required_alignment}{atomic_ref}% +\indexlibrarymember{required_alignment}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{required_alignment}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +static constexpr size_t required_alignment; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The alignment required for an object to be referenced by an atomic reference, +which is at least \tcode{alignof(T)}. + +\pnum +\begin{note} +Hardware could require an object +referenced by an \tcode{atomic_ref} +to have stricter alignment\iref{basic.align} +than other objects of type \tcode{T}. +Further, whether operations on an \tcode{atomic_ref} +are lock-free could depend on the alignment of the referenced object. +For example, lock-free operations on \tcode{std::complex} +could be supported only if aligned to \tcode{2*alignof(double)}. +\end{note} +\end{itemdescr} + +\indexlibrarymember{is_always_lock_free}{atomic_ref}% +\indexlibrarymember{is_always_lock_free}{atomic_ref}% +\indexlibrarymember{is_always_lock_free}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{is_always_lock_free}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +static constexpr bool is_always_lock_free; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The static data member \tcode{is_always_lock_free} is \tcode{true} +if the \tcode{atomic_ref} type's operations are always lock-free, +and \tcode{false} otherwise. +\end{itemdescr} + +\indexlibrarymember{is_lock_free}{atomic_ref}% +\indexlibrarymember{is_lock_free}{atomic_ref}% +\indexlibrarymember{is_lock_free}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{is_lock_free}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +bool is_lock_free() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if operations on all objects of the type \tcode{atomic_ref} +are lock-free, +\tcode{false} otherwise. +\end{itemdescr} + +\indexlibraryctor{atomic_ref}% +\indexlibraryctor{atomic_ref}% +\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}!constructor}% +\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}!constructor}% +\begin{itemdecl} +atomic_ref(T& obj); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The referenced object is aligned to \tcode{required_alignment}. + +\pnum +\ensures +\tcode{*this} references \tcode{obj}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibraryctor{atomic_ref}% +\indexlibraryctor{atomic_ref}% +\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}!constructor}% +\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}!constructor}% +\begin{itemdecl} +atomic_ref(const atomic_ref& ref) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{*this} references the object referenced by \tcode{ref}. +\end{itemdescr} + +\indexlibrarymember{store}{atomic_ref}% +\indexlibrarymember{store}{atomic_ref}% +\indexlibrarymember{store}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{store}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +void store(T desired, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The \tcode{order} argument is neither +\tcode{memory_order::consume}, +\tcode{memory_order::acquire}, nor +\tcode{memory_order::acq_rel}. + +\pnum +\effects +Atomically replaces the value referenced by \tcode{*ptr} +with the value of \tcode{desired}. +Memory is affected according to the value of \tcode{order}. +\end{itemdescr} + +\indexlibrarymember{operator=}{atomic_ref}% +\indexlibrarymember{operator=}{atomic_ref}% +\indexlibrarymember{operator=}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator=}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +T operator=(T desired) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +store(desired); +return desired; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{load}{atomic_ref}% +\indexlibrarymember{load}{atomic_ref}% +\indexlibrarymember{load}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{load}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +T load(memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The \tcode{order} argument is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Memory is affected according to the value of \tcode{order}. + +\pnum +\returns +Atomically returns the value referenced by \tcode{*ptr}. +\end{itemdescr} + +\indexlibrarymember{operator \placeholder{type}}{atomic_ref}% +\indexlibrarymember{operator T*}{atomic_ref}% +\indexlibrarymember{operator \placeholder{integral}}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator \placeholder{floating-point}}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +operator T() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return load();} +\end{itemdescr} + +\indexlibrarymember{exchange}{atomic_ref}% +\indexlibrarymember{exchange}{atomic_ref}% +\indexlibrarymember{exchange}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{exchange}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +T exchange(T desired, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically replaces the value referenced by \tcode{*ptr} +with \tcode{desired}. +Memory is affected according to the value of \tcode{order}. +This operation is an atomic read-modify-write operation\iref{intro.multithread}. + +\pnum +\returns +Atomically returns the value referenced by \tcode{*ptr} +immediately before the effects. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_weak}{atomic_ref}% +\indexlibrarymember{compare_exchange_weak}{atomic_ref}% +\indexlibrarymember{compare_exchange_weak}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{compare_exchange_weak}{atomic_ref<\placeholder{floating-point}>}% +\indexlibrarymember{compare_exchange_strong}{atomic_ref}% +\indexlibrarymember{compare_exchange_strong}{atomic_ref}% +\indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +bool compare_exchange_weak(T& expected, T desired, + memory_order success, memory_order failure) const noexcept; + +bool compare_exchange_strong(T& expected, T desired, + memory_order success, memory_order failure) const noexcept; + +bool compare_exchange_weak(T& expected, T desired, + memory_order order = memory_order::seq_cst) const noexcept; + +bool compare_exchange_strong(T& expected, T desired, + memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The \tcode{failure} argument is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Retrieves the value in \tcode{expected}. +It then atomically compares the value representation of +the value referenced by \tcode{*ptr} for equality +with that previously retrieved from \tcode{expected}, +and if \tcode{true}, replaces the value referenced by \tcode{*ptr} +with that in \tcode{desired}. +If and only if the comparison is \tcode{true}, +memory is affected according to the value of \tcode{success}, and +if the comparison is \tcode{false}, +memory is affected according to the value of \tcode{failure}. +When only one \tcode{memory_order} argument is supplied, +the value of \tcode{success} is \tcode{order}, and +the value of \tcode{failure} is \tcode{order} +except that a value of \tcode{memory_order::acq_rel} shall be replaced by +the value \tcode{memory_order::acquire} and +a value of \tcode{memory_order::release} shall be replaced by +the value \tcode{memory_order::relaxed}. +If and only if the comparison is \tcode{false} then, +after the atomic operation, +the value in \tcode{expected} is replaced by +the value read from the value referenced by \tcode{*ptr} +during the atomic comparison. +If the operation returns \tcode{true}, +these operations are atomic read-modify-write operations\iref{intro.races} +on the value referenced by \tcode{*ptr}. +Otherwise, these operations are atomic load operations on that memory. + +\pnum +\returns +The result of the comparison. + +\pnum +\remarks +A weak compare-and-exchange operation may fail spuriously. +That is, even when the contents of memory referred to +by \tcode{expected} and \tcode{ptr} are equal, +it may return \tcode{false} and +store back to \tcode{expected} the same memory contents +that were originally there. +\begin{note} +This spurious failure enables implementation of compare-and-exchange +on a broader class of machines, e.g., load-locked store-conditional machines. +A consequence of spurious failure is +that nearly all uses of weak compare-and-exchange will be in a loop. +When a compare-and-exchange is in a loop, +the weak version will yield better performance on some platforms. +When a weak compare-and-exchange would require a loop and +a strong one would not, the strong one is preferable. +\end{note} +\end{itemdescr} + +\indexlibrarymember{wait}{atomic_ref}% +\begin{itemdecl} +void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is +neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Repeatedly performs the following steps, in order: +\begin{itemize} +\item + Evaluates \tcode{load(order)} and + compares its value representation for equality against that of \tcode{old}. +\item + If they compare unequal, returns. +\item + Blocks until it + is unblocked by an atomic notifying operation or is unblocked spuriously. +\end{itemize} + +\pnum +\remarks +This function is an atomic waiting operation\iref{atomics.wait} +on atomic object \tcode{*ptr}. +\end{itemdescr} + +\indexlibrarymember{notify_one}{atomic_ref}% +\begin{itemdecl} +void notify_one() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of at least one atomic waiting operation on \tcode{*ptr} +that is eligible to be unblocked\iref{atomics.wait} by this call, +if any such atomic waiting operations exist. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait} +on atomic object \tcode{*ptr}. +\end{itemdescr} + +\indexlibrarymember{notify_all}{atomic_ref}% +\begin{itemdecl} +void notify_all() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of all atomic waiting operations on \tcode{*ptr} +that are eligible to be unblocked\iref{atomics.wait} by this call. + +\pnum +\remarks + This function is an atomic notifying operation\iref{atomics.wait} + on atomic object \tcode{*ptr}. +\end{itemdescr} + +\rSec3[atomics.ref.int]{Specializations for integral types} + +\pnum +\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}}% +There are specializations of the \tcode{atomic_ref} class template +for the integral types +\tcode{char}, +\tcode{signed char}, +\tcode{unsigned char}, +\tcode{short}, +\tcode{unsigned short}, +\tcode{int}, +\tcode{unsigned int}, +\tcode{long}, +\tcode{unsigned long}, +\tcode{long long}, +\tcode{unsigned long long}, +\keyword{char8_t}, +\keyword{char16_t}, +\keyword{char32_t}, +\keyword{wchar_t}, +and any other types needed by the typedefs in the header \libheaderref{cstdint}. +For each such type \tcode{\placeholder{integral}}, +the specialization \tcode{atomic_ref<\placeholder{integral}>} provides +additional atomic operations appropriate to integral types. +\begin{note} +The specialization \tcode{atomic_ref} +uses the primary template\iref{atomics.ref.generic}. +\end{note} + +\begin{codeblock} +namespace std { + template<> struct atomic_ref<@\placeholder{integral}@> { + private: + @\placeholder{integral}@* ptr; // \expos + public: + using value_type = @\placeholder{integral}@; + using difference_type = value_type; + static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + explicit atomic_ref(@\placeholder{integral}@&); + atomic_ref(const atomic_ref&) noexcept; + atomic_ref& operator=(const atomic_ref&) = delete; + + void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; + @\placeholdernc{integral}@ operator=(@\placeholder{integral}@) const noexcept; + @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const noexcept; + operator @\placeholdernc{integral}@() const noexcept; + + @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholder{integral}@, + memory_order, memory_order) const noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholder{integral}@, + memory_order, memory_order) const noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholder{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholder{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + + @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + + @\placeholdernc{integral}@ operator++(int) const noexcept; + @\placeholdernc{integral}@ operator--(int) const noexcept; + @\placeholdernc{integral}@ operator++() const noexcept; + @\placeholdernc{integral}@ operator--() const noexcept; + @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) const noexcept; + @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) const noexcept; + @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) const noexcept; + @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) const noexcept; + @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) const noexcept; + + void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() const noexcept; + void notify_all() const noexcept; + }; +} +\end{codeblock} + +\pnum +Descriptions are provided below only for members +that differ from the primary template. + +\pnum +The following operations perform arithmetic computations. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.int.comp}. + +\indexlibrarymember{fetch_add}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{fetch_and}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{fetch_or}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{fetch_xor}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +@\placeholdernc{integral}@ fetch_@\placeholdernc{key}@(@\placeholdernc{integral}@ operand, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically replaces the value referenced by \tcode{*ptr} with +the result of the computation applied to the value referenced by \tcode{*ptr} +and the given operand. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.races}. + +\pnum +\returns +Atomically, the value referenced by \tcode{*ptr} +immediately before the effects. + +\pnum +\indextext{signed integer representation!two's complement}% +\remarks +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 +the result converted back to the signed type. +\begin{note} +There are no undefined results arising from the computation. +\end{note} +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator-=}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator\&=}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator"|=}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator\caret=}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +@\placeholdernc{integral}@ operator @\placeholder{op}@=(@\placeholdernc{integral}@ operand) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return fetch_\placeholdernc{key}(operand) \placeholder{op} operand;} +\end{itemdescr} + +\rSec3[atomics.ref.float]{Specializations for floating-point types} + +\pnum +\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}}% +There are specializations of the \tcode{atomic_ref} class template +for the floating-point types +\tcode{float}, +\tcode{double}, and +\tcode{long double}. +For each such type \tcode{\placeholder{floating-point}}, +the specialization \tcode{atomic_ref<\placeholder{floating-\-point}>} provides +additional atomic operations appropriate to floating-point types. + +\begin{codeblock} +namespace std { + template<> struct atomic_ref<@\placeholder{floating-point}@> { + private: + @\placeholder{floating-point}@* ptr; // \expos + public: + using value_type = @\placeholder{floating-point}@; + using difference_type = value_type; + static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + explicit atomic_ref(@\placeholder{floating-point}@&); + atomic_ref(const atomic_ref&) noexcept; + atomic_ref& operator=(const atomic_ref&) = delete; + + void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; + @\placeholder{floating-point}@ operator=(@\placeholder{floating-point}@) const noexcept; + @\placeholder{floating-point}@ load(memory_order = memory_order::seq_cst) const noexcept; + operator @\placeholdernc{floating-point}@() const noexcept; + + @\placeholder{floating-point}@ exchange(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) const noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) const noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) const noexcept; + + @\placeholder{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) const noexcept; + @\placeholder{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) const noexcept; + + @\placeholder{floating-point}@ operator+=(@\placeholder{floating-point}@) const noexcept; + @\placeholder{floating-point}@ operator-=(@\placeholder{floating-point}@) const noexcept; + + void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() const noexcept; + void notify_all() const noexcept; + }; +} +\end{codeblock} + +\pnum +Descriptions are provided below only for members +that differ from the primary template. + +\pnum +The following operations perform arithmetic computations. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.int.comp}. + +\indexlibrarymember{fetch_add}{atomic_ref<\placeholder{floating-point}>}% +\indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +@\placeholder{floating-point}@ fetch_@\placeholdernc{key}@(@\placeholder{floating-point}@ operand, + memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically replaces the value referenced by \tcode{*ptr} with +the result of the computation applied to the value referenced by \tcode{*ptr} +and the given operand. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.races}. + +\pnum +\returns +Atomically, the value referenced by \tcode{*ptr} +immediately before the effects. + +\pnum +\remarks +If the result is not a representable value for its type\iref{expr.pre}, +the result is unspecified, +but the operations otherwise have no undefined behavior. +Atomic arithmetic operations on \tcode{\placeholder{floating-point}} should conform to +the \tcode{std::numeric_limits<\placeholder{floating-point}>} traits +associated with the floating-point type\iref{limits.syn}. +The floating-point environment\iref{cfenv} +for atomic arithmetic operations on \tcode{\placeholder{floating-point}} +may be different than the calling thread's floating-point environment. +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic_ref<\placeholder{floating-point}>}% +\indexlibrarymember{operator-=}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +@\placeholder{floating-point}@ operator @\placeholder{op}@=(@\placeholder{floating-point}@ operand) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return fetch_\placeholder{key}(operand) \placeholdernc{op} operand;} +\end{itemdescr} + +\rSec3[atomics.ref.pointer]{Partial specialization for pointers} +\indexlibraryglobal{atomic_ref}% + +\begin{codeblock} +namespace std { + template struct atomic_ref { + private: + T** ptr; // \expos + public: + using value_type = T*; + using difference_type = ptrdiff_t; + static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + explicit atomic_ref(T*&); + atomic_ref(const atomic_ref&) noexcept; + atomic_ref& operator=(const atomic_ref&) = delete; + + void store(T*, memory_order = memory_order::seq_cst) const noexcept; + T* operator=(T*) const noexcept; + T* load(memory_order = memory_order::seq_cst) const noexcept; + operator T*() const noexcept; + + T* exchange(T*, memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_weak(T*&, T*, + memory_order, memory_order) const noexcept; + bool compare_exchange_strong(T*&, T*, + memory_order, memory_order) const noexcept; + bool compare_exchange_weak(T*&, T*, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_strong(T*&, T*, + memory_order = memory_order::seq_cst) const noexcept; + + T* fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept; + T* fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept; + + T* operator++(int) const noexcept; + T* operator--(int) const noexcept; + T* operator++() const noexcept; + T* operator--() const noexcept; + T* operator+=(difference_type) const noexcept; + T* operator-=(difference_type) const noexcept; + + void wait(T*, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() const noexcept; + void notify_all() const noexcept; + }; +} +\end{codeblock} + +\pnum +Descriptions are provided below only for members +that differ from the primary template. + +\pnum +The following operations perform arithmetic computations. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.pointer.comp}. + +\indexlibrarymember{fetch_add}{atomic_ref}% +\indexlibrarymember{fetch_sub}{atomic_ref}% +\begin{itemdecl} +T* fetch_@\placeholdernc{key}@(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is a complete object type. + +\pnum +\effects +Atomically replaces the value referenced by \tcode{*ptr} with +the result of the computation applied to the value referenced by \tcode{*ptr} +and the given operand. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.races}. + +\pnum +\returns +Atomically, the value referenced by \tcode{*ptr} +immediately before the effects. + +\pnum +\remarks +The result may be an undefined address, +but the operations otherwise have no undefined behavior. +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic_ref}% +\indexlibrarymember{operator-=}{atomic_ref}% +\begin{itemdecl} +T* operator @\placeholder{op}@=(difference_type operand) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return fetch_\placeholder{key}(operand) \placeholdernc{op} operand;} +\end{itemdescr} + +\rSec3[atomics.ref.memop]{Member operators + common to integers and pointers to objects} + +\indexlibrarymember{operator++}{atomic_ref}% +\indexlibrarymember{operator++}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator++(int) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return fetch_add(1);} +\end{itemdescr} + +\indexlibrarymember{operator--}{atomic_ref}% +\indexlibrarymember{operator--}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator--(int) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return fetch_sub(1);} +\end{itemdescr} + +\indexlibrarymember{operator++}{atomic_ref}% +\indexlibrarymember{operator++}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator++() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return fetch_add(1) + 1;} +\end{itemdescr} + +\indexlibrarymember{operator--}{atomic_ref}% +\indexlibrarymember{operator--}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator--() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return fetch_sub(1) - 1;} +\end{itemdescr} + +\rSec2[atomics.types.generic]{Class template \tcode{atomic}} + +\rSec3[atomics.types.generic.general]{General} + +\indexlibraryglobal{atomic}% +\indexlibrarymember{value_type}{atomic}% +\begin{codeblock} +namespace std { + template struct atomic { + using value_type = T; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const volatile noexcept; + bool is_lock_free() const noexcept; + + // \ref{atomics.types.operations}, operations on atomic types + constexpr atomic() noexcept(is_nothrow_default_constructible_v); + constexpr atomic(T) noexcept; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + T load(memory_order = memory_order::seq_cst) const volatile noexcept; + T load(memory_order = memory_order::seq_cst) const noexcept; + operator T() const volatile noexcept; + operator T() const noexcept; + void store(T, memory_order = memory_order::seq_cst) volatile noexcept; + void store(T, memory_order = memory_order::seq_cst) noexcept; + T operator=(T) volatile noexcept; + T operator=(T) noexcept; + + T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept; + T exchange(T, memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept; + bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept; + bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept; + bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept; + bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept; + + void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept; + void wait(T, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() volatile noexcept; + void notify_one() noexcept; + void notify_all() volatile noexcept; + void notify_all() noexcept; + }; +} +\end{codeblock} + +\indexlibraryglobal{atomic}% +\pnum +The template argument for \tcode{T} shall meet the +\oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} requirements. +The program is ill-formed if any of +\begin{itemize} +\item \tcode{is_trivially_copyable_v}, +\item \tcode{is_copy_constructible_v}, +\item \tcode{is_move_constructible_v}, +\item \tcode{is_copy_assignable_v}, or +\item \tcode{is_move_assignable_v} +\end{itemize} +is \tcode{false}. +\begin{note} +Type arguments that are +not also statically initializable can be difficult to use. +\end{note} + +\pnum +The specialization \tcode{atomic} is a standard-layout struct. + +\pnum +\begin{note} +The representation of an atomic specialization +need not have the same size and alignment requirement as +its corresponding argument type. +\end{note} + +\rSec3[atomics.types.operations]{Operations on atomic types} + +\indexlibraryctor{atomic}% +\indexlibraryctor{atomic}% +\indexlibrary{\idxcode{atomic<\placeholder{integral}>}!constructor}% +\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}!constructor}% +\begin{itemdecl} +constexpr atomic() noexcept(is_nothrow_default_constructible_v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_default_constructible_v} is \tcode{true}. + +\pnum +\effects +Initializes the atomic object with the value of \tcode{T()}. +Initialization is not an atomic operation\iref{intro.multithread}. +\end{itemdescr} + +\indexlibraryctor{atomic}% +\indexlibraryctor{atomic}% +\indexlibrary{\idxcode{atomic<\placeholder{integral}>}!constructor}% +\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}!constructor}% +\begin{itemdecl} +constexpr atomic(T desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes the object with the value \tcode{desired}. +Initialization is not an atomic operation\iref{intro.multithread}. +\begin{note} +It is possible to have an access to an atomic object \tcode{A} +race with its construction, for example by communicating the address of the +just-constructed object \tcode{A} to another thread via +\tcode{memory_order::relaxed} operations on a suitable atomic pointer +variable, and then immediately accessing \tcode{A} in the receiving thread. +This results in undefined behavior. +\end{note} +\end{itemdescr} + +\indexlibrarymember{is_always_lock_free}{atomic}% +\indexlibrarymember{is_always_lock_free}{atomic}% +\indexlibrarymember{is_always_lock_free}{atomic<\placeholder{integral}>}% +\indexlibrarymember{is_always_lock_free}{atomic<\placeholder{floating-point}>}% +\indexlibrarymember{is_always_lock_free}{atomic>}% +\indexlibrarymember{is_always_lock_free}{atomic>}% +\begin{itemdecl} +static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The \keyword{static} data member \tcode{is_always_lock_free} is \tcode{true} +if the atomic type's operations are always lock-free, and \tcode{false} otherwise. +\begin{note} +The value of \tcode{is_always_lock_free} is consistent with the value of +the corresponding \tcode{ATOMIC_..._LOCK_FREE} macro, if defined. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{atomic_is_lock_free}% +\indexlibrarymember{is_lock_free}{atomic}% +\indexlibrarymember{is_lock_free}{atomic}% +\indexlibrarymember{is_lock_free}{atomic<\placeholder{integral}>}% +\indexlibrarymember{is_lock_free}{atomic<\placeholder{floating-point}>}% +\indexlibrarymember{is_lock_free}{atomic>}% +\indexlibrarymember{is_lock_free}{atomic>}% +\begin{itemdecl} +bool is_lock_free() const volatile noexcept; +bool is_lock_free() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if the object's operations are lock-free, \tcode{false} otherwise. +\begin{note} +The return value of the \tcode{is_lock_free} member function +is consistent with the value of \tcode{is_always_lock_free} for the same type. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{atomic_store}% +\indexlibraryglobal{atomic_store_explicit}% +\indexlibrarymember{store}{atomic}% +\indexlibrarymember{store}{atomic}% +\indexlibrarymember{store}{atomic<\placeholder{integral}>}% +\indexlibrarymember{store}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; +void store(T desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\expects +The \tcode{order} argument is neither \tcode{memory_order::consume}, +\tcode{memory_order::acquire}, nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Atomically replaces the value pointed to by \keyword{this} +with the value of \tcode{desired}. Memory is affected according to the value of +\tcode{order}. +\end{itemdescr} + +\indexlibrarymember{operator=}{atomic}% +\indexlibrarymember{operator=}{atomic}% +\indexlibrarymember{operator=}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator=}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +T operator=(T desired) volatile noexcept; +T operator=(T desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to \tcode{store(desired)}. + +\pnum +\returns +\tcode{desired}. +\end{itemdescr} + +\indexlibraryglobal{atomic_load}% +\indexlibraryglobal{atomic_load_explicit}% +\indexlibrarymember{load}{atomic}% +\indexlibrarymember{load}{atomic}% +\indexlibrarymember{load}{atomic<\placeholder{integral}>}% +\indexlibrarymember{load}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +T load(memory_order order = memory_order::seq_cst) const volatile noexcept; +T load(memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\expects +The \tcode{order} argument is neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Memory is affected according to the value of \tcode{order}. + +\pnum +\returns +Atomically returns the value pointed to by \keyword{this}. +\end{itemdescr} + +\indexlibrarymember{operator \placeholder{type}}{atomic}% +\indexlibrarymember{operator T*}{atomic}% +\indexlibrarymember{operator \placeholder{integral}}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator \placeholder{floating-point}}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +operator T() const volatile noexcept; +operator T() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return load();} +\end{itemdescr} + + +\indexlibraryglobal{atomic_exchange}% +\indexlibraryglobal{atomic_exchange_explicit}% +\indexlibrarymember{exchange}{atomic}% +\indexlibrarymember{exchange}{atomic}% +\indexlibrarymember{exchange}{atomic<\placeholder{integral}>}% +\indexlibrarymember{exchange}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; +T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Atomically replaces the value pointed to by \keyword{this} +with \tcode{desired}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.multithread}. + +\pnum +\returns +Atomically returns the value pointed to by \keyword{this} immediately before the effects. +\end{itemdescr} + +\indexlibraryglobal{atomic_compare_exchange_weak}% +\indexlibraryglobal{atomic_compare_exchange_strong}% +\indexlibraryglobal{atomic_compare_exchange_weak_explicit}% +\indexlibraryglobal{atomic_compare_exchange_strong_explicit}% +\indexlibrarymember{compare_exchange_weak}{atomic}% +\indexlibrarymember{compare_exchange_weak}{atomic}% +\indexlibrarymember{compare_exchange_weak}{atomic<\placeholder{integral}>}% +\indexlibrarymember{compare_exchange_weak}{atomic<\placeholder{floating-point}>}% +\indexlibrarymember{compare_exchange_strong}{atomic}% +\indexlibrarymember{compare_exchange_strong}{atomic}% +\indexlibrarymember{compare_exchange_strong}{atomic<\placeholder{integral}>}% +\indexlibrarymember{compare_exchange_strong}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +bool compare_exchange_weak(T& expected, T desired, + memory_order success, memory_order failure) volatile noexcept; +bool compare_exchange_weak(T& expected, T desired, + memory_order success, memory_order failure) noexcept; +bool compare_exchange_strong(T& expected, T desired, + memory_order success, memory_order failure) volatile noexcept; +bool compare_exchange_strong(T& expected, T desired, + memory_order success, memory_order failure) noexcept; +bool compare_exchange_weak(T& expected, T desired, + memory_order order = memory_order::seq_cst) volatile noexcept; +bool compare_exchange_weak(T& expected, T desired, + memory_order order = memory_order::seq_cst) noexcept; +bool compare_exchange_strong(T& expected, T desired, + memory_order order = memory_order::seq_cst) volatile noexcept; +bool compare_exchange_strong(T& expected, T desired, + memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\expects +The \tcode{failure} argument is neither \tcode{memory_order::release} nor +\tcode{memory_order::acq_rel}. + +\pnum +\effects +Retrieves the value in \tcode{expected}. It then atomically +compares the value representation of the value pointed to by \keyword{this} +for equality with that previously retrieved from \tcode{expected}, +and if true, replaces the value pointed to +by \keyword{this} with that in \tcode{desired}. +If and only if the comparison is \tcode{true}, memory is affected according to the +value of \tcode{success}, and if the comparison is false, memory is affected according +to the value of \tcode{failure}. When only one \tcode{memory_order} argument is +supplied, the value of \tcode{success} is \tcode{order}, and the value of +\tcode{failure} is \tcode{order} except that a value of \tcode{memory_order::acq_rel} +shall be replaced by the value \tcode{memory_order::acquire} and a value of +\tcode{memory_order::release} shall be replaced by the value +\tcode{memory_order::relaxed}. +If and only if the comparison is false then, after the atomic operation, +the value in \tcode{expected} is replaced by the value +pointed to by \keyword{this} during the atomic comparison. +If the operation returns \tcode{true}, these +operations are atomic read-modify-write +operations\iref{intro.multithread} on the memory +pointed to by \keyword{this}. +Otherwise, these operations are atomic load operations on that memory. + +\pnum +\returns +The result of the comparison. + +\pnum +\begin{note} +For example, the effect of +\tcode{compare_exchange_strong} +on objects without padding bits\iref{term.padding.bits} is +\begin{codeblock} +if (memcmp(this, &expected, sizeof(*this)) == 0) + memcpy(this, &desired, sizeof(*this)); +else + memcpy(&expected, this, sizeof(*this)); +\end{codeblock} +\end{note} +\begin{example} +The expected use of the compare-and-exchange operations is as follows. The +compare-and-exchange operations will update \tcode{expected} when another iteration of +the loop is needed. +\begin{codeblock} +expected = current.load(); +do { + desired = function(expected); +} while (!current.compare_exchange_weak(expected, desired)); +\end{codeblock} +\end{example} +\begin{example} +Because the expected value is updated only on failure, +code releasing the memory containing the \tcode{expected} value on success will work. +For example, list head insertion will act atomically and would not introduce a +data race in the following code: +\begin{codeblock} +do { + p->next = head; // make new list node point to the current head +} while (!head.compare_exchange_weak(p->next, p)); // try to insert +\end{codeblock} +\end{example} + +\pnum +Implementations should ensure that weak compare-and-exchange operations do not +consistently return \tcode{false} unless either the atomic object has value +different from \tcode{expected} or there are concurrent modifications to the +atomic object. + +\pnum +\remarks +A weak compare-and-exchange operation may fail spuriously. That is, even when +the contents of memory referred to by \tcode{expected} and \keyword{this} are +equal, it may return \tcode{false} and store back to \tcode{expected} the same memory +contents that were originally there. +\begin{note} +This +spurious failure enables implementation of compare-and-exchange on a broader class of +machines, e.g., load-locked store-conditional machines. A +consequence of spurious failure is that nearly all uses of weak compare-and-exchange +will be in a loop. +When a compare-and-exchange is in a loop, the weak version will yield better performance +on some platforms. When a weak compare-and-exchange would require a loop and a strong one +would not, the strong one is preferable. +\end{note} + +\pnum +\begin{note} +Under cases where the \tcode{memcpy} and \tcode{memcmp} semantics of the compare-and-exchange +operations apply, the comparisons can fail for values that compare equal with +\tcode{operator==} if the value representation has trap bits or alternate +representations of the same value. Notably, on implementations conforming to +ISO/IEC/IEEE 60559, floating-point \tcode{-0.0} and \tcode{+0.0} +will not compare equal with \tcode{memcmp} but will compare equal with \tcode{operator==}, +and NaNs with the same payload will compare equal with \tcode{memcmp} but will not +compare equal with \tcode{operator==}. +\end{note} +\begin{note} +Because compare-and-exchange acts on an object's value representation, +padding bits that never participate in the object's value representation +are ignored. As a consequence, the following code is guaranteed to avoid +spurious failure: +\begin{codeblock} +struct padded { + char clank = 0x42; + // Padding here. + unsigned biff = 0xC0DEFEFE; +}; +atomic pad = {}; + +bool zap() { + padded expected, desired{0, 0}; + return pad.compare_exchange_strong(expected, desired); +} +\end{codeblock} +\end{note} +\begin{note} +For a union with bits that participate in the value representation +of some members but not others, compare-and-exchange might always fail. +This is because such padding bits have an indeterminate value when they +do not participate in the value representation of the active member. +As a consequence, the following code is not guaranteed to ever succeed: +\begin{codeblock} +union pony { + double celestia = 0.; + short luna; // padded +}; +atomic princesses = {}; + +bool party(pony desired) { + pony expected; + return princesses.compare_exchange_strong(expected, desired); +} +\end{codeblock} +\end{note} +\end{itemdescr} + +\indexlibrarymember{wait}{atomic}% +\indexlibrarymember{wait}{atomic}% +\indexlibrarymember{wait}{atomic<\placeholder{integral}>}% +\indexlibrarymember{wait}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept; +void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Repeatedly performs the following steps, in order: +\begin{itemize} +\item + Evaluates \tcode{load(order)} and + compares its value representation for equality against that of \tcode{old}. +\item + If they compare unequal, returns. +\item + Blocks until it + is unblocked by an atomic notifying operation or is unblocked spuriously. +\end{itemize} + +\pnum +\remarks +This function is an atomic waiting operation\iref{atomics.wait}. +\end{itemdescr} + +\indexlibrarymember{notify_one}{atomic}% +\indexlibrarymember{notify_one}{atomic}% +\indexlibrarymember{notify_one}{atomic<\placeholder{integral}>}% +\indexlibrarymember{notify_one}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +void notify_one() volatile noexcept; +void notify_one() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of at least one atomic waiting operation +that is eligible to be unblocked\iref{atomics.wait} by this call, +if any such atomic waiting operations exist. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\indexlibrarymember{notify_all}{atomic}% +\indexlibrarymember{notify_all}{atomic}% +\indexlibrarymember{notify_all}{atomic<\placeholder{integral}>}% +\indexlibrarymember{notify_all}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +void notify_all() volatile noexcept; +void notify_all() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of all atomic waiting operations +that are eligible to be unblocked\iref{atomics.wait} by this call. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\rSec3[atomics.types.int]{Specializations for integers} + +\indexlibrary{\idxcode{atomic<\placeholder{integral}>}}% +\pnum +There are specializations of the \tcode{atomic} +class template for the integral types +\tcode{char}, +\tcode{signed char}, +\tcode{unsigned char}, +\tcode{short}, +\tcode{unsigned short}, +\tcode{int}, +\tcode{unsigned int}, +\tcode{long}, +\tcode{unsigned long}, +\tcode{long long}, +\tcode{unsigned long long}, +\keyword{char8_t}, +\keyword{char16_t}, +\keyword{char32_t}, +\keyword{wchar_t}, +and any other types needed by the typedefs in the header \libheaderref{cstdint}. +For each such type \tcode{\placeholder{integral}}, the specialization +\tcode{atomic<\placeholder{integral}>} provides additional atomic operations appropriate to integral types. +\begin{note} +The specialization \tcode{atomic} +uses the primary template\iref{atomics.types.generic}. +\end{note} + +\begin{codeblock} +namespace std { + template<> struct atomic<@\placeholder{integral}@> { + using value_type = @\placeholder{integral}@; + using difference_type = value_type; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const volatile noexcept; + bool is_lock_free() const noexcept; + + constexpr atomic() noexcept; + constexpr atomic(@\placeholdernc{integral}@) noexcept; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral}@ operator=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator=(@\placeholdernc{integral}@) noexcept; + @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const volatile noexcept; + @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const noexcept; + operator @\placeholdernc{integral}@() const volatile noexcept; + operator @\placeholdernc{integral}@() const noexcept; + + @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order, memory_order) volatile noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order, memory_order) noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order, memory_order) volatile noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order, memory_order) noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) noexcept; + + @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + + @\placeholdernc{integral}@ operator++(int) volatile noexcept; + @\placeholdernc{integral}@ operator++(int) noexcept; + @\placeholdernc{integral}@ operator--(int) volatile noexcept; + @\placeholdernc{integral}@ operator--(int) noexcept; + @\placeholdernc{integral}@ operator++() volatile noexcept; + @\placeholdernc{integral}@ operator++() noexcept; + @\placeholdernc{integral}@ operator--() volatile noexcept; + @\placeholdernc{integral}@ operator--() noexcept; + @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) noexcept; + @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) noexcept; + @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) noexcept; + @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) noexcept; + @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) noexcept; + + void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const volatile noexcept; + void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() volatile noexcept; + void notify_one() noexcept; + void notify_all() volatile noexcept; + void notify_all() noexcept; + }; +} +\end{codeblock} + +\pnum +The atomic integral specializations +are standard-layout structs. +They each have +a trivial destructor. + +\pnum +Descriptions are provided below only for members that differ from the primary template. + +\pnum +The following operations perform arithmetic computations. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.int.comp}. + +\begin{floattable} +{Atomic arithmetic computations}{atomic.types.int.comp}{lll|lll} +\hline +\hdstyle{\tcode{\placeholder{key}}} & + \hdstyle{Op} & + \hdstyle{Computation} & +\hdstyle{\tcode{\placeholder{key}}} & + \hdstyle{Op} & + \hdstyle{Computation} \\ \hline +\tcode{add} & + \tcode{+} & + addition & +\tcode{sub} & + \tcode{-} & + subtraction \\ +\tcode{or} & + \tcode{|} & + bitwise inclusive or & +\tcode{xor} & + \tcode{\caret} & + bitwise exclusive or \\ +\tcode{and} & + \tcode{\&} & + bitwise and &&&\\ +\end{floattable} + +\indexlibraryglobal{atomic_fetch_add}% +\indexlibraryglobal{atomic_fetch_and}% +\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_or_explicit}% +\indexlibraryglobal{atomic_fetch_sub_explicit}% +\indexlibraryglobal{atomic_fetch_xor_explicit}% +\indexlibrarymember{fetch_add}{atomic<\placeholder{integral}>}% +\indexlibrarymember{fetch_and}{atomic<\placeholder{integral}>}% +\indexlibrarymember{fetch_or}{atomic<\placeholder{integral}>}% +\indexlibrarymember{fetch_sub}{atomic<\placeholder{integral}>}% +\indexlibrarymember{fetch_xor}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; +T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Atomically replaces the value pointed to by +\keyword{this} with the result of the computation applied to the +value pointed to by \keyword{this} and the given \tcode{operand}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.multithread}. + +\pnum +\returns +Atomically, the value pointed to by \keyword{this} immediately before the effects. + +\pnum +\indextext{signed integer representation!two's complement}% +\remarks +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 +the result converted back to the signed type. +\begin{note} +There are no undefined results arising from the computation. +\end{note} + +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic}% +\indexlibrarymember{operator-=}{atomic}% +\indexlibrarymember{operator+=}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator-=}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator\&=}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator"|=}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator\caret=}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +T operator @\placeholder{op}@=(T operand) volatile noexcept; +T operator @\placeholder{op}@=(T operand) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} +\end{itemdescr} + +\rSec3[atomics.types.float]{Specializations for floating-point types} + +\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}}% +\pnum +There are specializations of the \tcode{atomic} +class template for the floating-point types +\tcode{float}, +\tcode{double}, and +\tcode{long double}. +For each such type \tcode{\placeholdernc{floating-point}}, +the specialization \tcode{atomic<\placeholder{floating-point}>} +provides additional atomic operations appropriate to floating-point types. + +\begin{codeblock} +namespace std { + template<> struct atomic<@\placeholder{floating-point}@> { + using value_type = @\placeholdernc{floating-point}@; + using difference_type = value_type; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const volatile noexcept; + bool is_lock_free() const noexcept; + + constexpr atomic() noexcept; + constexpr atomic(@\placeholder{floating-point}@) noexcept; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) volatile noexcept; + void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point}@ operator=(@\placeholder{floating-point}@) volatile noexcept; + @\placeholdernc{floating-point}@ operator=(@\placeholder{floating-point}@) noexcept; + @\placeholdernc{floating-point}@ load(memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{floating-point}@ load(memory_order = memory_order::seq_cst) noexcept; + operator @\placeholdernc{floating-point}@() volatile noexcept; + operator @\placeholdernc{floating-point}@() noexcept; + + @\placeholdernc{floating-point}@ exchange(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{floating-point}@ exchange(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) volatile noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) volatile noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) noexcept; + + @\placeholdernc{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) noexcept; + + @\placeholdernc{floating-point}@ operator+=(@\placeholder{floating-point}@) volatile noexcept; + @\placeholdernc{floating-point}@ operator+=(@\placeholder{floating-point}@) noexcept; + @\placeholdernc{floating-point}@ operator-=(@\placeholder{floating-point}@) volatile noexcept; + @\placeholdernc{floating-point}@ operator-=(@\placeholder{floating-point}@) noexcept; + + void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const volatile noexcept; + void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() volatile noexcept; + void notify_one() noexcept; + void notify_all() volatile noexcept; + void notify_all() noexcept; + }; +} +\end{codeblock} + +\pnum +The atomic floating-point specializations +are standard-layout structs. +They each have +a trivial destructor. + +\pnum +Descriptions are provided below only for members that differ from the primary template. + +\pnum +The following operations perform arithmetic addition and subtraction computations. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.int.comp}. + +\indexlibraryglobal{atomic_fetch_add}% +\indexlibraryglobal{atomic_fetch_sub}% +\indexlibraryglobal{atomic_fetch_add_explicit}% +\indexlibraryglobal{atomic_fetch_sub_explicit}% +\indexlibrarymember{fetch_add}{atomic<\placeholder{floating-point}>}% +\indexlibrarymember{fetch_sub}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; +T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Atomically replaces the value pointed to by \keyword{this} +with the result of the computation applied to the value pointed +to by \keyword{this} and the given \tcode{operand}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.multithread}. + +\pnum +\returns +Atomically, the value pointed to by \keyword{this} immediately before the effects. + +\pnum +\remarks +If the result is not a representable value for its type\iref{expr.pre} +the result is unspecified, but the operations otherwise have no undefined +behavior. Atomic arithmetic operations on \tcode{\placeholder{floating-point}} +should conform to the \tcode{std::numeric_limits<\placeholder{floating-point}>} +traits associated with the floating-point type\iref{limits.syn}. +The floating-point environment\iref{cfenv} for atomic arithmetic operations +on \tcode{\placeholder{floating-point}} may be different than the +calling thread's floating-point environment. +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic}% +\indexlibrarymember{operator-=}{atomic}% +\indexlibrarymember{operator+=}{atomic<\placeholder{floating-point}>}% +\indexlibrarymember{operator-=}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +T operator @\placeholder{op}@=(T operand) volatile noexcept; +T operator @\placeholder{op}@=(T operand) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} + +\pnum +\remarks +If the result is not a representable value for its type\iref{expr.pre} +the result is unspecified, but the operations otherwise have no undefined +behavior. Atomic arithmetic operations on \tcode{\placeholder{floating-point}} +should conform to the \tcode{std::numeric_limits<\placeholder{floating-point}>} +traits associated with the floating-point type\iref{limits.syn}. +The floating-point environment\iref{cfenv} for atomic arithmetic operations +on \tcode{\placeholder{floating-point}} may be different than the +calling thread's floating-point environment. +\end{itemdescr} + +\rSec3[atomics.types.pointer]{Partial specialization for pointers} +\indexlibraryglobal{atomic}% + +\begin{codeblock} +namespace std { + template struct atomic { + using value_type = T*; + using difference_type = ptrdiff_t; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const volatile noexcept; + bool is_lock_free() const noexcept; + + constexpr atomic() noexcept; + constexpr atomic(T*) noexcept; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + void store(T*, memory_order = memory_order::seq_cst) volatile noexcept; + void store(T*, memory_order = memory_order::seq_cst) noexcept; + T* operator=(T*) volatile noexcept; + T* operator=(T*) noexcept; + T* load(memory_order = memory_order::seq_cst) const volatile noexcept; + T* load(memory_order = memory_order::seq_cst) const noexcept; + operator T*() const volatile noexcept; + operator T*() const noexcept; + + T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept; + T* exchange(T*, memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept; + bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept; + bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept; + bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept; + bool compare_exchange_weak(T*&, T*, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_weak(T*&, T*, + memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(T*&, T*, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_strong(T*&, T*, + memory_order = memory_order::seq_cst) noexcept; + + T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; + T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; + 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* operator++(int) volatile noexcept; + T* operator++(int) noexcept; + T* operator--(int) volatile noexcept; + T* operator--(int) noexcept; + T* operator++() volatile noexcept; + T* operator++() noexcept; + T* operator--() volatile noexcept; + T* operator--() noexcept; + T* operator+=(ptrdiff_t) volatile noexcept; + T* operator+=(ptrdiff_t) noexcept; + T* operator-=(ptrdiff_t) volatile noexcept; + T* operator-=(ptrdiff_t) noexcept; + + void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept; + void wait(T*, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() volatile noexcept; + void notify_one() noexcept; + void notify_all() volatile noexcept; + void notify_all() noexcept; + }; +} +\end{codeblock} + +\indexlibraryglobal{atomic}% +\pnum +There is a partial specialization of the \tcode{atomic} class template for pointers. +Specializations of this partial specialization are standard-layout structs. +They each have a trivial destructor. + +\pnum +Descriptions are provided below only for members that differ from the primary template. + +\pnum +The following operations perform pointer arithmetic. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.pointer.comp}. + +\begin{floattable} +{Atomic pointer computations}{atomic.types.pointer.comp}{lll|lll} +\hline +\hdstyle{\tcode{\placeholder{key}}} & + \hdstyle{Op} & + \hdstyle{Computation} & +\hdstyle{\tcode{\placeholder{key}}} & + \hdstyle{Op} & + \hdstyle{Computation} \\ \hline +\tcode{add} & + \tcode{+} & + addition & +\tcode{sub} & + \tcode{-} & + subtraction \\ +\end{floattable} + +\indexlibraryglobal{atomic_fetch_add}% +\indexlibraryglobal{atomic_fetch_sub}% +\indexlibraryglobal{atomic_fetch_add_explicit}% +\indexlibraryglobal{atomic_fetch_sub_explicit}% +\indexlibrarymember{fetch_add}{atomic}% +\indexlibrarymember{fetch_sub}{atomic}% +\begin{itemdecl} +T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept; +T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\mandates +\tcode{T} is a complete object type. +\begin{note} +Pointer arithmetic on \tcode{void*} or function pointers is ill-formed. +\end{note} + +\pnum +\effects +Atomically replaces the value pointed to by +\keyword{this} with the result of the computation applied to the +value pointed to by \keyword{this} and the given \tcode{operand}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.multithread}. + +\pnum +\returns +Atomically, the value pointed to by \keyword{this} immediately before the effects. + +\pnum +\remarks +The result may be an undefined address, +but the operations otherwise have no undefined behavior. +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic}% +\indexlibrarymember{operator-=}{atomic}% +\begin{itemdecl} +T* operator @\placeholder{op}@=(ptrdiff_t operand) volatile noexcept; +T* operator @\placeholder{op}@=(ptrdiff_t operand) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} +\end{itemdescr} + +\rSec3[atomics.types.memop]{Member operators common to integers and pointers to objects} + +\indexlibrarymember{operator++}{atomic}% +\indexlibrarymember{operator++}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator++(int) volatile noexcept; +value_type operator++(int) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_add(1);} +\end{itemdescr} + +\indexlibrarymember{operator--}{atomic}% +\indexlibrarymember{operator--}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator--(int) volatile noexcept; +value_type operator--(int) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_sub(1);} +\end{itemdescr} + +\indexlibrarymember{operator++}{atomic}% +\indexlibrarymember{operator++}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator++() volatile noexcept; +value_type operator++() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_add(1) + 1;} +\end{itemdescr} + +\indexlibrarymember{operator--}{atomic}% +\indexlibrarymember{operator--}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator--() volatile noexcept; +value_type operator--() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_sub(1) - 1;} +\end{itemdescr} + +\rSec3[util.smartptr.atomic]{Partial specializations for smart pointers}% +\indextext{atomic!smart pointers|(}% + +\rSec4[util.smartptr.atomic.general]{General} + +\pnum +The library provides partial specializations of the \tcode{atomic} template +for shared-ownership smart pointers\iref{util.sharedptr}. +\begin{note} +The partial specializations are declared in header \libheaderref{memory}. +\end{note} +The behavior of all operations is as specified in \ref{atomics.types.generic}, +unless specified otherwise. +The template parameter \tcode{T} of these partial specializations +may be an incomplete type. + +\pnum +All changes to an atomic smart pointer in \ref{util.smartptr.atomic}, and +all associated \tcode{use_count} increments, +are guaranteed to be performed atomically. +Associated \tcode{use_count} decrements +are sequenced after the atomic operation, +but are not required to be part of it. +Any associated deletion and deallocation +are sequenced after the atomic update step and +are not part of the atomic operation. +\begin{note} +If the atomic operation uses locks, +locks acquired by the implementation +will be held when any \tcode{use_count} adjustments are performed, and +will not be held when any destruction or deallocation +resulting from this is performed. +\end{note} + +\pnum +\begin{example} +\begin{codeblock} +template class atomic_list { + struct node { + T t; + shared_ptr next; + }; + atomic> head; + +public: + auto find(T t) const { + auto p = head.load(); + while (p && p->t != t) + p = p->next; + + return shared_ptr(move(p)); + } + + void push_front(T t) { + auto p = make_shared(); + p->t = t; + p->next = head; + while (!head.compare_exchange_weak(p->next, p)) {} + } +}; +\end{codeblock} +\end{example} + +\rSec4[util.smartptr.atomic.shared]{Partial specialization for \tcode{shared_ptr}} +\indexlibraryglobal{atomic>}% +\begin{codeblock} +namespace std { + template struct atomic> { + using value_type = shared_ptr; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + constexpr atomic() noexcept; + constexpr atomic(nullptr_t) noexcept : atomic() { } + atomic(shared_ptr desired) noexcept; + atomic(const atomic&) = delete; + void operator=(const atomic&) = delete; + + shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; + operator shared_ptr() const noexcept; + void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; + void operator=(shared_ptr desired) noexcept; + + shared_ptr exchange(shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; + bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; + bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + + void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; + void notify_one() noexcept; + void notify_all() noexcept; + + private: + shared_ptr p; // \expos + }; +} +\end{codeblock} + +\indexlibraryctor{atomic>}% +\begin{itemdecl} +constexpr atomic() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{p\{\}}. +\end{itemdescr} + +\indexlibraryctor{atomic>}% +\begin{itemdecl} +atomic(shared_ptr desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes the object with the value \tcode{desired}. +Initialization is not an atomic operation\iref{intro.multithread}. +\begin{note} +It is possible to have an access to +an atomic object \tcode{A} race with its construction, +for example, +by communicating the address of the just-constructed object \tcode{A} +to another thread via \tcode{memory_order::relaxed} operations +on a suitable atomic pointer variable, and +then immediately accessing \tcode{A} in the receiving thread. +This results in undefined behavior. +\end{note} +\end{itemdescr} + +\indexlibrarymember{store}{atomic>}% +\begin{itemdecl} +void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is neither +\tcode{memory_order::consume}, +\tcode{memory_order::acquire}, nor +\tcode{memory_order::acq_rel}. + +\pnum +\effects +Atomically replaces the value pointed to by \keyword{this} with +the value of \tcode{desired} as if by \tcode{p.swap(desired)}. +Memory is affected according to the value of \tcode{order}. +\end{itemdescr} + +\indexlibrarymember{operator=}{atomic>}% +\begin{itemdecl} +void operator=(shared_ptr desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{store(desired)}. +\end{itemdescr} + +\indexlibrarymember{load}{atomic>}% +\begin{itemdecl} +shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Memory is affected according to the value of \tcode{order}. + +\pnum +\returns +Atomically returns \tcode{p}. +\end{itemdescr} + +\indexlibrarymember{operator shared_ptr}{atomic>}% +\begin{itemdecl} +operator shared_ptr() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return load();} +\end{itemdescr} + +\indexlibrarymember{exchange}{atomic>}% +\begin{itemdecl} +shared_ptr exchange(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically replaces \tcode{p} with \tcode{desired} +as if by \tcode{p.swap(desired)}. +Memory is affected according to the value of \tcode{order}. +This is an atomic read-modify-write operation\iref{intro.races}. + +\pnum +\returns +Atomically returns the value of \tcode{p} immediately before the effects. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_weak}{atomic>}% +\indexlibrarymember{compare_exchange_strong}{atomic>}% +\begin{itemdecl} +bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; +bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{failure} is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +If \tcode{p} is equivalent to \tcode{expected}, +assigns \tcode{desired} to \tcode{p} and +has synchronization semantics corresponding to the value of \tcode{success}, +otherwise assigns \tcode{p} to \tcode{expected} and +has synchronization semantics corresponding to the value of \tcode{failure}. + +\pnum +\returns +\tcode{true} if \tcode{p} was equivalent to \tcode{expected}, +\tcode{false} otherwise. + +\pnum +\remarks +Two \tcode{shared_ptr} objects are equivalent if +they store the same pointer value and +either share ownership or are both empty. +The weak form may fail spuriously. See \ref{atomics.types.operations}. + +\pnum +If the operation returns \tcode{true}, +\tcode{expected} is not accessed after the atomic update and +the operation is an atomic read-modify-write operation\iref{intro.multithread} +on the memory pointed to by \keyword{this}. +Otherwise, the operation is an atomic load operation on that memory, and +\tcode{expected} is updated with the existing value +read from the atomic object in the attempted atomic update. +The \tcode{use_count} update corresponding to the write to \tcode{expected} +is part of the atomic operation. +The write to \tcode{expected} itself +is not required to be part of the atomic operation. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_weak}{atomic>}% +\begin{itemdecl} +bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return compare_exchange_weak(expected, desired, order, fail_order); +\end{codeblock} +where \tcode{fail_order} is the same as \tcode{order} +except that a value of \tcode{memory_order::acq_rel} +shall be replaced by the value \tcode{memory_order::acquire} and +a value of \tcode{memory_order::release} +shall be replaced by the value \tcode{memory_order::relaxed}. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_strong}{atomic>}% +\begin{itemdecl} +bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return compare_exchange_strong(expected, desired, order, fail_order); +\end{codeblock} +where \tcode{fail_order} is the same as \tcode{order} +except that a value of \tcode{memory_order::acq_rel} +shall be replaced by the value \tcode{memory_order::acquire} and +a value of \tcode{memory_order::release} +shall be replaced by the value \tcode{memory_order::relaxed}. +\end{itemdescr} + +\indexlibrarymember{wait}{atomic>}% +\begin{itemdecl} +void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is +neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Repeatedly performs the following steps, in order: +\begin{itemize} +\item + Evaluates \tcode{load(order)} and compares it to \tcode{old}. +\item + If the two are not equivalent, returns. +\item + Blocks until it + is unblocked by an atomic notifying operation or is unblocked spuriously. +\end{itemize} + +\pnum +\remarks +Two \tcode{shared_ptr} objects are equivalent +if they store the same pointer and either share ownership or are both empty. +This function is an atomic waiting operation\iref{atomics.wait}. +\end{itemdescr} + +\indexlibrarymember{notify_one}{atomic>}% +\begin{itemdecl} +void notify_one() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of at least one atomic waiting operation +that is eligible to be unblocked\iref{atomics.wait} by this call, +if any such atomic waiting operations exist. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\indexlibrarymember{notify_all}{atomic>}% +\begin{itemdecl} +void notify_all() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of all atomic waiting operations +that are eligible to be unblocked\iref{atomics.wait} by this call. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\rSec4[util.smartptr.atomic.weak]{Partial specialization for \tcode{weak_ptr}} + +\indexlibraryglobal{atomic>}% +\begin{codeblock} +namespace std { + template struct atomic> { + using value_type = weak_ptr; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + constexpr atomic() noexcept; + atomic(weak_ptr desired) noexcept; + atomic(const atomic&) = delete; + void operator=(const atomic&) = delete; + + weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; + operator weak_ptr() const noexcept; + void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; + void operator=(weak_ptr desired) noexcept; + + weak_ptr exchange(weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; + bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; + bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + + void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; + void notify_one() noexcept; + void notify_all() noexcept; + + private: + weak_ptr p; // \expos + }; +} +\end{codeblock} + +\indexlibraryctor{atomic>}% +\begin{itemdecl} +constexpr atomic() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{p\{\}}. +\end{itemdescr} + +\indexlibraryctor{atomic>}% +\begin{itemdecl} +atomic(weak_ptr desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes the object with the value \tcode{desired}. +Initialization is not an atomic operation\iref{intro.multithread}. +\begin{note} +It is possible to have an access to +an atomic object \tcode{A} race with its construction, +for example, +by communicating the address of the just-constructed object \tcode{A} +to another thread via \tcode{memory_order::relaxed} operations +on a suitable atomic pointer variable, and +then immediately accessing \tcode{A} in the receiving thread. +This results in undefined behavior. +\end{note} +\end{itemdescr} + +\indexlibrarymember{store}{atomic>}% +\begin{itemdecl} +void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is neither +\tcode{memory_order::consume}, +\tcode{memory_order::acquire}, nor +\tcode{memory_order::acq_rel}. + +\pnum +\effects +Atomically replaces the value pointed to by \keyword{this} with +the value of \tcode{desired} as if by \tcode{p.swap(desired)}. +Memory is affected according to the value of \tcode{order}. +\end{itemdescr} + +\indexlibrarymember{operator=}{atomic>}% +\begin{itemdecl} +void operator=(weak_ptr desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{store(desired)}. +\end{itemdescr} + +\indexlibrarymember{load}{atomic>}% +\begin{itemdecl} +weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Memory is affected according to the value of \tcode{order}. + +\pnum +\returns +Atomically returns \tcode{p}. +\end{itemdescr} + +\indexlibrarymember{operator weak_ptr}{atomic>}% +\begin{itemdecl} +operator weak_ptr() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return load();} +\end{itemdescr} + +\indexlibrarymember{exchange}{atomic>}% +\begin{itemdecl} +weak_ptr exchange(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically replaces \tcode{p} with \tcode{desired} +as if by \tcode{p.swap(desired)}. +Memory is affected according to the value of \tcode{order}. +This is an atomic read-modify-write operation\iref{intro.races}. + +\pnum +\returns +Atomically returns the value of \tcode{p} immediately before the effects. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_weak}{atomic>}% +\begin{itemdecl} +bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; +bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{failure} is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +If \tcode{p} is equivalent to \tcode{expected}, +assigns \tcode{desired} to \tcode{p} and +has synchronization semantics corresponding to the value of \tcode{success}, +otherwise assigns \tcode{p} to \tcode{expected} and +has synchronization semantics corresponding to the value of \tcode{failure}. + +\pnum +\returns +\tcode{true} if \tcode{p} was equivalent to \tcode{expected}, +\tcode{false} otherwise. + +\pnum +\remarks +Two \tcode{weak_ptr} objects are equivalent if +they store the same pointer value and +either share ownership or are both empty. +The weak form may fail spuriously. See \ref{atomics.types.operations}. + +\pnum +If the operation returns \tcode{true}, +\tcode{expected} is not accessed after the atomic update and +the operation is an atomic read-modify-write operation\iref{intro.multithread} +on the memory pointed to by \keyword{this}. +Otherwise, the operation is an atomic load operation on that memory, and +\tcode{expected} is updated with the existing value +read from the atomic object in the attempted atomic update. +The \tcode{use_count} update corresponding to the write to \tcode{expected} +is part of the atomic operation. +The write to \tcode{expected} itself +is not required to be part of the atomic operation. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_weak}{atomic>}% +\begin{itemdecl} +bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return compare_exchange_weak(expected, desired, order, fail_order); +\end{codeblock} +where \tcode{fail_order} is the same as \tcode{order} +except that a value of \tcode{memory_order::acq_rel} +shall be replaced by the value \tcode{memory_order::acquire} and +a value of \tcode{memory_order::release} +shall be replaced by the value \tcode{memory_order::relaxed}. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_strong}{atomic>}% +\begin{itemdecl} +bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return compare_exchange_strong(expected, desired, order, fail_order); +\end{codeblock} +where \tcode{fail_order} is the same as \tcode{order} +except that a value of \tcode{memory_order::acq_rel} +shall be replaced by the value \tcode{memory_order::acquire} and +a value of \tcode{memory_order::release} +shall be replaced by the value \tcode{memory_order::relaxed}. +\end{itemdescr} + +\indexlibrarymember{wait}{atomic>}% +\begin{itemdecl} +void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is +neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Repeatedly performs the following steps, in order: +\begin{itemize} +\item + Evaluates \tcode{load(order)} and compares it to \tcode{old}. +\item + If the two are not equivalent, returns. +\item + Blocks until it + is unblocked by an atomic notifying operation or is unblocked spuriously. +\end{itemize} + +\pnum +\remarks +Two \tcode{weak_ptr} objects are equivalent +if they store the same pointer and either share ownership or are both empty. +This function is an atomic waiting operation\iref{atomics.wait}. +\end{itemdescr} + + +\indexlibrarymember{notify_one}{atomic>}% +\begin{itemdecl} +void notify_one() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of at least one atomic waiting operation +that is eligible to be unblocked\iref{atomics.wait} by this call, +if any such atomic waiting operations exist. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\indexlibrarymember{notify_all}{atomic>}% +\begin{itemdecl} +void notify_all() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of all atomic waiting operations +that are eligible to be unblocked\iref{atomics.wait} by this call. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} +\indextext{atomic!smart pointers|)} + +\rSec2[atomics.nonmembers]{Non-member functions} + +\pnum +A non-member function template whose name matches the pattern +\tcode{atomic_\placeholder{f}} or the pattern \tcode{atomic_\placeholder{f}_explicit} +invokes the member function \tcode{\placeholder{f}}, with the value of the +first parameter as the object expression and the values of the remaining parameters +(if any) as the arguments of the member function call, in order. An argument +for a parameter of type \tcode{atomic::value_type*} is dereferenced when +passed to the member function call. +If no such member function exists, the program is ill-formed. + +\pnum +\begin{note} +The non-member functions enable programmers to write code that can be +compiled as either C or \Cpp{}, for example in a shared header file. +\end{note} + +\rSec2[atomics.flag]{Flag type and operations} + +\begin{codeblock} +namespace std { + struct atomic_flag { + constexpr atomic_flag() noexcept; + atomic_flag(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) volatile = delete; + + bool test(memory_order = memory_order::seq_cst) const volatile noexcept; + bool test(memory_order = memory_order::seq_cst) const noexcept; + bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept; + bool test_and_set(memory_order = memory_order::seq_cst) noexcept; + void clear(memory_order = memory_order::seq_cst) volatile noexcept; + void clear(memory_order = memory_order::seq_cst) noexcept; + + void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept; + void wait(bool, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() volatile noexcept; + void notify_one() noexcept; + void notify_all() volatile noexcept; + void notify_all() noexcept; + }; +} +\end{codeblock} + +\pnum +The \tcode{atomic_flag} type provides the classic test-and-set functionality. It has two states, set and clear. + +\pnum +Operations on an object of type \tcode{atomic_flag} shall be lock-free. +The operations should also be address-free. + +\pnum +The \tcode{atomic_flag} type is a standard-layout struct. +It has a trivial destructor. + +\indexlibraryctor{atomic_flag}% +\begin{itemdecl} +constexpr atomic_flag::atomic_flag() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{*this} to the clear state. +\end{itemdescr} + +\indexlibraryglobal{atomic_flag_test}% +\indexlibraryglobal{atomic_flag_test_explicit}% +\indexlibrarymember{test}{atomic_flag}% +\begin{itemdecl} +bool atomic_flag_test(const volatile atomic_flag* object) noexcept; +bool atomic_flag_test(const atomic_flag* object) noexcept; +bool atomic_flag_test_explicit(const volatile atomic_flag* object, + memory_order order) noexcept; +bool atomic_flag_test_explicit(const atomic_flag* object, + memory_order order) noexcept; +bool atomic_flag::test(memory_order order = memory_order::seq_cst) const volatile noexcept; +bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +For \tcode{atomic_flag_test}, let \tcode{order} be \tcode{memory_order::seq_cst}. + +\pnum +\expects +\tcode{order} is +neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Memory is affected according to the value of \tcode{order}. + +\pnum +\returns +Atomically returns the value pointed to by \tcode{object} or \keyword{this}. +\end{itemdescr} + +\indexlibraryglobal{atomic_flag_test_and_set}% +\indexlibraryglobal{atomic_flag_test_and_set_explicit}% +\indexlibrarymember{test_and_set}{atomic_flag}% +\begin{itemdecl} +bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept; +bool atomic_flag_test_and_set(atomic_flag* object) noexcept; +bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept; +bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept; +bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept; +bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically sets the value pointed to by \tcode{object} or by \keyword{this} to \tcode{true}. Memory is affected according to the value of +\tcode{order}. These operations are atomic read-modify-write operations\iref{intro.multithread}. + +\pnum +\returns +Atomically, the value of the object immediately before the effects. +\end{itemdescr} + +\indexlibraryglobal{atomic_flag_clear}% +\indexlibraryglobal{atomic_flag_clear_explicit}% +\indexlibrarymember{clear}{atomic_flag}% +\begin{itemdecl} +void atomic_flag_clear(volatile atomic_flag* object) noexcept; +void atomic_flag_clear(atomic_flag* object) noexcept; +void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept; +void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept; +void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept; +void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The \tcode{order} argument is neither \tcode{memory_order::consume}, +\tcode{memory_order::acquire}, nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Atomically sets the value pointed to by \tcode{object} or by \keyword{this} to +\tcode{false}. Memory is affected according to the value of \tcode{order}. +\end{itemdescr} + +\indexlibraryglobal{atomic_flag_wait}% +\indexlibraryglobal{atomic_flag_wait_explicit}% +\indexlibrarymember{wait}{atomic_flag}% +\begin{itemdecl} +void atomic_flag_wait(const volatile atomic_flag* object, bool old) noexcept; +void atomic_flag_wait(const atomic_flag* object, bool old) noexcept; +void atomic_flag_wait_explicit(const volatile atomic_flag* object, + bool old, memory_order order) noexcept; +void atomic_flag_wait_explicit(const atomic_flag* object, + bool old, memory_order order) noexcept; +void atomic_flag::wait(bool old, memory_order order = + memory_order::seq_cst) const volatile noexcept; +void atomic_flag::wait(bool old, memory_order order = + memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +For \tcode{atomic_flag_wait}, +let \tcode{order} be \tcode{memory_order::seq_cst}. +Let \tcode{flag} be \tcode{object} for the non-member functions and +\keyword{this} for the member functions. + +\pnum +\expects +\tcode{order} is +neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Repeatedly performs the following steps, in order: +\begin{itemize} +\item + Evaluates \tcode{flag->test(order) != old}. +\item + If the result of that evaluation is \tcode{true}, returns. +\item + Blocks until it + is unblocked by an atomic notifying operation or is unblocked spuriously. +\end{itemize} + +\pnum +\remarks +This function is an atomic waiting operation\iref{atomics.wait}. +\end{itemdescr} + +\begin{itemdecl} +void atomic_flag_notify_one(volatile atomic_flag* object) noexcept; +void atomic_flag_notify_one(atomic_flag* object) noexcept; +void atomic_flag::notify_one() volatile noexcept; +void atomic_flag::notify_one() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of at least one atomic waiting operation +that is eligible to be unblocked\iref{atomics.wait} by this call, +if any such atomic waiting operations exist. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\begin{itemdecl} +void atomic_flag_notify_all(volatile atomic_flag* object) noexcept; +void atomic_flag_notify_all(atomic_flag* object) noexcept; +void atomic_flag::notify_all() volatile noexcept; +void atomic_flag::notify_all() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of all atomic waiting operations +that are eligible to be unblocked\iref{atomics.wait} by this call. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\rSec2[atomics.fences]{Fences} + +\pnum +This subclause introduces synchronization primitives called \term{fences}. Fences can have +acquire semantics, release semantics, or both. A fence with acquire semantics is called +an \term{acquire fence}. A fence with release semantics is called a \term{release +fence}. + +\pnum +A release fence $A$ synchronizes with an acquire fence $B$ if there exist +atomic operations $X$ and $Y$, both operating on some atomic object +$M$, such that $A$ is sequenced before $X$, $X$ modifies +$M$, $Y$ is sequenced before $B$, and $Y$ reads the value +written by $X$ or a value written by any side effect in the hypothetical release +sequence $X$ would head if it were a release operation. + +\pnum +A release fence $A$ synchronizes with an atomic operation $B$ that +performs an acquire operation on an atomic object $M$ if there exists an atomic +operation $X$ such that $A$ is sequenced before $X$, $X$ +modifies $M$, and $B$ reads the value written by $X$ or a value +written by any side effect in the hypothetical release sequence $X$ would head if +it were a release operation. + +\pnum +An atomic operation $A$ that is a release operation on an atomic object +$M$ synchronizes with an acquire fence $B$ if there exists some atomic +operation $X$ on $M$ such that $X$ is sequenced before $B$ +and reads the value written by $A$ or a value written by any side effect in the +release sequence headed by $A$. + +\indexlibraryglobal{atomic_thread_fence}% +\begin{itemdecl} +extern "C" void atomic_thread_fence(memory_order order) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Depending on the value of \tcode{order}, this operation: +\begin{itemize} +\item has no effects, if \tcode{order == memory_order::relaxed}; + +\item is an acquire fence, if \tcode{order == memory_order::acquire} or \tcode{order == memory_order::consume}; + +\item is a release fence, if \tcode{order == memory_order::release}; + +\item is both an acquire fence and a release fence, if \tcode{order == memory_order::acq_rel}; + +\item is a sequentially consistent acquire and release fence, if \tcode{order == memory_order::seq_cst}. +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{atomic_signal_fence}% +\begin{itemdecl} +extern "C" void atomic_signal_fence(memory_order order) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{atomic_thread_fence(order)}, except that +the resulting ordering constraints are established only between a thread and a +signal handler executed in the same thread. + +\pnum +\begin{note} +\tcode{atomic_signal_fence} can be used to specify the order in which actions +performed by the thread become visible to the signal handler. +Compiler optimizations and reorderings of loads and stores are inhibited in +the same way as with \tcode{atomic_thread_fence}, but the hardware fence instructions +that \tcode{atomic_thread_fence} would have inserted are not emitted. +\end{note} +\end{itemdescr} + +\rSec2[stdatomic.h.syn]{C compatibility} + +The header \libheaderdef{stdatomic.h} provides the following definitions: + +\begin{codeblock} +template + using @\exposid{std-atomic}@ = std::atomic; // \expos + +#define _Atomic(T) @\exposid{std-atomic}@ + +#define ATOMIC_BOOL_LOCK_FREE @\seebelow@ +#define ATOMIC_CHAR_LOCK_FREE @\seebelow@ +#define ATOMIC_CHAR16_T_LOCK_FREE @\seebelow@ +#define ATOMIC_CHAR32_T_LOCK_FREE @\seebelow@ +#define ATOMIC_WCHAR_T_LOCK_FREE @\seebelow@ +#define ATOMIC_SHORT_LOCK_FREE @\seebelow@ +#define ATOMIC_INT_LOCK_FREE @\seebelow@ +#define ATOMIC_LONG_LOCK_FREE @\seebelow@ +#define ATOMIC_LLONG_LOCK_FREE @\seebelow@ +#define ATOMIC_POINTER_LOCK_FREE @\seebelow@ + +using std::@\libglobal{memory_order}@; // \seebelow +using std::@\libglobal{memory_order_relaxed}@; // \seebelow +using std::@\libglobal{memory_order_consume}@; // \seebelow +using std::@\libglobal{memory_order_acquire}@; // \seebelow +using std::@\libglobal{memory_order_release}@; // \seebelow +using std::@\libglobal{memory_order_acq_rel}@; // \seebelow +using std::@\libglobal{memory_order_seq_cst}@; // \seebelow + +using std::@\libglobal{atomic_flag}@; // \seebelow + +using std::@\libglobal{atomic_bool}@; // \seebelow +using std::@\libglobal{atomic_char}@; // \seebelow +using std::@\libglobal{atomic_schar}@; // \seebelow +using std::@\libglobal{atomic_uchar}@; // \seebelow +using std::@\libglobal{atomic_short}@; // \seebelow +using std::@\libglobal{atomic_ushort}@; // \seebelow +using std::@\libglobal{atomic_int}@; // \seebelow +using std::@\libglobal{atomic_uint}@; // \seebelow +using std::@\libglobal{atomic_long}@; // \seebelow +using std::@\libglobal{atomic_ulong}@; // \seebelow +using std::@\libglobal{atomic_llong}@; // \seebelow +using std::@\libglobal{atomic_ullong}@; // \seebelow +using std::@\libglobal{atomic_char8_t}@; // \seebelow +using std::@\libglobal{atomic_char16_t}@; // \seebelow +using std::@\libglobal{atomic_char32_t}@; // \seebelow +using std::@\libglobal{atomic_wchar_t}@; // \seebelow +using std::@\libglobal{atomic_int8_t}@; // \seebelow +using std::@\libglobal{atomic_uint8_t}@; // \seebelow +using std::@\libglobal{atomic_int16_t}@; // \seebelow +using std::@\libglobal{atomic_uint16_t}@; // \seebelow +using std::@\libglobal{atomic_int32_t}@; // \seebelow +using std::@\libglobal{atomic_uint32_t}@; // \seebelow +using std::@\libglobal{atomic_int64_t}@; // \seebelow +using std::@\libglobal{atomic_uint64_t}@; // \seebelow +using std::@\libglobal{atomic_int_least8_t}@; // \seebelow +using std::@\libglobal{atomic_uint_least8_t}@; // \seebelow +using std::@\libglobal{atomic_int_least16_t}@; // \seebelow +using std::@\libglobal{atomic_uint_least16_t}@; // \seebelow +using std::@\libglobal{atomic_int_least32_t}@; // \seebelow +using std::@\libglobal{atomic_uint_least32_t}@; // \seebelow +using std::@\libglobal{atomic_int_least64_t}@; // \seebelow +using std::@\libglobal{atomic_uint_least64_t}@; // \seebelow +using std::@\libglobal{atomic_int_fast8_t}@; // \seebelow +using std::@\libglobal{atomic_uint_fast8_t}@; // \seebelow +using std::@\libglobal{atomic_int_fast16_t}@; // \seebelow +using std::@\libglobal{atomic_uint_fast16_t}@; // \seebelow +using std::@\libglobal{atomic_int_fast32_t}@; // \seebelow +using std::@\libglobal{atomic_uint_fast32_t}@; // \seebelow +using std::@\libglobal{atomic_int_fast64_t}@; // \seebelow +using std::@\libglobal{atomic_uint_fast64_t}@; // \seebelow +using std::@\libglobal{atomic_intptr_t}@; // \seebelow +using std::@\libglobal{atomic_uintptr_t}@; // \seebelow +using std::@\libglobal{atomic_size_t}@; // \seebelow +using std::@\libglobal{atomic_ptrdiff_t}@; // \seebelow +using std::@\libglobal{atomic_intmax_t}@; // \seebelow +using std::@\libglobal{atomic_uintmax_t}@; // \seebelow + +using std::@\libglobal{atomic_is_lock_free}@; // \seebelow +using std::@\libglobal{atomic_load}@; // \seebelow +using std::@\libglobal{atomic_load_explicit}@; // \seebelow +using std::@\libglobal{atomic_store}@; // \seebelow +using std::@\libglobal{atomic_store_explicit}@; // \seebelow +using std::@\libglobal{atomic_exchange}@; // \seebelow +using std::@\libglobal{atomic_exchange_explicit}@; // \seebelow +using std::@\libglobal{atomic_compare_exchange_strong}@; // \seebelow +using std::@\libglobal{atomic_compare_exchange_strong_explicit}@; // \seebelow +using std::@\libglobal{atomic_compare_exchange_weak}@; // \seebelow +using std::@\libglobal{atomic_compare_exchange_weak_explicit}@; // \seebelow +using std::@\libglobal{atomic_fetch_add}@; // \seebelow +using std::@\libglobal{atomic_fetch_add_explicit}@; // \seebelow +using std::@\libglobal{atomic_fetch_sub}@; // \seebelow +using std::@\libglobal{atomic_fetch_sub_explicit}@; // \seebelow +using std::@\libglobal{atomic_fetch_or}@; // \seebelow +using std::@\libglobal{atomic_fetch_or_explicit}@; // \seebelow +using std::@\libglobal{atomic_fetch_and}@; // \seebelow +using std::@\libglobal{atomic_fetch_and_explicit}@; // \seebelow +using std::@\libglobal{atomic_flag_test_and_set}@; // \seebelow +using std::@\libglobal{atomic_flag_test_and_set_explicit}@; // \seebelow +using std::@\libglobal{atomic_flag_clear}@; // \seebelow +using std::@\libglobal{atomic_flag_clear_explicit}@; // \seebelow + +using std::@\libglobal{atomic_thread_fence}@; // \seebelow +using std::@\libglobal{atomic_signal_fence}@; // \seebelow +\end{codeblock} + +\pnum +Each \grammarterm{using-declaration} for some name $A$ in the synopsis above +makes available the same entity as \tcode{std::$A$} +declared in \libheaderrefx{atomic}{atomics.syn}. +Each macro listed above other than \tcode{_Atomic(T)} +is defined as in \libheader{atomic}. +It is unspecified whether \libheader{stdatomic.h} makes available +any declarations in namespace \tcode{std}. + +\pnum +Each of the \grammarterm{using-declaration}s for +\tcode{int$N$_t}, \tcode{uint$N$_t}, \tcode{intptr_t}, and \tcode{uintptr_t} +listed above is defined if and only if the implementation defines +the corresponding \grammarterm{typedef-name} in \ref{atomics.syn}. + +\pnum +Neither the \tcode{_Atomic} macro, +nor any of the non-macro global namespace declarations, +are provided by any \Cpp{} standard library header +other than \libheader{stdatomic.h}. + +\pnum +\recommended +Implementations should ensure +that C and \Cpp{} representations of atomic objects are compatible, +so that the same object can be accessed as both an \tcode{_Atomic(T)} +from C code and an \tcode{atomic} from \Cpp{} code. +The representations should be the same, and +the mechanisms used to ensure atomicity and memory ordering +should be compatible. + \rSec1[thread.mutex]{Mutual exclusion} \rSec2[thread.mutex.general]{General} @@ -6300,8 +10137,8 @@ \begin{itemdescr} \pnum \expects -\tcode{Alloc} meets the \oldconcept{Allocator} -requirements (\tref{cpp17.allocator}). +\tcode{Alloc} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \end{itemdescr} \indexlibraryctor{promise}% @@ -7244,8 +11081,7 @@ \begin{itemize} \item If \tcode{launch::async} is set in \tcode{policy}, calls -\tcode{invoke(auto(std::forward(f)), auto(std::for\-ward(args))...)} -(\ref{func.require}, \ref{thread.thread.constr}) +\tcode{invoke(auto(std::forward(f)), auto(std::for\-ward(args))...)}\iref{func.require,thread.thread.constr} as if in a new thread of execution represented by a \tcode{thread} object with the values produced by \tcode{auto} being materialized\iref{conv.rval} in the thread that called \tcode{async}. diff --git a/source/time.tex b/source/time.tex index 63be16fd12..667d1fc334 100644 --- a/source/time.tex +++ b/source/time.tex @@ -65,15 +65,15 @@ \begin{codeblock} #include // see \ref{compare.syn} -namespace std { - namespace chrono { - // \ref{time.duration}, class template \tcode{duration} - template> class duration; +namespace std::chrono { + // \ref{time.duration}, class template \tcode{duration} + template> class duration; - // \ref{time.point}, class template \tcode{time_point} - template class time_point; - } + // \ref{time.point}, class template \tcode{time_point} + template class time_point; +} +namespace std { // \ref{time.traits.specializations}, \tcode{common_type} specializations template struct common_type, @@ -82,735 +82,737 @@ template struct common_type, chrono::time_point>; +} - namespace chrono { - // \ref{time.traits}, customization traits - template struct treat_as_floating_point; - template - inline constexpr bool treat_as_floating_point_v = treat_as_floating_point::value; - - template struct duration_values; - - template struct is_clock; - template inline constexpr bool is_clock_v = is_clock::value; - - // \ref{time.duration.nonmember}, \tcode{duration} arithmetic - template - constexpr common_type_t, duration> - operator+(const duration& lhs, const duration& rhs); - template - constexpr common_type_t, duration> - operator-(const duration& lhs, const duration& rhs); - template - constexpr duration, Period> - operator*(const duration& d, const Rep2& s); - template - constexpr duration, Period> - operator*(const Rep1& s, const duration& d); - template - constexpr duration, Period> - operator/(const duration& d, const Rep2& s); - template - constexpr common_type_t - operator/(const duration& lhs, const duration& rhs); - template - constexpr duration, Period> - operator%(const duration& d, const Rep2& s); - template - constexpr common_type_t, duration> - operator%(const duration& lhs, const duration& rhs); - - // \ref{time.duration.comparisons}, \tcode{duration} comparisons - template - constexpr bool operator==(const duration& lhs, - const duration& rhs); - template - constexpr bool operator< (const duration& lhs, - const duration& rhs); - template - constexpr bool operator> (const duration& lhs, - const duration& rhs); - template - constexpr bool operator<=(const duration& lhs, - const duration& rhs); - template - constexpr bool operator>=(const duration& lhs, - const duration& rhs); - template - requires @\seebelow@ - constexpr auto operator<=>(const duration& lhs, - const duration& rhs); - - // \ref{time.duration.cast}, conversions - template - constexpr ToDuration duration_cast(const duration& d); - template - constexpr ToDuration floor(const duration& d); - template - constexpr ToDuration ceil(const duration& d); - template - constexpr ToDuration round(const duration& d); - - // \ref{time.duration.io}, \tcode{duration} I/O - template - basic_ostream& - operator<<(basic_ostream& os, - const duration& d); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - duration& d, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // convenience typedefs - using nanoseconds = duration<@\term{signed integer type of at least 64 bits}@, nano>; - using microseconds = duration<@\term{signed integer type of at least 55 bits}@, micro>; - using milliseconds = duration<@\term{signed integer type of at least 45 bits}@, milli>; - using seconds = duration<@\term{signed integer type of at least 35 bits}@>; - using minutes = duration<@\term{signed integer type of at least 29 bits}@, ratio< 60>>; - using hours = duration<@\term{signed integer type of at least 23 bits}@, ratio<3600>>; - using days = duration<@\term{signed integer type of at least 25 bits}@, - ratio_multiply, hours::period>>; - using weeks = duration<@\term{signed integer type of at least 22 bits}@, - ratio_multiply, days::period>>; - using years = duration<@\term{signed integer type of at least 17 bits}@, - ratio_multiply, days::period>>; - using months = duration<@\term{signed integer type of at least 20 bits}@, - ratio_divide>>; - - // \ref{time.point.nonmember}, \tcode{time_point} arithmetic - template - constexpr time_point>> - operator+(const time_point& lhs, const duration& rhs); - template - constexpr time_point, Duration2>> - operator+(const duration& lhs, const time_point& rhs); - template - constexpr time_point>> - operator-(const time_point& lhs, const duration& rhs); - template - constexpr common_type_t - operator-(const time_point& lhs, - const time_point& rhs); - - // \ref{time.point.comparisons}, \tcode{time_point} comparisons - template - constexpr bool operator==(const time_point& lhs, - const time_point& rhs); - template - constexpr bool operator< (const time_point& lhs, - const time_point& rhs); - template - constexpr bool operator> (const time_point& lhs, - const time_point& rhs); - template - constexpr bool operator<=(const time_point& lhs, - const time_point& rhs); - template - constexpr bool operator>=(const time_point& lhs, - const time_point& rhs); - template Duration2> - constexpr auto operator<=>(const time_point& lhs, - const time_point& rhs); - - // \ref{time.point.cast}, conversions - template - constexpr time_point - time_point_cast(const time_point& t); - template - constexpr time_point floor(const time_point& tp); - template - constexpr time_point ceil(const time_point& tp); - template - constexpr time_point round(const time_point& tp); - - // \ref{time.duration.alg}, specialized algorithms - template - constexpr duration abs(duration d); - - // \ref{time.clock.system}, class \tcode{system_clock} - class system_clock; +namespace std::chrono { + // \ref{time.traits}, customization traits + template struct treat_as_floating_point; + template + inline constexpr bool treat_as_floating_point_v = treat_as_floating_point::value; - template - using sys_time = time_point; - using sys_seconds = sys_time; - using sys_days = sys_time; + template struct duration_values; - template - basic_ostream& - operator<<(basic_ostream& os, const sys_time& tp); + template struct is_clock; + template inline constexpr bool is_clock_v = is_clock::value; - template - basic_ostream& - operator<<(basic_ostream& os, const sys_days& dp); + // \ref{time.duration.nonmember}, \tcode{duration} arithmetic + template + constexpr common_type_t, duration> + operator+(const duration& lhs, const duration& rhs); + template + constexpr common_type_t, duration> + operator-(const duration& lhs, const duration& rhs); + template + constexpr duration, Period> + operator*(const duration& d, const Rep2& s); + template + constexpr duration, Period> + operator*(const Rep1& s, const duration& d); + template + constexpr duration, Period> + operator/(const duration& d, const Rep2& s); + template + constexpr common_type_t + operator/(const duration& lhs, const duration& rhs); + template + constexpr duration, Period> + operator%(const duration& d, const Rep2& s); + template + constexpr common_type_t, duration> + operator%(const duration& lhs, const duration& rhs); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - sys_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); + // \ref{time.duration.comparisons}, \tcode{duration} comparisons + template + constexpr bool operator==(const duration& lhs, + const duration& rhs); + template + constexpr bool operator< (const duration& lhs, + const duration& rhs); + template + constexpr bool operator> (const duration& lhs, + const duration& rhs); + template + constexpr bool operator<=(const duration& lhs, + const duration& rhs); + template + constexpr bool operator>=(const duration& lhs, + const duration& rhs); + template + requires @\seebelow@ + constexpr auto operator<=>(const duration& lhs, + const duration& rhs); + + // \ref{time.duration.cast}, conversions + template + constexpr ToDuration duration_cast(const duration& d); + template + constexpr ToDuration floor(const duration& d); + template + constexpr ToDuration ceil(const duration& d); + template + constexpr ToDuration round(const duration& d); + + // \ref{time.duration.io}, \tcode{duration} I/O + template + basic_ostream& + operator<<(basic_ostream& os, + const duration& d); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + duration& d, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // convenience typedefs + using nanoseconds = duration<@\term{signed integer type of at least 64 bits}@, nano>; + using microseconds = duration<@\term{signed integer type of at least 55 bits}@, micro>; + using milliseconds = duration<@\term{signed integer type of at least 45 bits}@, milli>; + using seconds = duration<@\term{signed integer type of at least 35 bits}@>; + using minutes = duration<@\term{signed integer type of at least 29 bits}@, ratio< 60>>; + using hours = duration<@\term{signed integer type of at least 23 bits}@, ratio<3600>>; + using days = duration<@\term{signed integer type of at least 25 bits}@, + ratio_multiply, hours::period>>; + using weeks = duration<@\term{signed integer type of at least 22 bits}@, + ratio_multiply, days::period>>; + using years = duration<@\term{signed integer type of at least 17 bits}@, + ratio_multiply, days::period>>; + using months = duration<@\term{signed integer type of at least 20 bits}@, + ratio_divide>>; + + // \ref{time.point.nonmember}, \tcode{time_point} arithmetic + template + constexpr time_point>> + operator+(const time_point& lhs, const duration& rhs); + template + constexpr time_point, Duration2>> + operator+(const duration& lhs, const time_point& rhs); + template + constexpr time_point>> + operator-(const time_point& lhs, const duration& rhs); + template + constexpr common_type_t + operator-(const time_point& lhs, + const time_point& rhs); - // \ref{time.clock.utc}, class \tcode{utc_clock} - class utc_clock; + // \ref{time.point.comparisons}, \tcode{time_point} comparisons + template + constexpr bool operator==(const time_point& lhs, + const time_point& rhs); + template + constexpr bool operator< (const time_point& lhs, + const time_point& rhs); + template + constexpr bool operator> (const time_point& lhs, + const time_point& rhs); + template + constexpr bool operator<=(const time_point& lhs, + const time_point& rhs); + template + constexpr bool operator>=(const time_point& lhs, + const time_point& rhs); + template Duration2> + constexpr auto operator<=>(const time_point& lhs, + const time_point& rhs); + + // \ref{time.point.cast}, conversions + template + constexpr time_point + time_point_cast(const time_point& t); + template + constexpr time_point floor(const time_point& tp); + template + constexpr time_point ceil(const time_point& tp); + template + constexpr time_point round(const time_point& tp); + + // \ref{time.duration.alg}, specialized algorithms + template + constexpr duration abs(duration d); + + // \ref{time.clock.system}, class \tcode{system_clock} + class system_clock; - template - using utc_time = time_point; - using utc_seconds = utc_time; + template + using sys_time = time_point; + using sys_seconds = sys_time; + using sys_days = sys_time; - template - basic_ostream& - operator<<(basic_ostream& os, const utc_time& t); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - utc_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); + template + basic_ostream& + operator<<(basic_ostream& os, const sys_time& tp); - struct leap_second_info; + template + basic_ostream& + operator<<(basic_ostream& os, const sys_days& dp); - template - leap_second_info get_leap_second_info(const utc_time& ut); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + sys_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); - // \ref{time.clock.tai}, class \tcode{tai_clock} - class tai_clock; + // \ref{time.clock.utc}, class \tcode{utc_clock} + class utc_clock; - template - using tai_time = time_point; - using tai_seconds = tai_time; - - template - basic_ostream& - operator<<(basic_ostream& os, const tai_time& t); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - tai_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.clock.gps}, class \tcode{gps_clock} - class gps_clock; + template + using utc_time = time_point; + using utc_seconds = utc_time; - template - using gps_time = time_point; - using gps_seconds = gps_time; - - template - basic_ostream& - operator<<(basic_ostream& os, const gps_time& t); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - gps_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.clock.file}, type \tcode{file_clock} - using file_clock = @\seebelow@; + template + basic_ostream& + operator<<(basic_ostream& os, const utc_time& t); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + utc_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); - template - using file_time = time_point; - - template - basic_ostream& - operator<<(basic_ostream& os, const file_time& tp); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - file_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.clock.steady}, class \tcode{steady_clock} - class steady_clock; - - // \ref{time.clock.hires}, class \tcode{high_resolution_clock} - class high_resolution_clock; - - // \ref{time.clock.local}, local time - struct local_t {}; - template - using local_time = time_point; - using local_seconds = local_time; - using local_days = local_time; - - template - basic_ostream& - operator<<(basic_ostream& os, const local_time& tp); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - local_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.clock.cast}, \tcode{time_point} conversions - template - struct clock_time_conversion; - - template - auto clock_cast(const time_point& t); - - // \ref{time.cal.last}, class \tcode{last_spec} - struct last_spec; - - // \ref{time.cal.day}, class \tcode{day} - class day; - - constexpr bool operator==(const day& x, const day& y) noexcept; - constexpr strong_ordering operator<=>(const day& x, const day& y) noexcept; - - constexpr day operator+(const day& x, const days& y) noexcept; - constexpr day operator+(const days& x, const day& y) noexcept; - constexpr day operator-(const day& x, const days& y) noexcept; - constexpr days operator-(const day& x, const day& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const day& d); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - day& d, basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.month}, class \tcode{month} - class month; - - constexpr bool operator==(const month& x, const month& y) noexcept; - constexpr strong_ordering operator<=>(const month& x, const month& y) noexcept; - - constexpr month operator+(const month& x, const months& y) noexcept; - constexpr month operator+(const months& x, const month& y) noexcept; - constexpr month operator-(const month& x, const months& y) noexcept; - constexpr months operator-(const month& x, const month& y) noexcept; + struct leap_second_info; - template - basic_ostream& - operator<<(basic_ostream& os, const month& m); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - month& m, basic_string* abbrev = nullptr, - minutes* offset = nullptr); + template + leap_second_info get_leap_second_info(const utc_time& ut); - // \ref{time.cal.year}, class \tcode{year} - class year; + // \ref{time.clock.tai}, class \tcode{tai_clock} + class tai_clock; - constexpr bool operator==(const year& x, const year& y) noexcept; - constexpr strong_ordering operator<=>(const year& x, const year& y) noexcept; + template + using tai_time = time_point; + using tai_seconds = tai_time; + + template + basic_ostream& + operator<<(basic_ostream& os, const tai_time& t); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + tai_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.clock.gps}, class \tcode{gps_clock} + class gps_clock; - constexpr year operator+(const year& x, const years& y) noexcept; - constexpr year operator+(const years& x, const year& y) noexcept; - constexpr year operator-(const year& x, const years& y) noexcept; - constexpr years operator-(const year& x, const year& y) noexcept; + template + using gps_time = time_point; + using gps_seconds = gps_time; + + template + basic_ostream& + operator<<(basic_ostream& os, const gps_time& t); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + gps_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.clock.file}, type \tcode{file_clock} + using file_clock = @\seebelow@; - template - basic_ostream& - operator<<(basic_ostream& os, const year& y); + template + using file_time = time_point; + + template + basic_ostream& + operator<<(basic_ostream& os, const file_time& tp); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + file_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.clock.steady}, class \tcode{steady_clock} + class steady_clock; + + // \ref{time.clock.hires}, class \tcode{high_resolution_clock} + class high_resolution_clock; + + // \ref{time.clock.local}, local time + struct local_t {}; + template + using local_time = time_point; + using local_seconds = local_time; + using local_days = local_time; + + template + basic_ostream& + operator<<(basic_ostream& os, const local_time& tp); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + local_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.clock.cast}, \tcode{time_point} conversions + template + struct clock_time_conversion; - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - year& y, basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.wd}, class \tcode{weekday} - class weekday; - - constexpr bool operator==(const weekday& x, const weekday& y) noexcept; - - constexpr weekday operator+(const weekday& x, const days& y) noexcept; - constexpr weekday operator+(const days& x, const weekday& y) noexcept; - constexpr weekday operator-(const weekday& x, const days& y) noexcept; - constexpr days operator-(const weekday& x, const weekday& y) noexcept; + template + auto clock_cast(const time_point& t); - template - basic_ostream& - operator<<(basic_ostream& os, const weekday& wd); + // \ref{time.cal.last}, class \tcode{last_spec} + struct last_spec; - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - weekday& wd, basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.wdidx}, class \tcode{weekday_indexed} - class weekday_indexed; - - constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; + // \ref{time.cal.day}, class \tcode{day} + class day; - template - basic_ostream& - operator<<(basic_ostream& os, const weekday_indexed& wdi); + constexpr bool operator==(const day& x, const day& y) noexcept; + constexpr strong_ordering operator<=>(const day& x, const day& y) noexcept; - // \ref{time.cal.wdlast}, class \tcode{weekday_last} - class weekday_last; + constexpr day operator+(const day& x, const days& y) noexcept; + constexpr day operator+(const days& x, const day& y) noexcept; + constexpr day operator-(const day& x, const days& y) noexcept; + constexpr days operator-(const day& x, const day& y) noexcept; - constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const weekday_last& wdl); - - // \ref{time.cal.md}, class \tcode{month_day} - class month_day; - - constexpr bool operator==(const month_day& x, const month_day& y) noexcept; - constexpr strong_ordering operator<=>(const month_day& x, const month_day& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const month_day& md); - - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - month_day& md, basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.mdlast}, class \tcode{month_day_last} - class month_day_last; - - constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept; - constexpr strong_ordering operator<=>(const month_day_last& x, - const month_day_last& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const month_day_last& mdl); - - // \ref{time.cal.mwd}, class \tcode{month_weekday} - class month_weekday; - - constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const month_weekday& mwd); - - // \ref{time.cal.mwdlast}, class \tcode{month_weekday_last} - class month_weekday_last; - - constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const month_weekday_last& mwdl); - - // \ref{time.cal.ym}, class \tcode{year_month} - class year_month; - - constexpr bool operator==(const year_month& x, const year_month& y) noexcept; - constexpr strong_ordering operator<=>(const year_month& x, const year_month& y) noexcept; - - constexpr year_month operator+(const year_month& ym, const months& dm) noexcept; - constexpr year_month operator+(const months& dm, const year_month& ym) noexcept; - constexpr year_month operator-(const year_month& ym, const months& dm) noexcept; - constexpr months operator-(const year_month& x, const year_month& y) noexcept; - constexpr year_month operator+(const year_month& ym, const years& dy) noexcept; - constexpr year_month operator+(const years& dy, const year_month& ym) noexcept; - constexpr year_month operator-(const year_month& ym, const years& dy) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const year_month& ym); - - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - year_month& ym, basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.ymd}, class \tcode{year_month_day} - class year_month_day; - - constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept; - constexpr strong_ordering operator<=>(const year_month_day& x, - const year_month_day& y) noexcept; - - constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept; - constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept; - constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept; - constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept; - constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept; - constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const year_month_day& ymd); - - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - year_month_day& ymd, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.ymdlast}, class \tcode{year_month_day_last} - class year_month_day_last; - - constexpr bool operator==(const year_month_day_last& x, - const year_month_day_last& y) noexcept; - constexpr strong_ordering operator<=>(const year_month_day_last& x, - const year_month_day_last& y) noexcept; - - constexpr year_month_day_last - operator+(const year_month_day_last& ymdl, const months& dm) noexcept; - constexpr year_month_day_last - operator+(const months& dm, const year_month_day_last& ymdl) noexcept; - constexpr year_month_day_last - operator+(const year_month_day_last& ymdl, const years& dy) noexcept; - constexpr year_month_day_last - operator+(const years& dy, const year_month_day_last& ymdl) noexcept; - constexpr year_month_day_last - operator-(const year_month_day_last& ymdl, const months& dm) noexcept; - constexpr year_month_day_last - operator-(const year_month_day_last& ymdl, const years& dy) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const year_month_day_last& ymdl); - - // \ref{time.cal.ymwd}, class \tcode{year_month_weekday} - class year_month_weekday; - - constexpr bool operator==(const year_month_weekday& x, - const year_month_weekday& y) noexcept; - - constexpr year_month_weekday - operator+(const year_month_weekday& ymwd, const months& dm) noexcept; - constexpr year_month_weekday - operator+(const months& dm, const year_month_weekday& ymwd) noexcept; - constexpr year_month_weekday - operator+(const year_month_weekday& ymwd, const years& dy) noexcept; - constexpr year_month_weekday - operator+(const years& dy, const year_month_weekday& ymwd) noexcept; - constexpr year_month_weekday - operator-(const year_month_weekday& ymwd, const months& dm) noexcept; - constexpr year_month_weekday - operator-(const year_month_weekday& ymwd, const years& dy) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const year_month_weekday& ymwdi); - - // \ref{time.cal.ymwdlast}, class \tcode{year_month_weekday_last} - class year_month_weekday_last; - - constexpr bool operator==(const year_month_weekday_last& x, - const year_month_weekday_last& y) noexcept; - - constexpr year_month_weekday_last - operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept; - constexpr year_month_weekday_last - operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept; - constexpr year_month_weekday_last - operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept; - constexpr year_month_weekday_last - operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept; - constexpr year_month_weekday_last - operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept; - constexpr year_month_weekday_last - operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const year_month_weekday_last& ymwdl); - - // \ref{time.cal.operators}, civil calendar conventional syntax operators - constexpr year_month - operator/(const year& y, const month& m) noexcept; - constexpr year_month - operator/(const year& y, int m) noexcept; - constexpr month_day - operator/(const month& m, const day& d) noexcept; - constexpr month_day - operator/(const month& m, int d) noexcept; - constexpr month_day - operator/(int m, const day& d) noexcept; - constexpr month_day - operator/(const day& d, const month& m) noexcept; - constexpr month_day - operator/(const day& d, int m) noexcept; - constexpr month_day_last - operator/(const month& m, last_spec) noexcept; - constexpr month_day_last - operator/(int m, last_spec) noexcept; - constexpr month_day_last - operator/(last_spec, const month& m) noexcept; - constexpr month_day_last - operator/(last_spec, int m) noexcept; - constexpr month_weekday - operator/(const month& m, const weekday_indexed& wdi) noexcept; - constexpr month_weekday - operator/(int m, const weekday_indexed& wdi) noexcept; - constexpr month_weekday - operator/(const weekday_indexed& wdi, const month& m) noexcept; - constexpr month_weekday - operator/(const weekday_indexed& wdi, int m) noexcept; - constexpr month_weekday_last - operator/(const month& m, const weekday_last& wdl) noexcept; - constexpr month_weekday_last - operator/(int m, const weekday_last& wdl) noexcept; - constexpr month_weekday_last - operator/(const weekday_last& wdl, const month& m) noexcept; - constexpr month_weekday_last - operator/(const weekday_last& wdl, int m) noexcept; - constexpr year_month_day - operator/(const year_month& ym, const day& d) noexcept; - constexpr year_month_day - operator/(const year_month& ym, int d) noexcept; - constexpr year_month_day - operator/(const year& y, const month_day& md) noexcept; - constexpr year_month_day - operator/(int y, const month_day& md) noexcept; - constexpr year_month_day - operator/(const month_day& md, const year& y) noexcept; - constexpr year_month_day - operator/(const month_day& md, int y) noexcept; - constexpr year_month_day_last - operator/(const year_month& ym, last_spec) noexcept; - constexpr year_month_day_last - operator/(const year& y, const month_day_last& mdl) noexcept; - constexpr year_month_day_last - operator/(int y, const month_day_last& mdl) noexcept; - constexpr year_month_day_last - operator/(const month_day_last& mdl, const year& y) noexcept; - constexpr year_month_day_last - operator/(const month_day_last& mdl, int y) noexcept; - constexpr year_month_weekday - operator/(const year_month& ym, const weekday_indexed& wdi) noexcept; - constexpr year_month_weekday - operator/(const year& y, const month_weekday& mwd) noexcept; - constexpr year_month_weekday - operator/(int y, const month_weekday& mwd) noexcept; - constexpr year_month_weekday - operator/(const month_weekday& mwd, const year& y) noexcept; - constexpr year_month_weekday - operator/(const month_weekday& mwd, int y) noexcept; - constexpr year_month_weekday_last - operator/(const year_month& ym, const weekday_last& wdl) noexcept; - constexpr year_month_weekday_last - operator/(const year& y, const month_weekday_last& mwdl) noexcept; - constexpr year_month_weekday_last - operator/(int y, const month_weekday_last& mwdl) noexcept; - constexpr year_month_weekday_last - operator/(const month_weekday_last& mwdl, const year& y) noexcept; - constexpr year_month_weekday_last - operator/(const month_weekday_last& mwdl, int y) noexcept; - - // \ref{time.hms}, class template \tcode{hh_mm_ss} - template class hh_mm_ss; - - template - basic_ostream& - operator<<(basic_ostream& os, const hh_mm_ss& hms); - - // \ref{time.12}, 12/24 hour functions - constexpr bool is_am(const hours& h) noexcept; - constexpr bool is_pm(const hours& h) noexcept; - constexpr hours make12(const hours& h) noexcept; - constexpr hours make24(const hours& h, bool is_pm) noexcept; - - // \ref{time.zone.db}, time zone database - struct tzdb; - class tzdb_list; - - // \ref{time.zone.db.access}, time zone database access - const tzdb& get_tzdb(); - tzdb_list& get_tzdb_list(); - const time_zone* locate_zone(string_view tz_name); - const time_zone* current_zone(); - - // \ref{time.zone.db.remote}, remote time zone database support - const tzdb& reload_tzdb(); - string remote_version(); - - // \ref{time.zone.exception}, exception classes - class nonexistent_local_time; - class ambiguous_local_time; - - // \ref{time.zone.info}, information classes - struct sys_info; - template - basic_ostream& - operator<<(basic_ostream& os, const sys_info& si); - - struct local_info; - template - basic_ostream& - operator<<(basic_ostream& os, const local_info& li); - - // \ref{time.zone.timezone}, class \tcode{time_zone} - enum class choose {earliest, latest}; - class time_zone; - - bool operator==(const time_zone& x, const time_zone& y) noexcept; - strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept; - - // \ref{time.zone.zonedtraits}, class template \tcode{zoned_traits} - template struct zoned_traits; - - // \ref{time.zone.zonedtime}, class template \tcode{zoned_time} - template class zoned_time; - - using zoned_seconds = zoned_time; - - template - bool operator==(const zoned_time& x, - const zoned_time& y); - - template - basic_ostream& - operator<<(basic_ostream& os, - const zoned_time& t); - - // \ref{time.zone.leap}, leap second support - class leap_second; - - constexpr bool operator==(const leap_second& x, const leap_second& y); - constexpr strong_ordering operator<=>(const leap_second& x, const leap_second& y); + template + basic_ostream& + operator<<(basic_ostream& os, const day& d); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + day& d, basic_string* abbrev = nullptr, + minutes* offset = nullptr); - template - constexpr bool operator==(const leap_second& x, const sys_time& y); - template - constexpr bool operator< (const leap_second& x, const sys_time& y); - template - constexpr bool operator< (const sys_time& x, const leap_second& y); - template - constexpr bool operator> (const leap_second& x, const sys_time& y); - template - constexpr bool operator> (const sys_time& x, const leap_second& y); - template - constexpr bool operator<=(const leap_second& x, const sys_time& y); - template - constexpr bool operator<=(const sys_time& x, const leap_second& y); - template - constexpr bool operator>=(const leap_second& x, const sys_time& y); - template - constexpr bool operator>=(const sys_time& x, const leap_second& y); - template - requires @\libconcept{three_way_comparable_with}@> - constexpr auto operator<=>(const leap_second& x, const sys_time& y); + // \ref{time.cal.month}, class \tcode{month} + class month; - // \ref{time.zone.link}, class \tcode{time_zone_link} - class time_zone_link; + constexpr bool operator==(const month& x, const month& y) noexcept; + constexpr strong_ordering operator<=>(const month& x, const month& y) noexcept; - bool operator==(const time_zone_link& x, const time_zone_link& y); - strong_ordering operator<=>(const time_zone_link& x, const time_zone_link& y); + constexpr month operator+(const month& x, const months& y) noexcept; + constexpr month operator+(const months& x, const month& y) noexcept; + constexpr month operator-(const month& x, const months& y) noexcept; + constexpr months operator-(const month& x, const month& y) noexcept; - // \ref{time.format}, formatting - template struct @\placeholder{local-time-format-t}@; // \expos - template - @\placeholder{local-time-format-t}@ - local_time_format(local_time time, const string* abbrev = nullptr, - const seconds* offset_sec = nullptr); - } + template + basic_ostream& + operator<<(basic_ostream& os, const month& m); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + month& m, basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.year}, class \tcode{year} + class year; + + constexpr bool operator==(const year& x, const year& y) noexcept; + constexpr strong_ordering operator<=>(const year& x, const year& y) noexcept; + + constexpr year operator+(const year& x, const years& y) noexcept; + constexpr year operator+(const years& x, const year& y) noexcept; + constexpr year operator-(const year& x, const years& y) noexcept; + constexpr years operator-(const year& x, const year& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year& y); + + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + year& y, basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.wd}, class \tcode{weekday} + class weekday; + + constexpr bool operator==(const weekday& x, const weekday& y) noexcept; + + constexpr weekday operator+(const weekday& x, const days& y) noexcept; + constexpr weekday operator+(const days& x, const weekday& y) noexcept; + constexpr weekday operator-(const weekday& x, const days& y) noexcept; + constexpr days operator-(const weekday& x, const weekday& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const weekday& wd); + + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + weekday& wd, basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.wdidx}, class \tcode{weekday_indexed} + class weekday_indexed; + + constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const weekday_indexed& wdi); + + // \ref{time.cal.wdlast}, class \tcode{weekday_last} + class weekday_last; + + constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const weekday_last& wdl); + + // \ref{time.cal.md}, class \tcode{month_day} + class month_day; + + constexpr bool operator==(const month_day& x, const month_day& y) noexcept; + constexpr strong_ordering operator<=>(const month_day& x, const month_day& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const month_day& md); + + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + month_day& md, basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.mdlast}, class \tcode{month_day_last} + class month_day_last; + + constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept; + constexpr strong_ordering operator<=>(const month_day_last& x, + const month_day_last& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const month_day_last& mdl); + + // \ref{time.cal.mwd}, class \tcode{month_weekday} + class month_weekday; + + constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const month_weekday& mwd); + + // \ref{time.cal.mwdlast}, class \tcode{month_weekday_last} + class month_weekday_last; + + constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const month_weekday_last& mwdl); + + // \ref{time.cal.ym}, class \tcode{year_month} + class year_month; + + constexpr bool operator==(const year_month& x, const year_month& y) noexcept; + constexpr strong_ordering operator<=>(const year_month& x, const year_month& y) noexcept; + + constexpr year_month operator+(const year_month& ym, const months& dm) noexcept; + constexpr year_month operator+(const months& dm, const year_month& ym) noexcept; + constexpr year_month operator-(const year_month& ym, const months& dm) noexcept; + constexpr months operator-(const year_month& x, const year_month& y) noexcept; + constexpr year_month operator+(const year_month& ym, const years& dy) noexcept; + constexpr year_month operator+(const years& dy, const year_month& ym) noexcept; + constexpr year_month operator-(const year_month& ym, const years& dy) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year_month& ym); + + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + year_month& ym, basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.ymd}, class \tcode{year_month_day} + class year_month_day; + + constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept; + constexpr strong_ordering operator<=>(const year_month_day& x, + const year_month_day& y) noexcept; + + constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept; + constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept; + constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept; + constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept; + constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept; + constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year_month_day& ymd); + + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + year_month_day& ymd, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.ymdlast}, class \tcode{year_month_day_last} + class year_month_day_last; + + constexpr bool operator==(const year_month_day_last& x, + const year_month_day_last& y) noexcept; + constexpr strong_ordering operator<=>(const year_month_day_last& x, + const year_month_day_last& y) noexcept; + + constexpr year_month_day_last + operator+(const year_month_day_last& ymdl, const months& dm) noexcept; + constexpr year_month_day_last + operator+(const months& dm, const year_month_day_last& ymdl) noexcept; + constexpr year_month_day_last + operator+(const year_month_day_last& ymdl, const years& dy) noexcept; + constexpr year_month_day_last + operator+(const years& dy, const year_month_day_last& ymdl) noexcept; + constexpr year_month_day_last + operator-(const year_month_day_last& ymdl, const months& dm) noexcept; + constexpr year_month_day_last + operator-(const year_month_day_last& ymdl, const years& dy) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year_month_day_last& ymdl); + + // \ref{time.cal.ymwd}, class \tcode{year_month_weekday} + class year_month_weekday; + + constexpr bool operator==(const year_month_weekday& x, + const year_month_weekday& y) noexcept; + + constexpr year_month_weekday + operator+(const year_month_weekday& ymwd, const months& dm) noexcept; + constexpr year_month_weekday + operator+(const months& dm, const year_month_weekday& ymwd) noexcept; + constexpr year_month_weekday + operator+(const year_month_weekday& ymwd, const years& dy) noexcept; + constexpr year_month_weekday + operator+(const years& dy, const year_month_weekday& ymwd) noexcept; + constexpr year_month_weekday + operator-(const year_month_weekday& ymwd, const months& dm) noexcept; + constexpr year_month_weekday + operator-(const year_month_weekday& ymwd, const years& dy) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year_month_weekday& ymwdi); + + // \ref{time.cal.ymwdlast}, class \tcode{year_month_weekday_last} + class year_month_weekday_last; + + constexpr bool operator==(const year_month_weekday_last& x, + const year_month_weekday_last& y) noexcept; + + constexpr year_month_weekday_last + operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept; + constexpr year_month_weekday_last + operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept; + constexpr year_month_weekday_last + operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept; + constexpr year_month_weekday_last + operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept; + constexpr year_month_weekday_last + operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept; + constexpr year_month_weekday_last + operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year_month_weekday_last& ymwdl); + + // \ref{time.cal.operators}, civil calendar conventional syntax operators + constexpr year_month + operator/(const year& y, const month& m) noexcept; + constexpr year_month + operator/(const year& y, int m) noexcept; + constexpr month_day + operator/(const month& m, const day& d) noexcept; + constexpr month_day + operator/(const month& m, int d) noexcept; + constexpr month_day + operator/(int m, const day& d) noexcept; + constexpr month_day + operator/(const day& d, const month& m) noexcept; + constexpr month_day + operator/(const day& d, int m) noexcept; + constexpr month_day_last + operator/(const month& m, last_spec) noexcept; + constexpr month_day_last + operator/(int m, last_spec) noexcept; + constexpr month_day_last + operator/(last_spec, const month& m) noexcept; + constexpr month_day_last + operator/(last_spec, int m) noexcept; + constexpr month_weekday + operator/(const month& m, const weekday_indexed& wdi) noexcept; + constexpr month_weekday + operator/(int m, const weekday_indexed& wdi) noexcept; + constexpr month_weekday + operator/(const weekday_indexed& wdi, const month& m) noexcept; + constexpr month_weekday + operator/(const weekday_indexed& wdi, int m) noexcept; + constexpr month_weekday_last + operator/(const month& m, const weekday_last& wdl) noexcept; + constexpr month_weekday_last + operator/(int m, const weekday_last& wdl) noexcept; + constexpr month_weekday_last + operator/(const weekday_last& wdl, const month& m) noexcept; + constexpr month_weekday_last + operator/(const weekday_last& wdl, int m) noexcept; + constexpr year_month_day + operator/(const year_month& ym, const day& d) noexcept; + constexpr year_month_day + operator/(const year_month& ym, int d) noexcept; + constexpr year_month_day + operator/(const year& y, const month_day& md) noexcept; + constexpr year_month_day + operator/(int y, const month_day& md) noexcept; + constexpr year_month_day + operator/(const month_day& md, const year& y) noexcept; + constexpr year_month_day + operator/(const month_day& md, int y) noexcept; + constexpr year_month_day_last + operator/(const year_month& ym, last_spec) noexcept; + constexpr year_month_day_last + operator/(const year& y, const month_day_last& mdl) noexcept; + constexpr year_month_day_last + operator/(int y, const month_day_last& mdl) noexcept; + constexpr year_month_day_last + operator/(const month_day_last& mdl, const year& y) noexcept; + constexpr year_month_day_last + operator/(const month_day_last& mdl, int y) noexcept; + constexpr year_month_weekday + operator/(const year_month& ym, const weekday_indexed& wdi) noexcept; + constexpr year_month_weekday + operator/(const year& y, const month_weekday& mwd) noexcept; + constexpr year_month_weekday + operator/(int y, const month_weekday& mwd) noexcept; + constexpr year_month_weekday + operator/(const month_weekday& mwd, const year& y) noexcept; + constexpr year_month_weekday + operator/(const month_weekday& mwd, int y) noexcept; + constexpr year_month_weekday_last + operator/(const year_month& ym, const weekday_last& wdl) noexcept; + constexpr year_month_weekday_last + operator/(const year& y, const month_weekday_last& mwdl) noexcept; + constexpr year_month_weekday_last + operator/(int y, const month_weekday_last& mwdl) noexcept; + constexpr year_month_weekday_last + operator/(const month_weekday_last& mwdl, const year& y) noexcept; + constexpr year_month_weekday_last + operator/(const month_weekday_last& mwdl, int y) noexcept; + + // \ref{time.hms}, class template \tcode{hh_mm_ss} + template class hh_mm_ss; + + template + basic_ostream& + operator<<(basic_ostream& os, const hh_mm_ss& hms); + + // \ref{time.12}, 12/24 hour functions + constexpr bool is_am(const hours& h) noexcept; + constexpr bool is_pm(const hours& h) noexcept; + constexpr hours make12(const hours& h) noexcept; + constexpr hours make24(const hours& h, bool is_pm) noexcept; + + // \ref{time.zone.db}, time zone database + struct tzdb; + class tzdb_list; + + // \ref{time.zone.db.access}, time zone database access + const tzdb& get_tzdb(); + tzdb_list& get_tzdb_list(); + const time_zone* locate_zone(string_view tz_name); + const time_zone* current_zone(); + + // \ref{time.zone.db.remote}, remote time zone database support + const tzdb& reload_tzdb(); + string remote_version(); + + // \ref{time.zone.exception}, exception classes + class nonexistent_local_time; + class ambiguous_local_time; + + // \ref{time.zone.info}, information classes + struct sys_info; + template + basic_ostream& + operator<<(basic_ostream& os, const sys_info& si); + + struct local_info; + template + basic_ostream& + operator<<(basic_ostream& os, const local_info& li); + + // \ref{time.zone.timezone}, class \tcode{time_zone} + enum class choose {earliest, latest}; + class time_zone; + + bool operator==(const time_zone& x, const time_zone& y) noexcept; + strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept; + + // \ref{time.zone.zonedtraits}, class template \tcode{zoned_traits} + template struct zoned_traits; + + // \ref{time.zone.zonedtime}, class template \tcode{zoned_time} + template class zoned_time; + + using zoned_seconds = zoned_time; + + template + bool operator==(const zoned_time& x, + const zoned_time& y); + + template + basic_ostream& + operator<<(basic_ostream& os, + const zoned_time& t); + + // \ref{time.zone.leap}, leap second support + class leap_second; + + constexpr bool operator==(const leap_second& x, const leap_second& y); + constexpr strong_ordering operator<=>(const leap_second& x, const leap_second& y); + + template + constexpr bool operator==(const leap_second& x, const sys_time& y); + template + constexpr bool operator< (const leap_second& x, const sys_time& y); + template + constexpr bool operator< (const sys_time& x, const leap_second& y); + template + constexpr bool operator> (const leap_second& x, const sys_time& y); + template + constexpr bool operator> (const sys_time& x, const leap_second& y); + template + constexpr bool operator<=(const leap_second& x, const sys_time& y); + template + constexpr bool operator<=(const sys_time& x, const leap_second& y); + template + constexpr bool operator>=(const leap_second& x, const sys_time& y); + template + constexpr bool operator>=(const sys_time& x, const leap_second& y); + template + requires @\libconcept{three_way_comparable_with}@> + constexpr auto operator<=>(const leap_second& x, const sys_time& y); + + // \ref{time.zone.link}, class \tcode{time_zone_link} + class time_zone_link; + bool operator==(const time_zone_link& x, const time_zone_link& y); + strong_ordering operator<=>(const time_zone_link& x, const time_zone_link& y); + + // \ref{time.format}, formatting + template struct @\placeholder{local-time-format-t}@; // \expos + template + @\placeholder{local-time-format-t}@ + local_time_format(local_time time, const string* abbrev = nullptr, + const seconds* offset_sec = nullptr); +} + +namespace std { template struct formatter, charT>; template @@ -848,99 +850,97 @@ template struct formatter; template struct formatter, charT>; +} - namespace chrono { - // \ref{time.parse}, parsing - template - @\unspec@ - parse(const charT* fmt, Parsable& tp); - template - @\unspec@ - parse(const basic_string& fmt, Parsable& tp); - - template - @\unspec@ - parse(const charT* fmt, Parsable& tp, - basic_string& abbrev); - template - @\unspec@ - parse(const basic_string& fmt, Parsable& tp, - basic_string& abbrev); - - template - @\unspec@ - parse(const charT* fmt, Parsable& tp, minutes& offset); - template - @\unspec@ - parse(const basic_string& fmt, Parsable& tp, - minutes& offset); - - template - @\unspec@ - parse(const charT* fmt, Parsable& tp, - basic_string& abbrev, minutes& offset); - template - @\unspec@ - parse(const basic_string& fmt, Parsable& tp, - basic_string& abbrev, minutes& offset); - - // calendrical constants - inline constexpr last_spec last{}; - - inline constexpr weekday Sunday{0}; - inline constexpr weekday Monday{1}; - inline constexpr weekday Tuesday{2}; - inline constexpr weekday Wednesday{3}; - inline constexpr weekday Thursday{4}; - inline constexpr weekday Friday{5}; - inline constexpr weekday Saturday{6}; - - inline constexpr month January{1}; - inline constexpr month February{2}; - inline constexpr month March{3}; - inline constexpr month April{4}; - inline constexpr month May{5}; - inline constexpr month June{6}; - inline constexpr month July{7}; - inline constexpr month August{8}; - inline constexpr month September{9}; - inline constexpr month October{10}; - inline constexpr month November{11}; - inline constexpr month December{12}; - } +namespace std::chrono { + // \ref{time.parse}, parsing + template + @\unspec@ + parse(const charT* fmt, Parsable& tp); + template + @\unspec@ + parse(const basic_string& fmt, Parsable& tp); + + template + @\unspec@ + parse(const charT* fmt, Parsable& tp, + basic_string& abbrev); + template + @\unspec@ + parse(const basic_string& fmt, Parsable& tp, + basic_string& abbrev); + + template + @\unspec@ + parse(const charT* fmt, Parsable& tp, minutes& offset); + template + @\unspec@ + parse(const basic_string& fmt, Parsable& tp, + minutes& offset); + + template + @\unspec@ + parse(const charT* fmt, Parsable& tp, + basic_string& abbrev, minutes& offset); + template + @\unspec@ + parse(const basic_string& fmt, Parsable& tp, + basic_string& abbrev, minutes& offset); + + // calendrical constants + inline constexpr last_spec last{}; + + inline constexpr weekday Sunday{0}; + inline constexpr weekday Monday{1}; + inline constexpr weekday Tuesday{2}; + inline constexpr weekday Wednesday{3}; + inline constexpr weekday Thursday{4}; + inline constexpr weekday Friday{5}; + inline constexpr weekday Saturday{6}; + + inline constexpr month January{1}; + inline constexpr month February{2}; + inline constexpr month March{3}; + inline constexpr month April{4}; + inline constexpr month May{5}; + inline constexpr month June{6}; + inline constexpr month July{7}; + inline constexpr month August{8}; + inline constexpr month September{9}; + inline constexpr month October{10}; + inline constexpr month November{11}; + inline constexpr month December{12}; +} - inline namespace literals { - inline namespace chrono_literals { - // \ref{time.duration.literals}, suffixes for duration literals - constexpr chrono::hours operator""h(unsigned long long); - constexpr chrono::duration<@\unspec,@ ratio<3600, 1>> operator""h(long double); +namespace std::inline literals::inline chrono_literals { + // \ref{time.duration.literals}, suffixes for duration literals + constexpr chrono::hours operator""h(unsigned long long); + constexpr chrono::duration<@\unspec,@ ratio<3600, 1>> operator""h(long double); - constexpr chrono::minutes operator""min(unsigned long long); - constexpr chrono::duration<@\unspec,@ ratio<60, 1>> operator""min(long double); + constexpr chrono::minutes operator""min(unsigned long long); + constexpr chrono::duration<@\unspec,@ ratio<60, 1>> operator""min(long double); - constexpr chrono::seconds operator""s(unsigned long long); - constexpr chrono::duration<@\unspec@>@\itcorr[-1]@ operator""s(long double); + constexpr chrono::seconds operator""s(unsigned long long); + constexpr chrono::duration<@\unspec@>@\itcorr[-1]@ operator""s(long double); - constexpr chrono::milliseconds operator""ms(unsigned long long); - constexpr chrono::duration<@\unspec,@ milli> operator""ms(long double); + constexpr chrono::milliseconds operator""ms(unsigned long long); + constexpr chrono::duration<@\unspec,@ milli> operator""ms(long double); - constexpr chrono::microseconds operator""us(unsigned long long); - constexpr chrono::duration<@\unspec,@ micro> operator""us(long double); + constexpr chrono::microseconds operator""us(unsigned long long); + constexpr chrono::duration<@\unspec,@ micro> operator""us(long double); - constexpr chrono::nanoseconds operator""ns(unsigned long long); - constexpr chrono::duration<@\unspec,@ nano> operator""ns(long double); + constexpr chrono::nanoseconds operator""ns(unsigned long long); + constexpr chrono::duration<@\unspec,@ nano> operator""ns(long double); - // \ref{time.cal.day.nonmembers}, non-member functions - constexpr chrono::day operator""d(unsigned long long d) noexcept; + // \ref{time.cal.day.nonmembers}, non-member functions + constexpr chrono::day operator""d(unsigned long long d) noexcept; - // \ref{time.cal.year.nonmembers}, non-member functions - constexpr chrono::year operator""y(unsigned long long y) noexcept; - } - } + // \ref{time.cal.year.nonmembers}, non-member functions + constexpr chrono::year operator""y(unsigned long long y) noexcept; +} - namespace chrono { - using namespace literals::chrono_literals; - } +namespace std::chrono { + using namespace literals::chrono_literals; } \end{codeblock} diff --git a/source/uax31.tex b/source/uax31.tex index 392e74ec96..64f4b873b7 100644 --- a/source/uax31.tex +++ b/source/uax31.tex @@ -29,14 +29,14 @@ where \tcode{} has the XID_Start property, \tcode{} has the XID_Continue property, and \tcode{} is a list of characters permitted between continue characters. -For \Cpp{} we add the character U+005F, LOW LINE, or \tcode{_}, +For \Cpp{} we add the character \unicode{005f}{low line}, or \tcode{_}, to the set of permitted \tcode{} characters, the \tcode{} set is empty, and the \tcode{} characters are unmodified. In the grammar used in UAX \#31, this is \begin{codeblock} := * - := XID_Start + U+005F + := XID_Start + @\textrm{\ucode{005f}}@ := + XID_Continue \end{codeblock} diff --git a/source/utilities.tex b/source/utilities.tex index 1b3144ba34..b85cbf93e1 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -10,24 +10,19 @@ \begin{libsumtab}{General utilities library summary}{utilities.summary} \ref{utility} & Utility components & \tcode{} \\ -\ref{intseq} & Compile-time integer sequences & \\ \ref{pairs} & Pairs & \\ \rowsep \ref{tuple} & Tuples & \tcode{} \\ \rowsep \ref{optional} & Optional objects & \tcode{} \\ \rowsep \ref{variant} & Variants & \tcode{} \\ \rowsep \ref{any} & Storage for any type & \tcode{} \\ \rowsep +\ref{expected} & Expected objects & \tcode{} \\ \rowsep \ref{bitset} & Fixed-size sequences of bits & \tcode{} \\ \rowsep -\ref{memory} & Memory & \tcode{}, \tcode{} \\ \rowsep -\ref{smartptr} & Smart pointers & \tcode{} \\ \rowsep -\ref{mem.res} & Memory resources & \tcode{} \\ \rowsep -\ref{allocator.adaptor} & Scoped allocators & \tcode{} \\ \rowsep \ref{function.objects} & Function objects & \tcode{} \\ \rowsep -\ref{meta} & Type traits & \tcode{} \\ \rowsep -\ref{ratio} & Compile-time rational arithmetic & \tcode{} \\ \rowsep \ref{type.index} & Type indexes & \tcode{} \\ \rowsep \ref{execpol} & Execution policies & \tcode{} \\ \rowsep \ref{charconv} & Primitive numeric conversions & \tcode{} \\ \rowsep -\ref{format} & Formatting & \tcode{} \\ +\ref{format} & Formatting & \tcode{} \\ \rowsep +\ref{bit} & Bit manipulation & \tcode{} \\ \end{libsumtab} \rSec1[utility]{Utility components} @@ -98,6 +93,9 @@ template constexpr underlying_type_t to_underlying(T value) noexcept; + // \ref{utility.unreachable}, unreachable + [[noreturn]] void unreachable(); + // \ref{intseq}, compile-time integer sequences% \indexlibraryglobal{index_sequence}% \indexlibraryglobal{make_index_sequence}% @@ -610,60 +608,38 @@ \tcode{static_cast>(value)}. \end{itemdescr} +\rSec2[utility.unreachable]{Function \tcode{unreachable}} -\rSec1[intseq]{Compile-time integer sequences} - -\rSec2[intseq.general]{In general} +\indexlibraryglobal{unreachable}% +\begin{itemdecl} +[[noreturn]] void unreachable(); +\end{itemdecl} +\begin{itemdescr} \pnum -The library provides a class template that can represent an integer sequence. -When used as an argument to a function template the template parameter pack defining the -sequence can be deduced and used in a pack expansion. +\expects +\tcode{false} is \tcode{true}. \begin{note} -The \tcode{index_sequence} alias template is provided for the common case of -an integer sequence of type \tcode{size_t}; see also \ref{tuple.apply}. +This precondition cannot be satisfied, thus the behavior +of calling \tcode{unreachable} is undefined. \end{note} -\rSec2[intseq.intseq]{Class template \tcode{integer_sequence}} - -\indexlibraryglobal{integer_sequence}% -\indexlibrarymember{value_type}{integer_sequence}% +\pnum +\begin{example} \begin{codeblock} -namespace std { - template struct integer_sequence { - using value_type = T; - static constexpr size_t size() noexcept { return sizeof...(I); } - }; +int f(int x) { + switch (x) { + case 0: + case 1: + return x; + default: + std::unreachable(); + } } +int a = f(1); // OK, \tcode{a} has value \tcode{1} +int b = f(3); // undefined behavior \end{codeblock} - -\pnum -\mandates -\tcode{T} is an integer type. - -\rSec2[intseq.make]{Alias template \tcode{make_integer_sequence}} - -\indexlibraryglobal{make_integer_sequence}% -\begin{itemdecl} -template - using make_integer_sequence = integer_sequence; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -$\tcode{N} \geq 0$. - -\pnum -The alias template -\tcode{make_integer_sequence} denotes a specialization of -\tcode{integer_sequence} with \tcode{N} non-type template arguments. -The type \tcode{make_integer_sequence} is an alias for the type -\tcode{integer_sequence}. -\begin{note} -\tcode{make_integer_sequence} is an alias for the type -\tcode{integer_sequence}. -\end{note} +\end{example} \end{itemdescr} \rSec1[pairs]{Pairs} @@ -765,8 +741,8 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_default_constructible_v} is \tcode{true} and -\item \tcode{is_default_constructible_v} is \tcode{true}. +\item \tcode{is_default_constructible_v} is \tcode{true} and +\item \tcode{is_default_constructible_v} is \tcode{true}. \end{itemize} \pnum @@ -776,11 +752,11 @@ \pnum \remarks The expression inside \keyword{explicit} evaluates to \tcode{true} -if and only if either \tcode{first_type} or -\tcode{second_type} is not implicitly default-constructible. +if and only if either \tcode{T1} or +\tcode{T2} is not implicitly default-constructible. \begin{note} This behavior can be implemented with a trait that checks -whether a \tcode{const first_type\&} or a \tcode{const second_type\&} +whether a \tcode{const T1\&} or a \tcode{const T2\&} can be initialized with \tcode{\{\}}. \end{note} \end{itemdescr} @@ -794,8 +770,8 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_copy_constructible_v} is \tcode{true} and -\item \tcode{is_copy_constructible_v} is \tcode{true}. +\item \tcode{is_copy_constructible_v} is \tcode{true} and +\item \tcode{is_copy_constructible_v} is \tcode{true}. \end{itemize} \pnum @@ -806,8 +782,7 @@ \remarks The expression inside \keyword{explicit} is equivalent to: \begin{codeblock} -!is_convertible_v || - !is_convertible_v +!is_convertible_v || !is_convertible_v \end{codeblock} \end{itemdescr} @@ -820,8 +795,8 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_constructible_v} is \tcode{true} and -\item \tcode{is_constructible_v} is \tcode{true}. +\item \tcode{is_constructible_v} is \tcode{true} and +\item \tcode{is_constructible_v} is \tcode{true}. \end{itemize} \pnum @@ -834,8 +809,13 @@ \remarks The expression inside \keyword{explicit} is equivalent to: \begin{codeblock} -!is_convertible_v || !is_convertible_v +!is_convertible_v || !is_convertible_v \end{codeblock} +This constructor is defined as deleted if +\tcode{reference_constructs_from_temporary_v} +is \tcode{true} or +\tcode{reference_constructs_from_temporary_v} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{pair}% @@ -854,10 +834,10 @@ \constraints \begin{itemize} \item -\tcode{is_constructible_v(\exposid{FWD}(p)))>} +\tcode{is_constructible_v(\exposid{FWD}(p)))>} is \tcode{true} and \item -\tcode{is_constructible_v(\exposid{FWD}(p)))>} +\tcode{is_constructible_v(\exposid{FWD}(p)))>} is \tcode{true}. \end{itemize} @@ -870,9 +850,15 @@ \remarks The expression inside \keyword{explicit} is equivalent to: \begin{codeblock} -!is_convertible_v(@\exposid{FWD}@(p))), first_type> || -!is_convertible_v(@\exposid{FWD}@(p))), second_type> +!is_convertible_v(@\exposid{FWD}@(p))), T1> || +!is_convertible_v(@\exposid{FWD}@(p))), T2> +\end{codeblock} +The constructor is defined as deleted if +\begin{codeblock} +reference_constructs_from_temporary_v(@\exposid{FWD}@(p)))> || +reference_constructs_from_temporary_v(@\exposid{FWD}@(p)))> \end{codeblock} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{pair}% @@ -886,8 +872,8 @@ \pnum \mandates \begin{itemize} -\item \tcode{is_constructible_v} is \tcode{true} and -\item \tcode{is_constructible_v} is \tcode{true}. +\item \tcode{is_constructible_v} is \tcode{true} and +\item \tcode{is_constructible_v} is \tcode{true}. \end{itemize} \pnum @@ -900,6 +886,11 @@ \tcode{std::forward(x)}.) This form of construction, whereby constructor arguments for \tcode{first} and \tcode{second} are each provided in a separate \tcode{tuple} object, is called \defn{piecewise construction}. +\begin{note} +If a data member of \tcode{pair} is of reference type and +its initialization binds it to a temporary object, +the program is ill-formed\iref{class.base.init}. +\end{note} \end{itemdescr} \indexlibrarymember{operator=}{pair}% @@ -919,8 +910,8 @@ \pnum \remarks This operator is defined as deleted unless -\tcode{is_copy_assignable_v} is \tcode{true} and -\tcode{is_copy_assignable_v} is \tcode{true}. +\tcode{is_copy_assignable_v} is \tcode{true} and +\tcode{is_copy_assignable_v} is \tcode{true}. \end{itemdescr} \indexlibrarymember{operator=}{pair}% @@ -933,9 +924,9 @@ \constraints \begin{itemize} \item -\tcode{is_copy_assignable} is \tcode{true} and +\tcode{is_copy_assignable_v} is \tcode{true} and \item -\tcode{is_copy_assignable} is \tcode{true}. +\tcode{is_copy_assignable_v} is \tcode{true}. \end{itemize} \pnum @@ -956,8 +947,8 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_assignable_v} is \tcode{true} and -\item \tcode{is_assignable_v} is \tcode{true}. +\item \tcode{is_assignable_v} is \tcode{true} and +\item \tcode{is_assignable_v} is \tcode{true}. \end{itemize} \pnum @@ -979,9 +970,9 @@ \constraints \begin{itemize} \item -\tcode{is_assignable_v} is \tcode{true}, and +\tcode{is_assignable_v} is \tcode{true}, and \item -\tcode{is_assignable_v} is \tcode{true}. +\tcode{is_assignable_v} is \tcode{true}. \end{itemize} \pnum @@ -1002,14 +993,14 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_move_assignable_v} is \tcode{true} and -\item \tcode{is_move_assignable_v} is \tcode{true}. +\item \tcode{is_move_assignable_v} is \tcode{true} and +\item \tcode{is_move_assignable_v} is \tcode{true}. \end{itemize} \pnum \effects -Assigns to \tcode{first} with \tcode{std::forward(p.first)} -and to \tcode{second} with\\ \tcode{std::forward(p.second)}. +Assigns to \tcode{first} with \tcode{std::forward(p.first)} +and to \tcode{second} with \tcode{std::forward(\brk{}p.second)}. \pnum \returns @@ -1033,15 +1024,15 @@ \constraints \begin{itemize} \item -\tcode{is_assignable} is \tcode{true} and +\tcode{is_assignable_v} is \tcode{true} and \item -\tcode{is_assignable} is \tcode{true}. +\tcode{is_assignable_v} is \tcode{true}. \end{itemize} \pnum \effects -Assigns \tcode{std::forward(p.first)} to \tcode{first} and -\tcode{std::forward(\brk{}p.second)} to \tcode{second}. +Assigns \tcode{std::forward(p.first)} to \tcode{first} and +\tcode{std::forward(p.second)} to \tcode{second}. \pnum \returns @@ -1057,8 +1048,8 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_assignable_v} is \tcode{true} and -\item \tcode{is_assignable_v} is \tcode{true}. +\item \tcode{is_assignable_v} is \tcode{true} and +\item \tcode{is_assignable_v} is \tcode{true}. \end{itemize} \pnum @@ -1081,11 +1072,12 @@ \constraints \begin{itemize} \item -\tcode{is_assignable_v} is \tcode{true}, and +\tcode{is_assignable_v} is \tcode{true}, and \item -\tcode{is_assignable_v} is \tcode{true}. +\tcode{is_assignable_v} is \tcode{true}. \end{itemize} +\pnum \effects Assigns \tcode{std::forward(p.first)} to \tcode{first} and \tcode{std::forward(u.second)} to \tcode{second}. @@ -1131,10 +1123,10 @@ The exception specification is equivalent to: \begin{itemize} \item -\tcode{is_nothrow_swappable_v \&\& is_nothrow_swappable_v} -for the\newline first overload, and +\tcode{is_nothrow_swappable_v \&\& is_nothrow_swappable_v} +for the first overload, and \item -\tcode{is_nothrow_swappable_v \&\& is_nothrow_swappable_v} +\tcode{is_nothrow_swappable_v \&\& is_nothrow_swappable_v} for the second overload. \end{itemize} \end{itemdescr} @@ -1695,6 +1687,11 @@ \begin{codeblock} !conjunction_v...> \end{codeblock} +This constructor is defined as deleted if +\begin{codeblock} +(reference_constructs_from_temporary_v || ...) +\end{codeblock} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{tuple}% @@ -1770,6 +1767,11 @@ \begin{codeblock} !(is_convertible_v(@\exposid{FWD}@(u))), Types> && ...) \end{codeblock} +The constructor is defined as deleted if +\begin{codeblock} +(reference_constructs_from_temporary_v(@\exposid{FWD}@(u)))> || ...) +\end{codeblock} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{tuple}% @@ -1807,6 +1809,12 @@ !is_convertible_v(@\exposid{FWD}@(u))), @$\tcode{T}_0$@> || !is_convertible_v(@\exposid{FWD}@(u))), @$\tcode{T}_1$@> \end{codeblock} +The constructor is defined as deleted if +\begin{codeblock} +reference_constructs_from_temporary_v<@$\tcode{T}_0$@, decltype(get<0>(@\exposid{FWD}@(u)))> || +reference_constructs_from_temporary_v<@$\tcode{T}_1$@, decltype(get<1>(@\exposid{FWD}@(u)))> +\end{codeblock} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{tuple}% @@ -1853,8 +1861,8 @@ \begin{itemdescr} \pnum \expects -\tcode{Alloc} meets the -\oldconcept{Allocator} requirements (\tref{cpp17.allocator}). +\tcode{Alloc} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \pnum \effects @@ -2368,6 +2376,13 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +If \tcode{tuple_size_v>} is 1, +then +\tcode{reference_constructs_from_temporary_v(declval()))>} +is \tcode{false}. + \pnum \effects Given the exposition-only function: @@ -2660,8 +2675,8 @@ \begin{itemdescr} \pnum \expects -\tcode{Alloc} meets the \oldconcept{Allocator} -requirements (\tref{cpp17.allocator}). +\tcode{Alloc} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \pnum \begin{note} @@ -2847,30 +2862,30 @@ // \ref{optional.observe}, observers constexpr const T* operator->() const noexcept; constexpr T* operator->() noexcept; - constexpr const T& operator*() const& noexcept; + constexpr const T& operator*() const & noexcept; constexpr T& operator*() & noexcept; constexpr T&& operator*() && noexcept; - constexpr const T&& operator*() const&& noexcept; + constexpr const T&& operator*() const && noexcept; constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; - constexpr const T& value() const&; + constexpr const T& value() const &; constexpr T& value() &; constexpr T&& value() &&; - constexpr const T&& value() const&&; - template constexpr T value_or(U&&) const&; + constexpr const T&& value() const &&; + template constexpr T value_or(U&&) const &; template constexpr T value_or(U&&) &&; // \ref{optional.monadic}, monadic operations template constexpr auto and_then(F&& f) &; template constexpr auto and_then(F&& f) &&; - template constexpr auto and_then(F&& f) const&; - template constexpr auto and_then(F&& f) const&&; + template constexpr auto and_then(F&& f) const &; + template constexpr auto and_then(F&& f) const &&; template constexpr auto transform(F&& f) &; template constexpr auto transform(F&& f) &&; - template constexpr auto transform(F&& f) const&; - template constexpr auto transform(F&& f) const&&; + template constexpr auto transform(F&& f) const &; + template constexpr auto transform(F&& f) const &&; template constexpr optional or_else(F&& f) &&; - template constexpr optional or_else(F&& f) const&; + template constexpr optional or_else(F&& f) const &; // \ref{optional.mod}, modifiers constexpr void reset() noexcept; @@ -3597,7 +3612,7 @@ \indexlibrarymember{operator*}{optional}% \begin{itemdecl} -constexpr const T& operator*() const& noexcept; +constexpr const T& operator*() const & noexcept; constexpr T& operator*() & noexcept; \end{itemdecl} @@ -3618,7 +3633,7 @@ \indexlibrarymember{operator*}{optional}% \begin{itemdecl} constexpr T&& operator*() && noexcept; -constexpr const T&& operator*() const&& noexcept; +constexpr const T&& operator*() const && noexcept; \end{itemdecl} \begin{itemdescr} @@ -3663,7 +3678,7 @@ \indexlibrarymember{value}{optional}% \begin{itemdecl} -constexpr const T& value() const&; +constexpr const T& value() const &; constexpr T& value() &; \end{itemdecl} @@ -3679,7 +3694,7 @@ \indexlibrarymember{value}{optional}% \begin{itemdecl} constexpr T&& value() &&; -constexpr const T&& value() const&&; +constexpr const T&& value() const &&; \end{itemdecl} \begin{itemdescr} @@ -3694,7 +3709,7 @@ \indexlibrarymember{value_or}{optional}% \begin{itemdecl} -template constexpr T value_or(U&& v) const&; +template constexpr T value_or(U&& v) const &; \end{itemdecl} \begin{itemdescr} @@ -3733,7 +3748,7 @@ \indexlibrarymember{and_then}{optional} \begin{itemdecl} template constexpr auto and_then(F&& f) &; -template constexpr auto and_then(F&& f) const&; +template constexpr auto and_then(F&& f) const &; \end{itemdecl} \begin{itemdescr} @@ -3759,7 +3774,7 @@ \indexlibrarymember{and_then}{optional} \begin{itemdecl} template constexpr auto and_then(F&& f) &&; -template constexpr auto and_then(F&& f) const&&; +template constexpr auto and_then(F&& f) const &&; \end{itemdecl} \begin{itemdescr} @@ -3785,7 +3800,7 @@ \indexlibrarymember{transform}{optional} \begin{itemdecl} template constexpr auto transform(F&& f) &; -template constexpr auto transform(F&& f) const&; +template constexpr auto transform(F&& f) const &; \end{itemdecl} \begin{itemdescr} @@ -3816,7 +3831,7 @@ \indexlibrarymember{transform}{optional} \begin{itemdecl} template constexpr auto transform(F&& f) &&; -template constexpr auto transform(F&& f) const&&; +template constexpr auto transform(F&& f) const &&; \end{itemdecl} \begin{itemdescr} @@ -3847,7 +3862,7 @@ \indexlibrarymember{or_else}{optional} \begin{itemdecl} -template constexpr optional or_else(F&& f) const&; +template constexpr optional or_else(F&& f) const &; \end{itemdecl} \begin{itemdescr} @@ -3937,11 +3952,13 @@ \rSec2[optional.bad.access]{Class \tcode{bad_optional_access}} \begin{codeblock} -class bad_optional_access : public exception { -public: - // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; -}; +namespace std { + class bad_optional_access : public exception { + public: + // see \ref{exception} for the specification of the special member functions + const char* what() const noexcept override; + }; +} \end{codeblock} \pnum @@ -5783,11 +5800,13 @@ \indexlibraryglobal{bad_variant_access}% \begin{codeblock} -class bad_variant_access : public exception { -public: - // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; -}; +namespace std { + class bad_variant_access : public exception { + public: + // see \ref{exception} for the specification of the special member functions + const char* what() const noexcept override; + }; +} \end{codeblock} \pnum @@ -5882,11 +5901,13 @@ \indexlibraryglobal{bad_any_cast}% \begin{codeblock} -class bad_any_cast : public bad_cast { -public: - // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; -}; +namespace std { + class bad_any_cast : public bad_cast { + public: + // see \ref{exception} for the specification of the special member functions + const char* what() const noexcept override; + }; +} \end{codeblock} \pnum @@ -6458,13352 +6479,6175 @@ \end{example} \end{itemdescr} -\rSec1[bitset]{Bitsets} -\indexlibraryglobal{bitset}% +\rSec1[expected]{Expected objects} +\indexlibraryglobal{expected}% -\rSec2[bitset.syn]{Header \tcode{} synopsis}% +\rSec2[expected.general]{In general} \pnum -The header \libheaderdef{bitset} defines a class template -and several related functions for representing -and manipulating fixed-size sequences of bits. +Subclause \ref{expected} describes the class template \tcode{expected} +that represents expected objects. +An \tcode{expected} object holds +an object of type \tcode{T} or an object of type \tcode{unexpected} and +manages the lifetime of the contained objects. -\begin{codeblock} -#include -#include // for \tcode{istream}\iref{istream.syn}, \tcode{ostream}\iref{ostream.syn}, see \ref{iosfwd.syn} +\rSec2[expected.syn]{Header \tcode{} synopsis} +\indexheader{expected}% +\indexlibraryglobal{unexpect_t}% +\indexlibraryglobal{unexpect}% +\begin{codeblock} namespace std { - template class bitset; + // \ref{expected.un.object}, class template \tcode{unexpected} + template class unexpected; - // \ref{bitset.operators}, bitset operators - template - bitset operator&(const bitset&, const bitset&) noexcept; - template - bitset operator|(const bitset&, const bitset&) noexcept; - template - bitset operator^(const bitset&, const bitset&) noexcept; - template - basic_istream& - operator>>(basic_istream& is, bitset& x); - template - basic_ostream& - operator<<(basic_ostream& os, const bitset& x); + // \ref{expected.bad}, class template \tcode{bad_expected_access} + template class bad_expected_access; + + // \ref{expected.bad.void}, specialization for \tcode{void} + template<> class bad_expected_access; + + // in-place construction of unexpected values + struct unexpect_t { + explicit unexpect_t() = default; + }; + inline constexpr unexpect_t unexpect{}; + + // \ref{expected.expected}, class template \tcode{expected} + template class expected; + + // \ref{expected.void}, partial specialization of \tcode{expected} for \tcode{void} types + template requires is_void_v class expected; } \end{codeblock} -\rSec2[template.bitset]{Class template \tcode{bitset}}% +\rSec2[expected.unexpected]{Unexpected objects} -\rSec3[template.bitset.general]{General}% -\indexlibraryglobal{bitset}% +\rSec3[expected.un.general]{General} + +\pnum +Subclause \ref{expected.unexpected} describes the class template \tcode{unexpected} +that represents unexpected objects stored in \tcode{expected} objects. + +\rSec3[expected.un.object]{Class template \tcode{unexpected}} + +\rSec4[expected.un.object.general]{General} + +\indexlibraryglobal{unexpected}% \begin{codeblock} namespace std { - template class bitset { + template + class unexpected { public: - // bit reference - class reference { - friend class bitset; - reference() noexcept; + constexpr unexpected(const unexpected&) = default; + constexpr unexpected(unexpected&&) = default; + template + constexpr explicit unexpected(in_place_t, Args&&...); + template + constexpr explicit unexpected(in_place_t, initializer_list, Args&&...); + template + constexpr explicit unexpected(Err&&); - public: - reference(const reference&) = default; - ~reference(); - reference& operator=(bool x) noexcept; // for \tcode{b[i] = x;} - reference& operator=(const reference&) noexcept; // for \tcode{b[i] = b[j];} - bool operator~() const noexcept; // flips the bit - operator bool() const noexcept; // for \tcode{x = b[i];} - reference& flip() noexcept; // for \tcode{b[i].flip();} - }; + constexpr unexpected& operator=(const unexpected&) = default; + constexpr unexpected& operator=(unexpected&&) = default; - // \ref{bitset.cons}, constructors - constexpr bitset() noexcept; - constexpr bitset(unsigned long long val) noexcept; - template - explicit bitset( - const basic_string& str, - typename basic_string::size_type pos = 0, - typename basic_string::size_type n - = basic_string::npos, - charT zero = charT('0'), - charT one = charT('1')); - template - explicit bitset( - const charT* str, - typename basic_string::size_type n = basic_string::npos, - charT zero = charT('0'), - charT one = charT('1')); + constexpr const E& value() const & noexcept; + constexpr E& value() & noexcept; + constexpr const E&& value() const && noexcept; + constexpr E&& value() && noexcept; - // \ref{bitset.members}, bitset operations - bitset& operator&=(const bitset& rhs) noexcept; - bitset& operator|=(const bitset& rhs) noexcept; - bitset& operator^=(const bitset& rhs) noexcept; - bitset& operator<<=(size_t pos) noexcept; - bitset& operator>>=(size_t pos) noexcept; - bitset& set() noexcept; - bitset& set(size_t pos, bool val = true); - bitset& reset() noexcept; - bitset& reset(size_t pos); - bitset operator~() const noexcept; - bitset& flip() noexcept; - bitset& flip(size_t pos); + constexpr void swap(unexpected& other) noexcept(@\seebelow@); - // element access - constexpr bool operator[](size_t pos) const; // for \tcode{b[i];} - reference operator[](size_t pos); // for \tcode{b[i];} + template + friend constexpr bool operator==(const unexpected&, const unexpected&); - unsigned long to_ulong() const; - unsigned long long to_ullong() const; - template, - class Allocator = allocator> - basic_string - to_string(charT zero = charT('0'), charT one = charT('1')) const; + friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y))); - size_t count() const noexcept; - constexpr size_t size() const noexcept; - bool operator==(const bitset& rhs) const noexcept; - bool test(size_t pos) const; - bool all() const noexcept; - bool any() const noexcept; - bool none() const noexcept; - bitset operator<<(size_t pos) const noexcept; - bitset operator>>(size_t pos) const noexcept; + private: + E @\exposid{val}@; // \expos }; - // \ref{bitset.hash}, hash support - template struct hash; - template struct hash>; + template unexpected(E) -> unexpected; } \end{codeblock} \pnum -The class template -\tcode{bitset} -describes an object that can store a sequence consisting of a fixed number of -bits, \tcode{N}. +A program that instantiates the definition of \tcode{unexpected} for +a non-object type, +an array type, +a specialization of \tcode{unexpected}, or +a cv-qualified type +is ill-formed. -\pnum -Each bit represents either the value zero (reset) or one (set). -To -\term{toggle} -a bit is to change the value zero to one, or the value one to -zero. -Each bit has a non-negative position \tcode{pos}. -When converting -between an object of class -\tcode{bitset} -and a value of some -integral type, bit position \tcode{pos} corresponds to the -\term{bit value} -\tcode{1 << pos}. -The integral value corresponding to two -or more bits is the sum of their bit values. +\rSec4[expected.un.ctor]{Constructors} + +\indexlibraryctor{unexpected}% +\begin{itemdecl} +template + constexpr explicit unexpected(Err&& e); +\end{itemdecl} +\begin{itemdescr} \pnum -The functions described in \ref{template.bitset} can report three kinds of -errors, each associated with a distinct exception: +\constraints \begin{itemize} \item -an -\term{invalid-argument} -error is associated with exceptions of type -\tcode{invalid_argument}\iref{invalid.argument}; -\indexlibraryglobal{invalid_argument}% +\tcode{is_same_v, unexpected>} is \tcode{false}; and \item -an -\term{out-of-range} -error is associated with exceptions of type -\tcode{out_of_range}\iref{out.of.range}; -\indexlibraryglobal{out_of_range}% +\tcode{is_same_v, in_place_t>} is \tcode{false}; and \item -an -\term{overflow} -error is associated with exceptions of type -\tcode{overflow_error}\iref{overflow.error}. -\indexlibraryglobal{overflow_error}% +\tcode{is_constructible_v} is \tcode{true}. \end{itemize} -\rSec3[bitset.cons]{Constructors} +\pnum +\effects +Direct-non-list-initializes \exposid{val} with \tcode{std::forward(e)}. -\indexlibraryctor{bitset}% +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. +\end{itemdescr} + +\indexlibraryctor{unexpected}% \begin{itemdecl} -constexpr bitset() noexcept; +template + constexpr explicit unexpected(in_place_t, Args&&... args); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + \pnum \effects -Initializes all bits in \tcode{*this} to zero. +Direct-non-list-initializes +\exposid{val} with \tcode{std::forward(args)...}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. \end{itemdescr} -\indexlibraryctor{bitset}% +\indexlibraryctor{unexpected}% \begin{itemdecl} -constexpr bitset(unsigned long long val) noexcept; +template + constexpr explicit unexpected(in_place_t, initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. + \pnum \effects -Initializes the first \tcode{M} bit positions to the corresponding bit -values in \tcode{val}. -\tcode{M} is the smaller of \tcode{N} and the number of bits in the value -representation\iref{basic.types} of \tcode{unsigned long long}. -If \tcode{M < N}, the remaining bit positions are initialized to zero. +Direct-non-list-initializes +\exposid{val} with \tcode{il, std::forward(args)...}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. \end{itemdescr} -\indexlibraryctor{bitset}% +\rSec4[expected.un.obs]{Observers} + +\indexlibrarymember{value}{unexpected}% \begin{itemdecl} -template - explicit bitset( - const basic_string& str, - typename basic_string::size_type pos = 0, - typename basic_string::size_type n - = basic_string::npos, - charT zero = charT('0'), - charT one = charT('1')); +constexpr const E& value() const & noexcept; +constexpr E& value() & noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Determines the effective length -\tcode{rlen} of the initializing string as the smaller of -\tcode{n} and -\tcode{str.size() - pos}. -Initializes the first \tcode{M} bit -positions to values determined from the corresponding characters in the string -\tcode{str}. -\tcode{M} is the smaller of \tcode{N} and \tcode{rlen}. - -\pnum -An element of the constructed object has value zero if the -corresponding character in \tcode{str}, beginning at position -\tcode{pos}, is -\tcode{zero}. -Otherwise, the element has the value one. -Character position \tcode{pos + M - 1} corresponds to bit position zero. -Subsequent decreasing character positions correspond to increasing bit positions. - -\pnum -If \tcode{M < N}, remaining bit positions are initialized to zero. - -\pnum -The function uses \tcode{traits::eq} -to compare the character values. - -\pnum -\throws -\indexlibraryglobal{out_of_range}% -\tcode{out_of_range} if \tcode{pos > str.size()} or -\indexlibraryglobal{invalid_argument}% -\tcode{invalid_argument} if any of -the \tcode{rlen} characters in \tcode{str} -beginning at position \tcode{pos} -is other than \tcode{zero} or \tcode{one}. +\returns +\exposid{val}. \end{itemdescr} -\indexlibraryctor{bitset}% +\indexlibrarymember{value}{unexpected}% \begin{itemdecl} -template - explicit bitset( - const charT* str, - typename basic_string::size_type n = basic_string::npos, - charT zero = charT('0'), - charT one = charT('1')); +constexpr E&& value() && noexcept; +constexpr const E&& value() const && noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -As if by: -\begin{codeblock} -bitset(n == basic_string::npos - ? basic_string(str) - : basic_string(str, n), - 0, n, zero, one) -\end{codeblock} +\returns +\tcode{std::move(\exposid{val})}. \end{itemdescr} +\rSec4[expected.un.swap]{Swap} -\rSec3[bitset.members]{Members} - -\indexlibrarymember{operator\&=}{bitset}% +\indexlibrarymember{swap}{unexpected}% \begin{itemdecl} -bitset& operator&=(const bitset& rhs) noexcept; +constexpr void swap(unexpected& other) noexcept(is_nothrow_swappable_v); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Clears each bit in -\tcode{*this} -for which the corresponding bit in \tcode{rhs} is clear, and leaves all other bits unchanged. +\mandates +\tcode{is_swappable_v} is \tcode{true}. \pnum -\returns -\tcode{*this}. +\effects +Equivalent to: +\tcode{using std::swap; swap(\exposid{val}, other.\exposid{val});} \end{itemdescr} -\indexlibrarymember{operator"|=}{bitset}% \begin{itemdecl} -bitset& operator|=(const bitset& rhs) noexcept; +friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y))); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Sets each bit in -\tcode{*this} -for which the corresponding bit in \tcode{rhs} is set, and leaves all other bits unchanged. +\constraints +\tcode{is_swappable_v} is \tcode{true}. \pnum -\returns -\tcode{*this}. +\effects +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} -\indexlibrarymember{operator\caret=}{bitset}% +\rSec4[expected.un.eq]{Equality operator} + +\indexlibrarymember{operator==}{unexpected}% \begin{itemdecl} -bitset& operator^=(const bitset& rhs) noexcept; +template + friend constexpr bool operator==(const unexpected& x, const unexpected& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Toggles each bit in -\tcode{*this} -for which the corresponding bit in \tcode{rhs} is set, and leaves all other bits unchanged. +\mandates +The expression \tcode{x.value() == y.value()} is well-formed and +its result is convertible to \tcode{bool}. \pnum \returns -\tcode{*this}. +\tcode{x.value() == y.value()}. \end{itemdescr} -\indexlibrarymember{operator<<=}{bitset}% +\rSec2[expected.bad]{Class template \tcode{bad_expected_access}} + +\indexlibraryglobal{bad_expected_access}% +\begin{codeblock} +namespace std { + template + class bad_expected_access : public bad_expected_access { + public: + explicit bad_expected_access(E); + const char* what() const noexcept override; + E& error() & noexcept; + const E& error() const & noexcept; + E&& error() && noexcept; + const E&& error() const && noexcept; + private: + E @\exposid{val}@; // \expos + }; +} +\end{codeblock} + +\pnum +The class template \tcode{bad_expected_access} +defines the type of objects thrown as exceptions to report the situation +where an attempt is made to access the value of an \tcode{expected} object +for which \tcode{has_value()} is \tcode{false}. + +\indexlibraryctor{bad_expected_access}% \begin{itemdecl} -bitset& operator<<=(size_t pos) noexcept; +explicit bad_expected_access(E e); \end{itemdecl} \begin{itemdescr} \pnum \effects -Replaces each bit at position \tcode{I} in -\tcode{*this} -with a value determined as follows: +Initializes \exposid{val} with \tcode{std::move(e)}. +\end{itemdescr} -\begin{itemize} -\item -If \tcode{I < pos}, the new value is zero; -\item -If \tcode{I >= pos}, the new value is the previous -value of the bit at position \tcode{I - pos}. -\end{itemize} +\indexlibrarymember{error}{bad_expected_access}% +\begin{itemdecl} +const E& error() const & noexcept; +E& error() & noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{*this}. +\exposid{val}. \end{itemdescr} -\indexlibrarymember{operator>>=}{bitset}% +\indexlibrarymember{error}{bad_expected_access}% \begin{itemdecl} -bitset& operator>>=(size_t pos) noexcept; +E&& error() && noexcept; +const E&& error() const && noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\effects -Replaces each bit at position \tcode{I} in -\tcode{*this} -with a value determined as follows: - -\begin{itemize} -\item -If \tcode{pos >= N - I}, the new value is zero; -\item -If \tcode{pos < N - I}, the new value is the previous value of the bit at position \tcode{I + pos}. -\end{itemize} - \pnum \returns -\tcode{*this}. +\tcode{std::move(\exposid{val})}. \end{itemdescr} -% Do not use \indexlibrarymember. -\indexlibrary{\idxcode{set} (member)!\idxcode{bitset}}% -\indexlibrary{\idxcode{bitset}!\idxcode{set}}% +\indexlibrarymember{what}{bad_expected_access}% \begin{itemdecl} -bitset& set() noexcept; +const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} -\pnum -\effects -Sets all bits in -\tcode{*this}. - \pnum \returns -\tcode{*this}. +An implementation-defined \ntbs. \end{itemdescr} -% Do not use \indexlibrarymember. -\indexlibrary{\idxcode{set} (member)!\idxcode{bitset}}% -\indexlibrary{\idxcode{bitset}!\idxcode{set}}% +\rSec2[expected.bad.void]{Class template specialization \tcode{bad_expected_access}} + +\begin{codeblock} +namespace std { + template<> + class bad_expected_access : public exception { + protected: + bad_expected_access() noexcept; + bad_expected_access(const bad_expected_access&); + bad_expected_access(bad_expected_access&&); + bad_expected_access& operator=(const bad_expected_access&); + bad_expected_access& operator=(bad_expected_access&&); + ~bad_expected_access(); + public: + const char* what() const noexcept override; + }; +} +\end{codeblock} + +\indexlibrarymember{what}{bad_expected_access}% \begin{itemdecl} -bitset& set(size_t pos, bool val = true); +const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} -\pnum -\effects -Stores a new value in the bit at position \tcode{pos} in -\tcode{*this}. -If \tcode{val} is \tcode{true}, the stored value is one, otherwise it is zero. - \pnum \returns -\tcode{*this}. - -\pnum -\throws -\indexlibraryglobal{out_of_range}% -\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. +An implementation-defined \ntbs. \end{itemdescr} -\indexlibrarymember{reset}{bitset}% -\begin{itemdecl} -bitset& reset() noexcept; -\end{itemdecl} +\rSec2[expected.expected]{Class template \tcode{expected}} + +\rSec3[expected.object.general]{General} + +\begin{codeblock} +namespace std { + template + class expected { + public: + using @\libmember{value_type}{expected}@ = T; + using @\libmember{error_type}{expected}@ = E; + using @\libmember{unexpected_type}{expected}@ = unexpected; + + template + using @\libmember{rebind}{expected}@ = expected; + + // \ref{expected.object.ctor}, constructors + constexpr expected(); + constexpr explicit(@\seebelow@) expected(const expected&); + constexpr explicit(@\seebelow@) expected(expected&&) noexcept(@\seebelow@); + template + constexpr explicit(@\seebelow@) expected(const expected&); + template + constexpr explicit(@\seebelow@) expected(expected&&); + + template + constexpr explicit(@\seebelow@) expected(U&& v); + + template + constexpr expected(const unexpected&); + template + constexpr expected(unexpected&&); + + template + constexpr explicit expected(in_place_t, Args&&...); + template + constexpr explicit expected(in_place_t, initializer_list, Args&&...); + template + constexpr explicit expected(unexpect_t, Args&&...); + template + constexpr explicit expected(unexpect_t, initializer_list, Args&&...); + + // \ref{expected.object.dtor}, destructor + constexpr ~expected(); + + // \ref{expected.object.assign}, assignment + constexpr expected& operator=(const expected&); + constexpr expected& operator=(expected&&) noexcept(@\seebelow@); + template constexpr expected& operator=(U&&); + template + constexpr expected& operator=(const unexpected&); + template + constexpr expected& operator=(unexpected&&); + + template + constexpr T& emplace(Args&&...) noexcept; + template + constexpr T& emplace(initializer_list, Args&&...) noexcept; + + // \ref{expected.object.swap}, swap + constexpr void swap(expected&) noexcept(@\seebelow@); + friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); + + // \ref{expected.object.obs}, observers + constexpr const T* operator->() const noexcept; + constexpr T* operator->() noexcept; + constexpr const T& operator*() const & noexcept; + constexpr T& operator*() & noexcept; + constexpr const T&& operator*() const && noexcept; + constexpr T&& operator*() && noexcept; + constexpr explicit operator bool() const noexcept; + constexpr bool has_value() const noexcept; + constexpr const T& value() const &; + constexpr T& value() &; + constexpr const T&& value() const &&; + constexpr T&& value() &&; + constexpr const E& error() const &; + constexpr E& error() &; + constexpr const E&& error() const &&; + constexpr E&& error() &&; + template constexpr T value_or(U&&) const &; + template constexpr T value_or(U&&) &&; + + // \ref{expected.object.eq}, equality operators + template requires (!is_void_v) + friend constexpr bool operator==(const expected& x, const expected& y); + template + friend constexpr bool operator==(const expected&, const T2&); + template + friend constexpr bool operator==(const expected&, const unexpected&); + + private: + bool @\exposid{has_val}@; // \expos + union { + T @\exposid{val}@; // \expos + E @\exposid{unex}@; // \expos + }; + }; +} +\end{codeblock} -\begin{itemdescr} \pnum -\effects -Resets all bits in -\tcode{*this}. +Any object of type \tcode{expected} either +contains a value of type \tcode{T} or +a value of type \tcode{E} within its own storage. +Implementations are not permitted to use additional storage, +such as dynamic memory, +to allocate the object of type \tcode{T} or the object of type E. +These objects are allocated in a region of the \tcode{expected} storage +suitably aligned for the types \tcode{T} and \tcode{E}. +Members \exposid{has_val}, \exposid{val}, and \exposid{unex} +are provided for exposition only. +\exposid{has_val} indicates whether the \tcode{expected} object +contains an object of type \tcode{T}. \pnum -\returns -\tcode{*this}. -\end{itemdescr} +A program +that instantiates the definition of template \tcode{expected} +for a reference type, a function type, or +for possibly cv-qualified types \tcode{in_place_t}, \tcode{unexpect_t}, or +a specialization of \tcode{unexpected} for the \tcode{T} parameter +is ill-formed. +A program that instantiates +the definition of the template \tcode{expected} +with a type for the \tcode{E} parameter +that is not a valid template argument for \tcode{unexpected} is ill-formed. -\indexlibrarymember{reset}{bitset}% +\pnum +When \tcode{T} is not \cv{} \tcode{void}, it shall meet +the \oldconcept{Destructible} requirements (\tref{cpp17.destructible}). +\tcode{E} shall meet +the \oldconcept{Destructible} requirements. + +\rSec3[expected.object.ctor]{Constructors} + +\indexlibraryctor{expected}% \begin{itemdecl} -bitset& reset(size_t pos); +constexpr expected(); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_default_constructible_v} is \tcode{true}. + \pnum \effects -Resets the bit at position \tcode{pos} in -\tcode{*this}. +Value-initializes \exposid{val}. \pnum -\returns -\tcode{*this}. +\ensures +\tcode{has_value()} is \tcode{true}. \pnum \throws -\indexlibraryglobal{out_of_range}% -\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. +Any exception thrown by the initialization of \exposid{val}. \end{itemdescr} -\indexlibrarymember{operator\~{}}{bitset}% +\indexlibraryctor{expected}% \begin{itemdecl} -bitset operator~() const noexcept; +constexpr expected(const expected& rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an object \tcode{x} of class -\tcode{bitset} -and initializes it with -\tcode{*this}. +If \tcode{rhs.has_value()} is \tcode{true}, +direct-non-list-initializes \exposid{val} with \tcode{*rhs}. +Otherwise, direct-non-list-initializes \exposid{unex} with \tcode{rhs.error()}. \pnum -\returns -\tcode{x.flip()}. -\end{itemdescr} +\ensures +\tcode{rhs.has_value() == this->has_value()}. -\indexlibrarymember{flip}{bitset}% -\begin{itemdecl} -bitset& flip() noexcept; -\end{itemdecl} +\pnum +\throws +Any exception thrown by the initialization of \exposid{val} or \exposid{unex}. -\begin{itemdescr} \pnum -\effects -Toggles all bits in -\tcode{*this}. +\remarks +This constructor is defined as deleted unless +\begin{itemize} +\item +\tcode{is_copy_constructible_v} is \tcode{true} and +\item +\tcode{is_copy_constructible_v} is \tcode{true}. +\end{itemize} \pnum -\returns -\tcode{*this}. +This constructor is trivial if +\begin{itemize} +\item +\tcode{is_trivially_copy_constructible_v} is \tcode{true} and +\item +\tcode{is_trivially_copy_constructible_v} is \tcode{true}. +\end{itemize} \end{itemdescr} -\indexlibrarymember{flip}{bitset}% +\indexlibraryctor{expected}% \begin{itemdecl} -bitset& flip(size_t pos); +constexpr expected(expected&& rhs) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_move_constructible_v} is \tcode{true} and +\item +\tcode{is_move_constructible_v} is \tcode{true}. +\end{itemize} + \pnum \effects -Toggles the bit at position \tcode{pos} in -\tcode{*this}. +If \tcode{rhs.has_value()} is \tcode{true}, +direct-non-list-initializes \exposid{val} with \tcode{std::move(*rhs)}. +Otherwise, +direct-non-list-initializes \exposid{unex} with \tcode{std::move(rhs.error())}. \pnum -\returns -\tcode{*this}. +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. \pnum \throws -\indexlibraryglobal{out_of_range}% -\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. +Any exception thrown by the initialization of \exposid{val} or \exposid{unex}. + +\pnum +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_move_constructible_v \&\& +is_nothrow_move_constructible_v}. + +\pnum +This constructor is trivial if +\begin{itemize} +\item +\tcode{is_trivially_move_constructible_v} is \tcode{true} and +\item +\tcode{is_trivially_move_constructible_v} is \tcode{true}. +\end{itemize} \end{itemdescr} -\indexlibrarymember{to_ulong}{bitset}% +\indexlibraryctor{expected}% \begin{itemdecl} -unsigned long to_ulong() const; +template + constexpr explicit(@\seebelow@) expected(const expected& rhs); +template + constexpr explicit(@\seebelow@) expected(expected&& rhs); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x}. +Let: +\begin{itemize} +\item +\tcode{UF} be \tcode{const U\&} for the first overload and +\tcode{U} for the second overload. +\item +\tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. +\end{itemize} \pnum -\throws -\indexlibraryglobal{overflow_error}% -\tcode{overflow_error} if the integral value \tcode{x} -corresponding to the bits in \tcode{*this} -cannot be represented as type \tcode{unsigned long}. -\end{itemdescr} +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v} is \tcode{true}; and +\item +\tcode{is_constructible_v} is \tcode{true}; and +\item +\tcode{is_constructible_v\&>} is \tcode{false}; and +\item +\tcode{is_constructible_v>} is \tcode{false}; and +\item +\tcode{is_constructible_v\&>} is \tcode{false}; and +\item +\tcode{is_constructible_v>} is \tcode{false}; and +\item +\tcode{is_convertible_v\&, T>} is \tcode{false}; and +\item +\tcode{is_convertible_v\&\&, T>} is \tcode{false}; and +\item +\tcode{is_convertible_v\&, T>} is \tcode{false}; and +\item +\tcode{is_convertible_v\&\&, T>} is \tcode{false}; and +\item +\tcode{is_constructible_v, expected\&>} is \tcode{false}; and +\item +\tcode{is_constructible_v, expected>} is \tcode{false}; and +\item +\tcode{is_constructible_v, const expected\&>} is \tcode{false}; and +\item +\tcode{is_constructible_v, const expected>} is \tcode{false}. +\end{itemize} -\indexlibrarymember{to_ullong}{bitset}% -\begin{itemdecl} -unsigned long long to_ullong() const; -\end{itemdecl} +\pnum +\effects +If \tcode{rhs.has_value()}, +direct-non-list-initializes \exposid{val} with \tcode{std::forward(*rhs)}. +Otherwise, +direct-non-list-initializes \exposid{unex} with \tcode{std::forward(rhs.error())}. -\begin{itemdescr} \pnum -\returns -\tcode{x}. +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. \pnum \throws -\indexlibraryglobal{overflow_error}% -\tcode{overflow_error} if the integral value \tcode{x} -corresponding to the bits in \tcode{*this} -cannot be represented as type \tcode{unsigned long long}. +Any exception thrown by the initialization of \exposid{val} or \exposid{unex}. + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to +\tcode{!is_convertible_v || !is_convertible_v}. \end{itemdescr} -\indexlibrarymember{to_string}{bitset}% +\indexlibraryctor{expected}% \begin{itemdecl} -template, - class Allocator = allocator> - basic_string - to_string(charT zero = charT('0'), charT one = charT('1')) const; +template + constexpr explicit(!is_convertible_v) expected(U&& v); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v, in_place_t>} is \tcode{false}; and +\item +\tcode{is_same_v, remove_cvref_t>} is \tcode{false}; and +\item +\tcode{remove_cvref_t} is not a specialization of \tcode{unexpected}; and +\item +\tcode{is_constructible_v} is \tcode{true}. +\end{itemize} + \pnum \effects -Constructs a string object of the appropriate type -and initializes it to a string of length \tcode{N} characters. -Each character is determined by the value of its corresponding bit position in -\tcode{*this}. -Character position \tcode{N - 1} corresponds to bit position zero. -Subsequent decreasing character positions correspond to increasing bit -positions. -Bit value zero becomes the character \tcode{zero}, -bit value one becomes the character -\tcode{one}. +Direct-non-list-initializes \exposid{val} with \tcode{std::forward(v)}. \pnum -\returns -The created object. +\ensures +\tcode{has_value()} is \tcode{true}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. \end{itemdescr} -\indexlibrarymember{count}{bitset}% +\indexlibraryctor{expected}% \begin{itemdecl} -size_t count() const noexcept; +template + constexpr explicit(!is_convertible_v) expected(const unexpected& e); +template + constexpr explicit(!is_convertible_v) expected(unexpected&& e); \end{itemdecl} \begin{itemdescr} \pnum -\returns -A count of the number of bits set in -\tcode{*this}. -\end{itemdescr} +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. -\indexlibrarymember{size}{bitset}% -\begin{itemdecl} -constexpr size_t size() const noexcept; -\end{itemdecl} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. -\begin{itemdescr} \pnum -\returns -\tcode{N}. -\end{itemdescr} +\effects +Direct-non-list-initializes \exposid{unex} with \tcode{std::forward(e.value())}. -\indexlibrarymember{operator==}{bitset}% -\begin{itemdecl} -bool operator==(const bitset& rhs) const noexcept; -\end{itemdecl} +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. -\begin{itemdescr} \pnum -\returns -\tcode{true} if the value of each bit in -\tcode{*this} -equals the value of the corresponding bit in \tcode{rhs}. +\throws +Any exception thrown by the initialization of \exposid{unex}. \end{itemdescr} -\indexlibrarymember{test}{bitset}% +\indexlibraryctor{expected}% \begin{itemdecl} -bool test(size_t pos) const; +template + constexpr explicit expected(in_place_t, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{true} -if the bit at position \tcode{pos} -in -\tcode{*this} -has the value one. +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum -\throws -\indexlibraryglobal{out_of_range}% -\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. -\end{itemdescr} +\effects +Direct-non-list-initializes \exposid{val} with \tcode{std::forward(args)...}. -\indexlibrarymember{all}{bitset}% -\begin{itemdecl} -bool all() const noexcept; -\end{itemdecl} +\pnum +\ensures +\tcode{has_value()} is \tcode{true}. -\begin{itemdescr} \pnum -\returns -\tcode{count() == size()}. +\throws +Any exception thrown by the initialization of \exposid{val}. \end{itemdescr} -% Do not use \indexlibrarymember. -\indexlibrary{\idxcode{any} (member)!\idxcode{bitset}}% -\indexlibrary{\idxcode{bitset}!\idxcode{any}}% +\indexlibraryctor{expected}% \begin{itemdecl} -bool any() const noexcept; +template + constexpr explicit expected(in_place_t, initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{count() != 0}. -\end{itemdescr} +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. -\indexlibrarymember{none}{bitset}% -\begin{itemdecl} -bool none() const noexcept; -\end{itemdecl} +\pnum +\effects +Direct-non-list-initializes \exposid{val} with +\tcode{il, std::forward(args)...}. -\begin{itemdescr} \pnum -\returns -\tcode{count() == 0}. +\ensures +\tcode{has_value()} is \tcode{true}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. \end{itemdescr} -\indexlibrarymember{operator<<}{bitset}% +\indexlibraryctor{expected}% \begin{itemdecl} -bitset operator<<(size_t pos) const noexcept; +template + constexpr explicit expected(unexpect_t, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{bitset(*this) <<= pos}. -\end{itemdescr} +\constraints +\tcode{is_constructible_v} is \tcode{true}. -\indexlibrarymember{operator>>}{bitset}% -\begin{itemdecl} -bitset operator>>(size_t pos) const noexcept; -\end{itemdecl} +\pnum +\effects +Direct-non-list-initializes \exposid{unex} with +\tcode{std::forward(args)...}. -\begin{itemdescr} \pnum -\returns -\tcode{bitset(*this) >>= pos}. +\ensures +\tcode{has_value()} is \tcode{false}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. \end{itemdescr} -\indexlibrarymember{operator[]}{bitset}% +\indexlibraryctor{expected}% \begin{itemdecl} -constexpr bool operator[](size_t pos) const; +template + constexpr explicit expected(unexpect_t, initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{pos} is valid. +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. \pnum -\returns -\tcode{true} if the bit at position \tcode{pos} in \tcode{*this} has the value -one, otherwise \tcode{false}. +\effects +Direct-non-list-initializes \exposid{unex} with +\tcode{il, std::forward(args)...}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. \pnum \throws -Nothing. +Any exception thrown by the initialization of \exposid{unex}. \end{itemdescr} -\indexlibrarymember{operator[]}{bitset}% +\rSec3[expected.object.dtor]{Destructor} + +\indexlibrarydtor{expected}% \begin{itemdecl} -bitset::reference operator[](size_t pos); +constexpr ~expected(); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{pos} is valid. - -\pnum -\returns -An object of type -\tcode{bitset::reference} -such that -\tcode{(*this)[pos] == this->test(pos)}, -and such that -\tcode{(*this)[pos] = val} -is equivalent to -\tcode{this->set(pos, val)}. - -\pnum -\throws -Nothing. +\effects +If \tcode{has_value()} is \tcode{true}, destroys \exposid{val}, +otherwise destroys \exposid{unex}. \pnum \remarks -For the purpose of determining the presence of a data -race\iref{intro.multithread}, any access or update through the resulting -reference potentially accesses or modifies, respectively, the entire -underlying bitset. +If \tcode{is_trivially_destructible_v} is \tcode{true}, and +\tcode{is_trivially_destructible_v} is \tcode{true}, +then this destructor is a trivial destructor. \end{itemdescr} -\rSec2[bitset.hash]{\tcode{bitset} hash support} +\rSec3[expected.object.assign]{Assignment} -\indexlibraryglobal{hash_code}% +\pnum +This subclause makes use of the following exposition-only function: +\begin{codeblock} +template +constexpr void @\exposid{reinit-expected}@(T& newval, U& oldval, Args&&... args) { // \expos + if constexpr (is_nothrow_constructible_v) { + destroy_at(addressof(oldval)); + construct_at(addressof(newval), std::forward(args)...); + } else if constexpr (is_nothrow_move_constructible_v) { + T tmp(std::forward(args)...); + destroy_at(addressof(oldval)); + construct_at(addressof(newval), std::move(tmp)); + } else { + U tmp(std::move(oldval)); + destroy_at(addressof(oldval)); + try { + construct_at(addressof(newval), std::forward(args)...); + } catch (...) { + construct_at(addressof(oldval), std::move(tmp)); + throw; + } + } +} +\end{codeblock} + +\indexlibrarymember{operator=}{expected}% \begin{itemdecl} -template struct hash>; +constexpr expected& operator=(const expected& rhs); \end{itemdecl} \begin{itemdescr} \pnum -The specialization is enabled\iref{unord.hash}. -\end{itemdescr} - +\effects +\begin{itemize} +\item +If \tcode{this->has_value() \&\& rhs.has_value()} is \tcode{true}, +equivalent to \tcode{\exposid{val} = *rhs}. +\item +Otherwise, if \tcode{this->has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{unex}@, @\exposid{val}@, rhs.error()) +\end{codeblock} +\item +Otherwise, if \tcode{rhs.has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{val}@, @\exposid{unex}@, *rhs) +\end{codeblock} +\item +Otherwise, equivalent to \tcode{\exposid{unex} = rhs.error()}. +\end{itemize} +Then, if no exception was thrown, +equivalent to: \tcode{\exposid{has_val} = rhs.has_value(); return *this;} -\rSec2[bitset.operators]{\tcode{bitset} operators} +\pnum +\remarks +This operator is defined as deleted unless: +\begin{itemize} +\item +\tcode{is_copy_assignable_v} is \tcode{true} and +\item +\tcode{is_copy_constructible_v} is \tcode{true} and +\item +\tcode{is_copy_assignable_v} is \tcode{true} and +\item +\tcode{is_copy_constructible_v} is \tcode{true} and +\item +\tcode{is_nothrow_move_constructible_v || is_nothrow_move_constructible_v} +is \tcode{true}. +\end{itemize} +\end{itemdescr} -\indexlibrarymember{operator\&}{bitset}% +\indexlibrarymember{operator=}{expected}% \begin{itemdecl} -template - bitset operator&(const bitset& lhs, const bitset& rhs) noexcept; +constexpr expected& operator=(expected&& rhs) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{bitset(lhs) \&= rhs}. -\end{itemdescr} +\constraints +\begin{itemize} +\item +\tcode{is_move_constructible_v} is \tcode{true} and +\item +\tcode{is_move_assignable_v} is \tcode{true} and +\item +\tcode{is_move_constructible_v} is \tcode{true} and +\item +\tcode{is_move_assignable_v} is \tcode{true} and +\item +\tcode{is_nothrow_move_constructible_v || is_nothrow_move_constructible_v} +is \tcode{true}. +\end{itemize} -\indexlibrarymember{operator"|}{bitset}% -\begin{itemdecl} -template - bitset operator|(const bitset& lhs, const bitset& rhs) noexcept; -\end{itemdecl} +\pnum +\effects +\begin{itemize} +\item +If \tcode{this->has_value() \&\& rhs.has_value()} is \tcode{true}, +equivalent to \tcode{\exposid{val} = std::move(*rhs)}. +\item +Otherwise, if \tcode{this->has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{unex}@, @\exposid{val}@, std::move(rhs.error())) +\end{codeblock} +\item +Otherwise, if \tcode{rhs.has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{val}@, @\exposid{unex}@, std::move(*rhs)) +\end{codeblock} +\item +Otherwise, equivalent to \tcode{\exposid{unex} = std::move(rhs.error())}. +\end{itemize} +Then, if no exception was thrown, +equivalent to: \tcode{has_val = rhs.has_value(); return *this;} -\begin{itemdescr} \pnum -\returns -\tcode{bitset(lhs) |= rhs}. +\remarks +The exception specification is equivalent to: +\begin{codeblock} +is_nothrow_move_assignable_v && is_nothrow_move_constructible_v && +is_nothrow_move_assignable_v && is_nothrow_move_constructible_v +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator\caret}{bitset}% +\indexlibrarymember{operator=}{expected}% \begin{itemdecl} -template - bitset operator^(const bitset& lhs, const bitset& rhs) noexcept; +template + constexpr expected& operator=(U&& v); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v>} is \tcode{false}; and +\item +\tcode{remove_cvref_t} is not a specialization of \tcode{unexpected}; and +\item +\tcode{is_constructible_v} is \tcode{true}; and +\item +\tcode{is_assignable_v} is \tcode{true}; and +\item +\tcode{is_nothrow_constructible_v || is_nothrow_move_constructible_v ||\newline +is_nothrow_move_constructible_v} +is \tcode{true}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +If \tcode{has_value()} is \tcode{true}, +equivalent to: \tcode{\exposid{val} = std::forward(v);} +\item +Otherwise, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{val}@, @\exposid{unex}@, std::forward(v)); +@\exposid{has_val}@ = true; +\end{codeblock} +\end{itemize} + \pnum \returns -\tcode{bitset(lhs) \caret= rhs}. +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{operator>>}{bitset}% +\indexlibrarymember{operator=}{expected}% \begin{itemdecl} -template - basic_istream& - operator>>(basic_istream& is, bitset& x); +template + constexpr expected& operator=(const unexpected& e); +template + constexpr expected& operator=(unexpected&& e); \end{itemdecl} \begin{itemdescr} \pnum -A formatted input function\iref{istream.formatted}. +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. \pnum -\effects -Extracts up to \tcode{N} characters from \tcode{is}. -Stores these characters in a temporary object \tcode{str} of type -\tcode{basic_string}, -then evaluates the expression -\tcode{x = bitset(str)}. -Characters are extracted and stored until any of the following occurs: +\constraints \begin{itemize} \item -\tcode{N} characters have been extracted and stored; +\tcode{is_constructible_v} is \tcode{true}; and \item -\indextext{end-of-file}% -end-of-file occurs on the input sequence; +\tcode{is_assignable_v} is \tcode{true}; and \item -the next input character is neither -\tcode{is.widen('0')} -nor -\tcode{is.widen('1')} -(in which case the input character is not extracted). +\tcode{is_nothrow_constructible_v || is_nothrow_move_constructible_v ||\newline +is_nothrow_move_constructible_v} is \tcode{true}. \end{itemize} \pnum -If \tcode{N > 0} and no characters are stored in \tcode{str}, calls -\tcode{is.setstate(ios_base::failbit)} -(which may throw -\tcode{ios_base::failure}\iref{iostate.flags}). +\effects +\begin{itemize} +\item +If \tcode{has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{unex}@, @\exposid{val}@, std::forward(e.value())); +@\exposid{has_val}@ = false; +\end{codeblock} +\item +Otherwise, equivalent to: +\tcode{\exposid{unex} = std::forward(e.value());} +\end{itemize} \pnum \returns -\tcode{is}. +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{operator<<}{bitset}% +\indexlibrarymember{emplace}{expected}% \begin{itemdecl} -template - basic_ostream& - operator<<(basic_ostream& os, const bitset& x); +template + constexpr T& emplace(Args&&... args) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns +\constraints +\tcode{is_nothrow_constructible_v} is \tcode{true}. + +\pnum +\effects +Equivalent to: \begin{codeblock} -os << x.template to_string>( - use_facet>(os.getloc()).widen('0'), - use_facet>(os.getloc()).widen('1')) +if (has_value()) { + destroy_at(addressof(@\exposid{val}@)); +} else { + destroy_at(addressof(@\exposid{unex}@)); + @\exposid{has_val}@ = true; +} +return *construct_at(addressof(@\exposid{val}@), std::forward(args)...); \end{codeblock} -(see~\ref{ostream.formatted}). \end{itemdescr} -\rSec1[memory]{Memory} +\indexlibrarymember{emplace}{expected}% +\begin{itemdecl} +template + constexpr T& emplace(initializer_list il, Args&&... args) noexcept; +\end{itemdecl} -\rSec2[memory.general]{In general} +\begin{itemdescr} +\pnum +\constraints +\tcode{is_nothrow_constructible_v\&, Args...>} +is \tcode{true}. \pnum -Subclause~\ref{memory} describes the contents of the header -\libheaderref{memory} and some -of the contents of the header \libheaderref{cstdlib}. +\effects +Equivalent to: +\begin{codeblock} +if (has_value()) { + destroy_at(addressof(@\exposid{val}@)); +} else { + destroy_at(addressof(@\exposid{unex}@)); + @\exposid{has_val}@ = true; +} +return *construct_at(addressof(@\exposid{val}@), il, std::forward(args)...); +\end{codeblock} +\end{itemdescr} -\rSec2[memory.syn]{Header \tcode{} synopsis} +\rSec3[expected.object.swap]{Swap} -\pnum -The header \libheaderdef{memory} defines several types and function templates that -describe properties of pointers and pointer-like types, manage memory -for containers and other template types, destroy objects, and -construct objects in -uninitialized memory -buffers~(\ref{pointer.traits}--\ref{specialized.addressof} and \ref{specialized.algorithms}). -The header also defines the templates -\tcode{unique_ptr}, \tcode{shared_ptr}, \tcode{weak_ptr}, -\tcode{out_ptr_t}, \tcode{inout_ptr_t}, and various function -templates that operate on objects of these types\iref{smartptr}. +\indexlibrarymember{swap}{expected}% +\begin{itemdecl} +constexpr void swap(expected& rhs) noexcept(@\seebelow@); +\end{itemdecl} +\begin{itemdescr} \pnum -Let \tcode{\exposid{POINTER_OF}(T)} denote a type that is +\constraints \begin{itemize} \item -\tcode{T::pointer} if the \grammarterm{qualified-id} \tcode{T::pointer} -is valid and denotes a type, +\tcode{is_swappable_v} is \tcode{true} and \item -otherwise, \tcode{T::element_type*} -if the \grammarterm{qualified-id} \tcode{T::element_type} -is valid and denotes a type, -\item -otherwise, \tcode{pointer_traits::element_type*}. -\end{itemize} - -\pnum -Let \tcode{\exposid{POINTER_OF_OR}(T, U)} denote a type that is: -\begin{itemize} +\tcode{is_swappable_v} is \tcode{true} and \item -\tcode{\exposid{POINTER_OF}(T)} -if \tcode{\exposid{POINTER_OF}(T)} is valid and denotes a type, +\tcode{is_move_constructible_v \&\& is_move_constructible_v} +is \tcode{true}, and \item -otherwise, \tcode{U}. +\tcode{is_nothrow_move_constructible_v || is_nothrow_move_constructible_v} +is \tcode{true}. \end{itemize} -\begin{codeblock} -#include // see \ref{compare.syn} +\pnum +\effects +See \tref{expected.object.swap}. -namespace std { - // \ref{pointer.traits}, pointer traits - template struct pointer_traits; - template struct pointer_traits; +\begin{floattable}{\tcode{swap(expected\&)} effects}{expected.object.swap} +{lx{0.35\hsize}x{0.35\hsize}} +\topline +& \chdr{\tcode{this->has_value()}} & \rhdr{\tcode{!this->has_value()}} \\ \capsep +\lhdr{\tcode{rhs.has_value()}} & + equivalent to: \tcode{using std::swap; swap(\exposid{val}, rhs.\exposid{val});} & + calls \tcode{rhs.swap(*this)} \\ +\lhdr{\tcode{!rhs.has_value()}} & + \seebelow & + equivalent to: \tcode{using std::swap; swap(\exposid{unex}, rhs.\exposid{unex});} \\ +\end{floattable} - // \ref{pointer.conversion}, pointer conversion - template - constexpr T* to_address(T* p) noexcept; - template - constexpr auto to_address(const Ptr& p) noexcept; - - // \ref{ptr.align}, pointer alignment - void* align(size_t alignment, size_t size, void*& ptr, size_t& space); - template - [[nodiscard]] constexpr T* assume_aligned(T* ptr); - - // \ref{allocator.tag}, allocator argument tag - struct allocator_arg_t { explicit allocator_arg_t() = default; }; - inline constexpr allocator_arg_t allocator_arg{}; - - // \ref{allocator.uses}, \tcode{uses_allocator} - template struct uses_allocator; - - // \ref{allocator.uses.trait}, \tcode{uses_allocator} - template - inline constexpr bool @\libglobal{uses_allocator_v}@ = uses_allocator::value; - - // \ref{allocator.uses.construction}, uses-allocator construction - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - Args&&... args) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, - Tuple1&& x, Tuple2&& y) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - U&& u, V&& v) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - pair& pr) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - const pair& pr) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - pair&& pr) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - const pair&& pr) noexcept; - template - constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); - template - constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, - Args&&... args); - - // \ref{allocator.traits}, allocator traits - template struct allocator_traits; - - template - struct allocation_result { - Pointer ptr; - size_t count; - }; +For the case where \tcode{rhs.value()} is \tcode{false} and +\tcode{this->has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +if constexpr (is_nothrow_move_constructible_v) { + E tmp(std::move(rhs.@\exposid{unex}@)); + destroy_at(addressof(rhs.@\exposid{unex}@)); + try { + construct_at(addressof(rhs.@\exposid{val}@), std::move(@\exposid{val}@)); + destroy_at(addressof(@\exposid{val}@)); + construct_at(addressof(@\exposid{unex}@), std::move(tmp)); + } catch(...) { + construct_at(addressof(rhs.@\exposid{unex}@), std::move(tmp)); + throw; + } +} else { + T tmp(std::move(@\exposid{val}@)); + destroy_at(addressof(@\exposid{val}@)); + try { + construct_at(addressof(@\exposid{unex}@), std::move(rhs.@\exposid{unex}@)); + destroy_at(addressof(rhs.@\exposid{unex}@)); + construct_at(addressof(rhs.@\exposid{val}@), std::move(tmp)); + } catch (...) { + construct_at(addressof(@\exposid{val}@), std::move(tmp)); + throw; + } +} +@\exposid{has_val}@ = false; +rhs.@\exposid{has_val}@ = true; +\end{codeblock} - template - [[nodiscard] constexpr allocation_result::pointer> - allocate_at_least(Allocator& a, size_t n); +\pnum +\throws +Any exception thrown by the expressions in the \Fundescx{Effects}. - // \ref{default.allocator}, the default allocator - template class allocator; - template - constexpr bool operator==(const allocator&, const allocator&) noexcept; +\pnum +\remarks +The exception specification is equivalent to: +\begin{codeblock} +is_nothrow_move_constructible_v && is_nothrow_swappable_v && +is_nothrow_move_constructible_v && is_nothrow_swappable_v +\end{codeblock} +\end{itemdescr} - // \ref{specialized.addressof}, addressof - template - constexpr T* addressof(T& r) noexcept; - template - const T* addressof(const T&&) = delete; - - // \ref{specialized.algorithms}, specialized algorithms - // \ref{special.mem.concepts}, special memory concepts - template - concept @\exposconcept{nothrow-input-iterator}@ = @\seebelow@; // \expos - template - concept @\exposconcept{nothrow-forward-iterator}@ = @\seebelow@; // \expos - template - concept @\exposconcept{nothrow-sentinel-for}@ = @\seebelow@; // \expos - template - concept @\exposconcept{nothrow-input-range}@ = @\seebelow@; // \expos - template - concept @\exposconcept{nothrow-forward-range}@ = @\seebelow@; // \expos - - template - void uninitialized_default_construct(NoThrowForwardIterator first, - NoThrowForwardIterator last); - template - void uninitialized_default_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, - NoThrowForwardIterator last); - template - NoThrowForwardIterator - uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); - template - NoThrowForwardIterator - uninitialized_default_construct_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n); +\indexlibrarymember{swap}{expected}% +\begin{itemdecl} +friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); +\end{itemdecl} - namespace ranges { - template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> - requires @\libconcept{default_initializable}@> - I uninitialized_default_construct(I first, S last); - template<@\exposconcept{nothrow-forward-range}@ R> - requires @\libconcept{default_initializable}@> - borrowed_iterator_t uninitialized_default_construct(R&& r); - - template<@\exposconcept{nothrow-forward-iterator}@ I> - requires @\libconcept{default_initializable}@> - I uninitialized_default_construct_n(I first, iter_difference_t n); - } +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{x.swap(y)}. +\end{itemdescr} - template - void uninitialized_value_construct(NoThrowForwardIterator first, - NoThrowForwardIterator last); - template - void uninitialized_value_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, - NoThrowForwardIterator last); - template - NoThrowForwardIterator - uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); - template - NoThrowForwardIterator - uninitialized_value_construct_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n); +\rSec3[expected.object.obs]{Observers} - namespace ranges { - template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> - requires @\libconcept{default_initializable}@> - I uninitialized_value_construct(I first, S last); - template<@\exposconcept{nothrow-forward-range}@ R> - requires @\libconcept{default_initializable}@> - borrowed_iterator_t uninitialized_value_construct(R&& r); - - template<@\exposconcept{nothrow-forward-iterator}@ I> - requires @\libconcept{default_initializable}@> - I uninitialized_value_construct_n(I first, iter_difference_t n); - } +\indexlibrarymember{operator->}{expected}% +\begin{itemdecl} +constexpr const T* operator->() const noexcept; +constexpr T* operator->() noexcept; +\end{itemdecl} - template - NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last, - NoThrowForwardIterator result); - template - NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, ForwardIterator last, - NoThrowForwardIterator result); - template - NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, - NoThrowForwardIterator result); - template - NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, Size n, - NoThrowForwardIterator result); +\begin{itemdescr} +\pnum +\expects +\tcode{has_value()} is \tcode{true}. - namespace ranges { - template - using uninitialized_copy_result = in_out_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S1, - @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> - requires @\libconcept{constructible_from}@, iter_reference_t> - uninitialized_copy_result - uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast); - template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> - requires @\libconcept{constructible_from}@, range_reference_t> - uninitialized_copy_result, borrowed_iterator_t> - uninitialized_copy(IR&& in_range, OR&& out_range); - - template - using uninitialized_copy_n_result = in_out_result; - template<@\libconcept{input_iterator}@ I, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> - requires @\libconcept{constructible_from}@, iter_reference_t> - uninitialized_copy_n_result - uninitialized_copy_n(I ifirst, iter_difference_t n, O ofirst, S olast); - } +\pnum +\returns +\tcode{addressof(\exposid{val})}. +\end{itemdescr} - template - NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last, - NoThrowForwardIterator result); - template - NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, ForwardIterator last, - NoThrowForwardIterator result); - template - pair - uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result); - template - pair - uninitialized_move_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, Size n, NoThrowForwardIterator result); +\indexlibrarymember{operator*}{expected}% +\begin{itemdecl} +constexpr const T& operator*() const & noexcept; +constexpr T& operator*() & noexcept; +\end{itemdecl} - namespace ranges { - template - using uninitialized_move_result = in_out_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S1, - @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> - requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> - uninitialized_move_result - uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast); - template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> - requires @\libconcept{constructible_from}@, range_rvalue_reference_t> - uninitialized_move_result, borrowed_iterator_t> - uninitialized_move(IR&& in_range, OR&& out_range); - - template - using uninitialized_move_n_result = in_out_result; - template<@\libconcept{input_iterator}@ I, - @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> - requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> - uninitialized_move_n_result - uninitialized_move_n(I ifirst, iter_difference_t n, O ofirst, S olast); - } +\begin{itemdescr} +\pnum +\expects +\tcode{has_value()} is \tcode{true}. - template - void uninitialized_fill(NoThrowForwardIterator first, NoThrowForwardIterator last, - const T& x); - template - void uninitialized_fill(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, NoThrowForwardIterator last, - const T& x); - template - NoThrowForwardIterator - uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); - template - NoThrowForwardIterator - uninitialized_fill_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n, const T& x); +\pnum +\returns +\exposid{val}. +\end{itemdescr} - namespace ranges { - template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S, class T> - requires @\libconcept{constructible_from}@, const T&> - I uninitialized_fill(I first, S last, const T& x); - template<@\exposconcept{nothrow-forward-range}@ R, class T> - requires @\libconcept{constructible_from}@, const T&> - borrowed_iterator_t uninitialized_fill(R&& r, const T& x); - - template<@\exposconcept{nothrow-forward-iterator}@ I, class T> - requires @\libconcept{constructible_from}@, const T&> - I uninitialized_fill_n(I first, iter_difference_t n, const T& x); - } - - // \ref{specialized.construct}, \tcode{construct_at} - template - constexpr T* construct_at(T* location, Args&&... args); - - namespace ranges { - template - constexpr T* construct_at(T* location, Args&&... args); - } - - // \ref{specialized.destroy}, \tcode{destroy} - template - constexpr void destroy_at(T* location); - template - constexpr void destroy(NoThrowForwardIterator first, NoThrowForwardIterator last); - template - void destroy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, NoThrowForwardIterator last); - template - constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, Size n); - template - NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n); - - namespace ranges { - template<@\libconcept{destructible}@ T> - constexpr void destroy_at(T* location) noexcept; - - template<@\exposconcept{nothrow-input-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> - requires @\libconcept{destructible}@> - constexpr I destroy(I first, S last) noexcept; - template<@\exposconcept{nothrow-input-range}@ R> - requires @\libconcept{destructible}@> - constexpr borrowed_iterator_t destroy(R&& r) noexcept; - - template<@\exposconcept{nothrow-input-iterator}@ I> - requires @\libconcept{destructible}@> - constexpr I destroy_n(I first, iter_difference_t n) noexcept; - } - - // \ref{unique.ptr}, class template \tcode{unique_ptr} - template struct default_delete; - template struct default_delete; - template> class unique_ptr; - template class unique_ptr; - - template - unique_ptr make_unique(Args&&... args); // \tcode{T} is not array - template - unique_ptr make_unique(size_t n); // \tcode{T} is \tcode{U[]} - template - @\unspecnc@ make_unique(Args&&...) = delete; // \tcode{T} is \tcode{U[N]} - - template - unique_ptr make_unique_for_overwrite(); // \tcode{T} is not array - template - unique_ptr make_unique_for_overwrite(size_t n); // \tcode{T} is \tcode{U[]} - template - @\unspecnc@ make_unique_for_overwrite(Args&&...) = delete; // \tcode{T} is \tcode{U[N]} - - template - void swap(unique_ptr& x, unique_ptr& y) noexcept; - - template - bool operator==(const unique_ptr& x, const unique_ptr& y); - template - bool operator<(const unique_ptr& x, const unique_ptr& y); - template - bool operator>(const unique_ptr& x, const unique_ptr& y); - template - bool operator<=(const unique_ptr& x, const unique_ptr& y); - template - bool operator>=(const unique_ptr& x, const unique_ptr& y); - template - requires @\libconcept{three_way_comparable_with}@::pointer, - typename unique_ptr::pointer> - compare_three_way_result_t::pointer, - typename unique_ptr::pointer> - operator<=>(const unique_ptr& x, const unique_ptr& y); - - template - bool operator==(const unique_ptr& x, nullptr_t) noexcept; - template - bool operator<(const unique_ptr& x, nullptr_t); - template - bool operator<(nullptr_t, const unique_ptr& y); - template - bool operator>(const unique_ptr& x, nullptr_t); - template - bool operator>(nullptr_t, const unique_ptr& y); - template - bool operator<=(const unique_ptr& x, nullptr_t); - template - bool operator<=(nullptr_t, const unique_ptr& y); - template - bool operator>=(const unique_ptr& x, nullptr_t); - template - bool operator>=(nullptr_t, const unique_ptr& y); - template - requires @\libconcept{three_way_comparable}@::pointer> - compare_three_way_result_t::pointer> - operator<=>(const unique_ptr& x, nullptr_t); - - template - basic_ostream& operator<<(basic_ostream& os, const unique_ptr& p); - - // \ref{util.smartptr.weak.bad}, class \tcode{bad_weak_ptr} - class bad_weak_ptr; - - // \ref{util.smartptr.shared}, class template \tcode{shared_ptr} - template class shared_ptr; - - // \ref{util.smartptr.shared.create}, \tcode{shared_ptr} creation - template - shared_ptr make_shared(Args&&... args); // \tcode{T} is not array - template - shared_ptr allocate_shared(const A& a, Args&&... args); // \tcode{T} is not array - - template - shared_ptr make_shared(size_t N); // \tcode{T} is \tcode{U[]} - template - shared_ptr allocate_shared(const A& a, size_t N); // \tcode{T} is \tcode{U[]} - - template - shared_ptr make_shared(); // \tcode{T} is \tcode{U[N]} - template - shared_ptr allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]} - - template - shared_ptr make_shared(size_t N, const remove_extent_t& u); // \tcode{T} is \tcode{U[]} - template - shared_ptr allocate_shared(const A& a, size_t N, - const remove_extent_t& u); // \tcode{T} is \tcode{U[]} - - template - shared_ptr make_shared(const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} - template - shared_ptr allocate_shared(const A& a, const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} - - template - shared_ptr make_shared_for_overwrite(); // \tcode{T} is not \tcode{U[]} - template - shared_ptr allocate_shared_for_overwrite(const A& a); // \tcode{T} is not \tcode{U[]} - - template - shared_ptr make_shared_for_overwrite(size_t N); // \tcode{T} is \tcode{U[]} - template - shared_ptr allocate_shared_for_overwrite(const A& a, size_t N); // \tcode{T} is \tcode{U[]} - - // \ref{util.smartptr.shared.cmp}, \tcode{shared_ptr} comparisons - template - bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; - template - strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; - - template - bool operator==(const shared_ptr& x, nullptr_t) noexcept; - template - strong_ordering operator<=>(const shared_ptr& x, nullptr_t) noexcept; - - // \ref{util.smartptr.shared.spec}, \tcode{shared_ptr} specialized algorithms - template - void swap(shared_ptr& a, shared_ptr& b) noexcept; - - // \ref{util.smartptr.shared.cast}, \tcode{shared_ptr} casts - template - shared_ptr static_pointer_cast(const shared_ptr& r) noexcept; - template - shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; - template - shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; - template - shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; - template - shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; - template - shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; - template - shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept; - template - shared_ptr reinterpret_pointer_cast(shared_ptr&& r) noexcept; - - // \ref{util.smartptr.getdeleter}, \tcode{shared_ptr} \tcode{get_deleter} - template - D* get_deleter(const shared_ptr& p) noexcept; - - // \ref{util.smartptr.shared.io}, \tcode{shared_ptr} I/O - template - basic_ostream& operator<<(basic_ostream& os, const shared_ptr& p); - - // \ref{util.smartptr.weak}, class template \tcode{weak_ptr} - template class weak_ptr; - - // \ref{util.smartptr.weak.spec}, \tcode{weak_ptr} specialized algorithms - template void swap(weak_ptr& a, weak_ptr& b) noexcept; - - // \ref{util.smartptr.ownerless}, class template \tcode{owner_less} - template struct owner_less; - - // \ref{util.smartptr.enab}, class template \tcode{enable_shared_from_this} - template class enable_shared_from_this; - - // \ref{util.smartptr.hash}, hash support - template struct hash; - template struct hash>; - template struct hash>; - - // \ref{util.smartptr.atomic}, atomic smart pointers - template struct atomic; - template struct atomic>; - template struct atomic>; - - // \ref{out.ptr.t}, class template \tcode{out_ptr_t} - template - class out_ptr_t; - - // \ref{out.ptr}, function template \tcode{out_ptr} - template - auto out_ptr(Smart& s, Args&&... args); - - // \ref{inout.ptr.t}, class template \tcode{inout_ptr_t} - template - class inout_ptr_t; - - // \ref{inout.ptr}, function template \tcode{inout_ptr} - template - auto inout_ptr(Smart& s, Args&&... args); -} -\end{codeblock} - -\rSec2[pointer.traits]{Pointer traits} - -\rSec3[pointer.traits.general]{General} +\indexlibrarymember{operator*}{expected}% +\begin{itemdecl} +constexpr T&& operator*() && noexcept; +constexpr const T&& operator*() const && noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -The class template \tcode{pointer_traits} supplies a uniform interface to certain -attributes of pointer-like types. - -\indexlibraryglobal{pointer_traits}% -\begin{codeblock} -namespace std { - template struct pointer_traits { - using pointer = Ptr; - using element_type = @\seebelow@; - using difference_type = @\seebelow@; - - template using rebind = @\seebelow@; - - static pointer pointer_to(@\seebelow@ r); - }; - - template struct pointer_traits { - using pointer = T*; - using element_type = T; - using difference_type = ptrdiff_t; - - template using rebind = U*; - - static constexpr pointer pointer_to(@\seebelow@ r) noexcept; - }; -} -\end{codeblock} +\expects +\tcode{has_value()} is \tcode{true}. -\rSec3[pointer.traits.types]{Member types} +\pnum +\returns +\tcode{std::move(\exposid{val})}. +\end{itemdescr} -\indexlibrarymember{element_type}{pointer_traits}% +\indexlibrarymember{operator bool}{expected}% +\indexlibrarymember{has_value}{expected}% \begin{itemdecl} -using element_type = @\seebelow@; +constexpr explicit operator bool() const noexcept; +constexpr bool has_value() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ctype \tcode{Ptr::element_type} if -the \grammarterm{qualified-id} \tcode{Ptr::element_type} is valid and denotes a -type\iref{temp.deduct}; otherwise, \tcode{T} if -\tcode{Ptr} is a class template instantiation of the form \tcode{SomePointer}, -where \tcode{Args} is zero or more type arguments; otherwise, the specialization is -ill-formed. +\returns +\exposid{has_val}. \end{itemdescr} -\indexlibrarymember{difference_type}{pointer_traits}% +\indexlibrarymember{value}{expected}% \begin{itemdecl} -using difference_type = @\seebelow@; +constexpr const T& value() const &; +constexpr T& value() &; \end{itemdecl} \begin{itemdescr} \pnum -\ctype \tcode{Ptr::difference_type} if -the \grammarterm{qualified-id} \tcode{Ptr::difference_type} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{ptrdiff_t}. +\returns +\exposid{val}, if \tcode{has_value()} is \tcode{true}. + +\pnum +\throws +\tcode{bad_expected_access(error())} if \tcode{has_value()} is \tcode{false}. \end{itemdescr} -\indexlibrarymember{rebind}{pointer_traits}% +\indexlibrarymember{value}{expected}% \begin{itemdecl} -template using rebind = @\seebelow@; +constexpr T&& value() &&; +constexpr const T&& value() const &&; \end{itemdecl} \begin{itemdescr} \pnum -\templalias \tcode{Ptr::rebind} if -the \grammarterm{qualified-id} \tcode{Ptr::rebind} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{SomePointer} if -\tcode{Ptr} is a class template instantiation of the form \tcode{SomePointer}, -where \tcode{Args} is zero or more type arguments; otherwise, the instantiation of -\tcode{rebind} is ill-formed. -\end{itemdescr} +\returns +\tcode{std::move(\exposid{val})}, if \tcode{has_value()} is \tcode{true}. -\rSec3[pointer.traits.functions]{Member functions} +\pnum +\throws +\tcode{bad_expected_access(std::move(error()))} +if \tcode{has_value()} is \tcode{false}. +\end{itemdescr} -\indexlibrarymember{pointer_to}{pointer_traits}% +\indexlibrarymember{error}{expected}% \begin{itemdecl} -static pointer pointer_traits::pointer_to(@\seebelow@ r); -static constexpr pointer pointer_traits::pointer_to(@\seebelow@ r) noexcept; +constexpr const E& error() const & noexcept; +constexpr E& error() & noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\mandates -For the first member function, -\tcode{Ptr::pointer_to(r)} is well-formed. - \pnum \expects -For the first member function, -\tcode{Ptr::pointer_to(r)} returns a pointer to \tcode{r} -through which indirection is valid. +\tcode{has_value()} is \tcode{false}. \pnum \returns -The first member function returns \tcode{Ptr::pointer_to(r)}. -The second member function returns \tcode{addressof(r)}. - -\pnum -\remarks -If \tcode{element_type} is \cv{}~\keyword{void}, the type of -\tcode{r} is unspecified; otherwise, it is \tcode{element_type\&}. +\exposid{unex}. \end{itemdescr} -\rSec3[pointer.traits.optmem]{Optional members} - -\pnum -Specializations of \tcode{pointer_traits} may define the member declared -in this subclause to customize the behavior of the standard library. - -\indexlibrarymember{to_address}{pointer_traits}% +\indexlibrarymember{error}{expected}% \begin{itemdecl} -static element_type* to_address(pointer p) noexcept; +constexpr E&& error() && noexcept; +constexpr const E&& error() const && noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -A pointer of type \tcode{element_type*} that references -the same location as the argument \tcode{p}. +\expects +\tcode{has_value()} is \tcode{false}. \pnum -\begin{note} -This function is intended to be the inverse of \tcode{pointer_to}. -If defined, it customizes the behavior of -the non-member function -\tcode{to_address}\iref{pointer.conversion}. -\end{note} +\returns +\tcode{std::move(\exposid{unex})}. \end{itemdescr} -\rSec2[pointer.conversion]{Pointer conversion} - -\indexlibraryglobal{to_address}% +\indexlibrarymember{value_or}{expected}% \begin{itemdecl} -template constexpr T* to_address(T* p) noexcept; +template constexpr T value_or(U&& v) const &; \end{itemdecl} \begin{itemdescr} \pnum \mandates -\tcode{T} is not a function type. +\tcode{is_copy_constructible_v} is \tcode{true} and +\tcode{is_convertible_v} is \tcode{true}. \pnum \returns -\tcode{p}. +\tcode{has_value() ? **this : static_cast(std::forward(v))}. \end{itemdescr} -\indexlibraryglobal{to_address}% +\indexlibrarymember{value_or}{expected}% \begin{itemdecl} -template constexpr auto to_address(const Ptr& p) noexcept; +template constexpr T value_or(U&& v) &&; \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{is_move_constructible_v} is \tcode{true} and +\tcode{is_convertible_v} is \tcode{true}. + \pnum \returns -\tcode{pointer_traits::to_address(p)} if that expression is well-formed -(see \ref{pointer.traits.optmem}), -otherwise \tcode{to_address(p.operator->())}. +\tcode{has_value() ? std::move(**this) : static_cast(std::forward(v))}. \end{itemdescr} -\rSec2[ptr.align]{Pointer alignment} +\rSec3[expected.object.eq]{Equality operators} -\indexlibraryglobal{align}% +\indexlibrarymember{operator==}{expected}% \begin{itemdecl} -void* align(size_t alignment, size_t size, void*& ptr, size_t& space); +template requires (!is_void_v) + friend constexpr bool operator==(const expected& x, const expected& y); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\begin{itemize} -\item -\tcode{alignment} is a power of two - -\item -\tcode{ptr} represents the address of contiguous storage of at least -\tcode{space} bytes -\end{itemize} - -\pnum -\effects -If it is possible to fit \tcode{size} bytes -of storage aligned by \tcode{alignment} into the buffer pointed to by -\tcode{ptr} with length \tcode{space}, the function updates -\tcode{ptr} to represent the first possible address of such storage -and decreases \tcode{space} by the number of bytes used for alignment. -Otherwise, the function does nothing. +\mandates +The expressions \tcode{*x == *y} and \tcode{x.error() == y.error()} +are well-formed and their results are convertible to \tcode{bool}. \pnum \returns -A null pointer if the requested aligned buffer -would not fit into the available space, otherwise the adjusted value -of \tcode{ptr}. +If \tcode{x.has_value()} does not equal \tcode{y.has_value()}, \tcode{false}; +otherwise if \tcode{x.has_value()} is \tcode{true}, \tcode{*x == *y}; +otherwise \tcode{x.error() == y.error()}. +\end{itemdescr} + +\indexlibrarymember{operator==}{expected}% +\begin{itemdecl} +template friend constexpr bool operator==(const expected& x, const T2& v); +\end{itemdecl} +\begin{itemdescr} \pnum +\mandates +The expression \tcode{*x == v} is well-formed and +its result is convertible to \tcode{bool}. \begin{note} -The function updates its \tcode{ptr} -and \tcode{space} arguments so that it can be called repeatedly -with possibly different \tcode{alignment} and \tcode{size} -arguments for the same buffer. +\tcode{T1} need not be \oldconcept{EqualityComparable}. \end{note} + +\pnum +\returns +\tcode{x.has_value() \&\& static_cast(*x == v)}. \end{itemdescr} -\indexlibraryglobal{assume_aligned}% +\indexlibrarymember{operator==}{expected}% \begin{itemdecl} -template - [[nodiscard]] constexpr T* assume_aligned(T* ptr); +template friend constexpr bool operator==(const expected& x, const unexpected& e); \end{itemdecl} \begin{itemdescr} \pnum \mandates -\tcode{N} is a power of two. - -\pnum -\expects -\tcode{ptr} points to an object \tcode{X} of -a type similar\iref{conv.qual} to \tcode{T}, -where \tcode{X} has alignment \tcode{N}\iref{basic.align}. +The expression \tcode{x.error() == e.value()} is well-formed and +its result is convertible to \tcode{bool}. \pnum \returns -\tcode{ptr}. +\tcode{!x.has_value() \&\& static_cast(x.error() == e.value())}. +\end{itemdescr} -\pnum -\throws -Nothing. +\rSec2[expected.void]{Partial specialization of \tcode{expected} for \tcode{void} types} + +\rSec3[expected.void.general]{General} + +\begin{codeblock} +template requires is_void_v +class expected { +public: + using @\libmember{value_type}{expected}@ = T; + using @\libmember{error_type}{expected}@ = E; + using @\libmember{unexpected_type}{expected}@ = unexpected; + + template + using @\libmember{rebind}{expected}@ = expected; + + // \ref{expected.void.ctor}, constructors + constexpr expected() noexcept; + constexpr explicit(@\seebelow@) expected(const expected&); + constexpr explicit(@\seebelow@) expected(expected&&) noexcept(@\seebelow@); + template + constexpr explicit(@\seebelow@) expected(const expected&); + template + constexpr explicit(@\seebelow@) expected(expected&&); + + template + constexpr expected(const unexpected&); + template + constexpr expected(unexpected&&); + + constexpr explicit expected(in_place_t) noexcept; + template + constexpr explicit expected(unexpect_t, Args&&...); + template + constexpr explicit expected(unexpect_t, initializer_list, Args&&...); + + + // \ref{expected.void.dtor}, destructor + constexpr ~expected(); + + // \ref{expected.void.assign}, assignment + constexpr expected& operator=(const expected&); + constexpr expected& operator=(expected&&) noexcept(@\seebelow@); + template + constexpr expected& operator=(const unexpected&); + template + constexpr expected& operator=(unexpected&&); + constexpr void emplace() noexcept; + + // \ref{expected.void.swap}, swap + constexpr void swap(expected&) noexcept(@\seebelow@); + friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); + + // \ref{expected.void.obs}, observers + constexpr explicit operator bool() const noexcept; + constexpr bool has_value() const noexcept; + constexpr void operator*() const noexcept; + constexpr void value() const &; + constexpr void value() &&; + constexpr const E& error() const &; + constexpr E& error() &; + constexpr const E&& error() const &&; + constexpr E&& error() &&; + + // \ref{expected.void.eq}, equality operators + template requires is_void_v + friend constexpr bool operator==(const expected& x, const expected& y); + template + friend constexpr bool operator==(const expected&, const unexpected&); + +private: + bool @\exposid{has_val}@; // \expos + union { + E @\exposid{unex}@; // \expos + }; +}; +\end{codeblock} \pnum -\begin{note} -The alignment assumption on an object \tcode{X} -expressed by a call to \tcode{assume_aligned} -might result in generation of more efficient code. -It is up to the program to ensure that the assumption actually holds. -The call does not cause the compiler to verify or enforce this. -An implementation might only make the assumption -for those operations on \tcode{X} that access \tcode{X} -through the pointer returned by \tcode{assume_aligned}. -\end{note} -\end{itemdescr} +\tcode{E} shall meet the requirements of +\oldconcept{Destructible} (\tref{cpp17.destructible}). -\rSec2[allocator.tag]{Allocator argument tag} +\rSec3[expected.void.ctor]{Constructors} -\indexlibraryglobal{allocator_arg_t}% -\indexlibraryglobal{allocator_arg}% +\indexlibraryctor{expected}% \begin{itemdecl} -namespace std { - struct allocator_arg_t { explicit allocator_arg_t() = default; }; - inline constexpr allocator_arg_t allocator_arg{}; -} +constexpr expected() noexcept; \end{itemdecl} +\begin{itemdescr} \pnum -The \tcode{allocator_arg_t} struct is an empty class type used as a unique type to -disambiguate constructor and function overloading. Specifically, several types (see -\tcode{tuple}~\ref{tuple}) have constructors with \tcode{allocator_arg_t} as the first -argument, immediately followed by an argument of a type that meets the -\oldconcept{Allocator} requirements (\tref{cpp17.allocator}). - -\rSec2[allocator.uses]{\tcode{uses_allocator}} - -\rSec3[allocator.uses.trait]{\tcode{uses_allocator} trait} +\ensures +\tcode{has_value()} is \tcode{true}. +\end{itemdescr} -\indexlibraryglobal{uses_allocator}% +\indexlibraryctor{expected}% \begin{itemdecl} -template struct uses_allocator; +constexpr expected(const expected& rhs); \end{itemdecl} \begin{itemdescr} +\pnum +\effects +If \tcode{rhs.has_value()} is \tcode{false}, +direct-non-list-initializes \exposid{unex} with \tcode{rhs.error()}. + +\pnum +\ensures +\tcode{rhs.has_value() == this->has_value()}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. + \pnum \remarks -Automatically detects whether \tcode{T} has a nested \tcode{allocator_type} that -is convertible from \tcode{Alloc}. Meets the \oldconcept{BinaryTypeTrait} -requirements\iref{meta.rqmts}. The implementation shall provide a definition that is -derived from \tcode{true_type} if the \grammarterm{qualified-id} \tcode{T::allocator_type} -is valid and denotes a type\iref{temp.deduct} and -\tcode{is_convertible_v != false}, otherwise it shall be -derived from \tcode{false_type}. A program may specialize this template to derive from -\tcode{true_type} for a program-defined type \tcode{T} that does not have a nested -\tcode{allocator_type} but nonetheless can be constructed with an allocator where -either: -\begin{itemize} -\item the first argument of a constructor has type \tcode{allocator_arg_t} and the -second argument has type \tcode{Alloc} or +This constructor is defined as deleted +unless \tcode{is_copy_constructible_v} is \tcode{true}. -\item the last argument of a constructor has type \tcode{Alloc}. -\end{itemize} +\pnum +This constructor is trivial +if \tcode{is_trivially_copy_constructible_v} is \tcode{true}. \end{itemdescr} -\rSec3[allocator.uses.construction]{Uses-allocator construction} +\indexlibraryctor{expected}% +\begin{itemdecl} +constexpr expected(expected&& rhs) noexcept(is_nothrow_move_constructible_v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_move_constructible_v} is \tcode{true}. + +\pnum +\effects +If \tcode{rhs.has_value()} is \tcode{false}, +direct-non-list-initializes \exposid{unex} with \tcode{std::move(rhs.error())}. \pnum -\defnx{Uses-allocator construction}{uses-allocator construction} -with allocator \tcode{alloc} and constructor arguments \tcode{args...} -refers to the construction of an object of type \tcode{T} -such that \tcode{alloc} is passed to the constructor of \tcode{T} -if \tcode{T} uses an allocator type compatible with \tcode{alloc}. -When applied to the construction of an object of type \tcode{T}, -it is equivalent to initializing it with the value of the expression -\tcode{make_obj_using_allocator(alloc, args...)}, described below. +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. \pnum -The following utility functions support -three conventions for passing \tcode{alloc} to a constructor: -\begin{itemize} -\item - If \tcode{T} does not use an allocator compatible with \tcode{alloc}, - then \tcode{alloc} is ignored. -\item - Otherwise, if \tcode{T} has a constructor invocable as - \tcode{T(allocator_arg, alloc, args...)} (leading-allocator convention), - then uses-allocator construction chooses this constructor form. -\item - Otherwise, if \tcode{T} has a constructor invocable as - \tcode{T(args..., alloc)} (trailing-allocator convention), - then uses-allocator construction chooses this constructor form. -\end{itemize} +\throws +Any exception thrown by the initialization of \exposid{unex}. \pnum -The \tcode{uses_allocator_construction_args} function template -takes an allocator and argument list and -produces (as a tuple) a new argument list matching one of the above conventions. -Additionally, overloads are provided -that treat specializations of \tcode{pair} -such that uses-allocator construction is applied individually -to the \tcode{first} and \tcode{second} data members. -The \tcode{make_obj_using_allocator} and -\tcode{uninitialized_construct_using_allocator} function templates -apply the modified constructor arguments -to construct an object of type \tcode{T} -as a return value or in-place, respectively. -\begin{note} -For \tcode{uses_allocator_construction_args} and -\tcode{make_obj_using_allocator}, type \tcode{T} -is not deduced and must therefore be specified explicitly by the caller. -\end{note} +\remarks +This constructor is trivial +if \tcode{is_trivially_move_constructible_v} is \tcode{true}. +\end{itemdescr} -\indexlibraryglobal{uses_allocator_construction_args}% +\indexlibraryctor{expected}% \begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - Args&&... args) noexcept; +template + constexpr explicit(!is_convertible_v) expected(const expected& rhs); +template + constexpr explicit(!is_convertible_v) expected(expected&& rhs); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{T} is not a specialization of \tcode{pair}. +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. \pnum -\returns -A \tcode{tuple} value determined as follows: +\constraints \begin{itemize} \item - If \tcode{uses_allocator_v} is \tcode{false} and - \tcode{is_constructible_v} is \tcode{true}, - return \tcode{forward_as_tuple(std::forward(args)...)}. +\tcode{is_void_v} is \tcode{true}; and \item - Otherwise, if \tcode{uses_allocator_v} is \tcode{true} and - \tcode{is_constructible_v} - is \tcode{true}, - return -\begin{codeblock} -tuple( - allocator_arg, alloc, std::forward(args)...) -\end{codeblock} +\tcode{is_constructible_v} is \tcode{true}; and +\item +\tcode{is_constructible_v, expected\&>} +is \tcode{false}; and \item - Otherwise, if \tcode{uses_allocator_v} is \tcode{true} and - \tcode{is_constructible_v} is \tcode{true}, - return \tcode{forward_as_tuple(std::forward(args)..., alloc)}. +\tcode{is_constructible_v, expected>} +is \tcode{false}; and \item - Otherwise, the program is ill-formed. +\tcode{is_constructible_v, const expected\&>} +is \tcode{false}; and +\item +\tcode{is_constructible_v, const expected>} +is \tcode{false}. \end{itemize} -\begin{note} -This definition prevents a silent failure -to pass the allocator to a constructor of a type for which -\tcode{uses_allocator_v} is \tcode{true}. -\end{note} -\end{itemdescr} -\indexlibraryglobal{uses_allocator_construction_args}% -\begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, - Tuple1&& x, Tuple2&& y) noexcept; -\end{itemdecl} +\pnum +\effects +If \tcode{rhs.has_value()} is \tcode{false}, +direct-non-list-initializes \exposid{unex} +with \tcode{std::forward(rhs.er\-ror())}. -\begin{itemdescr} \pnum -\constraints -\tcode{T} is a specialization of \tcode{pair}. +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. \pnum -\effects -For \tcode{T} specified as \tcode{pair}, equivalent to: -\begin{codeblock} -return make_tuple( - piecewise_construct, - apply([&alloc](auto&&... args1) { - return uses_allocator_construction_args( - alloc, std::forward(args1)...); - }, std::forward(x)), - apply([&alloc](auto&&... args2) { - return uses_allocator_construction_args( - alloc, std::forward(args2)...); - }, std::forward(y))); -\end{codeblock} +\throws +Any exception thrown by the initialization of \exposid{unex}. \end{itemdescr} -\indexlibraryglobal{uses_allocator_construction_args}% +\indexlibraryctor{expected}% \begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept; +template + constexpr explicit(!is_convertible_v) expected(const unexpected& e); +template + constexpr explicit(!is_convertible_v) expected(unexpected&& e); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. + \pnum \constraints -\tcode{T} is a specialization of \tcode{pair}. +\tcode{is_constructible_v} is \tcode{true}. \pnum \effects -Equivalent to: -\begin{codeblock} -return uses_allocator_construction_args(alloc, piecewise_construct, - tuple<>{}, tuple<>{}); -\end{codeblock} +Direct-non-list-initializes \exposid{unex} +with \tcode{std::forward(e.value())}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. \end{itemdescr} -\indexlibraryglobal{uses_allocator_construction_args}% +\indexlibraryctor{expected}% \begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - U&& u, V&& v) noexcept; +constexpr explicit expected(in_place_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{T} is a specialization of \tcode{pair}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return uses_allocator_construction_args(alloc, piecewise_construct, - forward_as_tuple(std::forward(u)), - forward_as_tuple(std::forward(v))); -\end{codeblock} +\ensures +\tcode{has_value()} is \tcode{true}. \end{itemdescr} -\indexlibraryglobal{uses_allocator_construction_args}% +\indexlibraryctor{expected}% \begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - pair& pr) noexcept; -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - const pair& pr) noexcept; +template + constexpr explicit expected(unexpect_t, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{T} is a specialization of \tcode{pair}. +\tcode{is_constructible_v} is \tcode{true}. \pnum \effects -Equivalent to: -\begin{codeblock} -return uses_allocator_construction_args(alloc, piecewise_construct, - forward_as_tuple(pr.first), - forward_as_tuple(pr.second)); -\end{codeblock} -\end{itemdescr} +Direct-non-list-initializes \exposid{unex} +with \tcode{std::forward(args)...}. -\indexlibraryglobal{uses_allocator_construction_args}% -\begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - pair&& pr) noexcept; -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - const pair&& pr) noexcept; -\end{itemdecl} - -\begin{itemdescr} \pnum -\constraints -\tcode{T} is a specialization of \tcode{pair}. +\ensures +\tcode{has_value()} is \tcode{false}. \pnum -\effects -Equivalent to: -\begin{codeblock} -return uses_allocator_construction_args(alloc, piecewise_construct, - forward_as_tuple(get<0>(std::move(pr))), - forward_as_tuple(get<1>(std::move(pr)))); -\end{codeblock} +\throws +Any exception thrown by the initialization of \exposid{unex}. \end{itemdescr} -\indexlibraryglobal{make_obj_using_allocator}% +\indexlibraryctor{expected}% \begin{itemdecl} -template - constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); +template + constexpr explicit expected(unexpect_t, initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return make_from_tuple(uses_allocator_construction_args( - alloc, std::forward(args)...)); -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{uninitialized_construct_using_allocator}% -\begin{itemdecl} -template - constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args); -\end{itemdecl} +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. -\begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return apply([&](U&&... xs) { - return construct_at(p, std::forward(xs)...); - }, uses_allocator_construction_args(alloc, std::forward(args)...)); -\end{codeblock} -\end{itemdescr} - -\rSec2[allocator.traits]{Allocator traits} - -\rSec3[allocator.traits.general]{General} +Direct-non-list-initializes \exposid{unex} +with \tcode{il, std::forward(args)...}. \pnum -The class template \tcode{allocator_traits} supplies a uniform interface to all -allocator types. -An allocator cannot be a non-class type, however, even if \tcode{allocator_traits} -supplies the entire required interface. -\begin{note} -Thus, it is always possible to create -a derived class from an allocator. -\end{note} - -\indexlibraryglobal{allocator_traits}% -\begin{codeblock} -namespace std { - template struct allocator_traits { - using allocator_type = Alloc; - - using value_type = typename Alloc::value_type; - - using pointer = @\seebelow@; - using const_pointer = @\seebelow@; - using void_pointer = @\seebelow@; - using const_void_pointer = @\seebelow@; - - using difference_type = @\seebelow@; - using size_type = @\seebelow@; - - using propagate_on_container_copy_assignment = @\seebelow@; - using propagate_on_container_move_assignment = @\seebelow@; - using propagate_on_container_swap = @\seebelow@; - using is_always_equal = @\seebelow@; - - template using rebind_alloc = @\seebelow@; - template using rebind_traits = allocator_traits>; - - [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n); - [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n, - const_void_pointer hint); - - static constexpr void deallocate(Alloc& a, pointer p, size_type n); - - template - static constexpr void construct(Alloc& a, T* p, Args&&... args); - - template - static constexpr void destroy(Alloc& a, T* p); - - static constexpr size_type max_size(const Alloc& a) noexcept; +\ensures +\tcode{has_value()} is \tcode{false}. - static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs); - }; -} -\end{codeblock} +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} -\rSec3[allocator.traits.types]{Member types} +\rSec3[expected.void.dtor]{Destructor} -\indexlibrarymember{pointer}{allocator_traits}% +\indexlibrarydtor{expected}% \begin{itemdecl} -using pointer = @\seebelow@; +constexpr ~expected(); \end{itemdecl} \begin{itemdescr} \pnum -\ctype \tcode{Alloc::pointer} if -the \grammarterm{qualified-id} \tcode{Alloc::pointer} is valid and denotes a -type\iref{temp.deduct}; otherwise, \tcode{value_type*}. -\end{itemdescr} - -\indexlibrarymember{const_pointer}{allocator_traits}% -\begin{itemdecl} -using const_pointer = @\seebelow@; -\end{itemdecl} +\effects +If \tcode{has_value()} is \tcode{false}, destroys \exposid{unex}. -\begin{itemdescr} \pnum -\ctype \tcode{Alloc::const_pointer} if -the \grammarterm{qualified-id} \tcode{Alloc::const_pointer} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{pointer_traits::rebind<\brk{}const value_type>}. +\remarks +If \tcode{is_trivially_destructible_v} is \tcode{true}, +then this destructor is a trivial destructor. \end{itemdescr} -\indexlibrarymember{void_pointer}{allocator_traits}% +\rSec3[expected.void.assign]{Assignment} + +\indexlibrarymember{operator=}{expected}% \begin{itemdecl} -using void_pointer = @\seebelow@; +constexpr expected& operator=(const expected& rhs); \end{itemdecl} \begin{itemdescr} \pnum -\ctype \tcode{Alloc::void_pointer} if -the \grammarterm{qualified-id} \tcode{Alloc::void_pointer} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{pointer_traits::rebind<\brk{}void>}. -\end{itemdescr} +\effects +\begin{itemize} +\item +If \tcode{this->has_value() \&\& rhs.has_value()} is \tcode{true}, no effects. +\item +Otherwise, if \tcode{this->has_value()} is \tcode{true}, +equivalent to: \tcode{construct_at(addressof(\exposid{unex}), rhs.\exposid{unex}); \exposid{has_val} = false;} +\item +Otherwise, if \tcode{rhs.has_value()} is \tcode{true}, +destroys \exposid{unex} and sets \exposid{has_val} to \tcode{true}. +\item +Otherwise, equivalent to \tcode{\exposid{unex} = rhs.error()}. +\end{itemize} -\indexlibrarymember{const_void_pointer}{allocator_traits}% -\begin{itemdecl} -using const_void_pointer = @\seebelow@; -\end{itemdecl} +\pnum +\returns +\tcode{*this}. -\begin{itemdescr} \pnum -\ctype \tcode{Alloc::const_void_pointer} if -the \grammarterm{qualified-id} \tcode{Alloc::const_void_pointer} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{pointer_traits::\brk{}rebind}. +\remarks +This operator is defined as deleted unless +\tcode{is_copy_assignable_v} is \tcode{true} and +\tcode{is_copy_constructible_v} is \tcode{true}. \end{itemdescr} -\indexlibrarymember{difference_type}{allocator_traits}% +\indexlibrarymember{operator=}{expected}% \begin{itemdecl} -using difference_type = @\seebelow@; +constexpr expected& operator=(expected&& rhs) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\ctype \tcode{Alloc::difference_type} if -the \grammarterm{qualified-id} \tcode{Alloc::difference_type} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{pointer_traits::dif\-ference_type}. -\end{itemdescr} - -\indexlibrarymember{size_type}{allocator_traits}% -\begin{itemdecl} -using size_type = @\seebelow@; -\end{itemdecl} +\effects +\begin{itemize} +\item +If \tcode{this->has_value() \&\& rhs.has_value()} is \tcode{true}, no effects. +\item +Otherwise, if \tcode{this->has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +construct_at(addressof(@\exposid{unex}@), std::move(rhs.@\exposid{unex}@)); +@\exposid{has_val}@ = false; +\end{codeblock} +\item +Otherwise, if \tcode{rhs.has_value()} is \tcode{true}, +destroys \exposid{unex} and sets \exposid{has_val} to \tcode{true}. +\item +Otherwise, equivalent to \tcode{\exposid{unex} = rhs.error()}. +\end{itemize} -\begin{itemdescr} \pnum -\ctype \tcode{Alloc::size_type} if -the \grammarterm{qualified-id} \tcode{Alloc::size_type} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{make_unsigned_t}. -\end{itemdescr} +\returns +\tcode{*this}. -\indexlibrarymember{propagate_on_container_copy_assignment}{allocator_traits}% -\begin{itemdecl} -using propagate_on_container_copy_assignment = @\seebelow@; -\end{itemdecl} +\pnum +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_move_constructible_v \&\& is_nothrow_move_assignable_v}. -\begin{itemdescr} \pnum -\ctype \tcode{Alloc::propagate_on_container_copy_assignment} if -the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_copy_assignment} is valid and denotes a -type\iref{temp.deduct}; otherwise -\tcode{false_type}. +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{propagate_on_container_move_assignment}{allocator_traits}% +\indexlibrarymember{operator=}{expected}% \begin{itemdecl} -using propagate_on_container_move_assignment = @\seebelow@; +template + constexpr expected& operator=(const unexpected& e); +template + constexpr expected& operator=(unexpected&& e); \end{itemdecl} \begin{itemdescr} \pnum -\ctype \tcode{Alloc::propagate_on_container_move_assignment} if -the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_move_assignment} is valid and denotes a -type\iref{temp.deduct}; otherwise -\tcode{false_type}. -\end{itemdescr} +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. -\indexlibrarymember{propagate_on_container_swap}{allocator_traits}% -\begin{itemdecl} -using propagate_on_container_swap = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} \pnum -\ctype \tcode{Alloc::propagate_on_container_swap} if -the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_swap} is valid and denotes a -type\iref{temp.deduct}; otherwise -\tcode{false_type}. -\end{itemdescr} +\constraints +\tcode{is_constructible_v} is \tcode{true} and +\tcode{is_assignable_v} is \tcode{true}. -\indexlibrarymember{is_always_equal}{allocator_traits}% -\begin{itemdecl} -using is_always_equal = @\seebelow@; -\end{itemdecl} +\pnum +\effects +\begin{itemize} +\item +If \tcode{has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +construct_at(addressof(@\exposid{unex}@), std::forward(e.value())); +@\exposid{has_val}@ = false; +\end{codeblock} +\item +Otherwise, equivalent to: +\tcode{\exposid{unex} = std::forward(e.value());} +\end{itemize} -\begin{itemdescr} \pnum -\ctype \tcode{Alloc::is_always_equal} if -the \grammarterm{qualified-id} \tcode{Alloc::is_always_equal} -is valid and denotes a type\iref{temp.deduct}; -otherwise \tcode{is_empty::type}. +\returns +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{rebind_alloc}{allocator_traits}% +\indexlibrarymember{emplace}{expected}% \begin{itemdecl} -template using rebind_alloc = @\seebelow@; +constexpr void emplace() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\templalias \tcode{Alloc::rebind::other} if -the \grammarterm{qualified-id} \tcode{Alloc::rebind::other} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{Alloc} if \tcode{Alloc} is a class template instantiation -of the form \tcode{Alloc}, where \tcode{Args} is zero or more type arguments; -otherwise, the instantiation of \tcode{rebind_alloc} is ill-formed. +\effects +If \tcode{has_value()} is \tcode{false}, +destroys \exposid{unex} and sets \exposid{has_val} to \tcode{true}. \end{itemdescr} -\rSec3[allocator.traits.members]{Static member functions} +\rSec3[expected.void.swap]{Swap} -\indexlibrarymember{allocate}{allocator_traits}% +\indexlibrarymember{swap}{expected}% \begin{itemdecl} -[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n); +constexpr void swap(expected& rhs) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{a.allocate(n)}. -\end{itemdescr} - -\indexlibrarymember{allocate}{allocator_traits}% -\begin{itemdecl} -[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint); -\end{itemdecl} +\constraints +\tcode{is_swappable_v} is \tcode{true} and +\tcode{is_move_constructible_v} is \tcode{true}. -\begin{itemdescr} \pnum -\returns -\tcode{a.allocate(n, hint)} if that expression is well-formed; otherwise, \tcode{a.allocate(n)}. -\end{itemdescr} +\effects +See \tref{expected.void.swap}. -\indexlibrarymember{deallocate}{allocator_traits}% -\begin{itemdecl} -static constexpr void deallocate(Alloc& a, pointer p, size_type n); -\end{itemdecl} +\begin{floattable}{\tcode{swap(expected\&)} effects}{expected.void.swap} +{lx{0.35\hsize}x{0.35\hsize}} +\topline +& \chdr{\tcode{this->has_value()}} & \rhdr{\tcode{!this->has_value()}} \\ \capsep +\lhdr{\tcode{rhs.has_value()}} & + no effects & + calls \tcode{rhs.swap(*this)} \\ +\lhdr{\tcode{!rhs.has_value()}} & + \seebelow & + equivalent to: \tcode{using std::swap; swap(\exposid{unex}, rhs.\exposid{unex});} \\ +\end{floattable} -\begin{itemdescr} -\pnum -\effects -Calls \tcode{a.deallocate(p, n)}. +For the case where \tcode{rhs.value()} is \tcode{false} and +\tcode{this->has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +construct_at(addressof(@\exposid{unex}@), std::move(rhs.@\exposid{unex}@)); +destroy_at(addressof(rhs.@\exposid{unex}@)); +@\exposid{has_val}@ = false; +rhs.@\exposid{has_val}@ = true; +\end{codeblock} \pnum \throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{construct}{allocator_traits}% -\begin{itemdecl} -template - static constexpr void construct(Alloc& a, T* p, Args&&... args); -\end{itemdecl} +Any exception thrown by the expressions in the \Fundescx{Effects}. -\begin{itemdescr} \pnum -\effects -Calls \tcode{a.construct(p, std::forward(args)...)} -if that call is well-formed; -otherwise, invokes \tcode{construct_at(p, std::forward(args)...)}. +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_move_constructible_v \&\& is_nothrow_swappable_v}. \end{itemdescr} -\indexlibrarymember{destroy}{allocator_traits}% +\indexlibrarymember{swap}{expected}% \begin{itemdecl} -template - static constexpr void destroy(Alloc& a, T* p); +friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); \end{itemdecl} \begin{itemdescr} \pnum \effects -Calls \tcode{a.destroy(p)} if that call is well-formed; otherwise, invokes -\tcode{destroy_at(p)}. +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} -\indexlibrarymember{max_size}{allocator_traits}% -\begin{itemdecl} -static constexpr size_type max_size(const Alloc& a) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{a.max_size()} if that expression is well-formed; otherwise, -\tcode{numeric_limits::\brk{}max()/sizeof(value_type)}. -\end{itemdescr} +\rSec3[expected.void.obs]{Observers} -\indexlibrarymember{select_on_container_copy_construction}{allocator_traits}% +\indexlibrarymember{operator bool}{expected}% +\indexlibrarymember{has_value}{expected}% \begin{itemdecl} -static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs); +constexpr explicit operator bool() const noexcept; +constexpr bool has_value() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{rhs.select_on_container_copy_construction()} if that expression is -well-formed; otherwise, \tcode{rhs}. +\exposid{has_val}. \end{itemdescr} -\rSec3[allocator.traits.other]{Other} - -\pnum -The class template \tcode{allocation_result} has -the template parameters, data members, and special members specified above. -It has no base classes or members other than those specified. - +\indexlibrarymember{operator*}{expected}% \begin{itemdecl} -template -[[nodiscard]] constexpr allocation_result::pointer> - allocate_at_least(Allocator& a, size_t n); +constexpr void operator*() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{a.allocate_at_least(n)} if that expression is well-formed; -otherwise, \tcode{\{a.allocate(n), n\}}. +\expects +\tcode{has_value()} is \tcode{true}. \end{itemdescr} -\rSec2[default.allocator]{The default allocator} - -\rSec3[default.allocator.general]{General} - -\pnum -All specializations of the default allocator meet the -allocator completeness requirements\iref{allocator.requirements.completeness}. - -\indexlibraryglobal{allocator}% -\indexlibrarymember{value_type}{allocator}% -\indexlibrarymember{size_type}{allocator}% -\indexlibrarymember{difference_type}{allocator}% -\indexlibrarymember{propagate_on_container_move_assignment}{allocator}% -\indexlibrarymember{is_always_equal}{allocator}% -\indexlibrarymember{operator=}{allocator}% -\begin{codeblock} -namespace std { - template class allocator { - public: - using value_type = T; - using size_type = size_t; - using difference_type = ptrdiff_t; - using propagate_on_container_move_assignment = true_type; - - constexpr allocator() noexcept; - constexpr allocator(const allocator&) noexcept; - template constexpr allocator(const allocator&) noexcept; - constexpr ~allocator(); - constexpr allocator& operator=(const allocator&) = default; - - [[nodiscard]] constexpr T* allocate(size_t n); - [[nodiscard]] constexpr allocation_result allocate_at_least(size_t n); - constexpr void deallocate(T* p, size_t n); - }; -} -\end{codeblock} - -\pnum -\tcode{allocator_traits>::is_always_equal::value} -is \tcode{true} for any \tcode{T}. - -\rSec3[allocator.members]{Members} - -\pnum -Except for the destructor, member functions of the default allocator shall not introduce -data races\iref{intro.multithread} as a result of concurrent calls to those member -functions from different threads. Calls to these functions that allocate or deallocate a -particular unit of storage shall occur in a single total order, and each such -deallocation call shall happen before the next allocation (if any) in this order. - -\indexlibrarymember{allocate}{allocator}% +\indexlibrarymember{value}{expected}% \begin{itemdecl} -[[nodiscard]] constexpr T* allocate(size_t n); +constexpr void value() const &; \end{itemdecl} \begin{itemdescr} -\pnum -\mandates -\tcode{T} is not an incomplete type\iref{basic.types}. - -\pnum -\returns -A pointer to the initial element of an array of \tcode{n} \tcode{T}. - \pnum \throws -\tcode{bad_array_new_length} if -\tcode{numeric_limits::max() / sizeof(T) < n}, or -\tcode{bad_alloc} if the storage cannot be obtained. - -\pnum -\remarks -The storage for the array -is obtained by calling \tcode{::operator new}\iref{new.delete}, -but it is unspecified when or how often this -function is called. -This function starts the lifetime of the array object, -but not that of any of the array elements. +\tcode{bad_expected_access(error())} if \tcode{has_value()} is \tcode{false}. \end{itemdescr} -\indexlibrarymember{allocate_at_least}{allocator}% +\indexlibrarymember{value}{expected}% \begin{itemdecl} -[[nodiscard]] constexpr allocation_result allocate_at_least(size_t n); +constexpr void value() &&; \end{itemdecl} \begin{itemdescr} -\pnum -\mandates -\tcode{T} is not an incomplete type\iref{basic.types}. - -\pnum -\returns -\tcode{allocation_result\{ptr, count\}}, -where \tcode{ptr} is a pointer to -the initial element of an array of \tcode{count} \tcode{T} and -$\tcode{count} \geq \tcode{n}$. - \pnum \throws -\tcode{bad_array_new_length} -if $\tcode{numeric_limits::max() / sizeof(T)} < \tcode{n}$, -or \tcode{bad_alloc} if the storage cannot be obtained. - -\pnum -\remarks -The storage for the array is obtained by calling \tcode{::operator new}, -but it is unspecified when or how often this function is called. -This function starts the lifetime of the array object, -but not that of any of the array elements. +\tcode{bad_expected_access(std::move(error()))} +if \tcode{has_value()} is \tcode{false}. \end{itemdescr} -\indexlibrarymember{deallocate}{allocator}% +\indexlibrarymember{error}{expected}% \begin{itemdecl} -constexpr void deallocate(T* p, size_t n); +constexpr const E& error() const &; +constexpr E& error() &; \end{itemdecl} \begin{itemdescr} \pnum \expects -\begin{itemize} -\item -If \tcode{p} is memory that was obtained by a call to \tcode{allocate_at_least}, -let \tcode{ret} be the value returned and -\tcode{req} be the value passed as the first argument to that call. -\tcode{p} is equal to \tcode{ret.ptr} and -\tcode{n} is a value such that $\tcode{req} \leq \tcode{n} \leq \tcode{ret.count}$. -\item -Otherwise, \tcode{p} is a pointer value obtained from \tcode{allocate}. -\tcode{n} equals the value passed as the first argument -to the invocation of \tcode{allocate} which returned \tcode{p}. -\end{itemize} - -\pnum -\effects -Deallocates the storage referenced by \tcode{p}. - -\pnum -\remarks -Uses -\tcode{::operator delete}\iref{new.delete}, -but it is unspecified -when this function is called. -\end{itemdescr} - -\rSec3[allocator.globals]{Operators} - -\indexlibrarymember{operator==}{allocator}% -\begin{itemdecl} -template - constexpr bool operator==(const allocator&, const allocator&) noexcept; -\end{itemdecl} +\tcode{has_value()} is \tcode{false}. -\begin{itemdescr} \pnum \returns -\tcode{true}. +\exposid{unex}. \end{itemdescr} -\rSec2[specialized.addressof]{\tcode{addressof}} - -\indexlibraryglobal{addressof}% +\indexlibrarymember{error}{expected}% \begin{itemdecl} -template constexpr T* addressof(T& r) noexcept; +constexpr E&& error() &&; +constexpr const E&& error() const &&; \end{itemdecl} \begin{itemdescr} \pnum -\returns -The actual address of the object or function referenced by \tcode{r}, even in the -presence of an overloaded \tcode{operator\&}. +\expects +\tcode{has_value()} is \tcode{false}. \pnum -\remarks -An expression \tcode{addressof(E)} -is a constant subexpression\iref{defns.const.subexpr} -if \tcode{E} is an lvalue constant subexpression. +\returns +\tcode{std::move(\exposid{unex})}. \end{itemdescr} -\rSec2[c.malloc]{C library memory allocation} - -\pnum -\begin{note} -The header \libheaderref{cstdlib} -declares the functions described in this subclause. -\end{note} +\rSec3[expected.void.eq]{Equality operators} -\indexlibraryglobal{aligned_alloc}% -\indexlibraryglobal{calloc}% -\indexlibraryglobal{malloc}% -\indexlibraryglobal{realloc}% +\indexlibrarymember{operator==}{expected}% \begin{itemdecl} -void* aligned_alloc(size_t alignment, size_t size); -void* calloc(size_t nmemb, size_t size); -void* malloc(size_t size); -void* realloc(void* ptr, size_t size); +template requires is_void_v + friend constexpr bool operator==(const expected& x, const expected& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -These functions have the semantics specified in the C standard library. - -\pnum -\remarks -These functions do not attempt to allocate -storage by calling \tcode{::operator new()}\iref{new.delete}. -\indexlibrarymember{new}{operator}% +\mandates +The expression \tcode{x.error() == y.error()} is well-formed and +its result is convertible to \tcode{bool}. \pnum -These functions implicitly create objects\iref{intro.object} -in the returned region of storage and -return a pointer to a suitable created object. -In the case of \tcode{calloc} and \tcode{realloc}, -the objects are created before the storage is zeroed or copied, respectively. +\returns +If \tcode{x.has_value()} does not equal \tcode{y.has_value()}, \tcode{false}; +otherwise \tcode{x.has_value() || static_cast(x.error() == y.error())}. \end{itemdescr} -\indexlibraryglobal{free}% +\indexlibrarymember{operator==}{expected}% \begin{itemdecl} -void free(void* ptr); +template + friend constexpr bool operator==(const expected& x, const unexpected& e); \end{itemdecl} \begin{itemdescr} \pnum -\effects -This function has the semantics specified in the C standard library. +\mandates +The expression \tcode{x.error() == e.value()} is well-formed and +its result is convertible to \tcode{bool}. \pnum -\remarks -This function does not attempt to -deallocate storage by calling -\tcode{::operator delete()}\indexlibrarymember{delete}{operator}. +\returns +\tcode{!x.has_value() \&\& static_cast(x.error() == e.value())}. \end{itemdescr} -\xrefc{7.22.3} - -\rSec1[smartptr]{Smart pointers} - -\rSec2[unique.ptr]{Class template \tcode{unique_ptr}} +\rSec1[bitset]{Bitsets} +\indexlibraryglobal{bitset}% -\rSec3[unique.ptr.general]{General} +\rSec2[bitset.syn]{Header \tcode{} synopsis}% \pnum -A \defn{unique pointer} is an object that owns another object and -manages that other object through a pointer. More precisely, a unique pointer -is an object \textit{u} that stores a pointer to a second object \textit{p} and -will dispose of \textit{p} when \textit{u} is itself destroyed (e.g., when -leaving block scope\iref{stmt.dcl}). In this context, \textit{u} is said -to \defn{own} \tcode{p}. +The header \libheaderdef{bitset} defines a class template +and several related functions for representing +and manipulating fixed-size sequences of bits. -\pnum -The mechanism by which \textit{u} disposes of \textit{p} is known as -\textit{p}'s associated \defn{deleter}, a function object whose correct -invocation results in \textit{p}'s appropriate disposition (typically its deletion). +\begin{codeblock} +#include +#include // for \tcode{istream}\iref{istream.syn}, \tcode{ostream}\iref{ostream.syn}, see \ref{iosfwd.syn} -\pnum -Let the notation \textit{u.p} denote the pointer stored by \textit{u}, and -let \textit{u.d} denote the associated deleter. Upon request, \textit{u} can -\defn{reset} (replace) \textit{u.p} and \textit{u.d} with another pointer and -deleter, but properly disposes of its owned object via the associated -deleter before such replacement is considered completed. +namespace std { + template class bitset; -\pnum -Each object of a type \tcode{U} instantiated from the \tcode{unique_ptr} template -specified in \ref{unique.ptr} has the strict ownership semantics, specified above, -of a unique pointer. In partial satisfaction of these semantics, each such \tcode{U} -is \oldconcept{MoveConstructible} and \oldconcept{MoveAssignable}, but is not -\oldconcept{CopyConstructible} nor \oldconcept{CopyAssignable}. -The template parameter \tcode{T} of \tcode{unique_ptr} may be an incomplete type. + // \ref{bitset.operators}, bitset operators + template + bitset operator&(const bitset&, const bitset&) noexcept; + template + bitset operator|(const bitset&, const bitset&) noexcept; + template + bitset operator^(const bitset&, const bitset&) noexcept; + template + basic_istream& + operator>>(basic_istream& is, bitset& x); + template + basic_ostream& + operator<<(basic_ostream& os, const bitset& x); +} +\end{codeblock} -\pnum -\begin{note} -The uses -of \tcode{unique_ptr} include providing exception safety for -dynamically allocated memory, passing ownership of dynamically allocated -memory to a function, and returning dynamically allocated memory from a -function. -\end{note} +\rSec2[template.bitset]{Class template \tcode{bitset}}% -\rSec3[unique.ptr.dltr]{Default deleters} +\rSec3[template.bitset.general]{General}% +\indexlibraryglobal{bitset}% +\begin{codeblock} +namespace std { + template class bitset { + public: + // bit reference + class reference { + friend class bitset; + reference() noexcept; -\rSec4[unique.ptr.dltr.general]{In general} + public: + reference(const reference&) = default; + ~reference(); + reference& operator=(bool x) noexcept; // for \tcode{b[i] = x;} + reference& operator=(const reference&) noexcept; // for \tcode{b[i] = b[j];} + bool operator~() const noexcept; // flips the bit + operator bool() const noexcept; // for \tcode{x = b[i];} + reference& flip() noexcept; // for \tcode{b[i].flip();} + }; -\pnum -The class template \tcode{default_delete} serves as the default deleter (destruction policy) -for the class template \tcode{unique_ptr}. + // \ref{bitset.cons}, constructors + constexpr bitset() noexcept; + constexpr bitset(unsigned long long val) noexcept; + template + explicit bitset( + const basic_string& str, + typename basic_string::size_type pos = 0, + typename basic_string::size_type n + = basic_string::npos, + charT zero = charT('0'), + charT one = charT('1')); + template + explicit bitset( + const charT* str, + typename basic_string::size_type n = basic_string::npos, + charT zero = charT('0'), + charT one = charT('1')); -\pnum -The template parameter \tcode{T} of \tcode{default_delete} may be -an incomplete type. + // \ref{bitset.members}, bitset operations + bitset& operator&=(const bitset& rhs) noexcept; + bitset& operator|=(const bitset& rhs) noexcept; + bitset& operator^=(const bitset& rhs) noexcept; + bitset& operator<<=(size_t pos) noexcept; + bitset& operator>>=(size_t pos) noexcept; + bitset& set() noexcept; + bitset& set(size_t pos, bool val = true); + bitset& reset() noexcept; + bitset& reset(size_t pos); + bitset operator~() const noexcept; + bitset& flip() noexcept; + bitset& flip(size_t pos); -\rSec4[unique.ptr.dltr.dflt]{\tcode{default_delete}} + // element access + constexpr bool operator[](size_t pos) const; // for \tcode{b[i];} + reference operator[](size_t pos); // for \tcode{b[i];} -\begin{codeblock} -namespace std { - template struct default_delete { - constexpr default_delete() noexcept = default; - template default_delete(const default_delete&) noexcept; - void operator()(T*) const; + unsigned long to_ulong() const; + unsigned long long to_ullong() const; + template, + class Allocator = allocator> + basic_string + to_string(charT zero = charT('0'), charT one = charT('1')) const; + + size_t count() const noexcept; + constexpr size_t size() const noexcept; + bool operator==(const bitset& rhs) const noexcept; + bool test(size_t pos) const; + bool all() const noexcept; + bool any() const noexcept; + bool none() const noexcept; + bitset operator<<(size_t pos) const noexcept; + bitset operator>>(size_t pos) const noexcept; }; + + // \ref{bitset.hash}, hash support + template struct hash; + template struct hash>; } \end{codeblock} -\indexlibraryctor{default_delete}% -\begin{itemdecl} -template default_delete(const default_delete& other) noexcept; -\end{itemdecl} +\pnum +The class template +\tcode{bitset} +describes an object that can store a sequence consisting of a fixed number of +bits, \tcode{N}. -\begin{itemdescr} \pnum -\constraints -\tcode{U*} is implicitly convertible to \tcode{T*}. +Each bit represents either the value zero (reset) or one (set). +To +\term{toggle} +a bit is to change the value zero to one, or the value one to +zero. +Each bit has a non-negative position \tcode{pos}. +When converting +between an object of class +\tcode{bitset} +and a value of some +integral type, bit position \tcode{pos} corresponds to the +\term{bit value} +\tcode{1 << pos}. +The integral value corresponding to two +or more bits is the sum of their bit values. \pnum -\effects -Constructs a \tcode{default_delete} object -from another \tcode{default_delete} object. -\end{itemdescr} +The functions described in \ref{template.bitset} can report three kinds of +errors, each associated with a distinct exception: +\begin{itemize} +\item +an +\term{invalid-argument} +error is associated with exceptions of type +\tcode{invalid_argument}\iref{invalid.argument}; +\indexlibraryglobal{invalid_argument}% +\item +an +\term{out-of-range} +error is associated with exceptions of type +\tcode{out_of_range}\iref{out.of.range}; +\indexlibraryglobal{out_of_range}% +\item +an +\term{overflow} +error is associated with exceptions of type +\tcode{overflow_error}\iref{overflow.error}. +\indexlibraryglobal{overflow_error}% +\end{itemize} -\indexlibrarymember{operator()}{default_delete}% +\rSec3[bitset.cons]{Constructors} + +\indexlibraryctor{bitset}% \begin{itemdecl} -void operator()(T* ptr) const; +constexpr bitset() noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\mandates -\tcode{T} is a complete type. - \pnum \effects -Calls \keyword{delete} on \tcode{ptr}. +Initializes all bits in \tcode{*this} to zero. \end{itemdescr} -\rSec4[unique.ptr.dltr.dflt1]{\tcode{default_delete}} - -\begin{codeblock} -namespace std { - template struct default_delete { - constexpr default_delete() noexcept = default; - template default_delete(const default_delete&) noexcept; - template void operator()(U* ptr) const; - }; -} -\end{codeblock} - -\indexlibraryctor{default_delete} +\indexlibraryctor{bitset}% \begin{itemdecl} -template default_delete(const default_delete& other) noexcept; +constexpr bitset(unsigned long long val) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{U(*)[]} is convertible to \tcode{T(*)[]}. - \pnum \effects -Constructs a \tcode{default_delete} object from another \tcode{default_delete} object. +Initializes the first \tcode{M} bit positions to the corresponding bit +values in \tcode{val}. +\tcode{M} is the smaller of \tcode{N} and the number of bits in the value +representation\iref{term.object.representation} of \tcode{unsigned long long}. +If \tcode{M < N}, the remaining bit positions are initialized to zero. \end{itemdescr} -\indexlibrarymember{operator()}{default_delete}% +\indexlibraryctor{bitset}% \begin{itemdecl} -template void operator()(U* ptr) const; +template + explicit bitset( + const basic_string& str, + typename basic_string::size_type pos = 0, + typename basic_string::size_type n + = basic_string::npos, + charT zero = charT('0'), + charT one = charT('1')); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{U(*)[]} is convertible to \tcode{T(*)[]}. - -\pnum -\mandates -\tcode{U} is a complete type. - \pnum \effects -Calls \tcode{delete[]} on \tcode{ptr}. -\end{itemdescr} - -\rSec3[unique.ptr.single]{\tcode{unique_ptr} for single objects} - -\rSec4[unique.ptr.single.general]{General} - -\indexlibraryglobal{unique_ptr}% -\begin{codeblock} -namespace std { - template> class unique_ptr { - public: - using pointer = @\seebelow@; - using element_type = T; - using deleter_type = D; - - // \ref{unique.ptr.single.ctor}, constructors - constexpr unique_ptr() noexcept; - explicit unique_ptr(pointer p) noexcept; - unique_ptr(pointer p, @\seebelow@ d1) noexcept; - unique_ptr(pointer p, @\seebelow@ d2) noexcept; - unique_ptr(unique_ptr&& u) noexcept; - constexpr unique_ptr(nullptr_t) noexcept; - template - unique_ptr(unique_ptr&& u) noexcept; - - // \ref{unique.ptr.single.dtor}, destructor - ~unique_ptr(); - - // \ref{unique.ptr.single.asgn}, assignment - unique_ptr& operator=(unique_ptr&& u) noexcept; - template - unique_ptr& operator=(unique_ptr&& u) noexcept; - unique_ptr& operator=(nullptr_t) noexcept; - - // \ref{unique.ptr.single.observers}, observers - add_lvalue_reference_t operator*() const noexcept(@\seebelow@); - pointer operator->() const noexcept; - pointer get() const noexcept; - deleter_type& get_deleter() noexcept; - const deleter_type& get_deleter() const noexcept; - explicit operator bool() const noexcept; - - // \ref{unique.ptr.single.modifiers}, modifiers - pointer release() noexcept; - void reset(pointer p = pointer()) noexcept; - void swap(unique_ptr& u) noexcept; - - // disable copy from lvalue - unique_ptr(const unique_ptr&) = delete; - unique_ptr& operator=(const unique_ptr&) = delete; - }; -} -\end{codeblock} +Determines the effective length +\tcode{rlen} of the initializing string as the smaller of +\tcode{n} and +\tcode{str.size() - pos}. +Initializes the first \tcode{M} bit +positions to values determined from the corresponding characters in the string +\tcode{str}. +\tcode{M} is the smaller of \tcode{N} and \tcode{rlen}. \pnum -The default type for the template parameter \tcode{D} is -\tcode{default_delete}. A client-supplied template argument -\tcode{D} shall be a function -object type\iref{function.objects}, lvalue reference to function, or -lvalue reference to function object type -for which, given -a value \tcode{d} of type \tcode{D} and a value -\tcode{ptr} of type \tcode{unique_ptr::pointer}, the expression -\tcode{d(ptr)} is valid and has the effect of disposing of the -pointer as appropriate for that deleter. +An element of the constructed object has value zero if the +corresponding character in \tcode{str}, beginning at position +\tcode{pos}, is +\tcode{zero}. +Otherwise, the element has the value one. +Character position \tcode{pos + M - 1} corresponds to bit position zero. +Subsequent decreasing character positions correspond to increasing bit positions. \pnum -If the deleter's type \tcode{D} is not a reference type, \tcode{D} shall meet -the \oldconcept{Destructible} requirements (\tref{cpp17.destructible}). +If \tcode{M < N}, remaining bit positions are initialized to zero. \pnum -If the \grammarterm{qualified-id} \tcode{remove_reference_t::pointer} is valid and denotes a -type\iref{temp.deduct}, then \tcode{unique_ptr::pointer} shall be a synonym for \tcode{remove_reference_t::pointer}. Otherwise -\tcode{unique_ptr::pointer} shall be a synonym for \tcode{element_type*}. The type \tcode{unique_ptr::pointer} shall -meet the \oldconcept{NullablePointer} requirements (\tref{cpp17.nullablepointer}). +The function uses \tcode{traits::eq} +to compare the character values. \pnum -\begin{example} -Given an allocator type \tcode{X} (\tref{cpp17.allocator}) and -letting \tcode{A} be a synonym for \tcode{allocator_traits}, the types \tcode{A::pointer}, -\tcode{A::const_pointer}, \tcode{A::void_pointer}, and \tcode{A::const_void_pointer} -may be used as \tcode{unique_ptr::pointer}. -\end{example} - -\rSec4[unique.ptr.single.ctor]{Constructors} +\throws +\indexlibraryglobal{out_of_range}% +\tcode{out_of_range} if \tcode{pos > str.size()} or +\indexlibraryglobal{invalid_argument}% +\tcode{invalid_argument} if any of +the \tcode{rlen} characters in \tcode{str} +beginning at position \tcode{pos} +is other than \tcode{zero} or \tcode{one}. +\end{itemdescr} -\indexlibraryctor{unique_ptr}% +\indexlibraryctor{bitset}% \begin{itemdecl} -constexpr unique_ptr() noexcept; -constexpr unique_ptr(nullptr_t) noexcept; +template + explicit bitset( + const charT* str, + typename basic_string::size_type n = basic_string::npos, + charT zero = charT('0'), + charT one = charT('1')); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{is_pointer_v} is \tcode{false} and -\tcode{is_default_constructible_v} is \tcode{true}. - -\pnum -\expects -\tcode{D} meets the \oldconcept{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}), -and that construction does not throw an exception. - \pnum \effects -Constructs a \tcode{unique_ptr} object that owns -nothing, value-initializing the stored pointer and the stored deleter. - -\pnum -\ensures -\tcode{get() == nullptr}. \tcode{get_deleter()} -returns a reference to the stored deleter. +As if by: +\begin{codeblock} +bitset(n == basic_string::npos + ? basic_string(str) + : basic_string(str, n), + 0, n, zero, one) +\end{codeblock} \end{itemdescr} -\indexlibraryctor{unique_ptr}% -\begin{itemdecl} -explicit unique_ptr(pointer p) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_pointer_v} is \tcode{false} and -\tcode{is_default_constructible_v} is \tcode{true}. -\pnum -\mandates -This constructor is not selected by -class template argument deduction\iref{over.match.class.deduct}. +\rSec3[bitset.members]{Members} -\pnum -\expects -\tcode{D} meets the \oldconcept{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}), -and that construction does not throw an exception. +\indexlibrarymember{operator\&=}{bitset}% +\begin{itemdecl} +bitset& operator&=(const bitset& rhs) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum \effects -Constructs a \tcode{unique_ptr} which owns -\tcode{p}, initializing the stored pointer with \tcode{p} and -value-initializing the stored deleter. +Clears each bit in +\tcode{*this} +for which the corresponding bit in \tcode{rhs} is clear, and leaves all other bits unchanged. \pnum -\ensures -\tcode{get() == p}. \tcode{get_deleter()} -returns a reference to the stored deleter. +\returns +\tcode{*this}. \end{itemdescr} -\indexlibraryctor{unique_ptr}% +\indexlibrarymember{operator"|=}{bitset}% \begin{itemdecl} -unique_ptr(pointer p, const D& d) noexcept; -unique_ptr(pointer p, remove_reference_t&& d) noexcept; +bitset& operator|=(const bitset& rhs) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. - -\pnum -\mandates -These constructors are not selected by -class template argument deduction\iref{over.match.class.deduct}. - -\pnum -\expects -For the first constructor, if \tcode{D} is not a reference type, -\tcode{D} meets the \oldconcept{CopyConstructible} requirements and -such construction does not exit via an exception. -For the second constructor, if \tcode{D} is not a reference type, -\tcode{D} meets the \oldconcept{MoveConstructible} requirements and -such construction does not exit via an exception. - \pnum \effects -Constructs a \tcode{unique_ptr} object which owns \tcode{p}, initializing -the stored pointer with \tcode{p} and initializing the deleter -from \tcode{std::forward(d)}. - -\pnum -\ensures -\tcode{get() == p}. -\tcode{get_deleter()} returns a reference to the stored -deleter. If \tcode{D} is a reference type then \tcode{get_deleter()} -returns a reference to the lvalue \tcode{d}. - -\pnum -\remarks -If \tcode{D} is a reference type, -the second constructor is defined as deleted. +Sets each bit in +\tcode{*this} +for which the corresponding bit in \tcode{rhs} is set, and leaves all other bits unchanged. \pnum -\begin{example} -\begin{codeblock} -D d; -unique_ptr p1(new int, D()); // \tcode{D} must be \oldconcept{MoveConstructible} -unique_ptr p2(new int, d); // \tcode{D} must be \oldconcept{CopyConstructible} -unique_ptr p3(new int, d); // \tcode{p3} holds a reference to \tcode{d} -unique_ptr p4(new int, D()); // error: rvalue deleter object combined - // with reference deleter type -\end{codeblock} -\end{example} +\returns +\tcode{*this}. \end{itemdescr} -\indexlibraryctor{unique_ptr}% +\indexlibrarymember{operator\caret=}{bitset}% \begin{itemdecl} -unique_ptr(unique_ptr&& u) noexcept; +bitset& operator^=(const bitset& rhs) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{is_move_constructible_v} is \tcode{true}. - -\pnum -\expects -If \tcode{D} is not a reference type, -\tcode{D} meets the \oldconcept{MoveConstructible} -requirements (\tref{cpp17.moveconstructible}). -Construction -of the deleter from an rvalue of type \tcode{D} does not -throw an exception. - \pnum \effects -Constructs a \tcode{unique_ptr} from -\tcode{u}. If \tcode{D} is a reference type, this -deleter is copy constructed from \tcode{u}'s deleter; otherwise, this -deleter is move constructed from \tcode{u}'s deleter. -\begin{note} -The -construction of the deleter can be implemented with \tcode{std::forward}. -\end{note} +Toggles each bit in +\tcode{*this} +for which the corresponding bit in \tcode{rhs} is set, and leaves all other bits unchanged. \pnum -\ensures -\tcode{get()} yields the value \tcode{u.get()} -yielded before the construction. \tcode{u.get() == nullptr}. -\tcode{get_deleter()} returns a reference -to the stored deleter that was constructed from -\tcode{u.get_deleter()}. If \tcode{D} is a reference type then -\tcode{get_deleter()} and \tcode{u.get_deleter()} both reference -the same lvalue deleter. +\returns +\tcode{*this}. \end{itemdescr} -\indexlibraryctor{unique_ptr}% +\indexlibrarymember{operator<<=}{bitset}% \begin{itemdecl} -template unique_ptr(unique_ptr&& u) noexcept; +bitset& operator<<=(size_t pos) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints +\effects +Replaces each bit at position \tcode{I} in +\tcode{*this} +with a value determined as follows: + \begin{itemize} -\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{pointer}, -\item \tcode{U} is not an array type, and -\item either \tcode{D} is a reference type and \tcode{E} is the same type as \tcode{D}, or -\tcode{D} is not a reference type and \tcode{E} is implicitly convertible to \tcode{D}. +\item +If \tcode{I < pos}, the new value is zero; +\item +If \tcode{I >= pos}, the new value is the previous +value of the bit at position \tcode{I - pos}. \end{itemize} \pnum -\expects -If \tcode{E} is not a reference type, -construction of the deleter from an rvalue of type \tcode{E} -is well-formed and does not throw an exception. -Otherwise, \tcode{E} is a reference type and -construction of the deleter from an lvalue of type \tcode{E} -is well-formed and does not throw an exception. +\returns +\tcode{*this}. +\end{itemdescr} +\indexlibrarymember{operator>>=}{bitset}% +\begin{itemdecl} +bitset& operator>>=(size_t pos) noexcept; +\end{itemdecl} + +\begin{itemdescr} \pnum \effects -Constructs a \tcode{unique_ptr} from \tcode{u}. -If \tcode{E} is a reference type, this deleter is copy constructed from -\tcode{u}'s deleter; otherwise, this deleter is move constructed from \tcode{u}'s -deleter. -\begin{note} -The deleter constructor can be implemented with -\tcode{std::forward}. -\end{note} +Replaces each bit at position \tcode{I} in +\tcode{*this} +with a value determined as follows: + +\begin{itemize} +\item +If \tcode{pos >= N - I}, the new value is zero; +\item +If \tcode{pos < N - I}, the new value is the previous value of the bit at position \tcode{I + pos}. +\end{itemize} \pnum -\ensures -\tcode{get()} yields the value \tcode{u.get()} -yielded before the construction. \tcode{u.get() == nullptr}. -\tcode{get_deleter()} returns a reference -to the stored deleter that was constructed from -\tcode{u.get_deleter()}. +\returns +\tcode{*this}. \end{itemdescr} -\rSec4[unique.ptr.single.dtor]{Destructor} - -\indexlibrarydtor{unique_ptr}% +% Do not use \indexlibrarymember. +\indexlibrary{\idxcode{set} (member)!\idxcode{bitset}}% +\indexlibrary{\idxcode{bitset}!\idxcode{set}}% \begin{itemdecl} -~unique_ptr(); +bitset& set() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -The expression \tcode{get_deleter()(get())} is well-formed, -has well-defined behavior, and does not throw exceptions. -\begin{note} -The use of \tcode{default_delete} requires \tcode{T} to be a complete type. -\end{note} +\effects +Sets all bits in +\tcode{*this}. \pnum -\effects -If \tcode{get() == nullptr} there are no effects. -Otherwise \tcode{get_deleter()(get())}. +\returns +\tcode{*this}. \end{itemdescr} -\rSec4[unique.ptr.single.asgn]{Assignment} - -\indexlibrarymember{operator=}{unique_ptr}% +% Do not use \indexlibrarymember. +\indexlibrary{\idxcode{set} (member)!\idxcode{bitset}}% +\indexlibrary{\idxcode{bitset}!\idxcode{set}}% \begin{itemdecl} -unique_ptr& operator=(unique_ptr&& u) noexcept; +bitset& set(size_t pos, bool val = true); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_move_assignable_v} is \tcode{true}. +\effects +Stores a new value in the bit at position \tcode{pos} in +\tcode{*this}. +If \tcode{val} is \tcode{true}, the stored value is one, otherwise it is zero. \pnum -\expects -If \tcode{D} is not a reference type, \tcode{D} meets the -\oldconcept{MoveAssignable} requirements (\tref{cpp17.moveassignable}) and assignment -of the deleter from an rvalue of type \tcode{D} does not throw an exception. -Otherwise, \tcode{D} is a reference type; -\tcode{remove_reference_t} meets the \oldconcept{CopyAssignable} -requirements and assignment of the deleter from an -lvalue of type \tcode{D} does not throw an exception. +\returns +\tcode{*this}. \pnum -\effects -Calls \tcode{reset(u.release())} followed by -\tcode{get_deleter() = std::forward(u.get_dele\-ter())}. +\throws +\indexlibraryglobal{out_of_range}% +\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. +\end{itemdescr} + +\indexlibrarymember{reset}{bitset}% +\begin{itemdecl} +bitset& reset() noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\ensures -If \tcode{this != addressof(u)}, -\tcode{u.get() == nullptr}, -otherwise \tcode{u.get()} is unchanged. +\effects +Resets all bits in +\tcode{*this}. \pnum \returns \tcode{*this}. \end{itemdescr} -\indexlibrarymember{operator=}{unique_ptr}% +\indexlibrarymember{reset}{bitset}% \begin{itemdecl} -template unique_ptr& operator=(unique_ptr&& u) noexcept; +bitset& reset(size_t pos); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{pointer}, and -\item \tcode{U} is not an array type, and -\item \tcode{is_assignable_v} is \tcode{true}. -\end{itemize} +\effects +Resets the bit at position \tcode{pos} in +\tcode{*this}. \pnum -\expects -If \tcode{E} is not a reference type, -assignment of the deleter from an rvalue of type \tcode{E} -is well-formed and does not throw an exception. -Otherwise, \tcode{E} is a reference type and -assignment of the deleter from an lvalue of type \tcode{E} -is well-formed and does not throw an exception. +\returns +\tcode{*this}. \pnum -\effects -Calls \tcode{reset(u.release())} followed by -\tcode{get_deleter() = std::forward(u.get_dele\-ter())}. +\throws +\indexlibraryglobal{out_of_range}% +\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. +\end{itemdescr} + +\indexlibrarymember{operator\~{}}{bitset}% +\begin{itemdecl} +bitset operator~() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\ensures -\tcode{u.get() == nullptr}. +\effects +Constructs an object \tcode{x} of class +\tcode{bitset} +and initializes it with +\tcode{*this}. \pnum \returns -\tcode{*this}. +\tcode{x.flip()}. \end{itemdescr} -\indexlibrarymember{operator=}{unique_ptr}% +\indexlibrarymember{flip}{bitset}% \begin{itemdecl} -unique_ptr& operator=(nullptr_t) noexcept; +bitset& flip() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -As if by \tcode{reset()}. - -\pnum -\ensures -\tcode{get() == nullptr}. +Toggles all bits in +\tcode{*this}. \pnum \returns \tcode{*this}. \end{itemdescr} -\rSec4[unique.ptr.single.observers]{Observers} - -\indexlibrarymember{operator*}{unique_ptr}% +\indexlibrarymember{flip}{bitset}% \begin{itemdecl} -add_lvalue_reference_t operator*() const noexcept(noexcept(*declval())); +bitset& flip(size_t pos); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{get() != nullptr}. +\effects +Toggles the bit at position \tcode{pos} in +\tcode{*this}. \pnum \returns -\tcode{*get()}. +\tcode{*this}. +\pnum +\throws +\indexlibraryglobal{out_of_range}% +\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. \end{itemdescr} -\indexlibrarymember{operator->}{unique_ptr}% +\indexlibrarymember{to_ulong}{bitset}% \begin{itemdecl} -pointer operator->() const noexcept; +unsigned long to_ulong() const; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{get() != nullptr}. - \pnum \returns -\tcode{get()}. +\tcode{x}. \pnum -\begin{note} -The use of this function typically requires that \tcode{T} be a complete type. -\end{note} +\throws +\indexlibraryglobal{overflow_error}% +\tcode{overflow_error} if the integral value \tcode{x} +corresponding to the bits in \tcode{*this} +cannot be represented as type \tcode{unsigned long}. \end{itemdescr} -\indexlibrarymember{get}{unique_ptr}% +\indexlibrarymember{to_ullong}{bitset}% \begin{itemdecl} -pointer get() const noexcept; +unsigned long long to_ullong() const; \end{itemdecl} \begin{itemdescr} \pnum \returns -The stored pointer. +\tcode{x}. + +\pnum +\throws +\indexlibraryglobal{overflow_error}% +\tcode{overflow_error} if the integral value \tcode{x} +corresponding to the bits in \tcode{*this} +cannot be represented as type \tcode{unsigned long long}. \end{itemdescr} -\indexlibrarymember{get_deleter}{unique_ptr}% +\indexlibrarymember{to_string}{bitset}% \begin{itemdecl} -deleter_type& get_deleter() noexcept; -const deleter_type& get_deleter() const noexcept; +template, + class Allocator = allocator> + basic_string + to_string(charT zero = charT('0'), charT one = charT('1')) const; \end{itemdecl} \begin{itemdescr} +\pnum +\effects +Constructs a string object of the appropriate type +and initializes it to a string of length \tcode{N} characters. +Each character is determined by the value of its corresponding bit position in +\tcode{*this}. +Character position \tcode{N - 1} corresponds to bit position zero. +Subsequent decreasing character positions correspond to increasing bit +positions. +Bit value zero becomes the character \tcode{zero}, +bit value one becomes the character +\tcode{one}. + \pnum \returns -A reference to the stored deleter. +The created object. \end{itemdescr} -\indexlibrarymember{operator bool}{unique_ptr}% +\indexlibrarymember{count}{bitset}% \begin{itemdecl} -explicit operator bool() const noexcept; +size_t count() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{get() != nullptr}. +A count of the number of bits set in +\tcode{*this}. \end{itemdescr} -\rSec4[unique.ptr.single.modifiers]{Modifiers} - -\indexlibrarymember{release}{unique_ptr}% +\indexlibrarymember{size}{bitset}% \begin{itemdecl} -pointer release() noexcept; +constexpr size_t size() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\ensures -\tcode{get() == nullptr}. - \pnum \returns -The value \tcode{get()} had at the start of -the call to \tcode{release}. +\tcode{N}. \end{itemdescr} -\indexlibrarymember{reset}{unique_ptr}% +\indexlibrarymember{operator==}{bitset}% \begin{itemdecl} -void reset(pointer p = pointer()) noexcept; +bool operator==(const bitset& rhs) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -The expression \tcode{get_deleter()(get())} is well-formed, -has well-defined behavior, and does not throw exceptions. +\returns +\tcode{true} if the value of each bit in +\tcode{*this} +equals the value of the corresponding bit in \tcode{rhs}. +\end{itemdescr} -\pnum -\effects -Assigns \tcode{p} to the stored pointer, and then if and only if the old value of the -stored pointer, \tcode{old_p}, was not equal to \keyword{nullptr}, calls -\tcode{get_deleter()(old_p)}. -\begin{note} -The order of these operations is significant -because the call to \tcode{get_deleter()} might destroy \tcode{*this}. -\end{note} - -\pnum -\ensures -\tcode{get() == p}. -\begin{note} -The postcondition does not hold if the call to \tcode{get_deleter()} -destroys \tcode{*this} since \tcode{this->get()} is no longer a valid expression. -\end{note} -\end{itemdescr} - -\indexlibrarymember{swap}{unique_ptr}% +\indexlibrarymember{test}{bitset}% \begin{itemdecl} -void swap(unique_ptr& u) noexcept; +bool test(size_t pos) const; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{get_deleter()} is swappable\iref{swappable.requirements} and -does not throw an exception under \tcode{swap}. +\returns +\tcode{true} +if the bit at position \tcode{pos} +in +\tcode{*this} +has the value one. \pnum -\effects -Invokes \tcode{swap} on the stored pointers and on the stored -deleters of \tcode{*this} and \tcode{u}. +\throws +\indexlibraryglobal{out_of_range}% +\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. \end{itemdescr} -\rSec3[unique.ptr.runtime]{\tcode{unique_ptr} for array objects with a runtime length} - -\rSec4[unique.ptr.runtime.general]{General} - -\indexlibraryglobal{unique_ptr}% -\begin{codeblock} -namespace std { - template class unique_ptr { - public: - using pointer = @\seebelow@; - using element_type = T; - using deleter_type = D; - - // \ref{unique.ptr.runtime.ctor}, constructors - constexpr unique_ptr() noexcept; - template explicit unique_ptr(U p) noexcept; - template unique_ptr(U p, @\seebelow@ d) noexcept; - template unique_ptr(U p, @\seebelow@ d) noexcept; - unique_ptr(unique_ptr&& u) noexcept; - template - unique_ptr(unique_ptr&& u) noexcept; - constexpr unique_ptr(nullptr_t) noexcept; - - // destructor - ~unique_ptr(); - - // assignment - unique_ptr& operator=(unique_ptr&& u) noexcept; - template - unique_ptr& operator=(unique_ptr&& u) noexcept; - unique_ptr& operator=(nullptr_t) noexcept; - - // \ref{unique.ptr.runtime.observers}, observers - T& operator[](size_t i) const; - pointer get() const noexcept; - deleter_type& get_deleter() noexcept; - const deleter_type& get_deleter() const noexcept; - explicit operator bool() const noexcept; - - // \ref{unique.ptr.runtime.modifiers}, modifiers - pointer release() noexcept; - template void reset(U p) noexcept; - void reset(nullptr_t = nullptr) noexcept; - void swap(unique_ptr& u) noexcept; - - // disable copy from lvalue - unique_ptr(const unique_ptr&) = delete; - unique_ptr& operator=(const unique_ptr&) = delete; - }; -} -\end{codeblock} - -\pnum -A specialization for array types is provided with a slightly altered -interface. - -\begin{itemize} -\item Conversions between different types of -\tcode{unique_ptr} -that would be disallowed for the corresponding pointer-to-array types, -and conversions to or from the non-array forms of -\tcode{unique_ptr}, produce an ill-formed program. - -\item Pointers to types derived from \tcode{T} are -rejected by the constructors, and by \tcode{reset}. - -\item The observers \tcode{operator*} and -\tcode{operator->} are not provided. - -\item The indexing observer \tcode{operator[]} is provided. - -\item The default deleter will call \tcode{delete[]}. -\end{itemize} - -\pnum -Descriptions are provided below only for members that -differ from the primary template. - -\pnum -The template argument \tcode{T} shall be a complete type. - -\rSec4[unique.ptr.runtime.ctor]{Constructors} - -\indexlibraryctor{unique_ptr}% +\indexlibrarymember{all}{bitset}% \begin{itemdecl} -template explicit unique_ptr(U p) noexcept; +bool all() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -This constructor behaves the same as -the constructor in the primary template that -takes a single parameter of type \tcode{pointer}. - -\pnum -\constraints -\begin{itemize} -\item \tcode{U} is the same type as \tcode{pointer}, or -\item \tcode{pointer} is the same type as \tcode{element_type*}, -\tcode{U} is a pointer type \tcode{V*}, and -\tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. -\end{itemize} +\returns +\tcode{count() == size()}. \end{itemdescr} -\indexlibraryctor{unique_ptr}% +% Do not use \indexlibrarymember. +\indexlibrary{\idxcode{any} (member)!\idxcode{bitset}}% +\indexlibrary{\idxcode{bitset}!\idxcode{any}}% \begin{itemdecl} -template unique_ptr(U p, @\seebelow@ d) noexcept; -template unique_ptr(U p, @\seebelow@ d) noexcept; +bool any() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -These constructors behave the same as -the constructors in the primary template that -take a parameter of type \tcode{pointer} and a second parameter. - -\pnum -\constraints -\begin{itemize} -\item \tcode{U} is the same type as \tcode{pointer}, -\item \tcode{U} is \tcode{nullptr_t}, or -\item \tcode{pointer} is the same type as \tcode{element_type*}, - \tcode{U} is a pointer type \tcode{V*}, and - \tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. -\end{itemize} +\returns +\tcode{count() != 0}. \end{itemdescr} -\indexlibraryctor{unique_ptr}% +\indexlibrarymember{none}{bitset}% \begin{itemdecl} -template unique_ptr(unique_ptr&& u) noexcept; +bool none() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -This constructor behaves the same as in the primary template. - -\pnum -\constraints -Where \tcode{UP} is \tcode{unique_ptr}: -\begin{itemize} -\item \tcode{U} is an array type, and -\item \tcode{pointer} is the same type as \tcode{element_type*}, and -\item \tcode{UP::pointer} is the same type as \tcode{UP::element_type*}, and -\item \tcode{UP::element_type(*)[]} is convertible to \tcode{element_type(*)[]}, and -\item either \tcode{D} is a reference type and \tcode{E} is the same type as \tcode{D}, - or \tcode{D} is not a reference type and \tcode{E} is implicitly convertible to \tcode{D}. -\end{itemize} - -\begin{note} -This replaces the \constraints specification of the primary template. -\end{note} +\returns +\tcode{count() == 0}. \end{itemdescr} -\rSec4[unique.ptr.runtime.asgn]{Assignment} - -\indexlibrarymember{operator=}{unique_ptr}% +\indexlibrarymember{operator<<}{bitset}% \begin{itemdecl} -template unique_ptr& operator=(unique_ptr&& u) noexcept; +bitset operator<<(size_t pos) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -This operator behaves the same as in the primary template. - -\pnum -\constraints -Where \tcode{UP} is \tcode{unique_ptr}: -\begin{itemize} -\item \tcode{U} is an array type, and -\item \tcode{pointer} is the same type as \tcode{element_type*}, and -\item \tcode{UP::pointer} is the same type as \tcode{UP::element_type*}, and -\item \tcode{UP::element_type(*)[]} is convertible to \tcode{element_type(*)[]}, and -\item \tcode{is_assignable_v} is \tcode{true}. -\end{itemize} - -\begin{note} -This replaces the \constraints specification of the primary template. -\end{note} +\returns +\tcode{bitset(*this) <<= pos}. \end{itemdescr} -\rSec4[unique.ptr.runtime.observers]{Observers} - -\indexlibrarymember{operator[]}{unique_ptr}% +\indexlibrarymember{operator>>}{bitset}% \begin{itemdecl} -T& operator[](size_t i) const; +bitset operator>>(size_t pos) const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -$\tcode{i} <$ the -number of elements in the array to which -the stored pointer points. - \pnum \returns -\tcode{get()[i]}. +\tcode{bitset(*this) >>= pos}. \end{itemdescr} -\rSec4[unique.ptr.runtime.modifiers]{Modifiers} - -\indexlibrarymember{reset}{unique_ptr}% +\indexlibrarymember{operator[]}{bitset}% \begin{itemdecl} -void reset(nullptr_t p = nullptr) noexcept; +constexpr bool operator[](size_t pos) const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{reset(pointer())}. -\end{itemdescr} - -\indexlibrarymember{reset}{unique_ptr}% -\begin{itemdecl} -template void reset(U p) noexcept; -\end{itemdecl} +\expects +\tcode{pos} is valid. -\begin{itemdescr} \pnum -This function behaves the same as -the \tcode{reset} member of the primary template. +\returns +\tcode{true} if the bit at position \tcode{pos} in \tcode{*this} has the value +one, otherwise \tcode{false}. \pnum -\constraints -\begin{itemize} -\item \tcode{U} is the same type as \tcode{pointer}, or -\item \tcode{pointer} is the same type as \tcode{element_type*}, - \tcode{U} is a pointer type \tcode{V*}, and - \tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. -\end{itemize} +\throws +Nothing. \end{itemdescr} -\rSec3[unique.ptr.create]{Creation} - -\indexlibraryglobal{make_unique}% +\indexlibrarymember{operator[]}{bitset}% \begin{itemdecl} -template unique_ptr make_unique(Args&&... args); +bitset::reference operator[](size_t pos); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{T} is not an array type. +\expects +\tcode{pos} is valid. \pnum \returns -\tcode{unique_ptr(new T(std::forward(args)...))}. - -\end{itemdescr} - -\indexlibraryglobal{make_unique}% -\begin{itemdecl} -template unique_ptr make_unique(size_t n); -\end{itemdecl} +An object of type +\tcode{bitset::reference} +such that +\tcode{(*this)[pos] == this->test(pos)}, +and such that +\tcode{(*this)[pos] = val} +is equivalent to +\tcode{this->set(pos, val)}. -\begin{itemdescr} \pnum -\constraints -\tcode{T} is an array of unknown bound. +\throws +Nothing. \pnum -\returns -\tcode{unique_ptr(new remove_extent_t[n]())}. - +\remarks +For the purpose of determining the presence of a data +race\iref{intro.multithread}, any access or update through the resulting +reference potentially accesses or modifies, respectively, the entire +underlying bitset. \end{itemdescr} -\indexlibraryglobal{make_unique}% -\begin{itemdecl} -template @\unspec@ make_unique(Args&&...) = delete; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an array of known bound. - -\end{itemdescr} +\rSec2[bitset.hash]{\tcode{bitset} hash support} -\indexlibraryglobal{make_unique}% +\indexlibraryglobal{hash_code}% \begin{itemdecl} -template unique_ptr make_unique_for_overwrite(); +template struct hash>; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{T} is not an array type. - -\pnum -\returns -\tcode{unique_ptr(new T)}. +The specialization is enabled\iref{unord.hash}. \end{itemdescr} -\indexlibraryglobal{make_unique}% -\begin{itemdecl} -template unique_ptr make_unique_for_overwrite(size_t n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an array of unknown bound. -\pnum -\returns -\tcode{unique_ptr(new remove_extent_t[n])}. -\end{itemdescr} +\rSec2[bitset.operators]{\tcode{bitset} operators} -\indexlibraryglobal{make_unique}% +\indexlibrarymember{operator\&}{bitset}% \begin{itemdecl} -template @\unspec@ make_unique_for_overwrite(Args&&...) = delete; +template + bitset operator&(const bitset& lhs, const bitset& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{T} is an array of known bound. +\returns +\tcode{bitset(lhs) \&= rhs}. \end{itemdescr} -\rSec3[unique.ptr.special]{Specialized algorithms} - -\indexlibrary{\idxcode{swap(unique_ptr\&, unique_ptr\&)}}% +\indexlibrarymember{operator"|}{bitset}% \begin{itemdecl} -template void swap(unique_ptr& x, unique_ptr& y) noexcept; +template + bitset operator|(const bitset& lhs, const bitset& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_swappable_v} is \tcode{true}. - -\pnum -\effects -Calls \tcode{x.swap(y)}. +\returns +\tcode{bitset(lhs) |= rhs}. \end{itemdescr} -\indexlibrarymember{operator==}{unique_ptr}% +\indexlibrarymember{operator\caret}{bitset}% \begin{itemdecl} -template - bool operator==(const unique_ptr& x, const unique_ptr& y); +template + bitset operator^(const bitset& lhs, const bitset& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{x.get() == y.get()}. +\tcode{bitset(lhs) \caret= rhs}. \end{itemdescr} -\indexlibrarymember{operator<}{unique_ptr}% +\indexlibrarymember{operator>>}{bitset}% \begin{itemdecl} -template - bool operator<(const unique_ptr& x, const unique_ptr& y); +template + basic_istream& + operator>>(basic_istream& is, bitset& x); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{CT} denote -\begin{codeblock} -common_type_t::pointer, - typename unique_ptr::pointer> -\end{codeblock} +A formatted input function\iref{istream.formatted}. \pnum -\mandates +\effects +Extracts up to \tcode{N} characters from \tcode{is}. +Stores these characters in a temporary object \tcode{str} of type +\tcode{basic_string}, +then evaluates the expression +\tcode{x = bitset(str)}. +Characters are extracted and stored until any of the following occurs: \begin{itemize} -\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{CT} and -\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{CT}. +\item +\tcode{N} characters have been extracted and stored; +\item +\indextext{end-of-file}% +end-of-file occurs on the input sequence; +\item +the next input character is neither +\tcode{is.widen('0')} +nor +\tcode{is.widen('1')} +(in which case the input character is not extracted). \end{itemize} \pnum -\expects -The specialization -\tcode{less} is a function object type\iref{function.objects} that -induces a strict weak ordering\iref{alg.sorting} on the pointer values. +If \tcode{N > 0} and no characters are stored in \tcode{str}, calls +\tcode{is.setstate(ios_base::failbit)} +(which may throw +\tcode{ios_base::failure}\iref{iostate.flags}). \pnum \returns -\tcode{less()(x.get(), y.get())}. +\tcode{is}. \end{itemdescr} -\indexlibrarymember{operator>}{unique_ptr}% +\indexlibrarymember{operator<<}{bitset}% \begin{itemdecl} -template - bool operator>(const unique_ptr& x, const unique_ptr& y); +template + basic_ostream& + operator<<(basic_ostream& os, const bitset& x); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{y < x}. +\begin{codeblock} +os << x.template to_string>( + use_facet>(os.getloc()).widen('0'), + use_facet>(os.getloc()).widen('1')) +\end{codeblock} +(see~\ref{ostream.formatted}). \end{itemdescr} -\indexlibrarymember{operator<=}{unique_ptr}% -\begin{itemdecl} -template - bool operator<=(const unique_ptr& x, const unique_ptr& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!(y < x)}. -\end{itemdescr} +\rSec1[function.objects]{Function objects} -\indexlibrarymember{operator>=}{unique_ptr}% -\begin{itemdecl} -template - bool operator>=(const unique_ptr& x, const unique_ptr& y); -\end{itemdecl} +\rSec2[function.objects.general]{General} -\begin{itemdescr} \pnum -\returns -\tcode{!(x < y)}. -\end{itemdescr} - -\indexlibrarymember{operator<=>}{unique_ptr}% -\begin{itemdecl} -template - requires @\libconcept{three_way_comparable_with}@::pointer, - typename unique_ptr::pointer> - compare_three_way_result_t::pointer, - typename unique_ptr::pointer> - operator<=>(const unique_ptr& x, const unique_ptr& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{compare_three_way()(x.get(), y.get())}. -\end{itemdescr} - -\indexlibrarymember{operator==}{unique_ptr}% -\begin{itemdecl} -template - bool operator==(const unique_ptr& x, nullptr_t) noexcept; -\end{itemdecl} +A \defnx{function object type}{function object!type} is an object +type\iref{term.object.type} that can be the type of the +\grammarterm{postfix-expression} +in a function call\iref{expr.call,over.match.call}. +\begin{footnote} +Such a type is a function +pointer or a class type which has a member \tcode{operator()} or a class type +which has a conversion to a pointer to function. +\end{footnote} +A \defn{function object} is an +object of a function object type. In the places where one would expect to pass a +pointer to a function to an algorithmic template\iref{algorithms}, the +interface is specified to accept a function object. This not only makes +algorithmic templates work with pointers to functions, but also enables them to +work with arbitrary function objects. -\begin{itemdescr} -\pnum -\returns -\tcode{!x}. -\end{itemdescr} +\rSec2[functional.syn]{Header \tcode{} synopsis} -\indexlibrarymember{operator<}{unique_ptr}% -\begin{itemdecl} -template - bool operator<(const unique_ptr& x, nullptr_t); -template - bool operator<(nullptr_t, const unique_ptr& x); -\end{itemdecl} +\indexheader{functional}% +\indexlibraryglobal{unwrap_ref_decay}% +\indexlibraryglobal{unwrap_ref_decay_t}% +\begin{codeblock} +namespace std { + // \ref{func.invoke}, invoke + template + constexpr invoke_result_t invoke(F&& f, Args&&... args) + noexcept(is_nothrow_invocable_v); -\begin{itemdescr} -\pnum -\expects -The specialization \tcode{less::pointer>} is -a function object type\iref{function.objects} that induces a strict weak -ordering\iref{alg.sorting} on the pointer values. + template + constexpr R invoke_r(F&& f, Args&&... args) + noexcept(is_nothrow_invocable_r_v); -\pnum -\returns -The first function template returns -\begin{codeblock} -less::pointer>()(x.get(), nullptr) -\end{codeblock} -The second function template returns -\begin{codeblock} -less::pointer>()(nullptr, x.get()) -\end{codeblock} -\end{itemdescr} + // \ref{refwrap}, \tcode{reference_wrapper} + template class reference_wrapper; -\indexlibrarymember{operator>}{unique_ptr}% -\begin{itemdecl} -template - bool operator>(const unique_ptr& x, nullptr_t); -template - bool operator>(nullptr_t, const unique_ptr& x); -\end{itemdecl} + template constexpr reference_wrapper ref(T&) noexcept; + template constexpr reference_wrapper cref(const T&) noexcept; + template void ref(const T&&) = delete; + template void cref(const T&&) = delete; -\begin{itemdescr} -\pnum -\returns -The first function template returns \tcode{nullptr < x}. -The second function template returns \tcode{x < nullptr}. -\end{itemdescr} + template constexpr reference_wrapper ref(reference_wrapper) noexcept; + template constexpr reference_wrapper cref(reference_wrapper) noexcept; -\indexlibrarymember{operator<=}{unique_ptr}% -\begin{itemdecl} -template - bool operator<=(const unique_ptr& x, nullptr_t); -template - bool operator<=(nullptr_t, const unique_ptr& x); -\end{itemdecl} + // \ref{arithmetic.operations}, arithmetic operations + template struct plus; + template struct minus; + template struct multiplies; + template struct divides; + template struct modulus; + template struct negate; + template<> struct plus; + template<> struct minus; + template<> struct multiplies; + template<> struct divides; + template<> struct modulus; + template<> struct negate; -\begin{itemdescr} -\pnum -\returns -The first function template returns \tcode{!(nullptr < x)}. -The second function template returns \tcode{!(x < nullptr)}. -\end{itemdescr} + // \ref{comparisons}, comparisons + template struct equal_to; + template struct not_equal_to; + template struct greater; + template struct less; + template struct greater_equal; + template struct less_equal; + template<> struct equal_to; + template<> struct not_equal_to; + template<> struct greater; + template<> struct less; + template<> struct greater_equal; + template<> struct less_equal; -\indexlibrarymember{operator>=}{unique_ptr}% -\begin{itemdecl} -template - bool operator>=(const unique_ptr& x, nullptr_t); -template - bool operator>=(nullptr_t, const unique_ptr& x); -\end{itemdecl} + // \ref{comparisons.three.way}, class \tcode{compare_three_way} + struct compare_three_way; -\begin{itemdescr} -\pnum -\returns -The first function template returns \tcode{!(x < nullptr)}. -The second function template returns \tcode{!(nullptr < x)}. -\end{itemdescr} + // \ref{logical.operations}, logical operations + template struct logical_and; + template struct logical_or; + template struct logical_not; + template<> struct logical_and; + template<> struct logical_or; + template<> struct logical_not; -\indexlibrarymember{operator<=>}{unique_ptr}% -\begin{itemdecl} -template - requires @\libconcept{three_way_comparable}@::pointer> - compare_three_way_result_t::pointer> - operator<=>(const unique_ptr& x, nullptr_t); -\end{itemdecl} + // \ref{bitwise.operations}, bitwise operations + template struct bit_and; + template struct bit_or; + template struct bit_xor; + template struct bit_not; + template<> struct bit_and; + template<> struct bit_or; + template<> struct bit_xor; + template<> struct bit_not; -\begin{itemdescr} -\pnum -\returns -\begin{codeblock} -compare_three_way()(x.get(), static_cast::pointer>(nullptr)). -\end{codeblock} -\end{itemdescr} + // \ref{func.identity}, identity + struct identity; -\rSec3[unique.ptr.io]{I/O} + // \ref{func.not.fn}, function template \tcode{not_fn} + template constexpr @\unspec@ not_fn(F&& f); -\indexlibrarymember{operator<<}{unique_ptr}% -\begin{itemdecl} -template - basic_ostream& operator<<(basic_ostream& os, const unique_ptr& p); -\end{itemdecl} + // \ref{func.bind.partial}, function templates \tcode{bind_front} and \tcode{bind_back} + template constexpr @\unspec@ bind_front(F&&, Args&&...); + template constexpr @\unspec@ bind_back(F&&, Args&&...); -\begin{itemdescr} -\pnum -\constraints -\tcode{os << p.get()} is a valid expression. + // \ref{func.bind}, bind + template struct is_bind_expression; + template + inline constexpr bool @\libglobal{is_bind_expression_v}@ = is_bind_expression::value; + template struct is_placeholder; + template + inline constexpr int @\libglobal{is_placeholder_v}@ = is_placeholder::value; -\pnum -\effects -Equivalent to: \tcode{os << p.get();} + template + constexpr @\unspec@ bind(F&&, BoundArgs&&...); + template + constexpr @\unspec@ bind(F&&, BoundArgs&&...); -\pnum -\returns -\tcode{os}. -\end{itemdescr} + namespace placeholders { + // \tcode{\placeholder{M}} is the \impldef{number of placeholders for bind expressions} number of placeholders + @\seebelownc@ _1; + @\seebelownc@ _2; + . + . + . + @\seebelownc@ _@\placeholdernc{M}@; + } -\rSec2[util.smartptr.weak.bad]{Class \tcode{bad_weak_ptr}}% -\indextext{smart pointers|(}% + // \ref{func.memfn}, member function adaptors + template + constexpr @\unspec@ mem_fn(R T::*) noexcept; -\indexlibraryglobal{bad_weak_ptr}% -\begin{codeblock} -namespace std { - class bad_weak_ptr : public exception { - public: - // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; - }; -} -\end{codeblock} + // \ref{func.wrap}, polymorphic function wrappers + class bad_function_call; -\pnum -An exception of type \tcode{bad_weak_ptr} is thrown by the \tcode{shared_ptr} -constructor taking a \tcode{weak_ptr}. + template class function; // \notdef + template class function; -\indexlibrarymember{what}{bad_weak_ptr}% -\begin{itemdecl} -const char* what() const noexcept override; -\end{itemdecl} + // \ref{func.wrap.func.alg}, specialized algorithms + template + void swap(function&, function&) noexcept; -\begin{itemdescr} -\pnum -\returns -An \impldef{return value of \tcode{bad_weak_ptr::what}} \ntbs{}. -\end{itemdescr} + // \ref{func.wrap.func.nullptr}, null pointer comparison operator functions + template + bool operator==(const function&, nullptr_t) noexcept; -\rSec2[util.smartptr.shared]{Class template \tcode{shared_ptr}} + // \ref{func.wrap.move}, move only wrapper + template class move_only_function; // \notdef + template + class move_only_function; // \seebelow -\rSec3[util.smartptr.shared.general]{General} + // \ref{func.search}, searchers + template> + class default_searcher; -\pnum -\indexlibraryglobal{shared_ptr}% -The \tcode{shared_ptr} class template stores a pointer, usually obtained -via \keyword{new}. \tcode{shared_ptr} implements semantics of shared ownership; -the last remaining owner of the pointer is responsible for destroying -the object, or otherwise releasing the resources associated with the stored pointer. A -\tcode{shared_ptr} is said to be empty if it does not own a pointer. + template::value_type>, + class BinaryPredicate = equal_to<>> + class boyer_moore_searcher; -\begin{codeblock} -namespace std { - template class shared_ptr { - public: - using element_type = remove_extent_t; - using weak_type = weak_ptr; - - // \ref{util.smartptr.shared.const}, constructors - constexpr shared_ptr() noexcept; - constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { } - template - explicit shared_ptr(Y* p); - template - shared_ptr(Y* p, D d); - template - shared_ptr(Y* p, D d, A a); - template - shared_ptr(nullptr_t p, D d); - template - shared_ptr(nullptr_t p, D d, A a); - template - shared_ptr(const shared_ptr& r, element_type* p) noexcept; - template - shared_ptr(shared_ptr&& r, element_type* p) noexcept; - shared_ptr(const shared_ptr& r) noexcept; - template - shared_ptr(const shared_ptr& r) noexcept; - shared_ptr(shared_ptr&& r) noexcept; - template - shared_ptr(shared_ptr&& r) noexcept; - template - explicit shared_ptr(const weak_ptr& r); - template - shared_ptr(unique_ptr&& r); - - // \ref{util.smartptr.shared.dest}, destructor - ~shared_ptr(); - - // \ref{util.smartptr.shared.assign}, assignment - shared_ptr& operator=(const shared_ptr& r) noexcept; - template - shared_ptr& operator=(const shared_ptr& r) noexcept; - shared_ptr& operator=(shared_ptr&& r) noexcept; - template - shared_ptr& operator=(shared_ptr&& r) noexcept; - template - shared_ptr& operator=(unique_ptr&& r); - - // \ref{util.smartptr.shared.mod}, modifiers - void swap(shared_ptr& r) noexcept; - void reset() noexcept; - template - void reset(Y* p); - template - void reset(Y* p, D d); - template - void reset(Y* p, D d, A a); - - // \ref{util.smartptr.shared.obs}, observers - element_type* get() const noexcept; - T& operator*() const noexcept; - T* operator->() const noexcept; - element_type& operator[](ptrdiff_t i) const; - long use_count() const noexcept; - explicit operator bool() const noexcept; - template - bool owner_before(const shared_ptr& b) const noexcept; - template - bool owner_before(const weak_ptr& b) const noexcept; - }; + template::value_type>, + class BinaryPredicate = equal_to<>> + class boyer_moore_horspool_searcher; + // \ref{unord.hash}, class template hash template - shared_ptr(weak_ptr) -> shared_ptr; - template - shared_ptr(unique_ptr) -> shared_ptr; + struct hash; + + namespace ranges { + // \ref{range.cmp}, concept-constrained comparisons + struct equal_to; + struct not_equal_to; + struct greater; + struct less; + struct greater_equal; + struct less_equal; + } } \end{codeblock} \pnum -Specializations of \tcode{shared_ptr} shall be \oldconcept{CopyConstructible}, -\oldconcept{CopyAssignable}, and \oldconcept{\-Less\-Than\-Comparable}, allowing their use in standard -containers. Specializations of \tcode{shared_ptr} shall be -contextually convertible to \tcode{bool}, -allowing their use in boolean expressions and declarations in conditions. +\begin{example} +If a \Cpp{} program wants to have a by-element addition of two vectors \tcode{a} +and \tcode{b} containing \tcode{double} and put the result into \tcode{a}, +it can do: -\pnum -The template parameter \tcode{T} of \tcode{shared_ptr} -may be an incomplete type. -\begin{note} -\tcode{T} can be a function type. -\end{note} +\begin{codeblock} +transform(a.begin(), a.end(), b.begin(), a.begin(), plus()); +\end{codeblock} +\end{example} \pnum \begin{example} +To negate every element of \tcode{a}: + \begin{codeblock} -if (shared_ptr px = dynamic_pointer_cast(py)) { - // do something with \tcode{px} -} +transform(a.begin(), a.end(), a.begin(), negate()); \end{codeblock} + \end{example} +\rSec2[func.def]{Definitions} + \pnum -For purposes of determining the presence of a data race, member functions shall -access and modify only the \tcode{shared_ptr} and \tcode{weak_ptr} objects -themselves and not objects they refer to. Changes in \tcode{use_count()} do not -reflect modifications that can introduce data races. +The following definitions apply to this Clause: \pnum -For the purposes of subclause \ref{smartptr}, -a pointer type \tcode{Y*} is said to be -\defnx{compatible with}{compatible with!\idxcode{shared_ptr}} -a pointer type \tcode{T*} when either -\tcode{Y*} is convertible to \tcode{T*} or -\tcode{Y} is \tcode{U[N]} and \tcode{T} is \cv{}~\tcode{U[]}. +A \defn{call signature} is the name of a return type followed by a +parenthesized comma-separated list of zero or more argument types. -\rSec3[util.smartptr.shared.const]{Constructors} +\pnum +A \defnadj{callable}{type} is a function object type\iref{function.objects} or a pointer to member. \pnum -In the constructor definitions below, -enables \tcode{shared_from_this} with \tcode{p}, -for a pointer \tcode{p} of type \tcode{Y*}, -means that if \tcode{Y} has an unambiguous and accessible base class -that is a specialization of \tcode{enable_shared_from_this}\iref{util.smartptr.enab}, -then \tcode{remove_cv_t*} shall be implicitly convertible to \tcode{T*} and -the constructor evaluates the statement: -\begin{codeblock} -if (p != nullptr && p->weak_this.expired()) - p->weak_this = shared_ptr>(*this, const_cast*>(p)); -\end{codeblock} -The assignment to the \tcode{weak_this} member is not atomic and -conflicts with any potentially concurrent access to the same object\iref{intro.multithread}. +A \defnadj{callable}{object} is an object of a callable type. -\indexlibraryctor{shared_ptr}% -\begin{itemdecl} -constexpr shared_ptr() noexcept; -\end{itemdecl} - -\begin{itemdescr} \pnum -\ensures -\tcode{use_count() == 0 \&\& get() == nullptr}. -\end{itemdescr} - -\indexlibraryctor{shared_ptr}% -\begin{itemdecl} -template explicit shared_ptr(Y* p); -\end{itemdecl} +A \defnx{call wrapper type}{call wrapper!type} is a type that holds a callable object +and supports a call operation that forwards to that object. -\begin{itemdescr} \pnum -\constraints -When \tcode{T} is an array type, -the expression \tcode{delete[] p} is well-formed and either -\tcode{T} is \tcode{U[N]} and \tcode{Y(*)[N]} is convertible to \tcode{T*}, or -\tcode{T} is \tcode{U[]} and \tcode{Y(*)[]} is convertible to \tcode{T*}. -When \tcode{T} is not an array type, -the expression \tcode{delete p} is well-formed and -\tcode{Y*} is convertible to \tcode{T*}. +A \defn{call wrapper} is an object of a call wrapper type. \pnum -\mandates -\tcode{Y} is a complete type. +A \defn{target object} is the callable object held by a call wrapper. \pnum -\expects -The expression -\tcode{delete[] p}, when \tcode{T} is an array type, or -\tcode{delete p}, when \tcode{T} is not an array type, -has well-defined behavior, and -does not throw exceptions. +A call wrapper type may additionally hold +a sequence of objects and references +that may be passed as arguments to the target object. +These entities are collectively referred to +as \defnx{bound argument entities}{bound argument entity}. \pnum -\effects -When \tcode{T} is not an array type, -constructs a \tcode{shared_ptr} object -that owns the pointer \tcode{p}. -Otherwise, constructs a \tcode{shared_ptr} -that owns \tcode{p} and a deleter of an -unspecified type that calls \tcode{delete[] p}. -When \tcode{T} is not an array type, -enables \tcode{shared_from_this} with \tcode{p}. -If an exception is thrown, \tcode{delete p} is called -when \tcode{T} is not an array type, \tcode{delete[] p} otherwise. +The target object and bound argument entities of the call wrapper are +collectively referred to as \defnx{state entities}{state entity}. -\pnum -\ensures -\tcode{use_count() == 1 \&\& get() == p}. +\rSec2[func.require]{Requirements} \pnum -\throws -\tcode{bad_alloc}, or an \impldef{exception type when \tcode{shared_ptr} -constructor fails} exception when a resource other than memory cannot be obtained. -\end{itemdescr} +\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% +Define \tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} as follows: +\begin{itemize} +\item \tcode{(t$_1$.*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a +member function of a class \tcode{T} +and \tcode{is_base_of_v>} is \tcode{true}; -\indexlibraryctor{shared_ptr}% -\begin{itemdecl} -template shared_ptr(Y* p, D d); -template shared_ptr(Y* p, D d, A a); -template shared_ptr(nullptr_t p, D d); -template shared_ptr(nullptr_t p, D d, A a); -\end{itemdecl} +\item \tcode{(t$_1$.get().*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a +member function of a class \tcode{T} +and \tcode{remove_cvref_t} is a specialization of \tcode{reference_wrapper}; -\begin{itemdescr} -\pnum -\constraints -\tcode{is_move_constructible_v} is \tcode{true}, and -\tcode{d(p)} is a well-formed expression. -For the first two overloads: +\item \tcode{((*t$_1$).*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a +member function of a class \tcode{T} +and \tcode{t$_1$} does not satisfy the previous two items; -\begin{itemize} -\item -If \tcode{T} is an array type, then either -\tcode{T} is \tcode{U[N]} and \tcode{Y(*)[N]} is convertible to \tcode{T*}, or -\tcode{T} is \tcode{U[]} and \tcode{Y(*)[]} is convertible to \tcode{T*}. +\item \tcode{t$_1$.*f} when \tcode{N == 1} and \tcode{f} is a pointer to +data member of a class \tcode{T} +and \tcode{is_base_of_v>} is \tcode{true}; -\item -If \tcode{T} is not an array type, then \tcode{Y*} is convertible to \tcode{T*}. -\end{itemize} +\item \tcode{t$_1$.get().*f} when \tcode{N == 1} and \tcode{f} is a pointer to +data member of a class \tcode{T} +and \tcode{remove_cvref_t} is a specialization of \tcode{reference_wrapper}; -\pnum -\expects -Construction of \tcode{d} and a deleter of type \tcode{D} -initialized with \tcode{std::move(d)} do not throw exceptions. -The expression \tcode{d(p)} -has well-defined behavior and does not throw exceptions. -\tcode{A} meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). +\item \tcode{(*t$_1$).*f} when \tcode{N == 1} and \tcode{f} is a pointer to +data member of a class \tcode{T} +and \tcode{t$_1$} does not satisfy the previous two items; -\pnum -\effects -Constructs a \tcode{shared_ptr} object that owns the -object \tcode{p} and the deleter \tcode{d}. -When \tcode{T} is not an array type, -the first and second constructors enable \tcode{shared_from_this} with \tcode{p}. -The second and fourth constructors shall use a copy of \tcode{a} to -allocate memory for internal use. -If an exception is thrown, \tcode{d(p)} is called. +\item \tcode{f(t$_1$, t$_2$, $\dotsc$, t$_N$)} in all other cases. +\end{itemize} \pnum -\ensures -\tcode{use_count() == 1 \&\& get() == p}. +\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% +Define \tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} as +\tcode{static_cast(\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$))} +if \tcode{R} is \cv{}~\keyword{void}, otherwise +\tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} implicitly converted +to \tcode{R}. +If +\tcode{reference_converts_from_temporary_v} +is \tcode{true}, +\tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} +is ill-formed. \pnum -\throws -\tcode{bad_alloc}, or an \impldef{exception type when \tcode{shared_ptr} -constructor fails} exception -when a resource other than memory cannot be obtained. -\end{itemdescr} +\indextext{call wrapper}% +\indextext{call wrapper!simple}% +\indextext{call wrapper!forwarding}% +Every call wrapper\iref{func.def} meets the \oldconcept{MoveConstructible} +and \oldconcept{Destructible} requirements. +An \defn{argument forwarding call wrapper} is a +call wrapper that can be called with an arbitrary argument list +and delivers the arguments to the target object as references. +This forwarding step delivers rvalue arguments as rvalue references +and lvalue arguments as lvalue references. +\begin{note} +In a typical implementation, argument forwarding call wrappers have +an overloaded function call operator of the form +\begin{codeblock} +template + constexpr R operator()(UnBoundArgs&&... unbound_args) @\textit{cv-qual}@; +\end{codeblock} +\end{note} -\indexlibraryctor{shared_ptr}% -\begin{itemdecl} -template shared_ptr(const shared_ptr& r, element_type* p) noexcept; -template shared_ptr(shared_ptr&& r, element_type* p) noexcept; -\end{itemdecl} +\pnum +\label{term.perfect.forwarding.call.wrapper}% +A \defnadj{perfect forwarding}{call wrapper} is +an argument forwarding call wrapper +that forwards its state entities to the underlying call expression. +This forwarding step delivers a state entity of type \tcode{T} +as \cv{} \tcode{T\&} +when the call is performed on an lvalue of the call wrapper type and +as \cv{} \tcode{T\&\&} otherwise, +where \cv{} represents the cv-qualifiers of the call wrapper and +where \cv{} shall be neither \tcode{volatile} nor \tcode{const volatile}. -\begin{itemdescr} \pnum -\effects -Constructs a \tcode{shared_ptr} instance that -stores \tcode{p} and shares ownership with -the initial value of \tcode{r}. +A \defn{call pattern} defines the semantics of invoking +a perfect forwarding call wrapper. +A postfix call performed on a perfect forwarding call wrapper is +expression-equivalent\iref{defns.expression.equivalent} to +an expression \tcode{e} determined from its call pattern \tcode{cp} +by replacing all occurrences +of the arguments of the call wrapper and its state entities +with references as described in the corresponding forwarding steps. \pnum -\ensures -\tcode{get() == p}. -For the second overload, -\tcode{r} is empty and \tcode{r.get() == nullptr}. +\label{term.simple.call.wrapper}% +A \defn{simple call wrapper} is a perfect forwarding call wrapper that meets +the \oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} requirements +and whose copy constructor, move constructor, and assignment operators +are constexpr functions that do not throw exceptions. \pnum +The copy/move constructor of an argument forwarding call wrapper has +the same apparent semantics +as if memberwise copy/move of its state entities +were performed\iref{class.copy.ctor}. \begin{note} -Use of this constructor leads to a dangling pointer -unless \tcode{p} remains valid -at least until the ownership group of \tcode{r} is destroyed. +This implies that each of the copy/move constructors has +the same exception-specification as +the corresponding implicit definition and is declared as \keyword{constexpr} +if the corresponding implicit definition would be considered to be constexpr. \end{note} \pnum -\begin{note} -This constructor allows creation of an empty -\tcode{shared_ptr} instance with a non-null stored pointer. -\end{note} -\end{itemdescr} +Argument forwarding call wrappers returned by +a given standard library function template have the same type +if the types of their corresponding state entities are the same. -\indexlibraryctor{shared_ptr}% +\rSec2[func.invoke]{\tcode{invoke} functions} +\indexlibraryglobal{invoke}% +\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% \begin{itemdecl} -shared_ptr(const shared_ptr& r) noexcept; -template shared_ptr(const shared_ptr& r) noexcept; +template + constexpr invoke_result_t invoke(F&& f, Args&&... args) + noexcept(is_nothrow_invocable_v); \end{itemdecl} \begin{itemdescr} \pnum \constraints -For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. - -\pnum -\effects -If \tcode{r} is empty, constructs -an empty \tcode{shared_ptr} object; otherwise, constructs -a \tcode{shared_ptr} object that shares ownership with \tcode{r}. +\tcode{is_invocable_v} is \tcode{true}. \pnum -\ensures -\tcode{get() == r.get() \&\& use_count() == r.use_count()}. +\returns +\tcode{\placeholdernc{INVOKE}(std::forward(f), std::forward(args)...)}\iref{func.require}. \end{itemdescr} -\indexlibraryctor{shared_ptr}% +\indexlibraryglobal{invoke_r}% \begin{itemdecl} -shared_ptr(shared_ptr&& r) noexcept; -template shared_ptr(shared_ptr&& r) noexcept; +template + constexpr R invoke_r(F&& f, Args&&... args) + noexcept(is_nothrow_invocable_r_v); \end{itemdecl} \begin{itemdescr} \pnum \constraints -For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. - -\pnum -\effects -Move constructs a \tcode{shared_ptr} instance from \tcode{r}. +\tcode{is_invocable_r_v} is \tcode{true}. \pnum -\ensures -\tcode{*this} contains the old value of -\tcode{r}. \tcode{r} is empty, and \tcode{r.get() == nullptr}. +\returns +\tcode{\placeholdernc{INVOKE}(std::forward(f), std::forward(args)...)}\iref{func.require}. \end{itemdescr} -\indexlibraryctor{shared_ptr}% -\indexlibraryglobal{weak_ptr}% -\begin{itemdecl} -template explicit shared_ptr(const weak_ptr& r); -\end{itemdecl} +\rSec2[refwrap]{Class template \tcode{reference_wrapper}} -\begin{itemdescr} -\pnum -\constraints -\tcode{Y*} is compatible with \tcode{T*}. +\rSec3[refwrap.general]{General} + +\indexlibraryglobal{reference_wrapper}% +\indextext{function object!\idxcode{reference_wrapper}}% +\begin{codeblock} +namespace std { + template class reference_wrapper { + public: + // types + using type = T; + + // \ref{refwrap.const}, constructors + template + constexpr reference_wrapper(U&&) noexcept(@\seebelow@); + constexpr reference_wrapper(const reference_wrapper& x) noexcept; + + // \ref{refwrap.assign}, assignment + constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept; + + // \ref{refwrap.access}, access + constexpr operator T& () const noexcept; + constexpr T& get() const noexcept; + + // \ref{refwrap.invoke}, invocation + template + constexpr invoke_result_t operator()(ArgTypes&&...) const; + }; + + template + reference_wrapper(T&) -> reference_wrapper; +} +\end{codeblock} \pnum -\effects -Constructs a \tcode{shared_ptr} object that shares ownership with -\tcode{r} and stores a copy of the pointer stored in \tcode{r}. -If an exception is thrown, the constructor has no effect. +\tcode{reference_wrapper} is a \oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} wrapper +around a reference to an object or function of type \tcode{T}. \pnum -\ensures -\tcode{use_count() == r.use_count()}. +\tcode{reference_wrapper} is +a trivially copyable type\iref{term.trivially.copyable.type}. \pnum -\throws -\tcode{bad_weak_ptr} when \tcode{r.expired()}. -\end{itemdescr} +The template parameter \tcode{T} of \tcode{reference_wrapper} +may be an incomplete type. -\indexlibraryctor{shared_ptr}% -\indexlibraryglobal{unique_ptr}% +\rSec3[refwrap.const]{Constructors} + +\indexlibraryctor{reference_wrapper}% \begin{itemdecl} -template shared_ptr(unique_ptr&& r); +template + constexpr reference_wrapper(U&& u) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{\placeholdernc{FUN}} denote the exposition-only functions +\begin{codeblock} +void @\placeholdernc{FUN}@(T&) noexcept; +void @\placeholdernc{FUN}@(T&&) = delete; +\end{codeblock} + \pnum \constraints -\tcode{Y*} is compatible with \tcode{T*} and -\tcode{unique_ptr::pointer} is convertible to \tcode{element_type*}. +The expression \tcode{\placeholdernc{FUN}(declval())} is well-formed and +\tcode{is_same_v, reference_wrapper>} is \tcode{false}. \pnum \effects -If \tcode{r.get() == nullptr}, equivalent to \tcode{shared_ptr()}. -Otherwise, if \tcode{D} is not a reference type, -equivalent to \tcode{shared_ptr(r.release(), std::move(r.get_deleter()))}. -Otherwise, equivalent to \tcode{shared_ptr(r.release(), ref(r.get_deleter()))}. -If an exception is thrown, the constructor has no effect. -\end{itemdescr} +Creates a variable \tcode{r} +as if by \tcode{T\& r = std::forward(u)}, +then constructs a \tcode{reference_wrapper} object +that stores a reference to \tcode{r}. -\rSec3[util.smartptr.shared.dest]{Destructor} +\pnum +\remarks +The exception specification is equivalent to +\tcode{noexcept(\placeholdernc{FUN}(declval()))}. +\end{itemdescr} -\indexlibrarydtor{shared_ptr}% +\indexlibraryctor{reference_wrapper}% \begin{itemdecl} -~shared_ptr(); +constexpr reference_wrapper(const reference_wrapper& x) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -\begin{itemize} -\item If \tcode{*this} is empty or shares ownership with another -\tcode{shared_ptr} instance (\tcode{use_count() > 1}), there are no side effects. - -\item -Otherwise, if \tcode{*this} owns an object -\tcode{p} and a deleter \tcode{d}, \tcode{d(p)} is called. - -\item Otherwise, \tcode{*this} owns a pointer \tcode{p}, -and \tcode{delete p} is called. -\end{itemize} +Constructs a \tcode{reference_wrapper} object that +stores a reference to \tcode{x.get()}. \end{itemdescr} -\pnum -\begin{note} -Since the destruction of \tcode{*this} -decreases the number of instances that share ownership with \tcode{*this} -by one, -after \tcode{*this} has been destroyed -all \tcode{shared_ptr} instances that shared ownership with -\tcode{*this} will report a \tcode{use_count()} that is one less -than its previous value. -\end{note} - -\rSec3[util.smartptr.shared.assign]{Assignment} +\rSec3[refwrap.assign]{Assignment} -\indexlibrarymember{operator=}{shared_ptr}% +\indexlibrarymember{operator=}{reference_wrapper}% \begin{itemdecl} -shared_ptr& operator=(const shared_ptr& r) noexcept; -template shared_ptr& operator=(const shared_ptr& r) noexcept; +constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{shared_ptr(r).swap(*this)}. - -\pnum -\returns -\tcode{*this}. - -\pnum -\begin{note} -The use count updates caused by the temporary object -construction and destruction are not observable side -effects, so the implementation can meet the effects (and the -implied guarantees) via different means, without creating a -temporary. In particular, in the example: -\begin{codeblock} -shared_ptr p(new int); -shared_ptr q(p); -p = p; -q = p; -\end{codeblock} -both assignments can be no-ops. -\end{note} +\ensures +\tcode{*this} stores a reference to \tcode{x.get()}. \end{itemdescr} -\indexlibrarymember{operator=}{shared_ptr}% +\rSec3[refwrap.access]{Access} + +\indexlibrarymember{operator T\&}{reference_wrapper}% \begin{itemdecl} -shared_ptr& operator=(shared_ptr&& r) noexcept; -template shared_ptr& operator=(shared_ptr&& r) noexcept; +constexpr operator T& () const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{shared_ptr(std::move(r)).swap(*this)}. - \pnum \returns -\tcode{*this}. +The stored reference. \end{itemdescr} -\indexlibrarymember{operator=}{shared_ptr}% +\indexlibrarymember{get}{reference_wrapper}% \begin{itemdecl} -template shared_ptr& operator=(unique_ptr&& r); +constexpr T& get() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{shared_ptr(std::move(r)).swap(*this)}. - \pnum \returns -\tcode{*this}. +The stored reference. \end{itemdescr} -\rSec3[util.smartptr.shared.mod]{Modifiers} +\rSec3[refwrap.invoke]{Invocation} -\indexlibrarymember{swap}{shared_ptr}% +\indexlibrarymember{operator()}{reference_wrapper}% \begin{itemdecl} -void swap(shared_ptr& r) noexcept; +template + constexpr invoke_result_t + operator()(ArgTypes&&... args) const; \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{T} is a complete type. \pnum -\effects -Exchanges the contents of \tcode{*this} and \tcode{r}. +\returns +\tcode{\placeholdernc{INVOKE}(get(), std::forward(args)...)}.\iref{func.require} \end{itemdescr} -\indexlibrarymember{reset}{shared_ptr}% -\begin{itemdecl} -void reset() noexcept; -\end{itemdecl} -\begin{itemdescr} +\rSec3[refwrap.helpers]{Helper functions} + \pnum -\effects -Equivalent to \tcode{shared_ptr().swap(*this)}. -\end{itemdescr} +The template parameter \tcode{T} of +the following \tcode{ref} and \tcode{cref} function templates +may be an incomplete type. -\indexlibrarymember{reset}{shared_ptr}% +\indexlibrarymember{ref}{reference_wrapper}% \begin{itemdecl} -template void reset(Y* p); +template constexpr reference_wrapper ref(T& t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{shared_ptr(p).swap(*this)}. +\returns +\tcode{reference_wrapper(t)}. \end{itemdescr} -\indexlibrarymember{reset}{shared_ptr}% +\indexlibrarymember{ref}{reference_wrapper}% \begin{itemdecl} -template void reset(Y* p, D d); +template constexpr reference_wrapper ref(reference_wrapper t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{shared_ptr(p, d).swap(*this)}. +\returns +\tcode{t}. \end{itemdescr} -\indexlibrarymember{reset}{shared_ptr}% +\indexlibrarymember{cref}{reference_wrapper}% \begin{itemdecl} -template void reset(Y* p, D d, A a); +template constexpr reference_wrapper cref(const T& t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{shared_ptr(p, d, a).swap(*this)}. +\returns +\tcode{reference_wrapper (t)}. \end{itemdescr} -\rSec3[util.smartptr.shared.obs]{Observers} -\indexlibrarymember{get}{shared_ptr}% +\indexlibrarymember{cref}{reference_wrapper}% \begin{itemdecl} -element_type* get() const noexcept; +template constexpr reference_wrapper cref(reference_wrapper t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -The stored pointer. +\tcode{t}. \end{itemdescr} -\indexlibrarymember{operator*}{shared_ptr}% -\begin{itemdecl} -T& operator*() const noexcept; -\end{itemdecl} +\rSec2[arithmetic.operations]{Arithmetic operations} -\begin{itemdescr} -\pnum -\expects -\tcode{get() != 0}. +\rSec3[arithmetic.operations.general]{General} \pnum -\returns -\tcode{*get()}. +The library provides basic function object classes for all of the arithmetic +operators in the language\iref{expr.mul,expr.add}. -\pnum -\remarks -When \tcode{T} is an array type or \cv{}~\keyword{void}, -it is unspecified whether this -member function is declared. If it is declared, it is unspecified what its -return type is, except that the declaration (although not necessarily the -definition) of the function shall be well-formed. -\end{itemdescr} +\rSec3[arithmetic.operations.plus]{Class template \tcode{plus}} -\indexlibrarymember{operator->}{shared_ptr}% +\indexlibraryglobal{plus}% \begin{itemdecl} -T* operator->() const noexcept; +template struct plus { + constexpr T operator()(const T& x, const T& y) const; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\expects -\tcode{get() != 0}. +\indexlibrarymember{operator()}{plus}% +\begin{itemdecl} +constexpr T operator()(const T& x, const T& y) const; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{get()}. - -\pnum -\remarks -When \tcode{T} is an array type, -it is unspecified whether this member function is declared. -If it is declared, it is unspecified what its return type is, -except that the declaration (although not necessarily the definition) -of the function shall be well-formed. +\tcode{x + y}. \end{itemdescr} -\indexlibrarymember{operator[]}{shared_ptr}% +\indexlibraryglobal{plus<>}% \begin{itemdecl} -element_type& operator[](ptrdiff_t i) const; +template<> struct plus { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) + std::forward(u)); + + using is_transparent = @\unspec@; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\expects -\tcode{get() != 0 \&\& i >= 0}. -If \tcode{T} is \tcode{U[N]}, \tcode{i < N}. +\indexlibrarymember{operator()}{plus<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) + std::forward(u)); +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{get()[i]}. +\tcode{std::forward(t) + std::forward(u)}. +\end{itemdescr} -\pnum -\throws -Nothing. +\rSec3[arithmetic.operations.minus]{Class template \tcode{minus}} -\pnum -\remarks -When \tcode{T} is not an array type, -it is unspecified whether this member function is declared. -If it is declared, it is unspecified what its return type is, -except that the declaration (although not necessarily the definition) -of the function shall be well-formed. -\end{itemdescr} +\indexlibraryglobal{minus}% +\begin{itemdecl} +template struct minus { + constexpr T operator()(const T& x, const T& y) const; +}; +\end{itemdecl} -\indexlibrarymember{use_count}{shared_ptr}% +\indexlibrarymember{operator()}{minus}% \begin{itemdecl} -long use_count() const noexcept; +constexpr T operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} -\pnum -\sync -None. - \pnum \returns -The number of \tcode{shared_ptr} objects, \tcode{*this} included, -that share ownership with \tcode{*this}, or \tcode{0} when \tcode{*this} is -empty. - -\pnum -\begin{note} -\tcode{get() == nullptr} -does not imply a specific return value of \tcode{use_count()}. -\end{note} +\tcode{x - y}. +\end{itemdescr} -\pnum -\begin{note} -\tcode{weak_ptr::lock()} -can affect the return value of \tcode{use_count()}. -\end{note} +\indexlibraryglobal{minus<>}% +\begin{itemdecl} +template<> struct minus { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) - std::forward(u)); -\pnum -\begin{note} -When multiple threads -might affect the return value of \tcode{use_count()}, -the result is approximate. -In particular, \tcode{use_count() == 1} does not imply that accesses through -a previously destroyed \tcode{shared_ptr} have in any sense completed. -\end{note} -\end{itemdescr} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibrarymember{operator bool}{shared_ptr}% +\indexlibrarymember{operator()}{minus<>}% \begin{itemdecl} -explicit operator bool() const noexcept; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) - std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{get() != 0}. +\tcode{std::forward(t) - std::forward(u)}. \end{itemdescr} -\indexlibrarymember{owner_before}{shared_ptr}% +\rSec3[arithmetic.operations.multiplies]{Class template \tcode{multiplies}} + +\indexlibraryglobal{multiplies}% +\begin{itemdecl} +template struct multiplies { + constexpr T operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{multiplies}% \begin{itemdecl} -template bool owner_before(const shared_ptr& b) const noexcept; -template bool owner_before(const weak_ptr& b) const noexcept; +constexpr T operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum \returns -An unspecified value such that -\begin{itemize} -\item \tcode{x.owner_before(y)} defines a strict weak ordering as defined in~\ref{alg.sorting}; - -\item under the equivalence relation defined by \tcode{owner_before}, -\tcode{!a.owner_before(b) \&\& !b.owner_before(a)}, two \tcode{shared_ptr} or -\tcode{weak_ptr} instances are equivalent if and only if they share ownership or -are both empty. -\end{itemize} - +\tcode{x * y}. \end{itemdescr} -\rSec3[util.smartptr.shared.create]{Creation} +\indexlibraryglobal{multiplies<>}% +\begin{itemdecl} +template<> struct multiplies { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) * std::forward(u)); -\pnum -The common requirements that apply to all -\tcode{make_shared}, -\tcode{allocate_shared}, -\tcode{make_shared_for_overwrite}, and -\tcode{allocate_shared_for_overwrite} overloads, -unless specified otherwise, are described below. + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% +\indexlibrarymember{operator()}{multiplies<>}% \begin{itemdecl} -template - shared_ptr make_shared(@\placeholdernc{args}@); -template - shared_ptr allocate_shared(const A& a, @\placeholdernc{args}@); -template - shared_ptr make_shared_for_overwrite(@\placeholdernc{args}@); -template - shared_ptr allocate_shared_for_overwrite(const A& a, @\placeholdernc{args}@); +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) * std::forward(u)); \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{A} meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). - -\pnum -\effects -Allocates memory for an object of type \tcode{T} -(or \tcode{U[N]} when \tcode{T} is \tcode{U[]}, -where \tcode{N} is determined from \placeholder{args} as specified by the concrete overload). -The object is initialized from \placeholder{args} as specified by the concrete overload. -The \tcode{allocate_shared} and \tcode{allocate_shared_for_overwrite} templates -use a copy of \tcode{a} -(rebound for an unspecified \tcode{value_type}) to allocate memory. -If an exception is thrown, the functions have no effect. - -\pnum -\ensures -\tcode{r.get() != 0 \&\& r.use_count() == 1}, -where \tcode{r} is the return value. - \pnum \returns -A \tcode{shared_ptr} instance that stores and owns the address of -the newly constructed object. +\tcode{std::forward(t) * std::forward(u)}. +\end{itemdescr} -\pnum -\throws -\tcode{bad_alloc}, or -an exception thrown from \tcode{allocate} or from the initialization of the object. +\rSec3[arithmetic.operations.divides]{Class template \tcode{divides}} -\pnum -\remarks -\begin{itemize} -\item - Implementations should perform no more than one memory allocation. - \begin{note} - This provides efficiency equivalent to an intrusive smart pointer. - \end{note} -\item - When an object of an array type \tcode{U} is specified to have - an initial value of \tcode{u} (of the same type), - this shall be interpreted to mean that - each array element of the object has as its initial value - the corresponding element from \tcode{u}. -\item - When an object of an array type is specified to have - a default initial value, - this shall be interpreted to mean that each array element of the object - has a default initial value. -\item - When a (sub)object of a non-array type \tcode{U} is specified to have - an initial value of \tcode{v}, or \tcode{U(l...)}, - where \tcode{l...} is a list of constructor arguments, - \tcode{make_shared} shall initialize this (sub)object - via the expression \tcode{::new(pv) U(v)} or \tcode{::new(pv) U(l...)} respectively, - where \tcode{pv} has type \tcode{void*} and points to storage - suitable to hold an object of type \tcode{U}. -\item - When a (sub)object of a non-array type \tcode{U} is specified to have - an initial value of \tcode{v}, or \tcode{U(l...)}, - where \tcode{l...} is a list of constructor arguments, - \tcode{allocate_shared} shall initialize this (sub)object - via the expression - \begin{itemize} - \item \tcode{allocator_traits::construct(a2, pv, v)} or - \item \tcode{allocator_traits::construct(a2, pv, l...)} - \end{itemize} - respectively, - where \tcode{pv} points to storage - suitable to hold an object of type \tcode{U} and - \tcode{a2} of type \tcode{A2} is a rebound copy of - the allocator \tcode{a} passed to \tcode{allocate_shared} - such that its \tcode{value_type} is \tcode{remove_cv_t}. -\item - When a (sub)object of non-array type \tcode{U} is specified to have - a default initial value, - \tcode{make_shared} shall initialize this (sub)object - via the expression \tcode{::new(pv) U()}, - where \tcode{pv} has type \tcode{void*} and points to storage - suitable to hold an object of type \tcode{U}. -\item - When a (sub)object of non-array type \tcode{U} is specified to have - a default initial value, - \tcode{allocate_shared} shall initialize this (sub)object - via the expression \tcode{allocator_traits::construct(a2, pv)}, - where \tcode{pv} points to storage - suitable to hold an object of type \tcode{U} and - \tcode{a2} of type \tcode{A2} is a rebound copy of - the allocator \tcode{a} passed to \tcode{allocate_shared} - such that its \tcode{value_type} is \tcode{remove_cv_t}. -\item - When a (sub)object of non-array type \tcode{U} is initialized by - \tcode{make_shared_for_overwrite} or\linebreak % avoid Overfull - \tcode{allocate_shared_for_overwrite}, - it is initialized via the expression \tcode{::new(pv) U}, - where \tcode{pv} has type \tcode{void*} and - points to storage suitable to hold an object of type \tcode{U}. -\item - Array elements are initialized in ascending order of their addresses. -\item - When the lifetime of the object managed by the return value ends, or - when the initialization of an array element throws an exception, - the initialized elements are destroyed in the reverse order - of their original construction. -\item - When a (sub)object of non-array type \tcode{U} - that was initialized by \tcode{make_shared} is to be destroyed, - it is destroyed via the expression \tcode{pv->\~{}U()} where - \tcode{pv} points to that object of type \tcode{U}. -\item - When a (sub)object of non-array type \tcode{U} - that was initialized by \tcode{allocate_shared} is to be destroyed, - it is destroyed via the expression - \tcode{allocator_traits::destroy(a2, pv)} where - \tcode{pv} points to that object of type \tcode{remove_cv_t} and - \tcode{a2} of type \tcode{A2} is a rebound copy of - the allocator \tcode{a} passed to \tcode{allocate_shared} - such that its \tcode{value_type} is \tcode{remove_cv_t}. -\end{itemize} -\begin{note} -These functions will typically allocate more memory than \tcode{sizeof(T)} to -allow for internal bookkeeping structures such as reference counts. -\end{note} -\end{itemdescr} +\indexlibraryglobal{divides}% +\begin{itemdecl} +template struct divides { + constexpr T operator()(const T& x, const T& y) const; +}; +\end{itemdecl} -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% +\indexlibrarymember{operator()}{divides}% \begin{itemdecl} -template - shared_ptr make_shared(Args&&... args); // \tcode{T} is not array -template - shared_ptr allocate_shared(const A& a, Args&&... args); // \tcode{T} is not array +constexpr T operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{T} is not an array type. - \pnum \returns -A \tcode{shared_ptr} to an object of type \tcode{T} -with an initial value \tcode{T(forward(args)...)}. +\tcode{x / y}. +\end{itemdescr} -\pnum -\remarks -The \tcode{shared_ptr} constructors called by these functions -enable \tcode{shared_from_this} -with the address of the newly constructed object of type \tcode{T}. +\indexlibraryglobal{divides<>}% +\begin{itemdecl} +template<> struct divides { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) / std::forward(u)); -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared(); // \tcode{shared_ptr} to \tcode{int()} -shared_ptr> q = make_shared>(16, 1); - // \tcode{shared_ptr} to vector of \tcode{16} elements with value \tcode{1} -\end{codeblock} -\end{example} -\end{itemdescr} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% +\indexlibrarymember{operator()}{divides<>}% \begin{itemdecl} -template shared_ptr - make_shared(size_t N); // \tcode{T} is \tcode{U[]} -template - shared_ptr allocate_shared(const A& a, size_t N); // \tcode{T} is \tcode{U[]} +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) / std::forward(u)); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{T} is of the form \tcode{U[]}. - \pnum \returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]} -with a default initial value, -where \tcode{U} is \tcode{remove_extent_t}. - -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared(1024); - // \tcode{shared_ptr} to a value-initialized \tcode{double[1024]} -shared_ptr q = make_shared(6); - // \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]} -\end{codeblock} -\end{example} +\tcode{std::forward(t) / std::forward(u)}. \end{itemdescr} -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% +\rSec3[arithmetic.operations.modulus]{Class template \tcode{modulus}} + +\indexlibraryglobal{modulus}% \begin{itemdecl} -template - shared_ptr make_shared(); // \tcode{T} is \tcode{U[N]} -template - shared_ptr allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]} +template struct modulus { + constexpr T operator()(const T& x, const T& y) const; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is of the form \tcode{U[N]}. - -\pnum -\returns -A \tcode{shared_ptr} to an object of type \tcode{T} -with a default initial value. - -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared(); - // \tcode{shared_ptr} to a value-initialized \tcode{double[1024]} -shared_ptr q = make_shared(); - // \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]} -\end{codeblock} -\end{example} -\end{itemdescr} - -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% +\indexlibrarymember{operator()}{modulus}% \begin{itemdecl} -template - shared_ptr make_shared(size_t N, - const remove_extent_t& u); // \tcode{T} is \tcode{U[]} -template - shared_ptr allocate_shared(const A& a, size_t N, - const remove_extent_t& u); // \tcode{T} is \tcode{U[]} +constexpr T operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{T} is of the form \tcode{U[]}. - \pnum \returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]}, -where \tcode{U} is \tcode{remove_extent_t} and -each array element has an initial value of \tcode{u}. - -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared(1024, 1.0); - // \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0} -shared_ptr q = make_shared(6, {1.0, 0.0}); - // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each \tcode{double[2]} element is \tcode{\{1.0, 0.0\}} -shared_ptr[]> r = make_shared[]>(4, {1, 2}); - // \tcode{shared_ptr} to a \tcode{vector[4]}, where each vector has contents \tcode{\{1, 2\}} -\end{codeblock} -\end{example} +\tcode{x \% y}. \end{itemdescr} -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% +\indexlibraryglobal{modulus<>}% \begin{itemdecl} -template - shared_ptr make_shared(const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} -template - shared_ptr allocate_shared(const A& a, - const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is of the form \tcode{U[N]}. - -\pnum -\returns -A \tcode{shared_ptr} to an object of type \tcode{T}, -where each array element of type \tcode{remove_extent_t} -has an initial value of \tcode{u}. +template<> struct modulus { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) % std::forward(u)); -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared(1.0); - // \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0} -shared_ptr q = make_shared({1.0, 0.0}); - // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each double[2] element is \tcode{\{1.0, 0.0\}} -shared_ptr[4]> r = make_shared[4]>({1, 2}); - // \tcode{shared_ptr} to a \tcode{vector[4]}, where each vector has contents \tcode{\{1, 2\}} -\end{codeblock} -\end{example} -\end{itemdescr} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% +\indexlibrarymember{operator()}{modulus<>}% \begin{itemdecl} -template - shared_ptr make_shared_for_overwrite(); -template - shared_ptr allocate_shared_for_overwrite(const A& a); +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) % std::forward(u)); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{T} is not an array of unknown bound. - \pnum \returns -A \tcode{shared_ptr} to an object of type \tcode{T}. +\tcode{std::forward(t) \% std::forward(u)}. +\end{itemdescr} -\pnum -\begin{example} -\begin{codeblock} -struct X { double data[1024]; }; -shared_ptr p = make_shared_for_overwrite(); - // \tcode{shared_ptr} to a default-initialized \tcode{X}, where each element in \tcode{X::data} has an indeterminate value +\rSec3[arithmetic.operations.negate]{Class template \tcode{negate}} -shared_ptr q = make_shared_for_overwrite(); - // \tcode{shared_ptr} to a default-initialized \tcode{double[1024]}, where each element has an indeterminate value -\end{codeblock} -\end{example} -\end{itemdescr} +\indexlibraryglobal{negate}% +\begin{itemdecl} +template struct negate { + constexpr T operator()(const T& x) const; +}; +\end{itemdecl} -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% +\indexlibrarymember{operator()}{negate}% \begin{itemdecl} -template - shared_ptr make_shared_for_overwrite(size_t N); -template - shared_ptr allocate_shared_for_overwrite(const A& a, size_t N); +constexpr T operator()(const T& x) const; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{T} is an array of unknown bound. - \pnum \returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]}, -where \tcode{U} is \tcode{remove_extent_t}. - -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared_for_overwrite(1024); - // \tcode{shared_ptr} to a default-initialized \tcode{double[1024]}, where each element has an indeterminate value -\end{codeblock} -\end{example} +\tcode{-x}. \end{itemdescr} -\rSec3[util.smartptr.shared.cmp]{Comparison} - -\indexlibrarymember{operator==}{shared_ptr}% +\indexlibraryglobal{negate<>}% \begin{itemdecl} -template - bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; -\end{itemdecl} +template<> struct negate { + template constexpr auto operator()(T&& t) const + -> decltype(-std::forward(t)); -\begin{itemdescr} -\pnum -\returns -\tcode{a.get() == b.get()}. -\end{itemdescr} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibrarymember{operator==}{shared_ptr}% +\indexlibrarymember{operator()}{negate<>}% \begin{itemdecl} -template - bool operator==(const shared_ptr& a, nullptr_t) noexcept; +template constexpr auto operator()(T&& t) const + -> decltype(-std::forward(t)); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{!a}. +\tcode{-std::forward(t)}. \end{itemdescr} -\indexlibrarymember{operator<=>}{shared_ptr}% -\begin{itemdecl} -template - strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; -\end{itemdecl} -\begin{itemdescr} +\rSec2[comparisons]{Comparisons} + +\rSec3[comparisons.general]{General} + \pnum -\returns -\tcode{compare_three_way()(a.get(), b.get())}. +The library provides basic function object classes for all of the comparison +operators in the language\iref{expr.rel,expr.eq}. \pnum +For templates \tcode{less}, \tcode{greater}, \tcode{less_equal}, and +\tcode{greater_equal}, the specializations for any pointer type +yield a result consistent with the +implementation-defined strict total order over pointers\iref{defns.order.ptr}. \begin{note} -Defining a comparison operator function allows \tcode{shared_ptr} objects -to be used as keys in associative containers. +If \tcode{a < b} is well-defined +for pointers \tcode{a} and \tcode{b} of type \tcode{P}, +then \tcode{(a < b) == less

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

()(a, b)}, and so forth. \end{note} -\end{itemdescr} +For template specializations \tcode{less}, \tcode{greater}, +\tcode{less_equal}, and \tcode{greater_equal}, +if the call operator calls a built-in operator comparing pointers, +the call operator yields a result consistent +with the implementation-defined strict total order over pointers. -\indexlibrarymember{operator<=>}{shared_ptr}% +\rSec3[comparisons.equal.to]{Class template \tcode{equal_to}} + +\indexlibraryglobal{equal_to}% \begin{itemdecl} -template - strong_ordering operator<=>(const shared_ptr& a, nullptr_t) noexcept; +template struct equal_to { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{equal_to}% +\begin{itemdecl} +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum \returns -\begin{codeblock} -compare_three_way()(a.get(), static_cast::element_type*>(nullptr). -\end{codeblock} +\tcode{x == y}. \end{itemdescr} -\rSec3[util.smartptr.shared.spec]{Specialized algorithms} +\indexlibraryglobal{equal_to<>}% +\begin{itemdecl} +template<> struct equal_to { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) == std::forward(u)); + + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibrarymember{swap}{shared_ptr}% +\indexlibrarymember{operator()}{equal_to<>}% \begin{itemdecl} -template - void swap(shared_ptr& a, shared_ptr& b) noexcept; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) == std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{a.swap(b)}. +\returns +\tcode{std::forward(t) == std::forward(u)}. \end{itemdescr} -\rSec3[util.smartptr.shared.cast]{Casts} +\rSec3[comparisons.not.equal.to]{Class template \tcode{not_equal_to}} -\indexlibrarymember{static_pointer_cast}{shared_ptr}% +\indexlibraryglobal{not_equal_to}% \begin{itemdecl} -template - shared_ptr static_pointer_cast(const shared_ptr& r) noexcept; -template - shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; +template struct not_equal_to { + constexpr bool operator()(const T& x, const T& y) const; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\mandates -The expression \tcode{static_cast((U*)nullptr)} is well-formed. - -\pnum -\returns -\begin{codeblock} -shared_ptr(@\placeholder{R}@, static_cast::element_type*>(r.get())) -\end{codeblock} -where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and -\tcode{std::move(r)} for the second. - -\pnum -\begin{note} -The seemingly equivalent expression -\tcode{shared_ptr(static_cast(r.get()))} -will eventually result in undefined behavior, attempting to delete the -same object twice. -\end{note} -\end{itemdescr} - -\indexlibrarymember{dynamic_pointer_cast}{shared_ptr}% +\indexlibrarymember{operator()}{not_equal_to}% \begin{itemdecl} -template - shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; -template - shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} -\pnum -\mandates -The expression \tcode{dynamic_cast((U*)nullptr)} is well-formed. -The expression \tcode{dynamic_cast::element_type*>(r.get())} is well-formed. - -\pnum -\expects -The expression \tcode{dynamic_cast::element_type*>(r.get())} has well-defined behavior. - \pnum \returns -\begin{itemize} -\item When \tcode{dynamic_cast::element_type*>(r.get())} - returns a non-null value \tcode{p}, - \tcode{shared_ptr(\placeholder{R}, p)}, - where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and - \tcode{std::move(r)} for the second. -\item Otherwise, \tcode{shared_ptr()}. -\end{itemize} - -\pnum -\begin{note} -The seemingly equivalent expression -\tcode{shared_ptr(dynamic_cast(r.get()))} will eventually result in -undefined behavior, attempting to delete the same object twice. -\end{note} +\tcode{x != y}. \end{itemdescr} -\indexlibrarymember{const_pointer_cast}{shared_ptr}% +\indexlibraryglobal{not_equal_to<>}% \begin{itemdecl} -template - shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; -template - shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -The expression \tcode{const_cast((U*)nullptr)} is well-formed. - -\pnum -\returns -\begin{codeblock} -shared_ptr(@\placeholder{R}@, const_cast::element_type*>(r.get())) -\end{codeblock} -where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and -\tcode{std::move(r)} for the second. +template<> struct not_equal_to { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) != std::forward(u)); -\pnum -\begin{note} -The seemingly equivalent expression -\tcode{shared_ptr(const_cast(r.get()))} will eventually result in -undefined behavior, attempting to delete the same object twice. -\end{note} -\end{itemdescr} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibrarymember{reinterpret_pointer_cast}{shared_ptr}% +\indexlibrarymember{operator()}{not_equal_to<>}% \begin{itemdecl} -template - shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept; -template - shared_ptr reinterpret_pointer_cast(shared_ptr&& r) noexcept; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) != std::forward(u)); \end{itemdecl} \begin{itemdescr} -\pnum -\mandates -The expression \tcode{reinterpret_cast((U*)nullptr)} is well-formed. - \pnum \returns -\begin{codeblock} -shared_ptr(@\placeholder{R}@, reinterpret_cast::element_type*>(r.get())) -\end{codeblock} -where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and -\tcode{std::move(r)} for the second. - -\pnum -\begin{note} -The seemingly equivalent expression -\tcode{shared_ptr(reinterpret_cast(r.get()))} will eventually result in -undefined behavior, attempting to delete the same object twice. -\end{note} +\tcode{std::forward(t) != std::forward(u)}. \end{itemdescr} -\rSec3[util.smartptr.getdeleter]{\tcode{get_deleter}} +\rSec3[comparisons.greater]{Class template \tcode{greater}} + +\indexlibraryglobal{greater}% +\begin{itemdecl} +template struct greater { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} -\indexlibrarymember{get_deleter}{shared_ptr}% +\indexlibrarymember{operator()}{greater}% \begin{itemdecl} -template - D* get_deleter(const shared_ptr& p) noexcept; +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum \returns -If \tcode{p} owns a deleter \tcode{d} of type cv-unqualified -\tcode{D}, returns \tcode{addressof(d)}; otherwise returns \keyword{nullptr}. -The returned -pointer remains valid as long as there exists a \tcode{shared_ptr} instance -that owns \tcode{d}. -\begin{note} -It is unspecified whether the pointer -remains valid longer than that. This can happen if the implementation doesn't destroy -the deleter until all \tcode{weak_ptr} instances that share ownership with -\tcode{p} have been destroyed. -\end{note} +\tcode{x > y}. \end{itemdescr} -\rSec3[util.smartptr.shared.io]{I/O} +\indexlibraryglobal{greater<>}% +\begin{itemdecl} +template<> struct greater { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) > std::forward(u)); + + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibrarymember{operator<<}{shared_ptr}% +\indexlibrarymember{operator()}{greater<>}% \begin{itemdecl} -template - basic_ostream& operator<<(basic_ostream& os, const shared_ptr& p); +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) > std::forward(u)); \end{itemdecl} \begin{itemdescr} -\pnum -\effects -As if by: \tcode{os <{}< p.get();} - \pnum \returns -\tcode{os}. +\tcode{std::forward(t) > std::forward(u)}. \end{itemdescr} -\rSec2[util.smartptr.weak]{Class template \tcode{weak_ptr}} - -\rSec3[util.smartptr.weak.general]{General} - -\pnum -\indexlibraryglobal{weak_ptr}% -The \tcode{weak_ptr} class template stores a weak reference to an object -that is already managed by a \tcode{shared_ptr}. To access the object, a -\tcode{weak_ptr} can be converted to a \tcode{shared_ptr} using the member -function \tcode{lock}. - -\begin{codeblock} -namespace std { - template class weak_ptr { - public: - using element_type = remove_extent_t; - - // \ref{util.smartptr.weak.const}, constructors - constexpr weak_ptr() noexcept; - template - weak_ptr(const shared_ptr& r) noexcept; - weak_ptr(const weak_ptr& r) noexcept; - template - weak_ptr(const weak_ptr& r) noexcept; - weak_ptr(weak_ptr&& r) noexcept; - template - weak_ptr(weak_ptr&& r) noexcept; - - // \ref{util.smartptr.weak.dest}, destructor - ~weak_ptr(); - - // \ref{util.smartptr.weak.assign}, assignment - weak_ptr& operator=(const weak_ptr& r) noexcept; - template - weak_ptr& operator=(const weak_ptr& r) noexcept; - template - weak_ptr& operator=(const shared_ptr& r) noexcept; - weak_ptr& operator=(weak_ptr&& r) noexcept; - template - weak_ptr& operator=(weak_ptr&& r) noexcept; - - // \ref{util.smartptr.weak.mod}, modifiers - void swap(weak_ptr& r) noexcept; - void reset() noexcept; - - // \ref{util.smartptr.weak.obs}, observers - long use_count() const noexcept; - bool expired() const noexcept; - shared_ptr lock() const noexcept; - template - bool owner_before(const shared_ptr& b) const noexcept; - template - bool owner_before(const weak_ptr& b) const noexcept; - }; - - template - weak_ptr(shared_ptr) -> weak_ptr; -} -\end{codeblock} - -\pnum -Specializations of \tcode{weak_ptr} shall be \oldconcept{CopyConstructible} and -\oldconcept{CopyAssignable}, allowing their use in standard -containers. The template parameter \tcode{T} of \tcode{weak_ptr} may be an -incomplete type. - -\rSec3[util.smartptr.weak.const]{Constructors} +\rSec3[comparisons.less]{Class template \tcode{less}} -\indexlibraryctor{weak_ptr}% +\indexlibraryglobal{less}% \begin{itemdecl} -constexpr weak_ptr() noexcept; +template struct less { + constexpr bool operator()(const T& x, const T& y) const; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\effects -Constructs an empty \tcode{weak_ptr} object that stores a null pointer value. - -\pnum -\ensures -\tcode{use_count() == 0}. -\end{itemdescr} - -\indexlibraryctor{weak_ptr}% +\indexlibrarymember{operator()}{less}% \begin{itemdecl} -weak_ptr(const weak_ptr& r) noexcept; -template weak_ptr(const weak_ptr& r) noexcept; -template weak_ptr(const shared_ptr& r) noexcept; +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -For the second and third constructors, \tcode{Y*} is compatible with \tcode{T*}. - -\pnum -\effects -If \tcode{r} is empty, constructs -an empty \tcode{weak_ptr} object that stores a null pointer value; -otherwise, constructs -a \tcode{weak_ptr} object that shares ownership -with \tcode{r} and stores a copy of the pointer stored in \tcode{r}. - -\pnum -\ensures -\tcode{use_count() == r.use_count()}. +\returns +\tcode{x < y}. \end{itemdescr} -\indexlibraryctor{weak_ptr}% +\indexlibraryglobal{less<>}% \begin{itemdecl} -weak_ptr(weak_ptr&& r) noexcept; -template weak_ptr(weak_ptr&& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. - -\pnum -\effects -Move constructs a \tcode{weak_ptr} instance from \tcode{r}. - -\pnum -\ensures -\tcode{*this} contains the old value of \tcode{r}. -\tcode{r} is empty, stores a null pointer value, and \tcode{r.use_count() == 0}. -\end{itemdescr} +template<> struct less { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) < std::forward(u)); -\rSec3[util.smartptr.weak.dest]{Destructor} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibrarydtor{weak_ptr}% +\indexlibrarymember{operator()}{less<>}% \begin{itemdecl} -~weak_ptr(); +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) < std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Destroys this \tcode{weak_ptr} object but has no -effect on the object its stored pointer points to. +\returns +\tcode{std::forward(t) < std::forward(u)}. \end{itemdescr} -\rSec3[util.smartptr.weak.assign]{Assignment} +\rSec3[comparisons.greater.equal]{Class template \tcode{greater_equal}} -\indexlibrarymember{operator=}{weak_ptr}% +\indexlibraryglobal{greater_equal}% \begin{itemdecl} -weak_ptr& operator=(const weak_ptr& r) noexcept; -template weak_ptr& operator=(const weak_ptr& r) noexcept; -template weak_ptr& operator=(const shared_ptr& r) noexcept; +template struct greater_equal { + constexpr bool operator()(const T& x, const T& y) const; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{weak_ptr(r).swap(*this)}. - -\pnum -\returns -\tcode{*this}. - -\pnum -\remarks -The implementation may meet the effects (and the -implied guarantees) via different means, without creating a temporary object. -\end{itemdescr} - -\indexlibrarymember{operator=}{weak_ptr}% +\indexlibrarymember{operator()}{greater_equal}% \begin{itemdecl} -weak_ptr& operator=(weak_ptr&& r) noexcept; -template weak_ptr& operator=(weak_ptr&& r) noexcept; +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{weak_ptr(std::move(r)).swap(*this)}. - \pnum \returns -\tcode{*this}. +\tcode{x >= y}. \end{itemdescr} -\rSec3[util.smartptr.weak.mod]{Modifiers} -\indexlibrarymember{swap}{weak_ptr}% +\indexlibraryglobal{greater_equal<>}% \begin{itemdecl} -void swap(weak_ptr& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Exchanges the contents of \tcode{*this} and \tcode{r}. -\end{itemdescr} +template<> struct greater_equal { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) >= std::forward(u)); -\indexlibrarymember{reset}{weak_ptr}% -\begin{itemdecl} -void reset() noexcept; + using is_transparent = @\unspec@; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{weak_ptr().swap(*this)}. -\end{itemdescr} - -\rSec3[util.smartptr.weak.obs]{Observers} -\indexlibrarymember{use_count}{weak_ptr}% +\indexlibrarymember{operator()}{greater_equal<>}% \begin{itemdecl} -long use_count() const noexcept; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) >= std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{0} if \tcode{*this} is empty; -otherwise, the number of \tcode{shared_ptr} instances -that share ownership with \tcode{*this}. +\tcode{std::forward(t) >= std::forward(u)}. \end{itemdescr} -\indexlibrarymember{expired}{weak_ptr}% -\begin{itemdecl} -bool expired() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{use_count() == 0}. -\end{itemdescr} +\rSec3[comparisons.less.equal]{Class template \tcode{less_equal}} -\indexlibrarymember{lock}{weak_ptr}% +\indexlibraryglobal{less_equal}% \begin{itemdecl} -shared_ptr lock() const noexcept; +template struct less_equal { + constexpr bool operator()(const T& x, const T& y) const; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\returns -\tcode{expired() ?\ shared_ptr() :\ shared_ptr(*this)}, executed atomically. -\end{itemdescr} - -\indexlibrarymember{owner_before}{weak_ptr}% +\indexlibrarymember{operator()}{less_equal}% \begin{itemdecl} -template bool owner_before(const shared_ptr& b) const noexcept; -template bool owner_before(const weak_ptr& b) const noexcept; +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum \returns -An unspecified value such that -\begin{itemize} -\item \tcode{x.owner_before(y)} defines a strict weak ordering as defined in~\ref{alg.sorting}; - -\item under the equivalence relation defined by \tcode{owner_before}, -\tcode{!a.owner_before(b) \&\& !b.owner_before(a)}, two \tcode{shared_ptr} or -\tcode{weak_ptr} instances are equivalent if and only if they share ownership or are -both empty. -\end{itemize} +\tcode{x <= y}. \end{itemdescr} +\indexlibraryglobal{less_equal<>}% +\begin{itemdecl} +template<> struct less_equal { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) <= std::forward(u)); -\rSec3[util.smartptr.weak.spec]{Specialized algorithms} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibrarymember{swap}{weak_ptr}% +\indexlibrarymember{operator()}{less_equal<>}% \begin{itemdecl} -template - void swap(weak_ptr& a, weak_ptr& b) noexcept; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) <= std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{a.swap(b)}. +\returns +\tcode{std::forward(t) <= std::forward(u)}. \end{itemdescr} -\rSec2[util.smartptr.ownerless]{Class template \tcode{owner_less}} - -\pnum -The class template \tcode{owner_less} allows ownership-based mixed comparisons of shared -and weak pointers. +\rSec3[comparisons.three.way]{Class \tcode{compare_three_way}} -\indexlibraryglobal{owner_less}% +\indexlibraryglobal{compare_three_way}% \begin{codeblock} namespace std { - template struct owner_less; - - template struct owner_less> { - bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; - bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; - bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; - }; - - template struct owner_less> { - bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; - bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; - bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; - }; - - template<> struct owner_less { - template - bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; - template - bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + struct compare_three_way { template - bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; - template - bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + constexpr auto operator()(T&& t, U&& u) const; using is_transparent = @\unspec@; }; } \end{codeblock} -\indexlibrarymember{operator()}{owner_less}% -\pnum -\tcode{operator()(x, y)} returns \tcode{x.owner_before(y)}. -\begin{note} -Note that -\begin{itemize} -\item \tcode{operator()} defines a strict weak ordering as defined in~\ref{alg.sorting}; - -\item -two \tcode{shared_ptr} or \tcode{weak_ptr} instances are equivalent -under the equivalence relation defined by \tcode{operator()}, -\tcode{!operator()(a, b) \&\& !operator()(b, a)}, -if and only if they share ownership or are both empty. -\end{itemize} -\end{note} +\begin{itemdecl} +template + constexpr auto operator()(T&& t, U&& u) const; +\end{itemdecl} -\rSec2[util.smartptr.enab]{Class template \tcode{enable_shared_from_this}} +\begin{itemdescr} +\pnum +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{three_way_comparable_with}. \pnum -\indexlibraryglobal{enable_shared_from_this}% -A class \tcode{T} can inherit from \tcode{enable_shared_from_this} -to inherit the \tcode{shared_from_this} member functions that obtain -a \tcode{shared_ptr} instance pointing to \tcode{*this}. +\expects +If the expression \tcode{std::forward(t) <=> std::forward(u)} results in +a call to a built-in operator \tcode{<=>} comparing pointers of type \tcode{P}, +the conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} +are equality-preserving\iref{concepts.equality}; +otherwise, \tcode{T} and \tcode{U} model \libconcept{three_way_comparable_with}. \pnum -\begin{example} -\begin{codeblock} -struct X: public enable_shared_from_this { }; +\effects +\begin{itemize} +\item + If the expression \tcode{std::forward(t) <=> std::forward(u)} results in + a call to a built-in operator \tcode{<=>} comparing pointers of type \tcode{P}, + returns \tcode{strong_ordering::less} + if (the converted value of) \tcode{t} precedes \tcode{u} + in the implementation-defined strict total order + over pointers\iref{defns.order.ptr}, + \tcode{strong_ordering::greater} + if \tcode{u} precedes \tcode{t}, and + otherwise \tcode{strong_ordering::equal}. +\item + Otherwise, equivalent to: \tcode{return std::forward(t) <=> std::forward(u);} +\end{itemize} +\end{itemdescr} -int main() { - shared_ptr p(new X); - shared_ptr q = p->shared_from_this(); - assert(p == q); - assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership -} -\end{codeblock} -\end{example} +\rSec2[range.cmp]{Concept-constrained comparisons} +\indexlibraryglobal{equal_to}% \begin{codeblock} -namespace std { - template class enable_shared_from_this { - protected: - constexpr enable_shared_from_this() noexcept; - enable_shared_from_this(const enable_shared_from_this&) noexcept; - enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; - ~enable_shared_from_this(); - - public: - shared_ptr shared_from_this(); - shared_ptr shared_from_this() const; - weak_ptr weak_from_this() noexcept; - weak_ptr weak_from_this() const noexcept; +struct ranges::equal_to { + template + constexpr bool operator()(T&& t, U&& u) const; - private: - mutable weak_ptr weak_this; // \expos - }; -} + using is_transparent = @\unspecnc@; +}; \end{codeblock} -\pnum -The template parameter \tcode{T} of \tcode{enable_shared_from_this} -may be an incomplete type. - -\indexlibraryctor{enable_shared_from_this}% -\begin{itemdecl} -constexpr enable_shared_from_this() noexcept; -enable_shared_from_this(const enable_shared_from_this&) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Value-initializes \tcode{weak_this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{enable_shared_from_this}% \begin{itemdecl} -enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; +template + constexpr bool operator()(T&& t, U&& u) const; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{*this}. +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{equality_comparable_with}. \pnum -\begin{note} -\tcode{weak_this} is not changed. -\end{note} -\end{itemdescr} - -\indexlibraryglobal{shared_ptr}% -\indexlibrarymember{shared_from_this}{enable_shared_from_this}% -\begin{itemdecl} -shared_ptr shared_from_this(); -shared_ptr shared_from_this() const; -\end{itemdecl} +\expects +If the expression \tcode{std::forward(t) == std::forward(u)} +results in a call to a built-in operator \tcode{==} comparing pointers of type +\tcode{P}, the conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} +are equality-preserving\iref{concepts.equality}; +otherwise, \tcode{T} and \tcode{U} model \libconcept{equality_comparable_with}. -\begin{itemdescr} \pnum -\returns -\tcode{shared_ptr(weak_this)}. -\end{itemdescr} - -\indexlibraryglobal{weak_ptr}% -\indexlibrarymember{weak_from_this}{enable_shared_from_this}% -\begin{itemdecl} -weak_ptr weak_from_this() noexcept; -weak_ptr weak_from_this() const noexcept; -\end{itemdecl} +\effects +\begin{itemize} +\item + If the expression \tcode{std::forward(t) == std::forward(u)} results in + a call to a built-in operator \tcode{==} comparing pointers: + returns \tcode{false} if either (the converted value of) \tcode{t} precedes + \tcode{u} or \tcode{u} precedes \tcode{t} in the implementation-defined strict + total order over pointers\iref{defns.order.ptr} and otherwise \tcode{true}. -\begin{itemdescr} -\pnum -\returns -\tcode{weak_this}. +\item + Otherwise, equivalent to: + \tcode{return std::forward(t) == std::forward(u);} +\end{itemize} \end{itemdescr} -\rSec2[util.smartptr.hash]{Smart pointer hash support} - -\indexlibrarymember{hash}{unique_ptr}% -\begin{itemdecl} -template struct hash>; -\end{itemdecl} +\indexlibraryglobal{not_equal_to}% +\begin{codeblock} +struct ranges::not_equal_to { + template + constexpr bool operator()(T&& t, U&& u) const; -\begin{itemdescr} -\pnum -Letting \tcode{UP} be \tcode{unique_ptr}, -the specialization \tcode{hash} is enabled\iref{unord.hash} -if and only if \tcode{hash} is enabled. -When enabled, for an object \tcode{p} of type \tcode{UP}, -\tcode{hash()(p)} evaluates to -the same value as \tcode{hash()(p.get())}. -The member functions are not guaranteed to be \keyword{noexcept}. -\end{itemdescr} + using is_transparent = @\unspecnc@; +}; +\end{codeblock} -\indexlibrarymember{hash}{shared_ptr}% \begin{itemdecl} -template struct hash>; +template + constexpr bool operator()(T&& t, U&& u) const; \end{itemdecl} \begin{itemdescr} \pnum -For an object \tcode{p} of type \tcode{shared_ptr}, -\tcode{hash>()(p)} evaluates to -the same value as \tcode{hash::element_type*>()(p.get())}. -\end{itemdescr}% -\indextext{smart pointers|)} - -\rSec2[out.ptr.t]{Class template \tcode{out_ptr_t}} - -\pnum -\tcode{out_ptr_t} is a class template used to adapt types -such as smart pointers\iref{smartptr} -for functions that use output pointer parameters. +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{equality_comparable_with}. \pnum -\begin{example} +\effects +Equivalent to: \begin{codeblock} -#include -#include - -int fopen_s(std::FILE** f, const char* name, const char* mode); - -struct fclose_deleter { - void operator()(std::FILE* f) const noexcept { - std::fclose(f); - } -}; - -int main(int, char*[]) { - constexpr const char* file_name = "ow.o"; - std::unique_ptr file_ptr; - int err = fopen_s(std::out_ptr(file_ptr), file_name, "r+b"); - if (err != 0) - return 1; - // \tcode{*file_ptr} is valid - return 0; -} +return !ranges::equal_to{}(std::forward(t), std::forward(u)); \end{codeblock} -\tcode{unique_ptr} can be used with \tcode{out_ptr} -to be passed into an output pointer-style function, -without needing to hold onto an intermediate pointer value and -manually delete it on error or failure. -\end{example} +\end{itemdescr} -\indexlibraryglobal{out_ptr_t}% +\indexlibraryglobal{greater}% \begin{codeblock} -namespace std { - template - class out_ptr_t { - public: - explicit out_ptr_t(Smart&, Args...); - out_ptr_t(const out_ptr_t&) = delete; - - ~out_ptr_t(); - - operator Pointer*() const noexcept; - operator void**() const noexcept; +struct ranges::greater { + template + constexpr bool operator()(T&& t, U&& u) const; - private: - Smart& s; // \expos - tuple a; // \expos - Pointer p; // \expos - }; -} + using is_transparent = @\unspecnc@; +}; \end{codeblock} -\pnum -\tcode{Pointer} shall meet the \oldconcept{NullablePointer} requirements. -If \tcode{Smart} is a specialization of \tcode{shared_ptr} and -\tcode{sizeof...(Args) == 0}, -the program is ill-formed. -\begin{note} -It is typically a user error to reset a \tcode{shared_ptr} -without specifying a deleter, -as \tcode{shared_ptr} will replace a custom deleter upon usage of \tcode{reset}, -as specified in \ref{util.smartptr.shared.mod}. -\end{note} - -\pnum -Program-defined specializations of \tcode{out_ptr_t} -that depend on at least one program-defined type -need not meet the requirements for the primary template. - -\pnum -Evaluations of the conversion functions -on the same object may conflict\iref{intro.races}. - -\indexlibraryctor{out_ptr_t}% -\begin{itemdecl} -explicit out_ptr_t(Smart& smart, Args... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{s} with \tcode{smart}, -\tcode{a} with \tcode{std::forward(args)...}, and -value-initializes \tcode{p}. - -\pnum -\begin{note} -The constructor is not \tcode{noexcept} -to allow for a variety of non-terminating and safe implementation strategies. -For example, an implementation can allocate -a \tcode{shared_ptr}'s internal node in the constructor and -let implementation-defined exceptions escape safely. -The destructor can then move the allocated control block in directly and -avoid any other exceptions. -\end{note} -\end{itemdescr} - -\indexlibrarydtor{out_ptr_t}% \begin{itemdecl} -~out_ptr_t(); +template + constexpr bool operator()(T&& t, U&& u) const; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{SP} be -\tcode{\exposid{POINTER_OF_OR}(Smart, Pointer)}\iref{memory.general}. +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. \pnum \effects Equivalent to: -\begin{itemize} -\item -% pretend to \item that there is real text here, but undo the vertical spacing -\mbox{}\vspace{-\baselineskip}\vspace{-\parskip} -\begin{codeblock} -if (p) { - apply([&](auto&&... args) { - s.reset(static_cast(p), std::forward(args)...); }, std::move(a)); -} -\end{codeblock} -if the expression -\tcode{s.reset(static_cast(p), std::forward(args)...)} -is well-\linebreak formed; -\item -otherwise, \begin{codeblock} -if (p) { - apply([&](auto&&... args) { - s = Smart(static_cast(p), std::forward(args)...); }, std::move(a)); -} +return ranges::less{}(std::forward(u), std::forward(t)); \end{codeblock} -if \tcode{is_constructible_v} is \tcode{true}; -\item -otherwise, the program is ill-formed. -\end{itemize} \end{itemdescr} -\begin{itemdecl} -operator Pointer*() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{operator void**()} has not been called on \tcode{*this}. +\indexlibraryglobal{less}% +\begin{codeblock} +struct ranges::less { + template + constexpr bool operator()(T&& t, U&& u) const; -\pnum -\returns -\tcode{addressof(const_cast(p))}. -\end{itemdescr} + using is_transparent = @\unspecnc@; +}; +\end{codeblock} \begin{itemdecl} -operator void**() const noexcept; +template + constexpr bool operator()(T&& t, U&& u) const; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_same_v} is \tcode{false}. - -\pnum -\mandates -\tcode{is_pointer_v} is \tcode{true}. +\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. \pnum \expects -\tcode{operator Pointer*()} has not been called on \tcode{*this}. +If the expression \tcode{std::forward(t) < std::forward(u)} results in a +call to a built-in operator \tcode{<} comparing pointers of type \tcode{P}, the +conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} are +equality-preserving\iref{concepts.equality}; +otherwise, \tcode{T} and \tcode{U} model \libconcept{totally_ordered_with}. +For any expressions +\tcode{ET} and \tcode{EU} such that \tcode{decltype((ET))} is \tcode{T} and +\tcode{decltype((EU))} is \tcode{U}, exactly one of +\tcode{ranges::less\{\}(ET, EU)}, +\tcode{ranges::less\{\}(EU, ET)}, or +\tcode{ranges::equal_to\{\}(ET, EU)} +is \tcode{true}. \pnum -\returns -A pointer value \tcode{v} such that: +\effects \begin{itemize} \item -the initial value \tcode{*v} is equivalent to \tcode{static_cast(p)} and +If the expression \tcode{std::forward(t) < std::forward(u)} results in a +call to a built-in operator \tcode{<} comparing pointers: +returns \tcode{true} if (the converted value of) \tcode{t} precedes \tcode{u} in +the implementation-defined strict total order over pointers\iref{defns.order.ptr} +and otherwise \tcode{false}. + \item -any modification of \tcode{*v} -that is not followed by a subsequent modification of \tcode{*this} -affects the value of \tcode{p} during the destruction of \tcode{*this}, -such that \tcode{static_cast(p) == *v}. +Otherwise, equivalent to: +\tcode{return std::forward(t) < std::forward(u);} \end{itemize} - -\pnum -\remarks -Accessing \tcode{*v} outside the lifetime of \tcode{*this} -has undefined behavior. - -\pnum -\begin{note} -\tcode{reinterpret_cast(static_cast(*this))} -can be a viable implementation strategy. -\end{note} \end{itemdescr} -\rSec2[out.ptr]{Function template \tcode{out_ptr}} +\indexlibraryglobal{greater_equal}% +\begin{codeblock} +struct ranges::greater_equal { + template + constexpr bool operator()(T&& t, U&& u) const; + + using is_transparent = @\unspecnc@; +}; +\end{codeblock} -\indexlibraryglobal{out_ptr}% \begin{itemdecl} -template - auto out_ptr(Smart& s, Args&&... args); +template + constexpr bool operator()(T&& t, U&& u) const; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{P} be \tcode{Pointer} -if \tcode{is_void_v} is \tcode{false}, -otherwise \tcode{\exposid{POINTER_OF}(Smart)}. - -\pnum -\returns -\tcode{out_ptr_t(s, std::forward(args)...)} -\end{itemdescr} - -\rSec2[inout.ptr.t]{Class template \tcode{inout_ptr_t}} - -\pnum -\tcode{inout_ptr_t} is a class template used to adapt types -such as smart pointers\iref{smartptr} -for functions that use output pointer parameters -whose dereferenced values may first be deleted -before being set to another allocated value. +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. \pnum -\begin{example} +\effects +Equivalent to: \begin{codeblock} -#include +return !ranges::less{}(std::forward(t), std::forward(u)); +\end{codeblock} +\end{itemdescr} -struct star_fish* star_fish_alloc(); -int star_fish_populate(struct star_fish** ps, const char* description); +\indexlibraryglobal{less_equal}% +\begin{itemdecl} +struct ranges::less_equal { + template + constexpr bool operator()(T&& t, U&& u) const; -struct star_fish_deleter { - void operator() (struct star_fish* c) const noexcept; + using is_transparent = @\unspecnc@; }; +\end{itemdecl} -using star_fish_ptr = std::unique_ptr; +\begin{itemdecl} +template + constexpr bool operator()(T&& t, U&& u) const; +\end{itemdecl} -int main(int, char*[]) { - star_fish_ptr peach(star_fish_alloc()); - // ... - // used, need to re-make - int err = star_fish_populate(std::inout_ptr(peach), "caring clown-fish liker"); - return err; -} -\end{codeblock} -A \tcode{unique_ptr} can be used with \tcode{inout_ptr} -to be passed into an output pointer-style function. -The original value will be properly deleted -according to the function it is used with and -a new value reset in its place. -\end{example} +\begin{itemdescr} +\pnum +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. -\indexlibraryglobal{inout_ptr_t}% +\pnum +\effects +Equivalent to: \begin{codeblock} -namespace std { - template - class inout_ptr_t { - public: - explicit inout_ptr_t(Smart&, Args...); - inout_ptr_t(const inout_ptr_t&) = delete; - - ~inout_ptr_t(); +return !ranges::less{}(std::forward(u), std::forward(t)); +\end{codeblock} +\end{itemdescr} - operator Pointer*() const noexcept; - operator void**() const noexcept; +\rSec2[logical.operations]{Logical operations} - private: - Smart& s; // \expos - tuple a; // \expos - Pointer p; // \expos - }; -} -\end{codeblock} +\rSec3[logical.operations.general]{General} \pnum -\tcode{Pointer} shall meet the \oldconcept{NullablePointer} requirements. -If \tcode{Smart} is a specialization of \tcode{shared_ptr}, -the program is ill-formed. -\begin{note} -It is impossible to properly acquire unique ownership of the managed resource -from a \tcode{shared_ptr} given its shared ownership model. -\end{note} +The library provides basic function object classes for all of the logical +operators in the language\iref{expr.log.and,expr.log.or,expr.unary.op}. -\pnum -Program-defined specializations of \tcode{inout_ptr_t} -that depend on at least one program-defined type -need not meet the requirements for the primary template. +\rSec3[logical.operations.and]{Class template \tcode{logical_and}} -\pnum -Evaluations of the conversion functions on the same object -may conflict\iref{intro.races}. +\indexlibraryglobal{logical_and}% +\begin{itemdecl} +template struct logical_and { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} -\indexlibraryctor{inout_ptr_t}% +\indexlibrarymember{operator()}{logical_and}% \begin{itemdecl} -explicit inout_ptr_t(Smart& smart, Args... args); +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \tcode{s} with \tcode{smart}, -\tcode{a} with \tcode{std::forward(args)...}, and -\tcode{p} to either -\begin{itemize} -\item \tcode{smart} if \tcode{is_pointer_v} is \tcode{true}, -\item otherwise, \tcode{smart.get()}. -\end{itemize} +\returns +\tcode{x \&\& y}. +\end{itemdescr} -\pnum -\remarks -An implementation can call \tcode{s.release()}. +\indexlibraryglobal{logical_and<>}% +\begin{itemdecl} +template<> struct logical_and { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) && std::forward(u)); -\pnum -\begin{note} -The constructor is not \tcode{noexcept} -to allow for a variety of non-terminating and safe implementation strategies. -For example, an intrusive pointer implementation with a control block -can allocate in the constructor and safely fail with an exception. -\end{note} -\end{itemdescr} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibrarydtor{inout_ptr_t}% +\indexlibrarymember{operator()}{logical_and<>}% \begin{itemdecl} -~inout_ptr_t(); +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) && std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{SP} be -\tcode{\exposid{POINTER_OF_OR}(Smart, Pointer)}\iref{memory.general}. +\returns +\tcode{std::forward(t) \&\& std::forward(u)}. +\end{itemdescr} -\pnum -Let \exposid{release-statement} be \tcode{s.release();} -if an implementation does not call \tcode{s.release()} in the constructor. -Otherwise, it is empty. +\rSec3[logical.operations.or]{Class template \tcode{logical_or}} -\pnum -\effects -Equivalent to: -\begin{itemize} -\item -% pretend to \item that there is real text here, but undo the vertical spacing -\mbox{}\vspace{-\baselineskip}\vspace{-\parskip} -\begin{codeblock} -if (p) { - apply([&](auto&&... args) { - s = Smart( static_cast(p), std::forward(args)...); }, std::move(a)); -} -\end{codeblock} -if \tcode{is_pointer_v} is \tcode{true}; -\item -otherwise, -\begin{codeblock} -if (p) { - apply([&](auto&&... args) { - @\exposid{release-statement}@; - s.reset(static_cast(p), std::forward(args)...); }, std::move(a)); -} -\end{codeblock} -if the expression -\tcode{s.reset(static_cast(p), std::forward(args)...)} -is well-\newline formed; -\item -otherwise, -\begin{codeblock} -if (p) { - apply([&](auto&&... args) { - @\exposid{release-statement}@; - s = Smart(static_cast(p), std::forward(args)...); }, std::move(a)); -} -\end{codeblock} -if \tcode{is_constructible_v} is \tcode{true}; -\item -otherwise, the program is ill-formed. -\end{itemize} -\end{itemdescr} +\indexlibraryglobal{logical_or}% +\begin{itemdecl} +template struct logical_or { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} +\indexlibrarymember{operator()}{logical_or}% \begin{itemdecl} -operator Pointer*() const noexcept; +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{operator void**()} has not been called on \tcode{*this}. - \pnum \returns -\tcode{addressof(const_cast(p))}. +\tcode{x || y}. \end{itemdescr} +\indexlibraryglobal{logical_or<>}% \begin{itemdecl} -operator void**() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_same_v} is \tcode{false}. +template<> struct logical_or { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) || std::forward(u)); -\pnum -\mandates -\tcode{is_pointer_v} is \tcode{true}. + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\pnum -\expects -\tcode{operator Pointer*()} has not been called on \tcode{*this}. +\indexlibrarymember{operator()}{logical_or<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) || std::forward(u)); +\end{itemdecl} +\begin{itemdescr} \pnum \returns -A pointer value \tcode{v} such that: -\begin{itemize} -\item -the initial value \tcode{*v} is equivalent to \tcode{static_cast(p)} and -\item -any modification of \tcode{*v} -that is not followed by subsequent modification of \tcode{*this} -affects the value of \tcode{p} during the destruction of \tcode{*this}, -such that \tcode{static_cast(p) == *v}. -\end{itemize} - -\pnum -\remarks -Accessing \tcode{*v} outside the lifetime of \tcode{*this} -has undefined behavior. - -\pnum -\begin{note} -\tcode{reinterpret_cast(static_cast(*this))} -can be a viable implementation strategy. -\end{note} +\tcode{std::forward(t) || std::forward(u)}. \end{itemdescr} -\rSec2[inout.ptr]{Function template \tcode{inout_ptr}} +\rSec3[logical.operations.not]{Class template \tcode{logical_not}} + +\indexlibraryglobal{logical_not}% +\begin{itemdecl} +template struct logical_not { + constexpr bool operator()(const T& x) const; +}; +\end{itemdecl} -\indexlibraryglobal{inout_ptr}% +\indexlibrarymember{operator()}{logical_not}% \begin{itemdecl} -template - auto inout_ptr(Smart& s, Args&&... args); +constexpr bool operator()(const T& x) const; \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{P} be \tcode{Pointer} if \tcode{is_void_v} is \tcode{false}, -otherwise \tcode{\exposid{POINTER_OF}(Smart)}. - \pnum \returns -\tcode{inout_ptr_t(s, std::forward(args)...)}. +\tcode{!x}. \end{itemdescr} -\rSec1[mem.res]{Memory resources} - -\rSec2[mem.res.syn]{Header \tcode{} synopsis} - -\indexheader{memory_resource}% -\begin{codeblock} -namespace std::pmr { - // \ref{mem.res.class}, class \tcode{memory_resource} - class memory_resource; - - bool operator==(const memory_resource& a, const memory_resource& b) noexcept; - - // \ref{mem.poly.allocator.class}, class template \tcode{polymorphic_allocator} - template class polymorphic_allocator; - - template - bool operator==(const polymorphic_allocator& a, - const polymorphic_allocator& b) noexcept; - - // \ref{mem.res.global}, global memory resources - memory_resource* new_delete_resource() noexcept; - memory_resource* null_memory_resource() noexcept; - memory_resource* set_default_resource(memory_resource* r) noexcept; - memory_resource* get_default_resource() noexcept; - - // \ref{mem.res.pool}, pool resource classes - struct pool_options; - class synchronized_pool_resource; - class unsynchronized_pool_resource; - class monotonic_buffer_resource; -} -\end{codeblock} +\indexlibraryglobal{logical_not<>}% +\begin{itemdecl} +template<> struct logical_not { + template constexpr auto operator()(T&& t) const + -> decltype(!std::forward(t)); -\rSec2[mem.res.class]{Class \tcode{memory_resource}} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\rSec3[mem.res.class.general]{General} +\indexlibrarymember{operator()}{logical_not<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t) const + -> decltype(!std::forward(t)); +\end{itemdecl} +\begin{itemdescr} \pnum -The \tcode{memory_resource} class is an abstract interface to an unbounded set of classes encapsulating memory resources. - -\indexlibraryglobal{memory_resource}% -\indexlibrarymember{operator=}{memory_resource}% -\begin{codeblock} -namespace std::pmr { - class memory_resource { - static constexpr size_t max_align = alignof(max_align_t); // \expos - - public: - memory_resource() = default; - memory_resource(const memory_resource&) = default; - virtual ~memory_resource(); - - memory_resource& operator=(const memory_resource&) = default; +\returns +\tcode{!std::forward(t)}. +\end{itemdescr} - [[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align); - void deallocate(void* p, size_t bytes, size_t alignment = max_align); - bool is_equal(const memory_resource& other) const noexcept; +\rSec2[bitwise.operations]{Bitwise operations} - private: - virtual void* do_allocate(size_t bytes, size_t alignment) = 0; - virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; +\rSec3[bitwise.operations.general]{General} - virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; - }; -} -\end{codeblock} +\pnum +The library provides basic function object classes for all of the bitwise +operators in the language\iref{expr.bit.and,expr.or,expr.xor,expr.unary.op}. +\rSec3[bitwise.operations.and]{Class template \tcode{bit_and}} -\rSec3[mem.res.public]{Public member functions} +\indexlibraryglobal{bit_and}% +\begin{itemdecl} +template struct bit_and { + constexpr T operator()(const T& x, const T& y) const; +}; +\end{itemdecl} -\indexlibrarydtor{memory_resource}% +\indexlibrarymember{operator()}{bit_and}% \begin{itemdecl} -~memory_resource(); +constexpr T operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Destroys this \tcode{memory_resource}. +\returns +\tcode{x \& y}. \end{itemdescr} -\indexlibrarymember{allocate}{memory_resource}% +\indexlibraryglobal{bit_and<>}% \begin{itemdecl} -[[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align); -\end{itemdecl} +template<> struct bit_and { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) & std::forward(u)); -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return do_allocate(bytes, alignment);} -\end{itemdescr} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibrarymember{deallocate}{memory_resource}% +\indexlibrarymember{operator()}{bit_and<>}% \begin{itemdecl} -void deallocate(void* p, size_t bytes, size_t alignment = max_align); +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) & std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{do_deallocate(p, bytes, alignment)}. +\returns +\tcode{std::forward(t) \& std::forward(u)}. \end{itemdescr} -\indexlibrarymember{is_equal}{memory_resource}% +\rSec3[bitwise.operations.or]{Class template \tcode{bit_or}} + +\indexlibraryglobal{bit_or}% +\begin{itemdecl} +template struct bit_or { + constexpr T operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{bit_or}% \begin{itemdecl} -bool is_equal(const memory_resource& other) const noexcept; +constexpr T operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return do_is_equal(other);} +\returns +\tcode{x | y}. \end{itemdescr} +\indexlibraryglobal{bit_or<>}% +\begin{itemdecl} +template<> struct bit_or { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) | std::forward(u)); -\rSec3[mem.res.private]{Private virtual member functions} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibrarymember{do_allocate}{memory_resource}% +\indexlibrarymember{operator()}{bit_or<>}% \begin{itemdecl} -virtual void* do_allocate(size_t bytes, size_t alignment) = 0; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) | std::forward(u)); \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{alignment} is a power of two. - \pnum \returns -A derived class shall implement this function to -return a pointer to allocated storage\iref{basic.stc.dynamic.allocation} -with a size of at least \tcode{bytes}, -aligned to the specified \tcode{alignment}. - -\pnum -\throws -A derived class implementation shall throw an appropriate exception if it is unable to allocate memory with the requested size and alignment. +\tcode{std::forward(t) | std::forward(u)}. \end{itemdescr} -\indexlibrarymember{do_deallocate}{memory_resource}% +\rSec3[bitwise.operations.xor]{Class template \tcode{bit_xor}} + +\indexlibraryglobal{bit_xor}% +\begin{itemdecl} +template struct bit_xor { + constexpr T operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{bit_xor}% \begin{itemdecl} -virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; +constexpr T operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{p} was returned from a prior call to \tcode{allocate(bytes, alignment)} -on a memory resource equal to \tcode{*this}, -and the storage at \tcode{p} has not yet been deallocated. +\returns +\tcode{x \caret{} y}. +\end{itemdescr} -\pnum -\effects -A derived class shall implement this function to dispose of allocated storage. +\indexlibraryglobal{bit_xor<>}% +\begin{itemdecl} +template<> struct bit_xor { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) ^ std::forward(u)); -\pnum -\throws -Nothing. -\end{itemdescr} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibrarymember{do_is_equal}{memory_resource}% +\indexlibrarymember{operator()}{bit_xor<>}% \begin{itemdecl} -virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) ^ std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum \returns -A derived class shall implement this function to return \tcode{true} if memory allocated from \keyword{this} can be deallocated from \tcode{other} and vice-versa, -otherwise \tcode{false}. -\begin{note} -It is possible that the most-derived type of \tcode{other} does not match the type of \keyword{this}. -For a derived class \tcode{D}, an implementation of this function -can immediately return \tcode{false} -if \tcode{dynamic_cast(\&other) == nullptr}. -\end{note} +\tcode{std::forward(t) \caret{} std::forward(u)}. \end{itemdescr} -\rSec3[mem.res.eq]{Equality} +\rSec3[bitwise.operations.not]{Class template \tcode{bit_not}} + +\begin{itemdecl} +template struct bit_not { + constexpr T operator()(const T& x) const; +}; +\end{itemdecl} -\indexlibrarymember{operator==}{memory_resource}% +\indexlibrarymember{operator()}{bit_not}% \begin{itemdecl} -bool operator==(const memory_resource& a, const memory_resource& b) noexcept; +constexpr T operator()(const T& x) const; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{\&a == \&b || a.is_equal(b)}. +\tcode{\~{}x}. \end{itemdescr} -\rSec2[mem.poly.allocator.class]{Class template \tcode{polymorphic_allocator}} +\indexlibraryglobal{bit_not<>}% +\begin{itemdecl} +template<> struct bit_not { + template constexpr auto operator()(T&& t) const + -> decltype(~std::forward(t)); -\rSec3[mem.poly.allocator.class.general]{General} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\pnum -A specialization of class template \tcode{pmr::polymorphic_allocator} -meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). -Constructed with different memory resources, -different instances of the same specialization of \tcode{pmr::polymorphic_allocator} -can exhibit entirely different allocation behavior. -This runtime polymorphism allows objects that use \tcode{polymorphic_allocator} -to behave as if they used different allocator types at run time -even though they use the same static allocator type. +\indexlibrarymember{operator()}{bit_not<>}% +\begin{itemdecl} +template constexpr auto operator()(T&&) const + -> decltype(~std::forward(t)); +\end{itemdecl} +\begin{itemdescr} \pnum -All specializations of class template \tcode{pmr::polymorphic_allocator} -meet the allocator completeness requirements\iref{allocator.requirements.completeness}. +\returns +\tcode{\~{}std::forward(t)}. +\end{itemdescr} -\indexlibraryglobal{polymorphic_allocator}% -\indexlibrarymember{value_type}{polymorphic_allocator}% -\begin{codeblock} -namespace std::pmr { - template class polymorphic_allocator { - memory_resource* memory_rsrc; // \expos - public: - using value_type = Tp; +\rSec2[func.identity]{Class \tcode{identity}} - // \ref{mem.poly.allocator.ctor}, constructors - polymorphic_allocator() noexcept; - polymorphic_allocator(memory_resource* r); +\indexlibraryglobal{identity}% +\begin{itemdecl} +struct identity { + template + constexpr T&& operator()(T&& t) const noexcept; - polymorphic_allocator(const polymorphic_allocator& other) = default; + using is_transparent = @\unspec@; +}; - template - polymorphic_allocator(const polymorphic_allocator& other) noexcept; - - polymorphic_allocator& operator=(const polymorphic_allocator&) = delete; - - // \ref{mem.poly.allocator.mem}, member functions - [[nodiscard]] Tp* allocate(size_t n); - void deallocate(Tp* p, size_t n); - - [[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); - void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t)); - template [[nodiscard]] T* allocate_object(size_t n = 1); - template void deallocate_object(T* p, size_t n = 1); - template [[nodiscard]] T* new_object(CtorArgs&&... ctor_args); - template void delete_object(T* p); - - template - void construct(T* p, Args&&... args); - - polymorphic_allocator select_on_container_copy_construction() const; - - memory_resource* resource() const; - }; -} -\end{codeblock} - -\rSec3[mem.poly.allocator.ctor]{Constructors} - -\indexlibraryctor{polymorphic_allocator}% -\begin{itemdecl} -polymorphic_allocator() noexcept; +template + constexpr T&& operator()(T&& t) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Sets \tcode{memory_rsrc} to \tcode{get_default_resource()}. +Equivalent to: \tcode{return std::forward(t);} \end{itemdescr} -\indexlibraryctor{polymorphic_allocator}% -\begin{itemdecl} -polymorphic_allocator(memory_resource* r); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{r} is non-null. - -\pnum -\effects -Sets \tcode{memory_rsrc} to \tcode{r}. - -\pnum -\throws -Nothing. -\pnum -\begin{note} -This constructor provides an implicit conversion from \tcode{memory_resource*}. -\end{note} -\end{itemdescr} +\rSec2[func.not.fn]{Function template \tcode{not_fn}} -\indexlibraryctor{polymorphic_allocator}% +\indexlibraryglobal{not_fn}% \begin{itemdecl} -template polymorphic_allocator(const polymorphic_allocator& other) noexcept; +template constexpr @\unspec@ not_fn(F&& f); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Sets \tcode{memory_rsrc} to \tcode{other.resource()}. -\end{itemdescr} - - -\rSec3[mem.poly.allocator.mem]{Member functions} - -\indexlibrarymember{allocate}{polymorphic_allocator}% -\begin{itemdecl} -[[nodiscard]] Tp* allocate(size_t n); -\end{itemdecl} +In the text that follows: +\begin{itemize} +\item \tcode{g} is a value of the result of a \tcode{not_fn} invocation, +\item \tcode{FD} is the type \tcode{decay_t}, +\item \tcode{fd} is the target object of \tcode{g}\iref{func.def} + of type \tcode{FD}, + direct-non-list-initialized with \tcode{std::forward(f)}, +\item \tcode{call_args} is an argument pack + used in a function call expression\iref{expr.call} of \tcode{g}. +\end{itemize} -\begin{itemdescr} \pnum -\effects -If \tcode{numeric_limits::max() / sizeof(Tp) < n}, -throws \tcode{bad_array_new_length}. -Otherwise equivalent to: -\begin{codeblock} -return static_cast(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp))); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{deallocate}{polymorphic_allocator}% -\begin{itemdecl} -void deallocate(Tp* p, size_t n); -\end{itemdecl} +\mandates +\tcode{is_constructible_v \&\& is_move_constructible_v} +is \tcode{true}. -\begin{itemdescr} \pnum \expects -\tcode{p} was allocated from a memory resource \tcode{x}, -equal to \tcode{*memory_rsrc}, -using \tcode{x.allocate(n * sizeof(Tp), alignof(Tp))}. +\tcode{FD} meets the \oldconcept{MoveConstructible} requirements. \pnum -\effects -Equivalent to \tcode{memory_rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp))}. +\returns +A perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} \tcode{g} +with call pattern \tcode{!invoke(fd, call_args...)}. \pnum \throws -Nothing. +Any exception thrown by the initialization of \tcode{fd}. \end{itemdescr} -\indexlibrarymember{allocate_bytes}{polymorphic_allocator}% +\rSec2[func.bind.partial]{Function templates \tcode{bind_front} and \tcode{bind_back}} + +\indexlibraryglobal{bind_front}% +\indexlibraryglobal{bind_back}% \begin{itemdecl} -[[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); +template + constexpr @\unspec@ bind_front(F&& f, Args&&... args); +template + constexpr @\unspec@ bind_back(F&& f, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return memory_rsrc->allocate(nbytes, alignment);} +Within this subclause: +\begin{itemize} +\item \tcode{g} is a value of +the result of a \tcode{bind_front} or \tcode{bind_back} invocation, +\item \tcode{FD} is the type \tcode{decay_t}, +\item \tcode{fd} is the target object of \tcode{g}\iref{func.def} + of type \tcode{FD}, + direct-non-list-initialized with \tcode{std::forward(f)}, +\item \tcode{BoundArgs} is a pack + that denotes \tcode{decay_t...}, +\item \tcode{bound_args} is + a pack of bound argument entities of \tcode{g}\iref{func.def} + of types \tcode{BoundArgs...}, + direct-non-list-initialized with \tcode{std::forward(args)...}, + respectively, and +\item \tcode{call_args} is an argument pack used in + a function call expression\iref{expr.call} of \tcode{g}. +\end{itemize} \pnum -\begin{note} -The return type is \tcode{void*} (rather than, e.g., \tcode{byte*}) -to support conversion to an arbitrary pointer type \tcode{U*} -by \tcode{static_cast}, thus facilitating construction of a \tcode{U} -object in the allocated memory. -\end{note} -\end{itemdescr} - -\indexlibrarymember{deallocate_bytes}{polymorphic_allocator}% -\begin{itemdecl} -void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t)); -\end{itemdecl} +\mandates +\begin{codeblock} +is_constructible_v && +is_move_constructible_v && +(is_constructible_v && ...) && +(is_move_constructible_v && ...) +\end{codeblock} +is \tcode{true}. -\begin{itemdescr} \pnum -\effects -Equivalent to \tcode{memory_rsrc->deallocate(p, nbytes, alignment)}. -\end{itemdescr} - -\indexlibrarymember{allocate_object}{polymorphic_allocator}% -\begin{itemdecl} -template - [[nodiscard]] T* allocate_object(size_t n = 1); -\end{itemdecl} +\expects +\tcode{FD} meets the \oldconcept{MoveConstructible} requirements. +For each $\tcode{T}_i$ in \tcode{BoundArgs}, +if $\tcode{T}_i$ is an object type, +$\tcode{T}_i$ meets the \oldconcept{MoveConstructible} requirements. -\begin{itemdescr} \pnum -\effects -Allocates memory suitable for holding -an array of \tcode{n} objects of type \tcode{T}, as follows: +\returns +A perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} \tcode{g} +with call pattern: \begin{itemize} \item - if \tcode{numeric_limits::max() / sizeof(T) < n}, - throws \tcode{bad_array_new_length}, +\tcode{invoke(fd, bound_args..., call_args...)} +for a \tcode{bind_front} invocation, or \item - otherwise equivalent to: -\begin{codeblock} -return static_cast(allocate_bytes(n*sizeof(T), alignof(T))); -\end{codeblock} +\tcode{invoke(fd, call_args..., bound_args...)} +for a \tcode{bind_back} invocation. \end{itemize} \pnum -\begin{note} -\tcode{T} is not deduced and must therefore be provided as a template argument. -\end{note} +\throws +Any exception thrown by +the initialization of the state entities of \tcode{g}\iref{func.def}. \end{itemdescr} -\indexlibrarymember{deallocate_object}{polymorphic_allocator}% -\begin{itemdecl} -template - void deallocate_object(T* p, size_t n = 1); -\end{itemdecl} +\rSec2[func.bind]{Function object binders}% + +\rSec3[func.bind.general]{General}% +\indextext{function object!binders|(} -\begin{itemdescr} \pnum -\effects -Equivalent to \tcode{deallocate_bytes(p, n*sizeof(T), alignof(T))}. -\end{itemdescr} +Subclause \ref{func.bind} describes a uniform mechanism for binding +arguments of callable objects. -\indexlibrarymember{new_object}{polymorphic_allocator}% -\begin{itemdecl} -template - [[nodiscard]] T* new_object(CtorArgs&&... ctor_args); -\end{itemdecl} +\rSec3[func.bind.isbind]{Class template \tcode{is_bind_expression}} -\begin{itemdescr} -\pnum -\effects -Allocates and constructs an object of type \tcode{T}, as follows.\newline -Equivalent to: +\indexlibraryglobal{is_bind_expression}% \begin{codeblock} -T* p = allocate_object(); -try { - construct(p, std::forward(ctor_args)...); -} catch (...) { - deallocate_object(p); - throw; +namespace std { + template struct is_bind_expression; // see below } -return p; \end{codeblock} \pnum -\begin{note} -\tcode{T} is not deduced and must therefore be provided as a template argument. -\end{note} -\end{itemdescr} - -\indexlibrarymember{new_object}{polymorphic_allocator}% -\begin{itemdecl} -template - void delete_object(T* p); -\end{itemdecl} +The class template \tcode{is_bind_expression} can be used to detect function objects +generated by \tcode{bind}. The function template \tcode{bind} +uses \tcode{is_bind_expression} to detect subexpressions. -\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -allocator_traits::destroy(*this, p); -deallocate_object(p); -\end{codeblock} -\end{itemdescr} +Specializations of the \tcode{is_bind_expression} template shall meet +the \oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts}. The implementation +provides a definition that has a base characteristic of +\tcode{true_type} if \tcode{T} is a type returned from \tcode{bind}, +otherwise it has a base characteristic of \tcode{false_type}. +A program may specialize this template for a program-defined type \tcode{T} +to have a base characteristic of \tcode{true_type} to indicate that +\tcode{T} should be treated as a subexpression in a \tcode{bind} call. -\indexlibrarymember{construct}{polymorphic_allocator}% -\begin{itemdecl} -template - void construct(T* p, Args&&... args); -\end{itemdecl} +\rSec3[func.bind.isplace]{Class template \tcode{is_placeholder}} -\begin{itemdescr} -\pnum -\mandates -Uses-allocator construction of \tcode{T} -with allocator \tcode{*this} (see~\ref{allocator.uses.construction}) -and constructor arguments \tcode{std::forward(args)...} is well-formed. +\indexlibraryglobal{is_placeholder}% +\begin{codeblock} +namespace std { + template struct is_placeholder; // see below +} +\end{codeblock} \pnum -\effects -Construct a \tcode{T} object in the storage -whose address is represented by \tcode{p} -by uses-allocator construction with allocator \tcode{*this} -and constructor arguments \tcode{std::forward(args)...}. +The class template \tcode{is_placeholder} can be used to detect the standard placeholders +\tcode{_1}, \tcode{_2}, and so on. The function template \tcode{bind} uses +\tcode{is_placeholder} to detect placeholders. \pnum -\throws -Nothing unless the constructor for \tcode{T} throws. -\end{itemdescr} - -\indexlibrarymember{select_on_container_copy_construction}{polymorphic_allocator}% -\begin{itemdecl} -polymorphic_allocator select_on_container_copy_construction() const; -\end{itemdecl} +Specializations of the \tcode{is_placeholder} template shall meet +the \oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts}. The implementation +provides a definition that has the base characteristic of +\tcode{integral_constant} if \tcode{T} is the type of +\tcode{std::placeholders::_\placeholder{J}}, otherwise it has a +base characteristic of \tcode{integral_constant}. A program +may specialize this template for a program-defined type \tcode{T} to +have a base characteristic of \tcode{integral_constant} +with \tcode{N > 0} to indicate that \tcode{T} should be +treated as a placeholder type. -\begin{itemdescr} -\pnum -\returns -\tcode{polymorphic_allocator()}. +\rSec3[func.bind.bind]{Function template \tcode{bind}} +\indexlibrary{\idxcode{bind}|(} \pnum -\begin{note} -The memory resource is not propagated. -\end{note} -\end{itemdescr} +In the text that follows: +\begin{itemize} +\item \tcode{g} is a value of the result of a \tcode{bind} invocation, +\item \tcode{FD} is the type \tcode{decay_t}, +\item \tcode{fd} is an lvalue that + is a target object of \tcode{g}\iref{func.def} of type \tcode{FD} + direct-non-list-initialized with \tcode{std::forward(f)}, +\item $\tcode{T}_i$ is the $i^\text{th}$ type in the template parameter pack \tcode{BoundArgs}, +\item $\tcode{TD}_i$ is the type \tcode{decay_t<$\tcode{T}_i$>}, +\item $\tcode{t}_i$ is the $i^\text{th}$ argument in the function parameter pack \tcode{bound_args}, +\item $\tcode{td}_i$ is a bound argument entity + of \tcode{g}\iref{func.def} of type $\tcode{TD}_i$ + direct-non-list-initialized with + \tcode{std::forward<\brk{}$\tcode{T}_i$>($\tcode{t}_i$)}, +\item $\tcode{U}_j$ is the $j^\text{th}$ deduced type of the \tcode{UnBoundArgs\&\&...} parameter + of the argument forwarding call wrapper, and +\item $\tcode{u}_j$ is the $j^\text{th}$ argument associated with $\tcode{U}_j$. +\end{itemize} -\indexlibrarymember{resource}{polymorphic_allocator}% +\indexlibraryglobal{bind}% \begin{itemdecl} -memory_resource* resource() const; +template + constexpr @\unspec@ bind(F&& f, BoundArgs&&... bound_args); +template + constexpr @\unspec@ bind(F&& f, BoundArgs&&... bound_args); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{memory_rsrc}. -\end{itemdescr} - -\rSec3[mem.poly.allocator.eq]{Equality} +\mandates +\tcode{is_constructible_v} is \tcode{true}. For each $\tcode{T}_i$ +in \tcode{BoundArgs}, \tcode{is_cons\-tructible_v<$\tcode{TD}_i$, $\tcode{T}_i$>} is \tcode{true}. -\indexlibrarymember{operator==}{polymorphic_allocator}% -\begin{itemdecl} -template - bool operator==(const polymorphic_allocator& a, - const polymorphic_allocator& b) noexcept; -\end{itemdecl} +\pnum +\expects +\tcode{FD} and each $\tcode{TD}_i$ meet +the \oldconcept{MoveConstructible} and \oldconcept{Destructible} requirements. +\tcode{\placeholdernc{INVOKE}(fd, $\tcode{w}_1$, $\tcode{w}_2$, $\dotsc$, +$\tcode{w}_N$)}\iref{func.require} is a valid expression for some +values $\tcode{w}_1$, $\tcode{w}_2$, $\dotsc{}$, $\tcode{w}_N$, where +$N$ has the value \tcode{sizeof...(bound_args)}. -\begin{itemdescr} \pnum \returns -\tcode{*a.resource() == *b.resource()}. -\end{itemdescr} - -\rSec2[mem.res.global]{Access to program-wide \tcode{memory_resource} objects} - -\indexlibraryglobal{new_delete_resource}% -\begin{itemdecl} -memory_resource* new_delete_resource() noexcept; -\end{itemdecl} +An argument forwarding call wrapper \tcode{g}\iref{func.require}. +A program that attempts to invoke a volatile-qualified \tcode{g} +is ill-formed. +When \tcode{g} is not volatile-qualified, invocation of +\tcode{g($\tcode{u}_1$, $\tcode{u}_2$, $\dotsc$, $\tcode{u}_M$)} +is expression-equivalent\iref{defns.expression.equivalent} to +\begin{codeblock} +@\placeholdernc{INVOKE}@(static_cast<@$\tcode{V}_\tcode{fd}$@>(@$\tcode{v}_\tcode{fd}$@), + static_cast<@$\tcode{V}_1$@>(@$\tcode{v}_1$@), static_cast<@$\tcode{V}_2$@>(@$\tcode{v}_2$@), @$\dotsc$@, static_cast<@$\tcode{V}_N$@>(@$\tcode{v}_N$@)) +\end{codeblock} +for the first overload, and +\begin{codeblock} +@\placeholdernc{INVOKE}@(static_cast<@$\tcode{V}_\tcode{fd}$@>(@$\tcode{v}_\tcode{fd}$@), + static_cast<@$\tcode{V}_1$@>(@$\tcode{v}_1$@), static_cast<@$\tcode{V}_2$@>(@$\tcode{v}_2$@), @$\dotsc$@, static_cast<@$\tcode{V}_N$@>(@$\tcode{v}_N$@)) +\end{codeblock} +for the second overload, +where the values and types of the target argument $\tcode{v}_\tcode{fd}$ and +of the bound arguments +$\tcode{v}_1$, $\tcode{v}_2$, $\dotsc$, $\tcode{v}_N$ are determined as specified below. -\begin{itemdescr} \pnum -\returns -A pointer to a static-duration object of a type derived from \tcode{memory_resource} -that can serve as a resource for allocating memory -using \tcode{::operator new} and \tcode{::operator delete}. -The same value is returned every time this function is called. -For a return value \tcode{p} and a memory resource \tcode{r}, -\tcode{p->is_equal(r)} returns \tcode{\&r == p}. -\end{itemdescr} - -\indexlibraryglobal{null_memory_resource}% -\begin{itemdecl} -memory_resource* null_memory_resource() noexcept; -\end{itemdecl} +\throws +Any exception thrown by the initialization of +the state entities of \tcode{g}. -\begin{itemdescr} \pnum -\returns -A pointer to a static-duration object of a type derived from \tcode{memory_resource} -for which \tcode{allocate()} always throws \tcode{bad_alloc} and -for which \tcode{deallocate()} has no effect. -The same value is returned every time this function is called. -For a return value \tcode{p} and a memory resource \tcode{r}, -\tcode{p->is_equal(r)} returns \tcode{\&r == p}. +\begin{note} +If all of \tcode{FD} and $\tcode{TD}_i$ meet +the requirements of \oldconcept{CopyConstructible}, then +the return type meets the requirements of \oldconcept{CopyConstructible}. +\end{note} \end{itemdescr} \pnum -The \defn{default memory resource pointer} is a pointer to a memory resource -that is used by certain facilities when an explicit memory resource -is not supplied through the interface. -Its initial value is the return value of \tcode{new_delete_resource()}. +\indextext{bound arguments}% +The values of the \term{bound arguments} $\tcode{v}_1$, $\tcode{v}_2$, $\dotsc$, $\tcode{v}_N$ and their +corresponding types $\tcode{V}_1$, $\tcode{V}_2$, $\dotsc$, $\tcode{V}_N$ depend on the +types $\tcode{TD}_i$ derived from +the call to \tcode{bind} and the +cv-qualifiers \cv{} of the call wrapper \tcode{g} as follows: +\begin{itemize} +\item if $\tcode{TD}_i$ is \tcode{reference_wrapper}, the +argument is \tcode{$\tcode{td}_i$.get()} and its type $\tcode{V}_i$ is \tcode{T\&}; -\indexlibraryglobal{set_default_resource}% -\begin{itemdecl} -memory_resource* set_default_resource(memory_resource* r) noexcept; -\end{itemdecl} +\item if the value of \tcode{is_bind_expression_v<$\tcode{TD}_i$>} +is \tcode{true}, the argument is +\begin{codeblock} +static_cast<@\cv{} $\tcode{TD}_i$@&>(@$\tcode{td}_i$@)(std::forward<@$\tcode{U}_j$@>(@$\tcode{u}_j$@)...) +\end{codeblock} +and its type $\tcode{V}_i$ is +\tcode{invoke_result_t<\cv{} $\tcode{TD}_i$\&, $\tcode{U}_j$...>\&\&}; + +\item if the value \tcode{j} of \tcode{is_placeholder_v<$\tcode{TD}_i$>} +is not zero, the argument is \tcode{std::forward<$\tcode{U}_j$>($\tcode{u}_j$)} +and its type $\tcode{V}_i$ +is \tcode{$\tcode{U}_j$\&\&}; + +\item otherwise, the value is $\tcode{td}_i$ and its type $\tcode{V}_i$ +is \tcode{\cv{} $\tcode{TD}_i$\&}. +\end{itemize} -\begin{itemdescr} \pnum -\effects -If \tcode{r} is non-null, -sets the value of the default memory resource pointer to \tcode{r}, -otherwise sets the default memory resource pointer to \tcode{new_delete_resource()}. +The value of the target argument $\tcode{v}_\tcode{fd}$ is \tcode{fd} and +its corresponding type $\tcode{V}_\tcode{fd}$ is \tcode{\cv{} FD\&}. +\indexlibrary{\idxcode{bind}|)}% + +\rSec3[func.bind.place]{Placeholders} + +\indexlibraryglobal{placeholders}% +\indexlibrary{1@\tcode{_1}}% +\begin{codeblock} +namespace std::placeholders { + // M is the \impldef{number of placeholders for bind expressions} number of placeholders + @\seebelow@ _1; + @\seebelow@ _2; + . + . + . + @\seebelow@ _M; +} +\end{codeblock} \pnum -\returns -The previous value of the default memory resource pointer. +All placeholder types meet the \oldconcept{DefaultConstructible} and +\oldconcept{CopyConstructible} requirements, and +their default constructors and copy/move +constructors are constexpr functions that +do not throw exceptions. It is \impldef{assignability of placeholder +objects} whether +placeholder types meet the \oldconcept{CopyAssignable} requirements, +but if so, their copy assignment operators are +constexpr functions that do not throw exceptions. \pnum -\remarks -Calling the \tcode{set_default_resource} and -\tcode{get_default_resource} functions shall not incur a data race. -A call to the \tcode{set_default_resource} function -shall synchronize with subsequent calls to -the \tcode{set_default_resource} and \tcode{get_default_resource} functions. -\end{itemdescr} +Placeholders should be defined as: +\begin{codeblock} +inline constexpr @\unspec@ _1{}; +\end{codeblock} +If they are not, they are declared as: +\begin{codeblock} +extern @\unspec@ _1; +\end{codeblock}% +\indextext{function object!binders|)} -\indexlibraryglobal{get_default_resource}% +\rSec2[func.memfn]{Function template \tcode{mem_fn}}% +\indextext{function object!\idxcode{mem_fn}|(} + +\indexlibraryglobal{mem_fn}% \begin{itemdecl} -memory_resource* get_default_resource() noexcept; +template constexpr @\unspec@ mem_fn(R T::* pm) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -The current value of the default memory resource pointer. +A simple call wrapper\iref{term.simple.call.wrapper} \tcode{fn} +with call pattern \tcode{invoke(pmd, call_args...)}, where +\tcode{pmd} is the target object of \tcode{fn} of type \tcode{R T::*} +direct-non-list-initialized with \tcode{pm}, and +\tcode{call_args} is an argument pack +used in a function call expression\iref{expr.call} of \tcode{fn}. \end{itemdescr} +\indextext{function object!\idxcode{mem_fn}|)} -\rSec2[mem.res.pool]{Pool resource classes} +\rSec2[func.wrap]{Polymorphic function wrappers}% -\rSec3[mem.res.pool.overview]{Classes \tcode{synchronized_pool_resource} and \tcode{unsynchronized_pool_resource}} +\rSec3[func.wrap.general]{General}% +\indextext{function object!wrapper|(} \pnum -The \tcode{synchronized_pool_resource} and -\tcode{unsynchronized_pool_resource} classes -(collectively called \defn{pool resource classes}) -are general-purpose memory resources having the following qualities: -\begin{itemize} -\item -Each resource frees its allocated memory on destruction, -even if \tcode{deallocate} has not been called for some of the allocated blocks. -\item -A pool resource consists of a collection of \defn{pools}, -serving requests for different block sizes. -Each individual pool manages a collection of \defn{chunks} -that are in turn divided into blocks of uniform size, -returned via calls to \tcode{do_allocate}. -Each call to \tcode{do_allocate(size, alignment)} is dispatched -to the pool serving the smallest blocks accommodating at least \tcode{size} bytes. -\item -When a particular pool is exhausted, -allocating a block from that pool results in the allocation -of an additional chunk of memory from the \defn{upstream allocator} -(supplied at construction), thus replenishing the pool. -With each successive replenishment, -the chunk size obtained increases geometrically. -\begin{note} -By allocating memory in chunks, -the pooling strategy increases the chance that consecutive allocations -will be close together in memory. -\end{note} -\item -Allocation requests that exceed the largest block size of any pool -are fulfilled directly from the upstream allocator. -\item -A \tcode{pool_options} struct may be passed to the pool resource constructors -to tune the largest block size and the maximum chunk size. -\end{itemize} +Subclause \ref{func.wrap} describes polymorphic wrapper classes that +encapsulate arbitrary callable objects. + +\rSec3[func.wrap.badcall]{Class \tcode{bad_function_call}}% +\indexlibraryglobal{bad_function_call}% \pnum -A \tcode{synchronized_pool_resource} may be accessed from multiple threads -without external synchronization -and may have thread-specific pools to reduce synchronization costs. -An \tcode{unsynchronized_pool_resource} class may not be accessed -from multiple threads simultaneously -and thus avoids the cost of synchronization entirely -in single-threaded applications. +An exception of type \tcode{bad_function_call} is thrown by +\tcode{function::operator()}\iref{func.wrap.func.inv} +when the function wrapper object has no target. -\indexlibraryglobal{pool_options}% -\indexlibraryglobal{synchronized_pool_resource}% -\indexlibraryglobal{unsynchronized_pool_resource}% \begin{codeblock} -namespace std::pmr { - struct pool_options { - size_t max_blocks_per_chunk = 0; - size_t largest_required_pool_block = 0; - }; - - class synchronized_pool_resource : public memory_resource { +namespace std { + class bad_function_call : public exception { public: - synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); - - synchronized_pool_resource() - : synchronized_pool_resource(pool_options(), get_default_resource()) {} - explicit synchronized_pool_resource(memory_resource* upstream) - : synchronized_pool_resource(pool_options(), upstream) {} - explicit synchronized_pool_resource(const pool_options& opts) - : synchronized_pool_resource(opts, get_default_resource()) {} + // see \ref{exception} for the specification of the special member functions + const char* what() const noexcept override; + }; +} +\end{codeblock} - synchronized_pool_resource(const synchronized_pool_resource&) = delete; - virtual ~synchronized_pool_resource(); +\indexlibrarymember{what}{bad_function_call}% +\begin{itemdecl} +const char* what() const noexcept override; +\end{itemdecl} - synchronized_pool_resource& operator=(const synchronized_pool_resource&) = delete; +\begin{itemdescr} +\pnum +\returns +An +\impldef{return value of \tcode{bad_function_call::what}} \ntbs{}. +\end{itemdescr} - void release(); - memory_resource* upstream_resource() const; - pool_options options() const; +\rSec3[func.wrap.func]{Class template \tcode{function}} - protected: - void* do_allocate(size_t bytes, size_t alignment) override; - void do_deallocate(void* p, size_t bytes, size_t alignment) override; +\rSec4[func.wrap.func.general]{General} +\indexlibraryglobal{function}% - bool do_is_equal(const memory_resource& other) const noexcept override; - }; +\indexlibrarymember{result_type}{function}% +\begin{codeblock} +namespace std { + template class function; // \notdef - class unsynchronized_pool_resource : public memory_resource { + template + class function { public: - unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); + using result_type = R; + + // \ref{func.wrap.func.con}, construct/copy/destroy + function() noexcept; + function(nullptr_t) noexcept; + function(const function&); + function(function&&) noexcept; + template function(F&&); - unsynchronized_pool_resource() - : unsynchronized_pool_resource(pool_options(), get_default_resource()) {} - explicit unsynchronized_pool_resource(memory_resource* upstream) - : unsynchronized_pool_resource(pool_options(), upstream) {} - explicit unsynchronized_pool_resource(const pool_options& opts) - : unsynchronized_pool_resource(opts, get_default_resource()) {} + function& operator=(const function&); + function& operator=(function&&); + function& operator=(nullptr_t) noexcept; + template function& operator=(F&&); + template function& operator=(reference_wrapper) noexcept; - unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete; - virtual ~unsynchronized_pool_resource(); + ~function(); - unsynchronized_pool_resource& operator=(const unsynchronized_pool_resource&) = delete; + // \ref{func.wrap.func.mod}, function modifiers + void swap(function&) noexcept; - void release(); - memory_resource* upstream_resource() const; - pool_options options() const; + // \ref{func.wrap.func.cap}, function capacity + explicit operator bool() const noexcept; - protected: - void* do_allocate(size_t bytes, size_t alignment) override; - void do_deallocate(void* p, size_t bytes, size_t alignment) override; + // \ref{func.wrap.func.inv}, function invocation + R operator()(ArgTypes...) const; - bool do_is_equal(const memory_resource& other) const noexcept override; + // \ref{func.wrap.func.targ}, function target access + const type_info& target_type() const noexcept; + template T* target() noexcept; + template const T* target() const noexcept; }; + + template + function(R(*)(ArgTypes...)) -> function; + + template function(F) -> function<@\seebelow@>; } \end{codeblock} -\rSec3[mem.res.pool.options]{\tcode{pool_options} data members} +\pnum +The \tcode{function} class template provides polymorphic wrappers that +generalize the notion of a function pointer. Wrappers can store, copy, +and call arbitrary callable objects\iref{func.def}, given a call +signature\iref{func.def}. + +\pnum +\indextext{callable type}% +A callable type\iref{func.def} \tcode{F} +is \defn{Lvalue-Callable} for argument +types \tcode{ArgTypes} +and return type \tcode{R} +if the expression +\tcode{\placeholdernc{INVOKE}(declval(), declval()...)}, +considered as an unevaluated operand\iref{term.unevaluated.operand}, is +well-formed\iref{func.require}. + +\pnum +The \tcode{function} class template is a call +wrapper\iref{func.def} whose call signature\iref{func.def} +is \tcode{R(ArgTypes...)}. \pnum -The members of \tcode{pool_options} -comprise a set of constructor options for pool resources. -The effect of each option on the pool resource behavior is described below: +\begin{note} +The types deduced by the deduction guides for \tcode{function} +might change in future revisions of \Cpp{}. +\end{note} + +\rSec4[func.wrap.func.con]{Constructors and destructor} -\indexlibrarymember{pool_options}{max_blocks_per_chunk}% +\indexlibraryctor{function}% \begin{itemdecl} -size_t max_blocks_per_chunk; +function() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -The maximum number of blocks that will be allocated at once -from the upstream memory resource\iref{mem.res.monotonic.buffer} -to replenish a pool. -If the value of \tcode{max_blocks_per_chunk} is zero or -is greater than an \impldef{largest supported value to configure the maximum number of blocks to replenish a pool} -limit, that limit is used instead. -The implementation -may choose to use a smaller value than is specified in this field and -may use different values for different pools. +\ensures +\tcode{!*this}. \end{itemdescr} -\indexlibrarymember{pool_options}{largest_required_pool_block}% +\indexlibraryctor{function}% \begin{itemdecl} -size_t largest_required_pool_block; +function(nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -The largest allocation size that is required to be fulfilled -using the pooling mechanism. -Attempts to allocate a single block larger than this threshold -will be allocated directly from the upstream memory resource. -If \tcode{largest_required_pool_block} is zero or -is greater than an \impldef{largest supported value to configure the largest allocation satisfied directly by a pool} -limit, that limit is used instead. -The implementation may choose a pass-through threshold -larger than specified in this field. +\ensures +\tcode{!*this}. \end{itemdescr} -\rSec3[mem.res.pool.ctor]{Constructors and destructors} - -\indexlibraryctor{synchronized_pool_resource}% -\indexlibraryctor{unsynchronized_pool_resource}% +\indexlibraryctor{function}% \begin{itemdecl} -synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); -unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); +function(const function& f); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{upstream} is the address of a valid memory resource. +\ensures +\tcode{!*this} if \tcode{!f}; otherwise, +the target object of \tcode{*this} is a copy of \tcode{f.target()}. \pnum -\effects -Constructs a pool resource object that will obtain memory from \tcode{upstream} -whenever the pool resource is unable to satisfy a memory request -from its own internal data structures. -The resulting object will hold a copy of \tcode{upstream}, -but will not own the resource to which \tcode{upstream} points. -\begin{note} -The intention is that calls to \tcode{upstream->allocate()} -will be substantially fewer than calls to \tcode{this->allocate()} -in most cases. -\end{note} -The behavior of the pooling mechanism is tuned -according to the value of the \tcode{opts} argument. +\throws +Nothing if \tcode{f}'s target is +a specialization of \tcode{reference_wrapper} or +a function pointer. Otherwise, may throw \tcode{bad_alloc} +or any exception thrown by the copy constructor of the stored callable object. \pnum -\throws -Nothing unless \tcode{upstream->allocate()} throws. -It is unspecified if, or under what conditions, -this constructor calls \tcode{upstream->allocate()}. +\recommended +Implementations should avoid the use of +dynamically allocated memory for small callable objects, for example, where +\tcode{f}'s target is an object holding only a pointer or reference +to an object and a member function pointer. \end{itemdescr} -\indexlibrarydtor{synchronized_pool_resource}% -\indexlibrarydtor{unsynchronized_pool_resource}% +\indexlibraryctor{function}% \begin{itemdecl} -virtual ~synchronized_pool_resource(); -virtual ~unsynchronized_pool_resource(); +function(function&& f) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Calls \tcode{release()}. -\end{itemdescr} - -\rSec3[mem.res.pool.mem]{Members} - -\indexlibrarymember{release}{synchronized_pool_resource}% -\indexlibrarymember{release}{unsynchronized_pool_resource}% -\begin{itemdecl} -void release(); -\end{itemdecl} +\ensures +If \tcode{!f}, \tcode{*this} has no target; +otherwise, the target of \tcode{*this} is equivalent to +the target of \tcode{f} before the construction, and +\tcode{f} is in a valid state with an unspecified value. -\begin{itemdescr} \pnum -\effects -Calls \tcode{upstream_resource()->deallocate()} as necessary -to release all allocated memory. -\begin{note} -The memory is released back to \tcode{upstream_resource()} -even if \tcode{deallocate} has not been called -for some of the allocated blocks. -\end{note} +\recommended +Implementations should avoid the use of +dynamically allocated memory for small callable objects, for example, +where \tcode{f}'s target is an object holding only a pointer or reference +to an object and a member function pointer. \end{itemdescr} -\indexlibrarymember{upstream_resource}{synchronized_pool_resource}% -\indexlibrarymember{upstream_resource}{unsynchronized_pool_resource}% +\indexlibraryctor{function}% \begin{itemdecl} -memory_resource* upstream_resource() const; +template function(F&& f); \end{itemdecl} \begin{itemdescr} \pnum -\returns -The value of the \tcode{upstream} argument -provided to the constructor of this object. -\end{itemdescr} - -\indexlibrarymember{options}{synchronized_pool_resource}% -\indexlibrarymember{options}{unsynchronized_pool_resource}% -\begin{itemdecl} -pool_options options() const; -\end{itemdecl} +Let \tcode{FD} be \tcode{decay_t}. -\begin{itemdescr} \pnum -\returns -The options that control the pooling behavior of this resource. -The values in the returned struct may differ -from those supplied to the pool resource constructor in that -values of zero will be replaced with \impldef{default configuration of a pool} -defaults, and sizes may be rounded to unspecified granularity. -\end{itemdescr} - -\indexlibrarymember{do_allocate}{synchronized_pool_resource}% -\indexlibrarymember{do_allocate}{unsynchronized_pool_resource}% -\begin{itemdecl} -void* do_allocate(size_t bytes, size_t alignment) override; -\end{itemdecl} +\constraints +\begin{itemize} +\item +\tcode{is_same_v, function>} is \tcode{false}, and +\item +\tcode{FD} is Lvalue-Callable\iref{func.wrap.func} for argument types +\tcode{ArgTypes...} and return type \tcode{R}. +\end{itemize} -\begin{itemdescr} \pnum -\effects -If the pool selected for a block of size \tcode{bytes} -is unable to satisfy the memory request from its own internal data structures, -it will call \tcode{upstream_resource()->allocate()} to obtain more memory. -If \tcode{bytes} is larger than that which the largest pool can handle, -then memory will be allocated using \tcode{upstream_resource()->allocate()}. +\mandates +\begin{itemize} +\item +\tcode{is_copy_constructible_v} is \tcode{true}, and +\item +\tcode{is_constructible_v} is \tcode{true}. +\end{itemize} \pnum -\returns -A pointer to allocated storage\iref{basic.stc.dynamic.allocation} -with a size of at least \tcode{bytes}. -The size and alignment of the allocated memory shall meet the requirements -for a class derived from \tcode{memory_resource}\iref{mem.res.class}. +\expects +\tcode{FD} meets the \oldconcept{CopyConstructible} requirements. \pnum -\throws -Nothing unless \tcode{upstream_resource()->allocate()} throws. -\end{itemdescr} - -\indexlibrarymember{do_deallocate}{synchronized_pool_resource}% -\indexlibrarymember{do_deallocate}{unsynchronized_pool_resource}% -\begin{itemdecl} -void do_deallocate(void* p, size_t bytes, size_t alignment) override; -\end{itemdecl} +\ensures +\tcode{!*this} is \tcode{true} if any of the following hold: +\begin{itemize} +\item \tcode{f} is a null function pointer value. +\item \tcode{f} is a null member pointer value. +\item \tcode{remove_cvref_t} is +a specialization of the \tcode{function} class template, and +\tcode{!f} is \tcode{true}. +\end{itemize} -\begin{itemdescr} \pnum -\effects -Returns the memory at \tcode{p} to the pool. -It is unspecified if, or under what circumstances, -this operation will result in a call to \tcode{upstream_resource()->deallocate()}. +Otherwise, \tcode{*this} has a target object of type \tcode{FD} +direct-non-list-initialized with \tcode{std::forward(f)}. \pnum \throws -Nothing. +Nothing if \tcode{FD} is +a specialization of \tcode{reference_wrapper} or +a function pointer type. +Otherwise, may throw \tcode{bad_alloc} or +any exception thrown by the initialization of the target object. + +\pnum +\recommended +Implementations should avoid the use of +dynamically allocated memory for small callable objects, for example, +where \tcode{f} refers to an object holding only a pointer or +reference to an object and a member function pointer. \end{itemdescr} -\indexlibrarymember{do_is_equal}{synchronized_pool_resource}% -\indexlibrarymember{do_is_equal}{unsynchronized_pool_resource}% + \begin{itemdecl} -bool do_is_equal(const memory_resource& other) const noexcept override; +template function(F) -> function<@\seebelow@>; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{this == \&other}. -\end{itemdescr} - -\rSec2[mem.res.monotonic.buffer]{Class \tcode{monotonic_buffer_resource}} - -\rSec3[mem.res.monotonic.buffer.general]{General} +\constraints +\tcode{\&F::operator()} is well-formed when treated as an unevaluated operand and +\tcode{decltype(\brk{}\&F::operator())} is of the form +\tcode{R(G::*)(A...)}~\cv{}~\tcode{\opt{\&}~\opt{noexcept}} +for a class type \tcode{G}. \pnum -A \tcode{monotonic_buffer_resource} is a special-purpose memory resource -intended for very fast memory allocations in situations -where memory is used to build up a few objects -and then is released all at once when the memory resource object is destroyed. +\remarks +The deduced type is \tcode{function}. -\indexlibraryglobal{monotonic_buffer_resource}% +\pnum +\begin{example} \begin{codeblock} -namespace std::pmr { - class monotonic_buffer_resource : public memory_resource { - memory_resource* upstream_rsrc; // \expos - void* current_buffer; // \expos - size_t next_buffer_size; // \expos - - public: - explicit monotonic_buffer_resource(memory_resource* upstream); - monotonic_buffer_resource(size_t initial_size, memory_resource* upstream); - monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream); - - monotonic_buffer_resource() - : monotonic_buffer_resource(get_default_resource()) {} - explicit monotonic_buffer_resource(size_t initial_size) - : monotonic_buffer_resource(initial_size, get_default_resource()) {} - monotonic_buffer_resource(void* buffer, size_t buffer_size) - : monotonic_buffer_resource(buffer, buffer_size, get_default_resource()) {} - - monotonic_buffer_resource(const monotonic_buffer_resource&) = delete; - - virtual ~monotonic_buffer_resource(); - - monotonic_buffer_resource& operator=(const monotonic_buffer_resource&) = delete; - - void release(); - memory_resource* upstream_resource() const; - - protected: - void* do_allocate(size_t bytes, size_t alignment) override; - void do_deallocate(void* p, size_t bytes, size_t alignment) override; - - bool do_is_equal(const memory_resource& other) const noexcept override; - }; +void f() { + int i{5}; + function g = [&](double) { return i; }; // deduces \tcode{function} } \end{codeblock} +\end{example} +\end{itemdescr} -\rSec3[mem.res.monotonic.buffer.ctor]{Constructors and destructor} - -\indexlibraryctor{monotonic_buffer_resource}% +\indexlibrarymember{operator=}{function}% \begin{itemdecl} -explicit monotonic_buffer_resource(memory_resource* upstream); -monotonic_buffer_resource(size_t initial_size, memory_resource* upstream); +function& operator=(const function& f); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{upstream} is the address of a valid memory resource. -\tcode{initial_size}, if specified, is greater than zero. +\effects +As if by \tcode{function(f).swap(*this);} \pnum -\effects -Sets \tcode{upstream_rsrc} to \tcode{upstream} and -\tcode{current_buffer} to \keyword{nullptr}. -If \tcode{initial_size} is specified, -sets \tcode{next_buffer_size} to at least \tcode{initial_size}; -otherwise sets \tcode{next_buffer_size} to an -\impldef{default \tcode{next_buffer_size} for a \tcode{monotonic_buffer_resource}} size. +\returns +\tcode{*this}. \end{itemdescr} -\indexlibraryctor{monotonic_buffer_resource}% +\indexlibrarymember{operator=}{function}% \begin{itemdecl} -monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream); +function& operator=(function&& f); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{upstream} is the address of a valid memory resource. -\tcode{buffer_size} is no larger than the number of bytes in \tcode{buffer}. +\effects +Replaces the target of \tcode{*this} +with the target of \tcode{f}. \pnum -\effects -Sets \tcode{upstream_rsrc} to \tcode{upstream}, -\tcode{current_buffer} to \tcode{buffer}, and -\tcode{next_buffer_size} to \tcode{buffer_size} (but not less than 1), -then increases \tcode{next_buffer_size} -by an \impldef{growth factor for \tcode{monotonic_buffer_resource}} growth factor (which need not be integral). +\returns +\tcode{*this}. \end{itemdescr} -\indexlibrarydtor{monotonic_buffer_resource}% +\indexlibrarymember{operator=}{function}% \begin{itemdecl} -~monotonic_buffer_resource(); +function& operator=(nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Calls \tcode{release()}. -\end{itemdescr} +If \tcode{*this != nullptr}, destroys the target of \keyword{this}. +\pnum +\ensures +\tcode{!(*this)}. -\rSec3[mem.res.monotonic.buffer.mem]{Members} +\pnum +\returns +\tcode{*this}. +\end{itemdescr} -\indexlibrarymember{release}{monotonic_buffer_resource}% +\indexlibrarymember{operator=}{function}% \begin{itemdecl} -void release(); +template function& operator=(F&& f); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Calls \tcode{upstream_rsrc->deallocate()} as necessary -to release all allocated memory. -Resets \tcode{current_buffer} and \tcode{next_buffer_size} -to their initial values at construction. +\constraints +\tcode{decay_t} is Lvalue-Callable\iref{func.wrap.func} +for argument types \tcode{ArgTypes...} and return type \tcode{R}. \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}. -\end{note} -\end{itemdescr} - -\indexlibrarymember{upstream_resource}{monotonic_buffer_resource}% -\begin{itemdecl} -memory_resource* upstream_resource() const; -\end{itemdecl} +\effects +As if by: \tcode{function(std::forward(f)).swap(*this);} -\begin{itemdescr} \pnum \returns -The value of \tcode{upstream_rsrc}. +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{do_allocate}{monotonic_buffer_resource}% +\indexlibrarymember{operator=}{function}% \begin{itemdecl} -void* do_allocate(size_t bytes, size_t alignment) override; +template function& operator=(reference_wrapper f) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -If the unused space in \tcode{current_buffer} -can fit a block with the specified \tcode{bytes} and \tcode{alignment}, -then allocate the return block from \tcode{current_buffer}; -otherwise set \tcode{current_buffer} to \tcode{upstream_rsrc->allocate(n, m)}, -where \tcode{n} is not less than \tcode{max(bytes, next_buffer_size)} and -\tcode{m} is not less than \tcode{alignment}, -and increase \tcode{next_buffer_size} -by an \impldef{growth factor for \tcode{monotonic_buffer_resource}} growth factor (which need not be integral), -then allocate the return block from the newly-allocated \tcode{current_buffer}. +As if by: \tcode{function(f).swap(*this);} \pnum \returns -A pointer to allocated storage\iref{basic.stc.dynamic.allocation} -with a size of at least \tcode{bytes}. -The size and alignment of the allocated memory shall meet the requirements -for a class derived from \tcode{memory_resource}\iref{mem.res.class}. - -\pnum -\throws -Nothing unless \tcode{upstream_rsrc->allocate()} throws. +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{do_deallocate}{monotonic_buffer_resource}% +\indexlibrarydtor{function}% \begin{itemdecl} -void do_deallocate(void* p, size_t bytes, size_t alignment) override; +~function(); \end{itemdecl} \begin{itemdescr} \pnum \effects -None. - -\pnum -\throws -Nothing. - -\pnum -\remarks -Memory used by this resource increases monotonically until its destruction. +If \tcode{*this != nullptr}, destroys the target of \keyword{this}. \end{itemdescr} -\indexlibrarymember{do_is_equal}{monotonic_buffer_resource}% +\rSec4[func.wrap.func.mod]{Modifiers} + +\indexlibrarymember{swap}{function}% \begin{itemdecl} -bool do_is_equal(const memory_resource& other) const noexcept override; +void swap(function& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{this == \&other}. +\effects +Interchanges the target objects of \tcode{*this} and \tcode{other}. \end{itemdescr} +\rSec4[func.wrap.func.cap]{Capacity} -\rSec1[allocator.adaptor]{Class template \tcode{scoped_allocator_adaptor}} - -\rSec2[allocator.adaptor.syn]{Header \tcode{} synopsis} - -\indexheader{scoped_allocator}% -\begin{codeblock} -namespace std { - // class template \tcode{scoped allocator adaptor} - template - class scoped_allocator_adaptor; - - // \ref{scoped.adaptor.operators}, scoped allocator operators - template - bool operator==(const scoped_allocator_adaptor& a, - const scoped_allocator_adaptor& b) noexcept; -} -\end{codeblock} - -\pnum -The class template \tcode{scoped_allocator_adaptor} is an allocator template that -specifies an allocator resource (the outer allocator) to be used by a container (as any -other allocator does) and also specifies an inner allocator resource to be passed to the -constructor of every element within the container. This adaptor is instantiated with one -outer and zero or more inner allocator types. If instantiated with only one allocator -type, the inner allocator becomes the \tcode{scoped_allocator_adaptor} itself, thus -using the same allocator resource for the container and every element within the -container and, if the elements themselves are containers, each of their elements -recursively. If instantiated with more than one allocator, the first allocator is the -outer allocator for use by the container, the second allocator is passed to the -constructors of the container's elements, and, if the elements themselves are -containers, the third allocator is passed to the elements' elements, and so on. If -containers are nested to a depth greater than the number of allocators, the last -allocator is used repeatedly, as in the single-allocator case, for any remaining -recursions. -\begin{note} -The \tcode{scoped_allocator_adaptor} is derived from the outer -allocator type so it can be substituted for the outer allocator type in most -expressions. -\end{note} - -\indexlibraryglobal{scoped_allocator_adaptor}% -\indexlibrarymember{outer_allocator_type}{scoped_allocator_adaptor}% -\indexlibrarymember{value_type}{scoped_allocator_adaptor}% -\indexlibrarymember{size_type}{scoped_allocator_adaptor}% -\indexlibrarymember{difference_type}{scoped_allocator_adaptor}% -\indexlibrarymember{pointer}{scoped_allocator_adaptor}% -\indexlibrarymember{const_pointer}{scoped_allocator_adaptor}% -\indexlibrarymember{void_pointer}{scoped_allocator_adaptor}% -\indexlibrarymember{const_void_pointer}{scoped_allocator_adaptor}% -\begin{codeblock} -namespace std { - template - class scoped_allocator_adaptor : public OuterAlloc { - private: - using OuterTraits = allocator_traits; // \expos - scoped_allocator_adaptor inner; // \expos - - public: - using outer_allocator_type = OuterAlloc; - using inner_allocator_type = @\seebelow@; - - using value_type = typename OuterTraits::value_type; - using size_type = typename OuterTraits::size_type; - using difference_type = typename OuterTraits::difference_type; - using pointer = typename OuterTraits::pointer; - using const_pointer = typename OuterTraits::const_pointer; - using void_pointer = typename OuterTraits::void_pointer; - using const_void_pointer = typename OuterTraits::const_void_pointer; - - using propagate_on_container_copy_assignment = @\seebelow@; - using propagate_on_container_move_assignment = @\seebelow@; - using propagate_on_container_swap = @\seebelow@; - using is_always_equal = @\seebelow@; - - template struct rebind { - using other = scoped_allocator_adaptor< - OuterTraits::template rebind_alloc, InnerAllocs...>; - }; - - scoped_allocator_adaptor(); - template - scoped_allocator_adaptor(OuterA2&& outerAlloc, - const InnerAllocs&... innerAllocs) noexcept; - - scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept; - scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; - - template - scoped_allocator_adaptor( - const scoped_allocator_adaptor& other) noexcept; - template - scoped_allocator_adaptor( - scoped_allocator_adaptor&& other) noexcept; - - scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default; - scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default; - - ~scoped_allocator_adaptor(); - - inner_allocator_type& inner_allocator() noexcept; - const inner_allocator_type& inner_allocator() const noexcept; - outer_allocator_type& outer_allocator() noexcept; - const outer_allocator_type& outer_allocator() const noexcept; - - [[nodiscard]] pointer allocate(size_type n); - [[nodiscard]] pointer allocate(size_type n, const_void_pointer hint); - void deallocate(pointer p, size_type n); - size_type max_size() const; - - template - void construct(T* p, Args&&... args); - - template - void destroy(T* p); - - scoped_allocator_adaptor select_on_container_copy_construction() const; - }; - - template - scoped_allocator_adaptor(OuterAlloc, InnerAllocs...) - -> scoped_allocator_adaptor; -} -\end{codeblock} - -\rSec2[allocator.adaptor.types]{Member types} - -\indexlibrarymember{inner_allocator_type}{scoped_allocator_adaptor}% +\indexlibrarymember{operator bool}{function}% \begin{itemdecl} -using inner_allocator_type = @\seebelow@; +explicit operator bool() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ctype \tcode{scoped_allocator_adaptor} if \tcode{sizeof...(InnerAllocs)} is -zero; otherwise,\\ \tcode{scoped_allocator_adaptor}. +\returns +\tcode{true} if \tcode{*this} has a target, otherwise \tcode{false}. \end{itemdescr} -\indexlibrarymember{propagate_on_container_copy_assignment}{scoped_allocator_adaptor}% +\rSec4[func.wrap.func.inv]{Invocation} + +\indexlibrary{\idxcode{function}!invocation}% +\indexlibrarymember{operator()}{function}% \begin{itemdecl} -using propagate_on_container_copy_assignment = @\seebelow@; +R operator()(ArgTypes... args) const; \end{itemdecl} \begin{itemdescr} \pnum -\ctype \tcode{true_type} if -\tcode{allocator_traits::propagate_on_container_copy_assignment::value} is -\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and -\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\returns +\tcode{\placeholdernc{INVOKE}(f, std::forward(args)...)}\iref{func.require}, +where \tcode{f} is the target object\iref{func.def} of \tcode{*this}. + +\pnum +\throws +\tcode{bad_function_call} if \tcode{!*this}; otherwise, any +exception thrown by the target object. \end{itemdescr} -\indexlibrarymember{propagate_on_container_move_assignment}{scoped_allocator_adaptor}% +\rSec4[func.wrap.func.targ]{Target access} + +\indexlibrarymember{target_type}{function}% \begin{itemdecl} -using propagate_on_container_move_assignment = @\seebelow@; +const type_info& target_type() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ctype \tcode{true_type} if -\tcode{allocator_traits::propagate_on_container_move_assignment::value} is -\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and -\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\returns +If \tcode{*this} has a target of type \tcode{T}, + \tcode{typeid(T)}; otherwise, \tcode{typeid(void)}. \end{itemdescr} -\indexlibrarymember{propagate_on_container_swap}{scoped_allocator_adaptor}% +\indexlibrarymember{target}{function}% \begin{itemdecl} -using propagate_on_container_swap = @\seebelow@; +template T* target() noexcept; +template const T* target() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ctype \tcode{true_type} if -\tcode{allocator_traits::propagate_on_container_swap::value} is -\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and -\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\returns +If \tcode{target_type() == typeid(T)} +a pointer to the stored function target; otherwise a null pointer. \end{itemdescr} -\indexlibrarymember{is_always_equal}{scoped_allocator_adaptor}% +\rSec4[func.wrap.func.nullptr]{Null pointer comparison operator functions} + +\indexlibrarymember{operator==}{function}% \begin{itemdecl} -using is_always_equal = @\seebelow@; +template + bool operator==(const function& f, nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ctype \tcode{true_type} if -\tcode{allocator_traits::is_always_equal::value} is -\tcode{true} for every \tcode{A} in the set of \tcode{OuterAlloc} and -\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\returns +\tcode{!f}. \end{itemdescr} -\rSec2[allocator.adaptor.cnstr]{Constructors} +\rSec4[func.wrap.func.alg]{Specialized algorithms} -\indexlibraryctor{scoped_allocator_adaptor}% +\indexlibrarymember{swap}{function}% \begin{itemdecl} -scoped_allocator_adaptor(); +template + void swap(function& f1, function& f2) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Value-initializes the \tcode{OuterAlloc} base class and the \tcode{inner} allocator -object. -\end{itemdescr} +As if by: \tcode{f1.swap(f2);} +\end{itemdescr}% -\indexlibraryctor{scoped_allocator_adaptor}% -\begin{itemdecl} -template - scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept; -\end{itemdecl} +\rSec3[func.wrap.move]{Move only wrapper} + +\rSec4[func.wrap.move.general]{General} -\begin{itemdescr} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +The header provides partial specializations of \tcode{move_only_function} +for each combination of the possible replacements +of the placeholders \cv{}, \placeholder{ref}, and \placeholder{noex} where +\begin{itemize} +\item +\cv{} is either const or empty, +\item +\placeholder{ref} is either \tcode{\&}, \tcode{\&\&}, or empty, and +\item +\placeholder{noex} is either \tcode{true} or \tcode{false}. +\end{itemize} \pnum -\effects -Initializes the \tcode{OuterAlloc} base class with -\tcode{std::forward(outerAlloc)} and \tcode{inner} with \tcode{innerAllocs...} -(hence recursively initializing each allocator within the adaptor with the corresponding -allocator from the argument list). -\end{itemdescr} +For each of the possible combinations of the placeholders mentioned above, +there is a placeholder \placeholder{inv-quals} defined as follows: +\begin{itemize} +\item +If \placeholder{ref} is empty, let \placeholder{inv-quals} be \tcode{\cv{}\&}, +\item +otherwise, let \placeholder{inv-quals} be \cv{} \placeholder{ref}. +\end{itemize} -\indexlibraryctor{scoped_allocator_adaptor}% -\begin{itemdecl} -scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept; -\end{itemdecl} +\rSec4[func.wrap.move.class]{Class template \tcode{move_only_function}} -\begin{itemdescr} -\pnum -\effects -Initializes each allocator within the adaptor with the corresponding allocator -from \tcode{other}. -\end{itemdescr} +\indexlibraryglobal{move_only_function}% +\begin{codeblock} +namespace std { + template class move_only_function; // \notdef -\indexlibraryctor{scoped_allocator_adaptor}% -\begin{itemdecl} -scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; -\end{itemdecl} + template + class move_only_function { + public: + using result_type = R; -\begin{itemdescr} -\pnum -\effects -Move constructs each allocator within the adaptor with the corresponding allocator -from \tcode{other}. -\end{itemdescr} + // \ref{func.wrap.move.ctor}, constructors, assignment, and destructor + move_only_function() noexcept; + move_only_function(nullptr_t) noexcept; + move_only_function(move_only_function&&) noexcept; + template move_only_function(F&&); + template + explicit move_only_function(in_place_type_t, Args&&...); + template + explicit move_only_function(in_place_type_t, initializer_list, Args&&...); -\indexlibraryctor{scoped_allocator_adaptor}% -\begin{itemdecl} -template - scoped_allocator_adaptor( - const scoped_allocator_adaptor& other) noexcept; -\end{itemdecl} + move_only_function& operator=(move_only_function&&); + move_only_function& operator=(nullptr_t) noexcept; + template move_only_function& operator=(F&&); -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. + ~move_only_function(); -\pnum -\effects -Initializes each allocator within the adaptor with the corresponding allocator -from \tcode{other}. -\end{itemdescr} + // \ref{func.wrap.move.inv}, invocation + explicit operator bool() const noexcept; + R operator()(ArgTypes...) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); -\indexlibraryctor{scoped_allocator_adaptor}% -\begin{itemdecl} -template - scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; -\end{itemdecl} + // \ref{func.wrap.move.util}, utility + void swap(move_only_function&) noexcept; + friend void swap(move_only_function&, move_only_function&) noexcept; + friend bool operator==(const move_only_function&, nullptr_t) noexcept; -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. + private: + template + static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; // \expos + }; +} +\end{codeblock} \pnum -\effects -Initializes each allocator within the adaptor with the corresponding allocator rvalue -from \tcode{other}. -\end{itemdescr} - -\rSec2[allocator.adaptor.members]{Members} +The \tcode{move_only_function} class template provides polymorphic wrappers +that generalize the notion of a callable object\iref{func.def}. +These wrappers can store, move, and call arbitrary callable objects, +given a call signature. \pnum -In the \tcode{construct} member functions, -\tcode{\placeholdernc{OUTERMOST}(x)} is -\tcode{\placeholdernc{OUTERMOST}(x.outer_allocator())} if -the expression \tcode{x.outer_allocator()} is -valid~\iref{temp.deduct} and -\tcode{x} otherwise; -\tcode{\placeholdernc{OUTERMOST_ALLOC_TRAITS}(x)} is -\tcode{allocator_traits>}. +\recommended +Implementations should avoid the use of dynamically allocated memory +for a small contained value. \begin{note} -\tcode{\placeholdernc{OUTERMOST}(x)} and -\tcode{\placeholdernc{OUTERMOST_ALL\-OC_TRAITS}(x)} are recursive operations. It -is incumbent upon the definition of \tcode{outer_allocator()} to ensure that the -recursion terminates. It will terminate for all instantiations of -\tcode{scoped_allocator_adaptor}. +Such small-object optimization can only be applied to a type \tcode{T} +for which \tcode{is_nothrow_move_constructible_v} is \tcode{true}. \end{note} -\indexlibrarymember{inner_allocator}{scoped_allocator_adaptor}% -\begin{itemdecl} -inner_allocator_type& inner_allocator() noexcept; -const inner_allocator_type& inner_allocator() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{*this} if \tcode{sizeof...(InnerAllocs)} is zero; otherwise, -\tcode{inner}. -\end{itemdescr} - -\indexlibrarymember{outer_allocator}{scoped_allocator_adaptor}% -\begin{itemdecl} -outer_allocator_type& outer_allocator() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{static_cast(*this)}. -\end{itemdescr} - -\indexlibrarymember{outer_allocator}{scoped_allocator_adaptor}% -\begin{itemdecl} -const outer_allocator_type& outer_allocator() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{static_cast(*this)}. -\end{itemdescr} - -\indexlibrarymember{allocate}{scoped_allocator_adaptor}% -\begin{itemdecl} -[[nodiscard]] pointer allocate(size_type n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{allocator_traits::allocate(outer_allocator(), n)}. -\end{itemdescr} - -\indexlibrarymember{allocate}{scoped_allocator_adaptor}% -\begin{itemdecl} -[[nodiscard]] pointer allocate(size_type n, const_void_pointer hint); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{allocator_traits::allocate(outer_allocator(), n, hint)}. -\end{itemdescr} - -\indexlibrarymember{deallocate}{scoped_allocator_adaptor}% -\begin{itemdecl} -void deallocate(pointer p, size_type n) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by: -\tcode{allocator_traits::deallocate(outer_allocator(), p, n);} -\end{itemdescr} - -\indexlibrarymember{max_size}{scoped_allocator_adaptor}% -\begin{itemdecl} -size_type max_size() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{allocator_traits::max_size(outer_allocator())}. -\end{itemdescr} +\rSec4[func.wrap.move.ctor]{Constructors, assignment, and destructor} -\indexlibrarymember{construct}{scoped_allocator_adaptor}% +\indexlibrarymember{\exposid{is-callable-from}}{move_only_function}% \begin{itemdecl} -template - void construct(T* p, Args&&... args); +template + static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: +If \placeholder{noex} is \tcode{true}, +\tcode{\exposid{is-callable-from}} is equal to: \begin{codeblock} -apply([p, this](auto&&... newargs) { - @\placeholdernc{OUTERMOST_ALLOC_TRAITS}@(*this)::construct( - @\placeholdernc{OUTERMOST}@(*this), p, - std::forward(newargs)...); - }, - uses_allocator_construction_args(inner_allocator(), - std::forward(args)...)); +is_nothrow_invocable_r_v && +is_nothrow_invocable_r_v +\end{codeblock} +Otherwise, \tcode{\exposid{is-callable-from}} is equal to: +\begin{codeblock} +is_invocable_r_v && +is_invocable_r_v \end{codeblock} \end{itemdescr} -\indexlibrarymember{destroy}{scoped_allocator_adaptor}% -\begin{itemdecl} -template - void destroy(T* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls \tcode{\placeholdernc{OUTERMOST_ALLOC_TRAITS}(*this)::destroy(\placeholdernc{OUTERMOST}(*this), p)}. -\end{itemdescr} - -\indexlibrarymember{select_on_container_copy_construction}{scoped_allocator_adaptor}% -\begin{itemdecl} -scoped_allocator_adaptor select_on_container_copy_construction() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A new \tcode{scoped_allocator_adaptor} object where each allocator \tcode{A} in the -adaptor is initialized from the result of calling -\tcode{allocator_traits::select_on_container_copy_construction()} on the -corresponding allocator in \tcode{*this}. -\end{itemdescr} - -\rSec2[scoped.adaptor.operators]{Operators} - -\indexlibrarymember{operator==}{scoped_allocator_adaptor}% +\indexlibraryctor{move_only_function}% \begin{itemdecl} -template - bool operator==(const scoped_allocator_adaptor& a, - const scoped_allocator_adaptor& b) noexcept; +move_only_function() noexcept; +move_only_function(nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -If \tcode{sizeof...(InnerAllocs)} is zero, -\begin{codeblock} -a.outer_allocator() == b.outer_allocator() -\end{codeblock} -otherwise -\begin{codeblock} -a.outer_allocator() == b.outer_allocator() && a.inner_allocator() == b.inner_allocator() -\end{codeblock} -\end{itemdescr} - -\rSec1[function.objects]{Function objects} - -\rSec2[function.objects.general]{General} - -\pnum -A \defnx{function object type}{function object!type} is an object -type\iref{basic.types} that can be the type of the -\grammarterm{postfix-expression} in a function call -(\ref{expr.call}, \ref{over.match.call}). -\begin{footnote} -Such a type is a function -pointer or a class type which has a member \tcode{operator()} or a class type -which has a conversion to a pointer to function. -\end{footnote} -A \defn{function object} is an -object of a function object type. In the places where one would expect to pass a -pointer to a function to an algorithmic template\iref{algorithms}, the -interface is specified to accept a function object. This not only makes -algorithmic templates work with pointers to functions, but also enables them to -work with arbitrary function objects. - -\rSec2[functional.syn]{Header \tcode{} synopsis} - -\indexheader{functional}% -\indexlibraryglobal{unwrap_ref_decay}% -\indexlibraryglobal{unwrap_ref_decay_t}% -\begin{codeblock} -namespace std { - // \ref{func.invoke}, invoke - template - constexpr invoke_result_t invoke(F&& f, Args&&... args) - noexcept(is_nothrow_invocable_v); - - template - constexpr R invoke_r(F&& f, Args&&... args) - noexcept(is_nothrow_invocable_r_v); - - // \ref{refwrap}, \tcode{reference_wrapper} - template class reference_wrapper; - - template constexpr reference_wrapper ref(T&) noexcept; - template constexpr reference_wrapper cref(const T&) noexcept; - template void ref(const T&&) = delete; - template void cref(const T&&) = delete; - - template constexpr reference_wrapper ref(reference_wrapper) noexcept; - template constexpr reference_wrapper cref(reference_wrapper) noexcept; - - // \ref{arithmetic.operations}, arithmetic operations - template struct plus; - template struct minus; - template struct multiplies; - template struct divides; - template struct modulus; - template struct negate; - template<> struct plus; - template<> struct minus; - template<> struct multiplies; - template<> struct divides; - template<> struct modulus; - template<> struct negate; - - // \ref{comparisons}, comparisons - template struct equal_to; - template struct not_equal_to; - template struct greater; - template struct less; - template struct greater_equal; - template struct less_equal; - template<> struct equal_to; - template<> struct not_equal_to; - template<> struct greater; - template<> struct less; - template<> struct greater_equal; - template<> struct less_equal; - - // \ref{comparisons.three.way}, class \tcode{compare_three_way} - struct compare_three_way; - - // \ref{logical.operations}, logical operations - template struct logical_and; - template struct logical_or; - template struct logical_not; - template<> struct logical_and; - template<> struct logical_or; - template<> struct logical_not; - - // \ref{bitwise.operations}, bitwise operations - template struct bit_and; - template struct bit_or; - template struct bit_xor; - template struct bit_not; - template<> struct bit_and; - template<> struct bit_or; - template<> struct bit_xor; - template<> struct bit_not; - - // \ref{func.identity}, identity - struct identity; - - // \ref{func.not.fn}, function template \tcode{not_fn} - template constexpr @\unspec@ not_fn(F&& f); - - // \ref{func.bind.front}, function template \tcode{bind_front} - template constexpr @\unspec@ bind_front(F&&, Args&&...); - - // \ref{func.bind}, bind - template struct is_bind_expression; - template - inline constexpr bool @\libglobal{is_bind_expression_v}@ = is_bind_expression::value; - template struct is_placeholder; - template - inline constexpr int @\libglobal{is_placeholder_v}@ = is_placeholder::value; - - template - constexpr @\unspec@ bind(F&&, BoundArgs&&...); - template - constexpr @\unspec@ bind(F&&, BoundArgs&&...); - - namespace placeholders { - // \tcode{\placeholder{M}} is the \impldef{number of placeholders for bind expressions} number of placeholders - @\seebelownc@ _1; - @\seebelownc@ _2; - . - . - . - @\seebelownc@ _@\placeholdernc{M}@; - } - - // \ref{func.memfn}, member function adaptors - template - constexpr @\unspec@ mem_fn(R T::*) noexcept; - - // \ref{func.wrap}, polymorphic function wrappers - class bad_function_call; - - template class function; // \notdef - template class function; - - // \ref{func.wrap.func.alg}, specialized algorithms - template - void swap(function&, function&) noexcept; - - // \ref{func.wrap.func.nullptr}, null pointer comparison operator functions - template - bool operator==(const function&, nullptr_t) noexcept; - - // \ref{func.wrap.move}, move only wrapper - template class move_only_function; // \notdef - template - class move_only_function; // \seebelow - - // \ref{func.search}, searchers - template> - class default_searcher; - - template::value_type>, - class BinaryPredicate = equal_to<>> - class boyer_moore_searcher; - - template::value_type>, - class BinaryPredicate = equal_to<>> - class boyer_moore_horspool_searcher; - - // \ref{unord.hash}, class template hash - template - struct hash; - - namespace ranges { - // \ref{range.cmp}, concept-constrained comparisons - struct equal_to; - struct not_equal_to; - struct greater; - struct less; - struct greater_equal; - struct less_equal; - } -} -\end{codeblock} - -\pnum -\begin{example} -If a \Cpp{} program wants to have a by-element addition of two vectors \tcode{a} -and \tcode{b} containing \tcode{double} and put the result into \tcode{a}, -it can do: - -\begin{codeblock} -transform(a.begin(), a.end(), b.begin(), a.begin(), plus()); -\end{codeblock} -\end{example} - -\pnum -\begin{example} -To negate every element of \tcode{a}: - -\begin{codeblock} -transform(a.begin(), a.end(), a.begin(), negate()); -\end{codeblock} - -\end{example} - -\rSec2[func.def]{Definitions} - -\pnum -The following definitions apply to this Clause: - -\pnum -A \defn{call signature} is the name of a return type followed by a -parenthesized comma-separated list of zero or more argument types. - -\pnum -A \defnadj{callable}{type} is a function object type\iref{function.objects} or a pointer to member. - -\pnum -A \defnadj{callable}{object} is an object of a callable type. - -\pnum -A \defnx{call wrapper type}{call wrapper!type} is a type that holds a callable object -and supports a call operation that forwards to that object. - -\pnum -A \defn{call wrapper} is an object of a call wrapper type. - -\pnum -A \defn{target object} is the callable object held by a call wrapper. - -\pnum -A call wrapper type may additionally hold -a sequence of objects and references -that may be passed as arguments to the target object. -These entities are collectively referred to -as \defnx{bound argument entities}{bound argument entity}. - -\pnum -The target object and bound argument entities of the call wrapper are -collectively referred to as \defnx{state entities}{state entity}. - -\rSec2[func.require]{Requirements} - -\pnum -\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% -Define \tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} as follows: -\begin{itemize} -\item \tcode{(t$_1$.*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a -member function of a class \tcode{T} -and \tcode{is_base_of_v>} is \tcode{true}; - -\item \tcode{(t$_1$.get().*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a -member function of a class \tcode{T} -and \tcode{remove_cvref_t} is a specialization of \tcode{reference_wrapper}; - -\item \tcode{((*t$_1$).*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a -member function of a class \tcode{T} -and \tcode{t$_1$} does not satisfy the previous two items; - -\item \tcode{t$_1$.*f} when \tcode{N == 1} and \tcode{f} is a pointer to -data member of a class \tcode{T} -and \tcode{is_base_of_v>} is \tcode{true}; - -\item \tcode{t$_1$.get().*f} when \tcode{N == 1} and \tcode{f} is a pointer to -data member of a class \tcode{T} -and \tcode{remove_cvref_t} is a specialization of \tcode{reference_wrapper}; - -\item \tcode{(*t$_1$).*f} when \tcode{N == 1} and \tcode{f} is a pointer to -data member of a class \tcode{T} -and \tcode{t$_1$} does not satisfy the previous two items; - -\item \tcode{f(t$_1$, t$_2$, $\dotsc$, t$_N$)} in all other cases. -\end{itemize} - -\pnum -\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% -Define \tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} as -\tcode{static_cast(\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$))} -if \tcode{R} is \cv{}~\keyword{void}, otherwise -\tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} implicitly converted -to \tcode{R}. - -\pnum -\indextext{call wrapper}% -\indextext{call wrapper!simple}% -\indextext{call wrapper!forwarding}% -Every call wrapper\iref{func.def} meets the \oldconcept{MoveConstructible} -and \oldconcept{Destructible} requirements. -An \defn{argument forwarding call wrapper} is a -call wrapper that can be called with an arbitrary argument list -and delivers the arguments to the target object as references. -This forwarding step delivers rvalue arguments as rvalue references -and lvalue arguments as lvalue references. -\begin{note} -In a typical implementation, argument forwarding call wrappers have -an overloaded function call operator of the form -\begin{codeblock} -template - constexpr R operator()(UnBoundArgs&&... unbound_args) @\textit{cv-qual}@; -\end{codeblock} -\end{note} - -\pnum -\indextext{call wrapper!perfect forwarding}% -A \defn{perfect forwarding call wrapper} is -an argument forwarding call wrapper -that forwards its state entities to the underlying call expression. -This forwarding step delivers a state entity of type \tcode{T} -as \cv{} \tcode{T\&} -when the call is performed on an lvalue of the call wrapper type and -as \cv{} \tcode{T\&\&} otherwise, -where \cv{} represents the cv-qualifiers of the call wrapper and -where \cv{} shall be neither \tcode{volatile} nor \tcode{const volatile}. - -\pnum -A \defn{call pattern} defines the semantics of invoking -a perfect forwarding call wrapper. -A postfix call performed on a perfect forwarding call wrapper is -expression-equivalent\iref{defns.expression-equivalent} to -an expression \tcode{e} determined from its call pattern \tcode{cp} -by replacing all occurrences -of the arguments of the call wrapper and its state entities -with references as described in the corresponding forwarding steps. - -\pnum -A \defn{simple call wrapper} is a perfect forwarding call wrapper that meets -the \oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} requirements -and whose copy constructor, move constructor, and assignment operators -are constexpr functions that do not throw exceptions. - -\pnum -The copy/move constructor of an argument forwarding call wrapper has -the same apparent semantics -as if memberwise copy/move of its state entities -were performed\iref{class.copy.ctor}. -\begin{note} -This implies that each of the copy/move constructors has -the same exception-specification as -the corresponding implicit definition and is declared as \keyword{constexpr} -if the corresponding implicit definition would be considered to be constexpr. -\end{note} - -\pnum -Argument forwarding call wrappers returned by -a given standard library function template have the same type -if the types of their corresponding state entities are the same. - -\rSec2[func.invoke]{\tcode{invoke} functions} -\indexlibraryglobal{invoke}% -\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% -\begin{itemdecl} -template - constexpr invoke_result_t invoke(F&& f, Args&&... args) - noexcept(is_nothrow_invocable_v); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_invocable_v} is \tcode{true}. - -\pnum -\returns -\tcode{\placeholdernc{INVOKE}(std::forward(f), std::forward(args)...)}\iref{func.require}. -\end{itemdescr} - -\indexlibraryglobal{invoke_r}% -\begin{itemdecl} -template - constexpr R invoke_r(F&& f, Args&&... args) - noexcept(is_nothrow_invocable_r_v); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_invocable_r_v} is \tcode{true}. - -\pnum -\returns -\tcode{\placeholdernc{INVOKE}(std::forward(f), std::forward(args)...)}\iref{func.require}. -\end{itemdescr} - -\rSec2[refwrap]{Class template \tcode{reference_wrapper}} - -\rSec3[refwrap.general]{General} - -\indexlibraryglobal{reference_wrapper}% -\indextext{function object!\idxcode{reference_wrapper}}% -\begin{codeblock} -namespace std { - template class reference_wrapper { - public: - // types - using type = T; - - // construct/copy/destroy - template - constexpr reference_wrapper(U&&) noexcept(@\seebelow@); - constexpr reference_wrapper(const reference_wrapper& x) noexcept; - - // assignment - constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept; - - // access - constexpr operator T& () const noexcept; - constexpr T& get() const noexcept; - - // invocation - template - constexpr invoke_result_t operator()(ArgTypes&&...) const; - }; - - template - reference_wrapper(T&) -> reference_wrapper; -} -\end{codeblock} - -\pnum -\tcode{reference_wrapper} is a \oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} wrapper -around a reference to an object or function of type \tcode{T}. - -\pnum -\tcode{reference_wrapper} is a trivially copyable type\iref{basic.types}. - -\pnum -The template parameter \tcode{T} of \tcode{reference_wrapper} -may be an incomplete type. - -\rSec3[refwrap.const]{Constructors and destructor} - -\indexlibraryctor{reference_wrapper}% -\begin{itemdecl} -template - constexpr reference_wrapper(U&& u) noexcept(@\seebelow@); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{\placeholdernc{FUN}} denote the exposition-only functions -\begin{codeblock} -void @\placeholdernc{FUN}@(T&) noexcept; -void @\placeholdernc{FUN}@(T&&) = delete; -\end{codeblock} - -\pnum -\constraints -The expression \tcode{\placeholdernc{FUN}(declval())} is well-formed and -\tcode{is_same_v, reference_wrapper>} is \tcode{false}. - -\pnum -\effects -Creates a variable \tcode{r} -as if by \tcode{T\& r = std::forward(u)}, -then constructs a \tcode{reference_wrapper} object -that stores a reference to \tcode{r}. - -\pnum -\remarks -The exception specification is equivalent to -\tcode{noexcept(\placeholdernc{FUN}(declval()))}. -\end{itemdescr} - -\indexlibraryctor{reference_wrapper}% -\begin{itemdecl} -constexpr reference_wrapper(const reference_wrapper& x) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs a \tcode{reference_wrapper} object that -stores a reference to \tcode{x.get()}. -\end{itemdescr} - -\rSec3[refwrap.assign]{Assignment} - -\indexlibrarymember{operator=}{reference_wrapper}% -\begin{itemdecl} -constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{*this} stores a reference to \tcode{x.get()}. -\end{itemdescr} - -\rSec3[refwrap.access]{Access} - -\indexlibrarymember{operator T\&}{reference_wrapper}% -\begin{itemdecl} -constexpr operator T& () const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The stored reference. -\end{itemdescr} - -\indexlibrarymember{get}{reference_wrapper}% -\begin{itemdecl} -constexpr T& get() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The stored reference. -\end{itemdescr} - -\rSec3[refwrap.invoke]{Invocation} - -\indexlibrarymember{operator()}{reference_wrapper}% -\begin{itemdecl} -template - constexpr invoke_result_t - operator()(ArgTypes&&... args) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{T} is a complete type. - -\pnum -\returns -\tcode{\placeholdernc{INVOKE}(get(), std::forward(args)...)}.\iref{func.require} -\end{itemdescr} - - -\rSec3[refwrap.helpers]{Helper functions} - -\pnum -The template parameter \tcode{T} of -the following \tcode{ref} and \tcode{cref} function templates -may be an incomplete type. - -\indexlibrarymember{ref}{reference_wrapper}% -\begin{itemdecl} -template constexpr reference_wrapper ref(T& t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{reference_wrapper(t)}. -\end{itemdescr} - -\indexlibrarymember{ref}{reference_wrapper}% -\begin{itemdecl} -template constexpr reference_wrapper ref(reference_wrapper t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{t}. -\end{itemdescr} - -\indexlibrarymember{cref}{reference_wrapper}% -\begin{itemdecl} -template constexpr reference_wrapper cref(const T& t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{reference_wrapper (t)}. -\end{itemdescr} - -\indexlibrarymember{cref}{reference_wrapper}% -\begin{itemdecl} -template constexpr reference_wrapper cref(reference_wrapper t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{t}. -\end{itemdescr} - -\rSec2[arithmetic.operations]{Arithmetic operations} - -\rSec3[arithmetic.operations.general]{General} - -\pnum -The library provides basic function object classes for all of the arithmetic -operators in the language~(\ref{expr.mul}, \ref{expr.add}). - -\rSec3[arithmetic.operations.plus]{Class template \tcode{plus}} - -\indexlibraryglobal{plus}% -\begin{itemdecl} -template struct plus { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{plus}% -\begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x + y}. -\end{itemdescr} - -\indexlibraryglobal{plus<>}% -\begin{itemdecl} -template<> struct plus { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) + std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{plus<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) + std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) + std::forward(u)}. -\end{itemdescr} - -\rSec3[arithmetic.operations.minus]{Class template \tcode{minus}} - -\indexlibraryglobal{minus}% -\begin{itemdecl} -template struct minus { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{minus}% -\begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x - y}. -\end{itemdescr} - -\indexlibraryglobal{minus<>}% -\begin{itemdecl} -template<> struct minus { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) - std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{minus<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) - std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) - std::forward(u)}. -\end{itemdescr} - -\rSec3[arithmetic.operations.multiplies]{Class template \tcode{multiplies}} - -\indexlibraryglobal{multiplies}% -\begin{itemdecl} -template struct multiplies { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{multiplies}% -\begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x * y}. -\end{itemdescr} - -\indexlibraryglobal{multiplies<>}% -\begin{itemdecl} -template<> struct multiplies { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) * std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{multiplies<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) * std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) * std::forward(u)}. -\end{itemdescr} - -\rSec3[arithmetic.operations.divides]{Class template \tcode{divides}} - -\indexlibraryglobal{divides}% -\begin{itemdecl} -template struct divides { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{divides}% -\begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x / y}. -\end{itemdescr} - -\indexlibraryglobal{divides<>}% -\begin{itemdecl} -template<> struct divides { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) / std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{divides<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) / std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) / std::forward(u)}. -\end{itemdescr} - -\rSec3[arithmetic.operations.modulus]{Class template \tcode{modulus}} - -\indexlibraryglobal{modulus}% -\begin{itemdecl} -template struct modulus { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{modulus}% -\begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x \% y}. -\end{itemdescr} - -\indexlibraryglobal{modulus<>}% -\begin{itemdecl} -template<> struct modulus { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) % std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{modulus<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) % std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) \% std::forward(u)}. -\end{itemdescr} - -\rSec3[arithmetic.operations.negate]{Class template \tcode{negate}} - -\indexlibraryglobal{negate}% -\begin{itemdecl} -template struct negate { - constexpr T operator()(const T& x) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{negate}% -\begin{itemdecl} -constexpr T operator()(const T& x) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{-x}. -\end{itemdescr} - -\indexlibraryglobal{negate<>}% -\begin{itemdecl} -template<> struct negate { - template constexpr auto operator()(T&& t) const - -> decltype(-std::forward(t)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{negate<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t) const - -> decltype(-std::forward(t)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{-std::forward(t)}. -\end{itemdescr} - - -\rSec2[comparisons]{Comparisons} - -\rSec3[comparisons.general]{General} - -\pnum -The library provides basic function object classes for all of the comparison -operators in the language~(\ref{expr.rel}, \ref{expr.eq}). - -\pnum -For templates \tcode{less}, \tcode{greater}, \tcode{less_equal}, and -\tcode{greater_equal}, the specializations for any pointer type -yield a result consistent with the -implementation-defined strict total order over pointers\iref{defns.order.ptr}. -\begin{note} -If \tcode{a < b} is well-defined -for pointers \tcode{a} and \tcode{b} of type \tcode{P}, -then \tcode{(a < b) == less

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

()(a, b)}, and so forth. -\end{note} -For template specializations \tcode{less}, \tcode{greater}, -\tcode{less_equal}, and \tcode{greater_equal}, -if the call operator calls a built-in operator comparing pointers, -the call operator yields a result consistent -with the implementation-defined strict total order over pointers. - -\rSec3[comparisons.equal.to]{Class template \tcode{equal_to}} - -\indexlibraryglobal{equal_to}% -\begin{itemdecl} -template struct equal_to { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{equal_to}% -\begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x == y}. -\end{itemdescr} - -\indexlibraryglobal{equal_to<>}% -\begin{itemdecl} -template<> struct equal_to { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) == std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{equal_to<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) == std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) == std::forward(u)}. -\end{itemdescr} - -\rSec3[comparisons.not.equal.to]{Class template \tcode{not_equal_to}} - -\indexlibraryglobal{not_equal_to}% -\begin{itemdecl} -template struct not_equal_to { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{not_equal_to}% -\begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x != y}. -\end{itemdescr} - -\indexlibraryglobal{not_equal_to<>}% -\begin{itemdecl} -template<> struct not_equal_to { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) != std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{not_equal_to<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) != std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) != std::forward(u)}. -\end{itemdescr} - -\rSec3[comparisons.greater]{Class template \tcode{greater}} - -\indexlibraryglobal{greater}% -\begin{itemdecl} -template struct greater { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{greater}% -\begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x > y}. -\end{itemdescr} - -\indexlibraryglobal{greater<>}% -\begin{itemdecl} -template<> struct greater { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) > std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{greater<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) > std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) > std::forward(u)}. -\end{itemdescr} - -\rSec3[comparisons.less]{Class template \tcode{less}} - -\indexlibraryglobal{less}% -\begin{itemdecl} -template struct less { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{less}% -\begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x < y}. -\end{itemdescr} - -\indexlibraryglobal{less<>}% -\begin{itemdecl} -template<> struct less { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) < std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{less<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) < std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) < std::forward(u)}. -\end{itemdescr} - -\rSec3[comparisons.greater.equal]{Class template \tcode{greater_equal}} - -\indexlibraryglobal{greater_equal}% -\begin{itemdecl} -template struct greater_equal { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{greater_equal}% -\begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x >= y}. -\end{itemdescr} - -\indexlibraryglobal{greater_equal<>}% -\begin{itemdecl} -template<> struct greater_equal { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) >= std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{greater_equal<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) >= std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) >= std::forward(u)}. -\end{itemdescr} - -\rSec3[comparisons.less.equal]{Class template \tcode{less_equal}} - -\indexlibraryglobal{less_equal}% -\begin{itemdecl} -template struct less_equal { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{less_equal}% -\begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x <= y}. -\end{itemdescr} - -\indexlibraryglobal{less_equal<>}% -\begin{itemdecl} -template<> struct less_equal { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) <= std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{less_equal<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) <= std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) <= std::forward(u)}. -\end{itemdescr} - -\rSec3[comparisons.three.way]{Class \tcode{compare_three_way}} - -\indexlibraryglobal{compare_three_way}% -\begin{codeblock} -struct compare_three_way { - template - constexpr auto operator()(T&& t, U&& u) const; - - using is_transparent = @\unspec@; -}; -\end{codeblock} - -\begin{itemdecl} -template - constexpr auto operator()(T&& t, U&& u) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} and \tcode{U} satisfy \libconcept{three_way_comparable_with}. - -\pnum -\expects -If the expression \tcode{std::forward(t) <=> std::forward(u)} results in -a call to a built-in operator \tcode{<=>} comparing pointers of type \tcode{P}, -the conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} -are equality-preserving\iref{concepts.equality}; -otherwise, \tcode{T} and \tcode{U} model \libconcept{three_way_comparable_with}. - -\pnum -\effects -\begin{itemize} -\item - If the expression \tcode{std::forward(t) <=> std::forward(u)} results in - a call to a built-in operator \tcode{<=>} comparing pointers of type \tcode{P}, - returns \tcode{strong_ordering::less} - if (the converted value of) \tcode{t} precedes \tcode{u} - in the implementation-defined strict total order - over pointers\iref{defns.order.ptr}, - \tcode{strong_ordering::greater} - if \tcode{u} precedes \tcode{t}, and - otherwise \tcode{strong_ordering::equal}. -\item - Otherwise, equivalent to: \tcode{return std::forward(t) <=> std::forward(u);} -\end{itemize} -\end{itemdescr} - -\rSec2[range.cmp]{Concept-constrained comparisons} - -\indexlibraryglobal{equal_to}% -\begin{codeblock} -struct ranges::equal_to { - template - constexpr bool operator()(T&& t, U&& u) const; - - using is_transparent = @\unspecnc@; -}; -\end{codeblock} - -\begin{itemdecl} -template - constexpr bool operator()(T&& t, U&& u) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} and \tcode{U} satisfy \libconcept{equality_comparable_with}. - -\pnum -\expects -If the expression \tcode{std::forward(t) == std::forward(u)} -results in a call to a built-in operator \tcode{==} comparing pointers of type -\tcode{P}, the conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} -are equality-preserving\iref{concepts.equality}; -otherwise, \tcode{T} and \tcode{U} model \libconcept{equality_comparable_with}. - -\pnum -\effects -\begin{itemize} -\item - If the expression \tcode{std::forward(t) == std::forward(u)} results in - a call to a built-in operator \tcode{==} comparing pointers: - returns \tcode{false} if either (the converted value of) \tcode{t} precedes - \tcode{u} or \tcode{u} precedes \tcode{t} in the implementation-defined strict - total order over pointers\iref{defns.order.ptr} and otherwise \tcode{true}. - -\item - Otherwise, equivalent to: - \tcode{return std::forward(t) == std::forward(u);} -\end{itemize} -\end{itemdescr} - -\indexlibraryglobal{not_equal_to}% -\begin{codeblock} -struct ranges::not_equal_to { - template - constexpr bool operator()(T&& t, U&& u) const; - - using is_transparent = @\unspecnc@; -}; -\end{codeblock} - -\begin{itemdecl} -template - constexpr bool operator()(T&& t, U&& u) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} and \tcode{U} satisfy \libconcept{equality_comparable_with}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return !ranges::equal_to{}(std::forward(t), std::forward(u)); -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{greater}% -\begin{codeblock} -struct ranges::greater { - template - constexpr bool operator()(T&& t, U&& u) const; - - using is_transparent = @\unspecnc@; -}; -\end{codeblock} - -\begin{itemdecl} -template - constexpr bool operator()(T&& t, U&& u) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return ranges::less{}(std::forward(u), std::forward(t)); -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{less}% -\begin{codeblock} -struct ranges::less { - template - constexpr bool operator()(T&& t, U&& u) const; - - using is_transparent = @\unspecnc@; -}; -\end{codeblock} - -\begin{itemdecl} -template - constexpr bool operator()(T&& t, U&& u) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. - -\pnum -\expects -If the expression \tcode{std::forward(t) < std::forward(u)} results in a -call to a built-in operator \tcode{<} comparing pointers of type \tcode{P}, the -conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} are -equality-preserving\iref{concepts.equality}; -otherwise, \tcode{T} and \tcode{U} model \libconcept{totally_ordered_with}. -For any expressions -\tcode{ET} and \tcode{EU} such that \tcode{decltype((ET))} is \tcode{T} and -\tcode{decltype((EU))} is \tcode{U}, exactly one of -\tcode{ranges::less\{\}(ET, EU)}, -\tcode{ranges::less\{\}(EU, ET)}, or -\tcode{ranges::equal_to\{\}(ET, EU)} -is \tcode{true}. - -\pnum -\effects -\begin{itemize} -\item -If the expression \tcode{std::forward(t) < std::forward(u)} results in a -call to a built-in operator \tcode{<} comparing pointers: -returns \tcode{true} if (the converted value of) \tcode{t} precedes \tcode{u} in -the implementation-defined strict total order over pointers\iref{defns.order.ptr} -and otherwise \tcode{false}. - -\item -Otherwise, equivalent to: -\tcode{return std::forward(t) < std::forward(u);} -\end{itemize} -\end{itemdescr} - -\indexlibraryglobal{greater_equal}% -\begin{codeblock} -struct ranges::greater_equal { - template - constexpr bool operator()(T&& t, U&& u) const; - - using is_transparent = @\unspecnc@; -}; -\end{codeblock} - -\begin{itemdecl} -template - constexpr bool operator()(T&& t, U&& u) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return !ranges::less{}(std::forward(t), std::forward(u)); -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{less_equal}% -\begin{itemdecl} -struct ranges::less_equal { - template - constexpr bool operator()(T&& t, U&& u) const; - - using is_transparent = @\unspecnc@; -}; -\end{itemdecl} - -\begin{itemdecl} -template - constexpr bool operator()(T&& t, U&& u) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return !ranges::less{}(std::forward(u), std::forward(t)); -\end{codeblock} -\end{itemdescr} - -\rSec2[logical.operations]{Logical operations} - -\rSec3[logical.operations.general]{General} - -\pnum -The library provides basic function object classes for all of the logical -operators in the language~(\ref{expr.log.and}, \ref{expr.log.or}, \ref{expr.unary.op}). - -\rSec3[logical.operations.and]{Class template \tcode{logical_and}} - -\indexlibraryglobal{logical_and}% -\begin{itemdecl} -template struct logical_and { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{logical_and}% -\begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x \&\& y}. -\end{itemdescr} - -\indexlibraryglobal{logical_and<>}% -\begin{itemdecl} -template<> struct logical_and { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) && std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{logical_and<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) && std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) \&\& std::forward(u)}. -\end{itemdescr} - -\rSec3[logical.operations.or]{Class template \tcode{logical_or}} - -\indexlibraryglobal{logical_or}% -\begin{itemdecl} -template struct logical_or { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{logical_or}% -\begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x || y}. -\end{itemdescr} - -\indexlibraryglobal{logical_or<>}% -\begin{itemdecl} -template<> struct logical_or { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) || std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{logical_or<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) || std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) || std::forward(u)}. -\end{itemdescr} - -\rSec3[logical.operations.not]{Class template \tcode{logical_not}} - -\indexlibraryglobal{logical_not}% -\begin{itemdecl} -template struct logical_not { - constexpr bool operator()(const T& x) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{logical_not}% -\begin{itemdecl} -constexpr bool operator()(const T& x) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!x}. -\end{itemdescr} - -\indexlibraryglobal{logical_not<>}% -\begin{itemdecl} -template<> struct logical_not { - template constexpr auto operator()(T&& t) const - -> decltype(!std::forward(t)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{logical_not<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t) const - -> decltype(!std::forward(t)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!std::forward(t)}. -\end{itemdescr} - - -\rSec2[bitwise.operations]{Bitwise operations} - -\rSec3[bitwise.operations.general]{General} - -\pnum -The library provides basic function object classes for all of the bitwise -operators in the language~(\ref{expr.bit.and}, \ref{expr.or}, -\ref{expr.xor}, \ref{expr.unary.op}). - -\rSec3[bitwise.operations.and]{Class template \tcode{bit_and}} - -\indexlibraryglobal{bit_and}% -\begin{itemdecl} -template struct bit_and { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_and}% -\begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x \& y}. -\end{itemdescr} - -\indexlibraryglobal{bit_and<>}% -\begin{itemdecl} -template<> struct bit_and { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) & std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_and<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) & std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) \& std::forward(u)}. -\end{itemdescr} - -\rSec3[bitwise.operations.or]{Class template \tcode{bit_or}} - -\indexlibraryglobal{bit_or}% -\begin{itemdecl} -template struct bit_or { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_or}% -\begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x | y}. -\end{itemdescr} - -\indexlibraryglobal{bit_or<>}% -\begin{itemdecl} -template<> struct bit_or { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) | std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_or<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) | std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) | std::forward(u)}. -\end{itemdescr} - -\rSec3[bitwise.operations.xor]{Class template \tcode{bit_xor}} - -\indexlibraryglobal{bit_xor}% -\begin{itemdecl} -template struct bit_xor { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_xor}% -\begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x \caret{} y}. -\end{itemdescr} - -\indexlibraryglobal{bit_xor<>}% -\begin{itemdecl} -template<> struct bit_xor { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) ^ std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_xor<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) ^ std::forward(u)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) \caret{} std::forward(u)}. -\end{itemdescr} - -\rSec3[bitwise.operations.not]{Class template \tcode{bit_not}} - -\begin{itemdecl} -template struct bit_not { - constexpr T operator()(const T& x) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_not}% -\begin{itemdecl} -constexpr T operator()(const T& x) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{\~{}x}. -\end{itemdescr} - -\indexlibraryglobal{bit_not<>}% -\begin{itemdecl} -template<> struct bit_not { - template constexpr auto operator()(T&& t) const - -> decltype(~std::forward(t)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_not<>}% -\begin{itemdecl} -template constexpr auto operator()(T&&) const - -> decltype(~std::forward(t)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{\~{}std::forward(t)}. -\end{itemdescr} - - -\rSec2[func.identity]{Class \tcode{identity}} - -\indexlibraryglobal{identity}% -\begin{itemdecl} -struct identity { - template - constexpr T&& operator()(T&& t) const noexcept; - - using is_transparent = @\unspec@; -}; - -template - constexpr T&& operator()(T&& t) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return std::forward(t);} -\end{itemdescr} - - -\rSec2[func.not.fn]{Function template \tcode{not_fn}} - -\indexlibraryglobal{not_fn}% -\begin{itemdecl} -template constexpr @\unspec@ not_fn(F&& f); -\end{itemdecl} - -\begin{itemdescr} -\pnum -In the text that follows: -\begin{itemize} -\item \tcode{g} is a value of the result of a \tcode{not_fn} invocation, -\item \tcode{FD} is the type \tcode{decay_t}, -\item \tcode{fd} is the target object of \tcode{g}\iref{func.def} - of type \tcode{FD}, - direct-non-list-initialized with \tcode{std::forward(f)}, -\item \tcode{call_args} is an argument pack - used in a function call expression\iref{expr.call} of \tcode{g}. -\end{itemize} - -\pnum -\mandates -\tcode{is_constructible_v \&\& is_move_constructible_v} -is \tcode{true}. - -\pnum -\expects -\tcode{FD} meets the \oldconcept{MoveConstructible} requirements. - -\pnum -\returns -A perfect forwarding call wrapper \tcode{g} -with call pattern \tcode{!invoke(fd, call_args...)}. - -\pnum -\throws -Any exception thrown by the initialization of \tcode{fd}. -\end{itemdescr} - -\rSec2[func.bind.front]{Function template \tcode{bind_front}} - -\indexlibraryglobal{bind_front}% -\begin{itemdecl} -template - constexpr @\unspec@ bind_front(F&& f, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Within this subclause: -\begin{itemize} -\item \tcode{g} is a value of the result of a \tcode{bind_front} invocation, -\item \tcode{FD} is the type \tcode{decay_t}, -\item \tcode{fd} is the target object of \tcode{g}\iref{func.def} - of type \tcode{FD}, - direct-non-list-initialized with \tcode{std::forward(f)}, -\item \tcode{BoundArgs} is a pack - that denotes \tcode{decay_t...}, -\item \tcode{bound_args} is - a pack of bound argument entities of \tcode{g}\iref{func.def} - of types \tcode{BoundArgs...}, - direct-non-list-initialized with \tcode{std::forward(args)...}, - respectively, and -\item \tcode{call_args} is an argument pack used in - a function call expression\iref{expr.call} of \tcode{g}. -\end{itemize} - -\pnum -\mandates -\begin{codeblock} -is_constructible_v && -is_move_constructible_v && -(is_constructible_v && ...) && -(is_move_constructible_v && ...) -\end{codeblock} -is \tcode{true}. - -\pnum -\expects -\tcode{FD} meets the \oldconcept{MoveConstructible} requirements. -For each $\tcode{T}_i$ in \tcode{BoundArgs}, -if $\tcode{T}_i$ is an object type, -$\tcode{T}_i$ meets the \oldconcept{MoveConstructible} requirements. - -\pnum -\returns -A perfect forwarding call wrapper \tcode{g} -with call pattern \tcode{invoke(fd, bound_args..., call_args...)}. - -\pnum -\throws -Any exception thrown by -the initialization of the state entities of \tcode{g}\iref{func.def}. -\end{itemdescr} - -\rSec2[func.bind]{Function object binders}% - -\rSec3[func.bind.general]{General}% -\indextext{function object!binders|(} - -\pnum -Subclause \ref{func.bind} describes a uniform mechanism for binding -arguments of callable objects. - -\rSec3[func.bind.isbind]{Class template \tcode{is_bind_expression}} - -\indexlibraryglobal{is_bind_expression}% -\begin{codeblock} -namespace std { - template struct is_bind_expression; // see below -} -\end{codeblock} - -\pnum -The class template \tcode{is_bind_expression} can be used to detect function objects -generated by \tcode{bind}. The function template \tcode{bind} -uses \tcode{is_bind_expression} to detect subexpressions. - -\pnum -Specializations of the \tcode{is_bind_expression} template shall meet -the \oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts}. The implementation -provides a definition that has a base characteristic of -\tcode{true_type} if \tcode{T} is a type returned from \tcode{bind}, -otherwise it has a base characteristic of \tcode{false_type}. -A program may specialize this template for a program-defined type \tcode{T} -to have a base characteristic of \tcode{true_type} to indicate that -\tcode{T} should be treated as a subexpression in a \tcode{bind} call. - -\rSec3[func.bind.isplace]{Class template \tcode{is_placeholder}} - -\indexlibraryglobal{is_placeholder}% -\begin{codeblock} -namespace std { - template struct is_placeholder; // see below -} -\end{codeblock} - -\pnum -The class template \tcode{is_placeholder} can be used to detect the standard placeholders -\tcode{_1}, \tcode{_2}, and so on. The function template \tcode{bind} uses -\tcode{is_placeholder} to detect placeholders. - -\pnum -Specializations of the \tcode{is_placeholder} template shall meet -the \oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts}. The implementation -provides a definition that has the base characteristic of -\tcode{integral_constant} if \tcode{T} is the type of -\tcode{std::placeholders::_\placeholder{J}}, otherwise it has a -base characteristic of \tcode{integral_constant}. A program -may specialize this template for a program-defined type \tcode{T} to -have a base characteristic of \tcode{integral_constant} -with \tcode{N > 0} to indicate that \tcode{T} should be -treated as a placeholder type. - -\rSec3[func.bind.bind]{Function template \tcode{bind}} -\indexlibrary{\idxcode{bind}|(} - -\pnum -In the text that follows: -\begin{itemize} -\item \tcode{g} is a value of the result of a \tcode{bind} invocation, -\item \tcode{FD} is the type \tcode{decay_t}, -\item \tcode{fd} is an lvalue that - is a target object of \tcode{g}\iref{func.def} of type \tcode{FD} - direct-non-list-initialized with \tcode{std::forward(f)}, -\item $\tcode{T}_i$ is the $i^\text{th}$ type in the template parameter pack \tcode{BoundArgs}, -\item $\tcode{TD}_i$ is the type \tcode{decay_t<$\tcode{T}_i$>}, -\item $\tcode{t}_i$ is the $i^\text{th}$ argument in the function parameter pack \tcode{bound_args}, -\item $\tcode{td}_i$ is a bound argument entity - of \tcode{g}\iref{func.def} of type $\tcode{TD}_i$ - direct-non-list-initialized with - \tcode{std::forward<\brk{}$\tcode{T}_i$>($\tcode{t}_i$)}, -\item $\tcode{U}_j$ is the $j^\text{th}$ deduced type of the \tcode{UnBoundArgs\&\&...} parameter - of the argument forwarding call wrapper, and -\item $\tcode{u}_j$ is the $j^\text{th}$ argument associated with $\tcode{U}_j$. -\end{itemize} - -\indexlibraryglobal{bind}% -\begin{itemdecl} -template - constexpr @\unspec@ bind(F&& f, BoundArgs&&... bound_args); -template - constexpr @\unspec@ bind(F&& f, BoundArgs&&... bound_args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{is_constructible_v} is \tcode{true}. For each $\tcode{T}_i$ -in \tcode{BoundArgs}, \tcode{is_cons\-tructible_v<$\tcode{TD}_i$, $\tcode{T}_i$>} is \tcode{true}. - -\pnum -\expects -\tcode{FD} and each $\tcode{TD}_i$ meet -the \oldconcept{MoveConstructible} and \oldconcept{Destructible} requirements. -\tcode{\placeholdernc{INVOKE}(fd, $\tcode{w}_1$, $\tcode{w}_2$, $\dotsc$, -$\tcode{w}_N$)}\iref{func.require} is a valid expression for some -values $\tcode{w}_1$, $\tcode{w}_2$, $\dotsc{}$, $\tcode{w}_N$, where -$N$ has the value \tcode{sizeof...(bound_args)}. - -\pnum -\returns -An argument forwarding call wrapper \tcode{g}\iref{func.require}. -A program that attempts to invoke a volatile-qualified \tcode{g} -is ill-formed. -When \tcode{g} is not volatile-qualified, invocation of -\tcode{g($\tcode{u}_1$, $\tcode{u}_2$, $\dotsc$, $\tcode{u}_M$)} -is expression-equivalent\iref{defns.expression-equivalent} to -\begin{codeblock} -@\placeholdernc{INVOKE}@(static_cast<@$\tcode{V}_\tcode{fd}$@>(@$\tcode{v}_\tcode{fd}$@), - static_cast<@$\tcode{V}_1$@>(@$\tcode{v}_1$@), static_cast<@$\tcode{V}_2$@>(@$\tcode{v}_2$@), @$\dotsc$@, static_cast<@$\tcode{V}_N$@>(@$\tcode{v}_N$@)) -\end{codeblock} -for the first overload, and -\begin{codeblock} -@\placeholdernc{INVOKE}@(static_cast<@$\tcode{V}_\tcode{fd}$@>(@$\tcode{v}_\tcode{fd}$@), - static_cast<@$\tcode{V}_1$@>(@$\tcode{v}_1$@), static_cast<@$\tcode{V}_2$@>(@$\tcode{v}_2$@), @$\dotsc$@, static_cast<@$\tcode{V}_N$@>(@$\tcode{v}_N$@)) -\end{codeblock} -for the second overload, -where the values and types of the target argument $\tcode{v}_\tcode{fd}$ and -of the bound arguments -$\tcode{v}_1$, $\tcode{v}_2$, $\dotsc$, $\tcode{v}_N$ are determined as specified below. - -\pnum -\throws -Any exception thrown by the initialization of -the state entities of \tcode{g}. - -\pnum -\begin{note} -If all of \tcode{FD} and $\tcode{TD}_i$ meet -the requirements of \oldconcept{CopyConstructible}, then -the return type meets the requirements of \oldconcept{CopyConstructible}. -\end{note} -\end{itemdescr} - -\pnum -\indextext{bound arguments}% -The values of the \term{bound arguments} $\tcode{v}_1$, $\tcode{v}_2$, $\dotsc$, $\tcode{v}_N$ and their -corresponding types $\tcode{V}_1$, $\tcode{V}_2$, $\dotsc$, $\tcode{V}_N$ depend on the -types $\tcode{TD}_i$ derived from -the call to \tcode{bind} and the -cv-qualifiers \cv{} of the call wrapper \tcode{g} as follows: -\begin{itemize} -\item if $\tcode{TD}_i$ is \tcode{reference_wrapper}, the -argument is \tcode{$\tcode{td}_i$.get()} and its type $\tcode{V}_i$ is \tcode{T\&}; - -\item if the value of \tcode{is_bind_expression_v<$\tcode{TD}_i$>} -is \tcode{true}, the argument is -\begin{codeblock} -static_cast<@\cv{} $\tcode{TD}_i$@&>(@$\tcode{td}_i$@)(std::forward<@$\tcode{U}_j$@>(@$\tcode{u}_j$@)...) -\end{codeblock} -and its type $\tcode{V}_i$ is -\tcode{invoke_result_t<\cv{} $\tcode{TD}_i$\&, $\tcode{U}_j$...>\&\&}; - -\item if the value \tcode{j} of \tcode{is_placeholder_v<$\tcode{TD}_i$>} -is not zero, the argument is \tcode{std::forward<$\tcode{U}_j$>($\tcode{u}_j$)} -and its type $\tcode{V}_i$ -is \tcode{$\tcode{U}_j$\&\&}; - -\item otherwise, the value is $\tcode{td}_i$ and its type $\tcode{V}_i$ -is \tcode{\cv{} $\tcode{TD}_i$\&}. -\end{itemize} - -\pnum -The value of the target argument $\tcode{v}_\tcode{fd}$ is \tcode{fd} and -its corresponding type $\tcode{V}_\tcode{fd}$ is \tcode{\cv{} FD\&}. -\indexlibrary{\idxcode{bind}|)}% - -\rSec3[func.bind.place]{Placeholders} - -\indexlibraryglobal{placeholders}% -\indexlibrary{1@\tcode{_1}}% -\begin{codeblock} -namespace std::placeholders { - // M is the \impldef{number of placeholders for bind expressions} number of placeholders - @\seebelow@ _1; - @\seebelow@ _2; - . - . - . - @\seebelow@ _M; -} -\end{codeblock} - -\pnum -All placeholder types meet the \oldconcept{DefaultConstructible} and -\oldconcept{CopyConstructible} requirements, and -their default constructors and copy/move -constructors are constexpr functions that -do not throw exceptions. It is \impldef{assignability of placeholder -objects} whether -placeholder types meet the \oldconcept{CopyAssignable} requirements, -but if so, their copy assignment operators are -constexpr functions that do not throw exceptions. - -\pnum -Placeholders should be defined as: -\begin{codeblock} -inline constexpr @\unspec@ _1{}; -\end{codeblock} -If they are not, they are declared as: -\begin{codeblock} -extern @\unspec@ _1; -\end{codeblock}% -\indextext{function object!binders|)} - -\rSec2[func.memfn]{Function template \tcode{mem_fn}}% -\indextext{function object!\idxcode{mem_fn}|(} - -\indexlibraryglobal{mem_fn}% -\begin{itemdecl} -template constexpr @\unspec@ mem_fn(R T::* pm) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A simple call wrapper\iref{func.def} \tcode{fn} -with call pattern \tcode{invoke(pmd, call_args...)}, where -\tcode{pmd} is the target object of \tcode{fn} of type \tcode{R T::*} -direct-non-list-initialized with \tcode{pm}, and -\tcode{call_args} is an argument pack -used in a function call expression\iref{expr.call} of \tcode{pm}. -\end{itemdescr} -\indextext{function object!\idxcode{mem_fn}|)} - -\rSec2[func.wrap]{Polymorphic function wrappers}% - -\rSec3[func.wrap.general]{General}% -\indextext{function object!wrapper|(} - -\pnum -Subclause \ref{func.wrap} describes polymorphic wrapper classes that -encapsulate arbitrary callable objects. - -\rSec3[func.wrap.badcall]{Class \tcode{bad_function_call}}% -\indexlibraryglobal{bad_function_call}% - -\pnum -An exception of type \tcode{bad_function_call} is thrown by -\tcode{function::operator()}\iref{func.wrap.func.inv} -when the function wrapper object has no target. - -\begin{codeblock} -namespace std { - class bad_function_call : public exception { - public: - // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; - }; -} -\end{codeblock} - -\indexlibrarymember{what}{bad_function_call}% -\begin{itemdecl} -const char* what() const noexcept override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -An -\impldef{return value of \tcode{bad_function_call::what}} \ntbs{}. -\end{itemdescr} - -\rSec3[func.wrap.func]{Class template \tcode{function}} - -\rSec4[func.wrap.func.general]{General} -\indexlibraryglobal{function}% - -\indexlibrarymember{result_type}{function}% -\begin{codeblock} -namespace std { - template class function; // \notdef - - template - class function { - public: - using result_type = R; - - // \ref{func.wrap.func.con}, construct/copy/destroy - function() noexcept; - function(nullptr_t) noexcept; - function(const function&); - function(function&&) noexcept; - template function(F&&); - - function& operator=(const function&); - function& operator=(function&&); - function& operator=(nullptr_t) noexcept; - template function& operator=(F&&); - template function& operator=(reference_wrapper) noexcept; - - ~function(); - - // \ref{func.wrap.func.mod}, function modifiers - void swap(function&) noexcept; - - // \ref{func.wrap.func.cap}, function capacity - explicit operator bool() const noexcept; - - // \ref{func.wrap.func.inv}, function invocation - R operator()(ArgTypes...) const; - - // \ref{func.wrap.func.targ}, function target access - const type_info& target_type() const noexcept; - template T* target() noexcept; - template const T* target() const noexcept; - }; - - template - function(R(*)(ArgTypes...)) -> function; - - template function(F) -> function<@\seebelow@>; -} -\end{codeblock} - -\pnum -The \tcode{function} class template provides polymorphic wrappers that -generalize the notion of a function pointer. Wrappers can store, copy, -and call arbitrary callable objects\iref{func.def}, given a call -signature\iref{func.def}, allowing functions to be first-class objects. - -\pnum -\indextext{callable type}% -A callable type\iref{func.def} \tcode{F} -is \defn{Lvalue-Callable} for argument -types \tcode{ArgTypes} -and return type \tcode{R} -if the expression -\tcode{\placeholdernc{INVOKE}(declval(), declval()...)}, -considered as an unevaluated operand\iref{term.unevaluated.operand}, is -well-formed\iref{func.require}. - -\pnum -The \tcode{function} class template is a call -wrapper\iref{func.def} whose call signature\iref{func.def} -is \tcode{R(ArgTypes...)}. - -\pnum -\begin{note} -The types deduced by the deduction guides for \tcode{function} -might change in future revisions of \Cpp{}. -\end{note} - -\rSec4[func.wrap.func.con]{Constructors and destructor} - -\indexlibraryctor{function}% -\begin{itemdecl} -function() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{!*this}. -\end{itemdescr} - -\indexlibraryctor{function}% -\begin{itemdecl} -function(nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{!*this}. -\end{itemdescr} - -\indexlibraryctor{function}% -\begin{itemdecl} -function(const function& f); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{!*this} if \tcode{!f}; otherwise, -the target object of \tcode{*this} is a copy of \tcode{f.target()}. - -\pnum -\throws -Nothing if \tcode{f}'s target is -a specialization of \tcode{reference_wrapper} or -a function pointer. Otherwise, may throw \tcode{bad_alloc} -or any exception thrown by the copy constructor of the stored callable object. - -\pnum -\recommended -Implementations should avoid the use of -dynamically allocated memory for small callable objects, for example, where -\tcode{f}'s target is an object holding only a pointer or reference -to an object and a member function pointer. -\end{itemdescr} - -\indexlibraryctor{function}% -\begin{itemdecl} -function(function&& f) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -If \tcode{!f}, \tcode{*this} has no target; -otherwise, the target of \tcode{*this} is equivalent to -the target of \tcode{f} before the construction, and -\tcode{f} is in a valid state with an unspecified value. - -\pnum -\recommended -Implementations should avoid the use of -dynamically allocated memory for small callable objects, for example, -where \tcode{f}'s target is an object holding only a pointer or reference -to an object and a member function pointer. -\end{itemdescr} - -\indexlibraryctor{function}% -\begin{itemdecl} -template function(F&& f); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{FD} be \tcode{decay_t}. - -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_same_v, function>} is \tcode{false}, and -\item -\tcode{FD} is Lvalue-Callable\iref{func.wrap.func} for argument types -\tcode{ArgTypes...} and return type \tcode{R}. -\end{itemize} - -\pnum -\mandates -\begin{itemize} -\item -\tcode{is_copy_constructible_v} is \tcode{true}, and -\item -\tcode{is_constructible_v} is \tcode{true}. -\end{itemize} - -\pnum -\expects -\tcode{FD} meets the \oldconcept{CopyConstructible} requirements. - -\pnum -\ensures -\tcode{!*this} is \tcode{true} if any of the following hold: -\begin{itemize} -\item \tcode{f} is a null function pointer value. -\item \tcode{f} is a null member pointer value. -\item \tcode{remove_cvref_t} is -a specialization of the \tcode{function} class template, and -\tcode{!f} is \tcode{true}. -\end{itemize} - -\pnum -Otherwise, \tcode{*this} has a target object of type \tcode{FD} -direct-non-list-initialized with \tcode{std::forward(f)}. - -\pnum -\throws -Nothing if \tcode{FD} is -a specialization of \tcode{reference_wrapper} or -a function pointer type. -Otherwise, may throw \tcode{bad_alloc} or -any exception thrown by the initialization of the target object. - -\pnum -\recommended -Implementations should avoid the use of -dynamically allocated memory for small callable objects, for example, -where \tcode{f} refers to an object holding only a pointer or -reference to an object and a member function pointer. -\end{itemdescr} - - -\begin{itemdecl} -template function(F) -> function<@\seebelow@>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{\&F::operator()} is well-formed when treated as an unevaluated operand and -\tcode{decltype(\brk{}\&F::operator())} is of the form -\tcode{R(G::*)(A...)}~\cv{}~\tcode{\opt{\&}~\opt{noexcept}} -for a class type \tcode{G}. - -\pnum -\remarks -The deduced type is \tcode{function}. - -\pnum -\begin{example} -\begin{codeblock} -void f() { - int i{5}; - function g = [&](double) { return i; }; // deduces \tcode{function} -} -\end{codeblock} -\end{example} -\end{itemdescr} - -\indexlibrarymember{operator=}{function}% -\begin{itemdecl} -function& operator=(const function& f); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by \tcode{function(f).swap(*this);} - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{function}% -\begin{itemdecl} -function& operator=(function&& f); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Replaces the target of \tcode{*this} -with the target of \tcode{f}. - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{function}% -\begin{itemdecl} -function& operator=(nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If \tcode{*this != nullptr}, destroys the target of \keyword{this}. - -\pnum -\ensures -\tcode{!(*this)}. - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{function}% -\begin{itemdecl} -template function& operator=(F&& f); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{decay_t} is Lvalue-Callable\iref{func.wrap.func} -for argument types \tcode{ArgTypes...} and return type \tcode{R}. - -\pnum -\effects -As if by: \tcode{function(std::forward(f)).swap(*this);} - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{function}% -\begin{itemdecl} -template function& operator=(reference_wrapper f) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by: \tcode{function(f).swap(*this);} - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarydtor{function}% -\begin{itemdecl} -~function(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If \tcode{*this != nullptr}, destroys the target of \keyword{this}. -\end{itemdescr} - -\rSec4[func.wrap.func.mod]{Modifiers} - -\indexlibrarymember{swap}{function}% -\begin{itemdecl} -void swap(function& other) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Interchanges the target objects of \tcode{*this} and \tcode{other}. -\end{itemdescr} - -\rSec4[func.wrap.func.cap]{Capacity} - -\indexlibrarymember{operator bool}{function}% -\begin{itemdecl} -explicit operator bool() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if \tcode{*this} has a target, otherwise \tcode{false}. -\end{itemdescr} - -\rSec4[func.wrap.func.inv]{Invocation} - -\indexlibrary{\idxcode{function}!invocation}% -\indexlibrarymember{operator()}{function}% -\begin{itemdecl} -R operator()(ArgTypes... args) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{\placeholdernc{INVOKE}(f, std::forward(args)...)}\iref{func.require}, -where \tcode{f} is the target object\iref{func.def} of \tcode{*this}. - -\pnum -\throws -\tcode{bad_function_call} if \tcode{!*this}; otherwise, any -exception thrown by the target object. -\end{itemdescr} - -\rSec4[func.wrap.func.targ]{Target access} - -\indexlibrarymember{target_type}{function}% -\begin{itemdecl} -const type_info& target_type() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -If \tcode{*this} has a target of type \tcode{T}, - \tcode{typeid(T)}; otherwise, \tcode{typeid(void)}. -\end{itemdescr} - -\indexlibrarymember{target}{function}% -\begin{itemdecl} -template T* target() noexcept; -template const T* target() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -If \tcode{target_type() == typeid(T)} -a pointer to the stored function target; otherwise a null pointer. -\end{itemdescr} - -\rSec4[func.wrap.func.nullptr]{Null pointer comparison operator functions} - -\indexlibrarymember{operator==}{function}% -\begin{itemdecl} -template - bool operator==(const function& f, nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!f}. -\end{itemdescr} - -\rSec4[func.wrap.func.alg]{Specialized algorithms} - -\indexlibrarymember{swap}{function}% -\begin{itemdecl} -template - void swap(function& f1, function& f2) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by: \tcode{f1.swap(f2);} -\end{itemdescr}% - -\rSec3[func.wrap.move]{Move only wrapper} - -\rSec4[func.wrap.move.general]{General} - -\pnum -The header provides partial specializations of \tcode{move_only_function} -for each combination of the possible replacements -of the placeholders \cv{}, \placeholder{ref}, and \placeholder{noex} where -\begin{itemize} -\item -\cv{} is either const or empty, -\item -\placeholder{ref} is either \tcode{\&}, \tcode{\&\&}, or empty, and -\item -\placeholder{noex} is either \tcode{true} or \tcode{false}. -\end{itemize} - -\pnum -For each of the possible combinations of the placeholders mentioned above, -there is a placeholder \placeholder{inv-quals} defined as follows: -\begin{itemize} -\item -If \placeholder{ref} is empty, let \placeholder{inv-quals} be \tcode{\cv{}\&}, -\item -otherwise, let \placeholder{inv-quals} be \cv{} \placeholder{ref}. -\end{itemize} - -\rSec4[func.wrap.move.class]{Class template \tcode{move_only_function}} - -\indexlibraryglobal{move_only_function}% -\begin{codeblock} -namespace std { - template class move_only_function; // \notdef - - template - class move_only_function { - public: - using result_type = R; - - // \ref{func.wrap.move.ctor}, constructors, assignment, and destructor - move_only_function() noexcept; - move_only_function(nullptr_t) noexcept; - move_only_function(move_only_function&&) noexcept; - template move_only_function(F&&); - template - explicit move_only_function(in_place_type_t, Args&&...); - template - explicit move_only_function(in_place_type_t, initializer_list, Args&&...); - - move_only_function& operator=(move_only_function&&); - move_only_function& operator=(nullptr_t) noexcept; - template move_only_function& operator=(F&&); - - ~move_only_function(); - - // \ref{func.wrap.move.inv}, invocation - explicit operator bool() const noexcept; - R operator()(ArgTypes...) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); - - // \ref{func.wrap.move.util}, utility - void swap(move_only_function&) noexcept; - friend void swap(move_only_function&, move_only_function&) noexcept; - friend bool operator==(const move_only_function&, nullptr_t) noexcept; - - private: - template - static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; // \expos - }; -} -\end{codeblock} - -\pnum -The \tcode{move_only_function} class template provides polymorphic wrappers -that generalize the notion of a callable object\iref{func.def}. -These wrappers can store, move, and call arbitrary callable objects, -given a call signature, allowing functions to be first-class objects. - -\pnum -\recommended -Implementations should avoid the use of dynamically allocated memory -for a small contained value. -\begin{note} -Such small-object optimization can only be applied to a type \tcode{T} -for which \tcode{is_nothrow_move_constructible_v} is \tcode{true}. -\end{note} - -\rSec4[func.wrap.move.ctor]{Constructors, assignment, and destructor} - -\indexlibrarymember{\exposid{is-callable-from}}{move_only_function}% -\begin{itemdecl} -template - static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -If \placeholder{noex} is \tcode{true}, -\tcode{\exposid{is-callable-from}} is equal to: -\begin{codeblock} -is_nothrow_invocable_r_v && -is_nothrow_invocable_r_v -\end{codeblock} -Otherwise, \tcode{\exposid{is-callable-from}} is equal to: -\begin{codeblock} -is_invocable_r_v && -is_invocable_r_v -\end{codeblock} -\end{itemdescr} - -\indexlibraryctor{move_only_function}% -\begin{itemdecl} -move_only_function() noexcept; -move_only_function(nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{*this} has no target object. -\end{itemdescr} - -\indexlibraryctor{move_only_function}% -\begin{itemdecl} -move_only_function(move_only_function&& f) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -The target object of \tcode{*this} is -the target object \tcode{f} had before construction, and -\tcode{f} is in a valid state with an unspecified value. -\end{itemdescr} - -\indexlibraryctor{move_only_function}% -\begin{itemdecl} -template move_only_function(F&& f); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VT} be \tcode{decay_t}. - -\pnum -\constraints -\begin{itemize} -\item -\tcode{remove_cvref_t} is not the same type as \tcode{move_only_function}, and -\item -\tcode{remove_cvref_t} is not a specialization of \tcode{in_place_type_t}, and -\item -\tcode{\exposid{is-callable-from}} is \tcode{true}. -\end{itemize} - -\pnum -\mandates -\tcode{is_constructible_v} is \tcode{true}. - -\pnum -\expects -\tcode{VT} meets the \oldconcept{Destructible} requirements, and -if \tcode{is_move_constructible_v} is \tcode{true}, -\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. - -\pnum -\ensures -\tcode{*this} has no target object if any of the following hold: -\begin{itemize} -\item -\tcode{f} is a null function pointer value, or -\item -\tcode{f} is a null member pointer value, or -\item -\tcode{remove_cvref_t} is a specialization of -the \tcode{move_only_function} class template, -and \tcode{f} has no target object. -\end{itemize} -Otherwise, \tcode{*this} has a target object of type \tcode{VT} -direct-non-list-initialized with \tcode{std::forward(f)}. - -\pnum -\throws -Any exception thrown by the initialization of the target object. -May throw \tcode{bad_alloc} unless \tcode{VT} is -a function pointer or a specialization of \tcode{reference_wrapper}. -\end{itemdescr} - -\indexlibraryctor{move_only_function}% -\begin{itemdecl} -template - explicit move_only_function(in_place_type_t, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VT} be \tcode{decay_t}. - -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_constructible_v} is \tcode{true}, and -\item -\tcode{\exposid{is-callable-from}} is \tcode{true}. -\end{itemize} - -\pnum -\mandates -\tcode{VT} is the same type as \tcode{T}. - -\pnum -\expects -\tcode{VT} meets the \oldconcept{Destructible} requirements, and -if \tcode{is_move_constructible_v} is \tcode{true}, -\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. - -\pnum -\ensures -\tcode{*this} has a target object of type \tcode{VT} -direct-non-list-initialized with \tcode{std::forward\brk{}(args)...}. - -\pnum -\throws -Any exception thrown by the initialization of the target object. -May throw \tcode{bad_alloc} unless \tcode{VT} is -a function pointer or a specialization of \tcode{reference_wrapper}. -\end{itemdescr} - -\indexlibraryctor{move_only_function}% -\begin{itemdecl} -template - explicit move_only_function(in_place_type_t, initializer_list ilist, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VT} be \tcode{decay_t}. - -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_constructible_v\&, ArgTypes...>} is -\tcode{true}, and -\item -\tcode{\exposid{is-callable-from}} is \tcode{true}. -\end{itemize} - -\pnum -\mandates -\tcode{VT} is the same type as \tcode{T}. - -\pnum -\expects -\tcode{VT} meets the \oldconcept{Destructible} requirements, and -if \tcode{is_move_constructible_v} is \tcode{true}, -\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. - -\pnum -\ensures -\tcode{*this} has a target object of type \tcode{VT} -direct-non-list-initialized with -\tcode{ilist, std::for\-ward(args)...}. - -\pnum -\throws -Any exception thrown by the initialization of the target object. -May throw \tcode{bad_alloc} unless \tcode{VT} is -a function pointer or a specialization of \tcode{reference_wrapper}. -\end{itemdescr} - -\indexlibrarymember{operator=}{move_only_function}% -\begin{itemdecl} -move_only_function& operator=(move_only_function&& f); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{move_only_function(std::move(f)).swap(*this);} - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{move_only_function}% -\begin{itemdecl} -move_only_function& operator=(nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Destroys the target object of \tcode{*this}, if any. - -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{move_only_function}% -\begin{itemdecl} -template move_only_function& operator=(F&& f); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{move_only_function(std::forward(f)).swap(*this);} - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarydtor{move_only_function}% -\begin{itemdecl} -~move_only_function(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Destroys the target object of \tcode{*this}, if any. -\end{itemdescr} - -\rSec4[func.wrap.move.inv]{Invocation} - -\indexlibrarymember{operator bool}{move_only_function}% -\begin{itemdecl} -explicit operator bool() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if \tcode{*this} has a target object, otherwise \tcode{false}. -\end{itemdescr} - -\indexlibrarymember{operator()}{move_only_function}% -\begin{itemdecl} -R operator()(ArgTypes... args) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{*this} has a target object. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return @\placeholder{INVOKE}@(static_cast(f), std::forward(args)...); -\end{codeblock} -where \tcode{f} is an lvalue designating the target object of \tcode{*this} and -\tcode{F} is the type of \tcode{f}. -\end{itemdescr} - -\rSec4[func.wrap.move.util]{Utility} - -\indexlibrarymember{swap}{move_only_function}% -\begin{itemdecl} -void swap(move_only_function& other) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Exchanges the target objects of \tcode{*this} and \tcode{other}. -\end{itemdescr} - -\indexlibrarymember{swap}{move_only_function}% -\begin{itemdecl} -friend void swap(move_only_function& f1, move_only_function& f2) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{f1.swap(f2)}. -\end{itemdescr} - -\indexlibrarymember{operator==}{move_only_function}% -\begin{itemdecl} -friend bool operator==(const move_only_function& f, nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if \tcode{f} has no target object, otherwise \tcode{false}. -\end{itemdescr} -\indextext{function object!wrapper|)} - -\rSec2[func.search]{Searchers} - -\rSec3[func.search.general]{General} - -\pnum -Subclause \ref{func.search} provides function object types\iref{function.objects} for -operations that search for a sequence \range{pat\textunderscore\nobreak first}{pat_last} in another -sequence \range{first}{last} that is provided to the object's function call -operator. The first sequence (the pattern to be searched for) is provided to -the object's constructor, and the second (the sequence to be searched) is -provided to the function call operator. - -\pnum -Each specialization of a class template specified in \ref{func.search} -shall meet the \oldconcept{CopyConst\-ruct\-ible} and \oldconcept{CopyAssignable} requirements. -Template parameters named -\begin{itemize} -\item \tcode{ForwardIterator}, -\item \tcode{ForwardIterator1}, -\item \tcode{ForwardIterator2}, -\item \tcode{RandomAccessIterator}, -\item \tcode{RandomAccessIterator1}, -\item \tcode{RandomAccessIterator2}, and -\item \tcode{BinaryPredicate} -\end{itemize} -of templates specified in -\ref{func.search} shall meet the same requirements and semantics as -specified in \ref{algorithms.general}. -Template parameters named \tcode{Hash} shall meet the \oldconcept{Hash} -requirements (\tref{cpp17.hash}). - -\pnum -The Boyer-Moore searcher implements the Boyer-Moore search algorithm. -The Boyer-Moore-Horspool searcher implements the Boyer-Moore-Horspool search algorithm. -In general, the Boyer-Moore searcher will use more memory and give better runtime performance than Boyer-Moore-Horspool. - -\rSec3[func.search.default]{Class template \tcode{default_searcher}} - -\indexlibraryglobal{default_searcher}% -\begin{codeblock} -template> - class default_searcher { - public: - constexpr default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last, - BinaryPredicate pred = BinaryPredicate()); - - template - constexpr pair - operator()(ForwardIterator2 first, ForwardIterator2 last) const; - - private: - ForwardIterator1 pat_first_; // \expos - ForwardIterator1 pat_last_; // \expos - BinaryPredicate pred_; // \expos - }; -\end{codeblock} - -\indexlibraryctor{default_searcher}% -\begin{itemdecl} -constexpr default_searcher(ForwardIterator pat_first, ForwardIterator pat_last, - BinaryPredicate pred = BinaryPredicate()); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -% FIXME: The mbox prevents TeX from adding a bizarre hyphen after pat_last_. -Constructs a \tcode{default_searcher} object, initializing \tcode{pat_first_} -with \tcode{pat_first}, \mbox{\tcode{pat_last_}} with \tcode{pat_last}, and -\tcode{pred_} with \tcode{pred}. - -\pnum -\throws -Any exception thrown by the copy constructor of \tcode{BinaryPredicate} or -\tcode{ForwardIterator1}. -\end{itemdescr} - -\indexlibrarymember{operator()}{default_searcher}% -\begin{itemdecl} -template - constexpr pair - operator()(ForwardIterator2 first, ForwardIterator2 last) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Returns a pair of iterators \tcode{i} and \tcode{j} such that -\begin{itemize} -\item \tcode{i == search(first, last, pat_first_, pat_last_, pred_)}, and -\item if \tcode{i == last}, then \tcode{j == last}, -otherwise \tcode{j == next(i, distance(pat_first_, pat_last_))}. -\end{itemize} -\end{itemdescr} - -\rSec3[func.search.bm]{Class template \tcode{boyer_moore_searcher}} - -\indexlibraryglobal{boyer_moore_searcher}% -\begin{codeblock} -template::value_type>, - class BinaryPredicate = equal_to<>> - class boyer_moore_searcher { - public: - boyer_moore_searcher(RandomAccessIterator1 pat_first, - RandomAccessIterator1 pat_last, - Hash hf = Hash(), - BinaryPredicate pred = BinaryPredicate()); - - template - pair - operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; - - private: - RandomAccessIterator1 pat_first_; // \expos - RandomAccessIterator1 pat_last_; // \expos - Hash hash_; // \expos - BinaryPredicate pred_; // \expos - }; -\end{codeblock} - -\indexlibraryctor{boyer_moore_searcher}% -\begin{itemdecl} -boyer_moore_searcher(RandomAccessIterator1 pat_first, - RandomAccessIterator1 pat_last, - Hash hf = Hash(), - BinaryPredicate pred = BinaryPredicate()); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The value type of \tcode{RandomAccessIterator1} meets -the \oldconcept{DefaultConstructible}, -the \oldconcept{Copy\-Constructible}, and -the \oldconcept{CopyAssignable} requirements. - -\pnum -Let \tcode{V} be \tcode{iterator_traits::val\-ue_type}. -For any two values \tcode{A} and \tcode{B} of type \tcode{V}, -if \tcode{pred(A, B) == true}, then \tcode{hf(A) == hf(B)} is \tcode{true}. - -\pnum -\effects -Initializes -\tcode{pat_first_} with \tcode{pat_first}, -\tcode{pat_last_} with \tcode{pat_last}, -\tcode{hash_} with \tcode{hf}, and -\tcode{pred_} with \tcode{pred}. - -\pnum -\throws -Any exception thrown by the copy constructor of \tcode{RandomAccessIterator1}, -or by the default constructor, copy constructor, or the copy assignment operator of the value type of \tcode{RandomAccess\-Iterator1}, -or the copy constructor or \tcode{operator()} of \tcode{BinaryPredicate} or \tcode{Hash}. -May throw \tcode{bad_alloc} if additional memory needed for internal data structures cannot be allocated. -\end{itemdescr} - -\indexlibrarymember{operator()}{boyer_moore_searcher}% -\begin{itemdecl} -template - pair - operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{RandomAccessIterator1} and \tcode{RandomAccessIterator2} -have the same value type. - -\pnum -\effects -Finds a subsequence of equal values in a sequence. - -\pnum -\returns -A pair of iterators \tcode{i} and \tcode{j} such that -\begin{itemize} -\item \tcode{i} is the first iterator -in the range \range{first}{last - (pat_last_ - pat_first_)} such that -for every non-negative integer \tcode{n} less than \tcode{pat_last_ - pat_first_} -the following condition holds: -\tcode{pred(*(i + n), *(pat_first_ + n)) != false}, and -\item \tcode{j == next(i, distance(pat_first_, pat_last_))}. -\end{itemize} -Returns \tcode{make_pair(first, first)} if \range{pat_first_}{pat_last_} is empty, -otherwise returns \tcode{make_pair(last, last)} if no such iterator is found. - -\pnum -\complexity -At most \tcode{(last - first) * (pat_last_ - pat_first_)} applications of the predicate. -\end{itemdescr} - -\rSec3[func.search.bmh]{Class template \tcode{boyer_moore_horspool_searcher}} - -\indexlibraryglobal{boyer_moore_horspool_searcher}% -\begin{codeblock} -template::value_type>, - class BinaryPredicate = equal_to<>> - class boyer_moore_horspool_searcher { - public: - boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, - RandomAccessIterator1 pat_last, - Hash hf = Hash(), - BinaryPredicate pred = BinaryPredicate()); - - template - pair - operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; - - private: - RandomAccessIterator1 pat_first_; // \expos - RandomAccessIterator1 pat_last_; // \expos - Hash hash_; // \expos - BinaryPredicate pred_; // \expos - }; -\end{codeblock} - -\indexlibraryctor{boyer_moore_horspool_searcher}% -\begin{itemdecl} -boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, - RandomAccessIterator1 pat_last, - Hash hf = Hash(), - BinaryPredicate pred = BinaryPredicate()); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The value type of \tcode{RandomAccessIterator1} meets the \oldconcept{DefaultConstructible}, -\oldconcept{Copy\-Constructible}, and \oldconcept{CopyAssignable} requirements. - -\pnum -Let \tcode{V} be \tcode{iterator_traits::val\-ue_type}. -For any two values \tcode{A} and \tcode{B} of type \tcode{V}, -if \tcode{pred(A, B) == true}, then \tcode{hf(A) == hf(B)} is \tcode{true}. - -\pnum -\effects -Initializes -\tcode{pat_first_} with \tcode{pat_first}, -\tcode{pat_last_} with \tcode{pat_last}, -\tcode{hash_} with \tcode{hf}, and -\tcode{pred_} with \tcode{pred}. - -\pnum -\throws -Any exception thrown by the copy constructor of \tcode{RandomAccessIterator1}, -or by the default constructor, copy constructor, or the copy assignment operator of the value type of \tcode{RandomAccess\-Iterator1}, -or the copy constructor or \tcode{operator()} of \tcode{BinaryPredicate} or \tcode{Hash}. -May throw \tcode{bad_alloc} if additional memory needed for internal data structures cannot be allocated. -\end{itemdescr} - -\indexlibrarymember{operator()}{boyer_moore_horspool_searcher}% -\begin{itemdecl} -template - pair - operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{RandomAccessIterator1} and \tcode{RandomAccessIterator2} -have the same value type. - -\pnum -\effects -Finds a subsequence of equal values in a sequence. - -\pnum -\returns -A pair of iterators \tcode{i} and \tcode{j} such that -\begin{itemize} -\item \tcode{i} is the first iterator in the range -\range{first}{last - (pat_last_ - pat_first_)} such that -for every non-negative integer \tcode{n} less than \tcode{pat_last_ - pat_first_} -the following condition holds: -\tcode{pred(*(i + n), *(pat_first_ + n)) != false}, and -\item \tcode{j == next(i, distance(pat_first_, pat_last_))}. -\end{itemize} -Returns \tcode{make_pair(first, first)} if \range{pat_first_}{pat_last_} is empty, -otherwise returns \tcode{make_pair(last, last)} if no such iterator is found. - -\pnum -\complexity -At most \tcode{(last - first) * (pat_last_ - pat_first_)} applications of the predicate. -\end{itemdescr} - -\rSec2[unord.hash]{Class template \tcode{hash}} - -\pnum -\indexlibraryglobal{hash}% -\indextext{\idxcode{hash}!instantiation restrictions}% -The unordered associative containers defined in \ref{unord} use -specializations of the class template \tcode{hash}\iref{functional.syn} -as the default hash function. - -\pnum -Each specialization of \tcode{hash} is either enabled or disabled, -as described below. -\begin{note} -Enabled specializations meet the \oldconcept{Hash} requirements, and -disabled specializations do not. -\end{note} -Each header that declares the template \tcode{hash} -provides enabled specializations of \tcode{hash} for \tcode{nullptr_t} and -all cv-unqualified arithmetic, enumeration, and pointer types. -For any type \tcode{Key} for which neither the library nor the user provides -an explicit or partial specialization of the class template \tcode{hash}, -\tcode{hash} is disabled. - -\pnum -If the library provides an explicit or partial specialization of \tcode{hash}, -that specialization is enabled except as noted otherwise, -and its member functions are \keyword{noexcept} except as noted otherwise. - -\pnum -If \tcode{H} is a disabled specialization of \tcode{hash}, -these values are \tcode{false}: -\tcode{is_default_constructible_v}, -\tcode{is_copy_constructible_v}, -\tcode{is_move_constructible_v}, -\tcode{is_copy_assignable_v}, and -\tcode{is_move_assignable_v}. -Disabled specializations of \tcode{hash} -are not function object types\iref{function.objects}. -\begin{note} -This means that the specialization of \tcode{hash} exists, but -any attempts to use it as a \oldconcept{Hash} will be ill-formed. -\end{note} - -\pnum -An enabled specialization \tcode{hash} will: -\begin{itemize} -\item meet the \oldconcept{Hash} requirements (\tref{cpp17.hash}), -with \tcode{Key} as the function -call argument type, the \oldconcept{Default\-Constructible} requirements (\tref{cpp17.defaultconstructible}), -the \oldconcept{CopyAssignable} requirements (\tref{cpp17.copyassignable}), -\item be swappable\iref{swappable.requirements} for lvalues, -\item meet the requirement that if \tcode{k1 == k2} is \tcode{true}, \tcode{h(k1) == h(k2)} is -also \tcode{true}, where \tcode{h} is an object of type \tcode{hash} and \tcode{k1} and \tcode{k2} -are objects of type \tcode{Key}; -\item meet the requirement that the expression \tcode{h(k)}, where \tcode{h} -is an object of type \tcode{hash} and \tcode{k} is an object of type -\tcode{Key}, shall not throw an exception unless \tcode{hash} is a -program-defined specialization. -\end{itemize} - -\rSec1[meta]{Metaprogramming and type traits} - -\rSec2[meta.general]{General} - -\pnum -Subclause \ref{meta} describes components used by \Cpp{} programs, particularly in -templates, to support the widest possible range of types, optimise -template code usage, detect type related user errors, and perform -type inference and transformation at compile time. It includes type -classification traits, type property inspection traits, and type -transformations. The type classification traits describe a complete taxonomy -of all possible \Cpp{} types, and state where in that taxonomy a given -type belongs. The type property inspection traits allow important -characteristics of types or of combinations of types to be inspected. The -type transformations allow certain properties of types to be manipulated. - -\pnum -\indextext{signal-safe!type traits}% -All functions specified in \ref{meta} are signal-safe\iref{support.signal}. - -\rSec2[meta.rqmts]{Requirements} - -\pnum -A \defnoldconcept{UnaryTypeTrait} describes a property -of a type. It shall be a class template that takes one template type -argument and, optionally, additional arguments that help define the -property being described. It shall be \oldconcept{DefaultConstructible}, -\oldconcept{CopyConstructible}, -and publicly and unambiguously derived, directly or indirectly, from -its \defn{base characteristic}, which is -a specialization of the template -\tcode{integral_constant}\iref{meta.help}, with -the arguments to the template \tcode{integral_constant} determined by the -requirements for the particular property being described. -The member names of the base characteristic shall not be hidden and shall be -unambiguously available in the \oldconcept{UnaryTypeTrait}. - -\pnum -A \defnoldconcept{BinaryTypeTrait} describes a -relationship between two types. It shall be a class template that -takes two template type arguments and, optionally, additional -arguments that help define the relationship being described. It shall -be \oldconcept{DefaultConstructible}, \oldconcept{CopyConstructible}, -and publicly and unambiguously derived, directly or -indirectly, from -its \term{base characteristic}, which is a specialization -of the template -\tcode{integral_constant}\iref{meta.help}, with -the arguments to the template \tcode{integral_constant} determined by the -requirements for the particular relationship being described. -The member names of the base characteristic shall not be hidden and shall be -unambiguously available in the \oldconcept{BinaryTypeTrait}. - -\pnum -A \defnoldconcept{TransformationTrait} -modifies a property -of a type. It shall be a class template that takes one -template type argument and, optionally, additional arguments that help -define the modification. It shall define a publicly accessible nested type -named \tcode{type}, which shall be a synonym for the modified type. - -\pnum -Unless otherwise specified, -the behavior of a program that adds specializations -for any of the templates specified in \ref{meta} -is undefined. - -\pnum -Unless otherwise specified, an incomplete type may be used -to instantiate a template specified in \ref{meta}. -The behavior of a program is undefined if: -\begin{itemize} -\item - an instantiation of a template specified in \ref{meta} - directly or indirectly depends on - an incompletely-defined object type \tcode{T}, and -\item - that instantiation could yield a different result - were \tcode{T} hypothetically completed. -\end{itemize} - -\rSec2[meta.type.synop]{Header \tcode{} synopsis} - -\indexheader{type_traits}% -% FIXME: Many index entries missing. -\begin{codeblock} -namespace std { - // \ref{meta.help}, helper class - template struct integral_constant; - - template - using bool_constant = integral_constant; - using true_type = bool_constant; - using false_type = bool_constant; - - // \ref{meta.unary.cat}, primary type categories - template struct is_void; - template struct is_null_pointer; - template struct is_integral; - template struct is_floating_point; - template struct is_array; - template struct is_pointer; - template struct is_lvalue_reference; - template struct is_rvalue_reference; - template struct is_member_object_pointer; - template struct is_member_function_pointer; - template struct is_enum; - template struct is_union; - template struct is_class; - template struct is_function; - - // \ref{meta.unary.comp}, composite type categories - template struct is_reference; - template struct is_arithmetic; - template struct is_fundamental; - template struct is_object; - template struct is_scalar; - template struct is_compound; - template struct is_member_pointer; - - // \ref{meta.unary.prop}, type properties - template struct is_const; - template struct is_volatile; - template struct is_trivial; - template struct is_trivially_copyable; - template struct is_standard_layout; - template struct is_empty; - template struct is_polymorphic; - template struct is_abstract; - template struct is_final; - template struct is_aggregate; - - template struct is_signed; - template struct is_unsigned; - template struct is_bounded_array; - template struct is_unbounded_array; - template struct is_scoped_enum; - - template struct is_constructible; - template struct is_default_constructible; - template struct is_copy_constructible; - template struct is_move_constructible; - - template struct is_assignable; - template struct is_copy_assignable; - template struct is_move_assignable; - - template struct is_swappable_with; - template struct is_swappable; - - template struct is_destructible; - - template struct is_trivially_constructible; - template struct is_trivially_default_constructible; - template struct is_trivially_copy_constructible; - template struct is_trivially_move_constructible; - - template struct is_trivially_assignable; - template struct is_trivially_copy_assignable; - template struct is_trivially_move_assignable; - template struct is_trivially_destructible; - - template struct is_nothrow_constructible; - template struct is_nothrow_default_constructible; - template struct is_nothrow_copy_constructible; - template struct is_nothrow_move_constructible; - - template struct is_nothrow_assignable; - template struct is_nothrow_copy_assignable; - template struct is_nothrow_move_assignable; - - template struct is_nothrow_swappable_with; - template struct is_nothrow_swappable; - - template struct is_nothrow_destructible; - - template struct has_virtual_destructor; - - template struct has_unique_object_representations; - - // \ref{meta.unary.prop.query}, type property queries - template struct alignment_of; - template struct rank; - template struct extent; - - // \ref{meta.rel}, type relations - template struct is_same; - template struct is_base_of; - template struct is_convertible; - template struct is_nothrow_convertible; - template struct is_layout_compatible; - template struct is_pointer_interconvertible_base_of; - - template struct is_invocable; - template struct is_invocable_r; - - template struct is_nothrow_invocable; - template struct is_nothrow_invocable_r; - - // \ref{meta.trans.cv}, const-volatile modifications - template struct remove_const; - template struct remove_volatile; - template struct remove_cv; - template struct add_const; - template struct add_volatile; - template struct add_cv; - - template - using @\libglobal{remove_const_t}@ = typename remove_const::type; - template - using @\libglobal{remove_volatile_t}@ = typename remove_volatile::type; - template - using @\libglobal{remove_cv_t}@ = typename remove_cv::type; - template - using @\libglobal{add_const_t}@ = typename add_const::type; - template - using @\libglobal{add_volatile_t}@ = typename add_volatile::type; - template - using @\libglobal{add_cv_t}@ = typename add_cv::type; - - // \ref{meta.trans.ref}, reference modifications - template struct remove_reference; - template struct add_lvalue_reference; - template struct add_rvalue_reference; - - template - using @\libglobal{remove_reference_t}@ = typename remove_reference::type; - template - using @\libglobal{add_lvalue_reference_t}@ = typename add_lvalue_reference::type; - template - using @\libglobal{add_rvalue_reference_t}@ = typename add_rvalue_reference::type; - - // \ref{meta.trans.sign}, sign modifications - template struct make_signed; - template struct make_unsigned; - - template - using @\libglobal{make_signed_t}@ = typename make_signed::type; - template - using @\libglobal{make_unsigned_t}@ = typename make_unsigned::type; - - // \ref{meta.trans.arr}, array modifications - template struct remove_extent; - template struct remove_all_extents; - - template - using @\libglobal{remove_extent_t}@ = typename remove_extent::type; - template - using @\libglobal{remove_all_extents_t}@ = typename remove_all_extents::type; - - // \ref{meta.trans.ptr}, pointer modifications - template struct remove_pointer; - template struct add_pointer; - - template - using @\libglobal{remove_pointer_t}@ = typename remove_pointer::type; - template - using @\libglobal{add_pointer_t}@ = typename add_pointer::type; - - // \ref{meta.trans.other}, other transformations - template struct type_identity; - template // see \ref{meta.trans.other} - struct aligned_storage; - template struct aligned_union; - template struct remove_cvref; - template struct decay; - template struct enable_if; - template struct conditional; - template struct common_type; - template class TQual, template class UQual> - struct basic_common_reference { }; - template struct common_reference; - template struct underlying_type; - template struct invoke_result; - template struct unwrap_reference; - template struct unwrap_ref_decay; - - template - using @\libglobal{type_identity_t}@ = typename type_identity::type; - template // see \ref{meta.trans.other} - using @\libglobal{aligned_storage_t}@ = typename aligned_storage::type; - template - using @\libglobal{aligned_union_t}@ = typename aligned_union::type; - template - using @\libglobal{remove_cvref_t}@ = typename remove_cvref::type; - template - using @\libglobal{decay_t}@ = typename decay::type; - template - using @\libglobal{enable_if_t}@ = typename enable_if::type; - template - using @\libglobal{conditional_t}@ = typename conditional::type; - template - using @\libglobal{common_type_t}@ = typename common_type::type; - template - using @\libglobal{common_reference_t}@ = typename common_reference::type; - template - using @\libglobal{underlying_type_t}@ = typename underlying_type::type; - template - using @\libglobal{invoke_result_t}@ = typename invoke_result::type; - template - using unwrap_reference_t = typename unwrap_reference::type; - template - using unwrap_ref_decay_t = typename unwrap_ref_decay::type; - template - using @\libglobal{void_t}@ = void; - - // \ref{meta.logical}, logical operator traits - template struct conjunction; - template struct disjunction; - template struct negation; - - // \ref{meta.unary.cat}, primary type categories - template - inline constexpr bool @\libglobal{is_void_v}@ = is_void::value; - template - inline constexpr bool @\libglobal{is_null_pointer_v}@ = is_null_pointer::value; - template - inline constexpr bool @\libglobal{is_integral_v}@ = is_integral::value; - template - inline constexpr bool @\libglobal{is_floating_point_v}@ = is_floating_point::value; - template - inline constexpr bool @\libglobal{is_array_v}@ = is_array::value; - template - inline constexpr bool @\libglobal{is_pointer_v}@ = is_pointer::value; - template - inline constexpr bool @\libglobal{is_lvalue_reference_v}@ = is_lvalue_reference::value; - template - inline constexpr bool @\libglobal{is_rvalue_reference_v}@ = is_rvalue_reference::value; - template - inline constexpr bool @\libglobal{is_member_object_pointer_v}@ = is_member_object_pointer::value; - template - inline constexpr bool @\libglobal{is_member_function_pointer_v}@ = is_member_function_pointer::value; - template - inline constexpr bool @\libglobal{is_enum_v}@ = is_enum::value; - template - inline constexpr bool @\libglobal{is_union_v}@ = is_union::value; - template - inline constexpr bool @\libglobal{is_class_v}@ = is_class::value; - template - inline constexpr bool @\libglobal{is_function_v}@ = is_function::value; - - // \ref{meta.unary.comp}, composite type categories - template - inline constexpr bool @\libglobal{is_reference_v}@ = is_reference::value; - template - inline constexpr bool @\libglobal{is_arithmetic_v}@ = is_arithmetic::value; - template - inline constexpr bool @\libglobal{is_fundamental_v}@ = is_fundamental::value; - template - inline constexpr bool @\libglobal{is_object_v}@ = is_object::value; - template - inline constexpr bool @\libglobal{is_scalar_v}@ = is_scalar::value; - template - inline constexpr bool @\libglobal{is_compound_v}@ = is_compound::value; - template - inline constexpr bool @\libglobal{is_member_pointer_v}@ = is_member_pointer::value; - - // \ref{meta.unary.prop}, type properties - template - inline constexpr bool @\libglobal{is_const_v}@ = is_const::value; - template - inline constexpr bool @\libglobal{is_volatile_v}@ = is_volatile::value; - template - inline constexpr bool @\libglobal{is_trivial_v}@ = is_trivial::value; - template - inline constexpr bool @\libglobal{is_trivially_copyable_v}@ = is_trivially_copyable::value; - template - inline constexpr bool @\libglobal{is_standard_layout_v}@ = is_standard_layout::value; - template - inline constexpr bool @\libglobal{is_empty_v}@ = is_empty::value; - template - inline constexpr bool @\libglobal{is_polymorphic_v}@ = is_polymorphic::value; - template - inline constexpr bool @\libglobal{is_abstract_v}@ = is_abstract::value; - template - inline constexpr bool @\libglobal{is_final_v}@ = is_final::value; - template - inline constexpr bool @\libglobal{is_aggregate_v}@ = is_aggregate::value; - template - inline constexpr bool @\libglobal{is_signed_v}@ = is_signed::value; - template - inline constexpr bool @\libglobal{is_unsigned_v}@ = is_unsigned::value; - template - inline constexpr bool @\libglobal{is_bounded_array_v}@ = is_bounded_array::value; - template - inline constexpr bool @\libglobal{is_unbounded_array_v}@ = is_unbounded_array::value; - template - inline constexpr bool @\libglobal{is_scoped_enum_v}@ = is_scoped_enum::value; - template - inline constexpr bool @\libglobal{is_constructible_v}@ = is_constructible::value; - template - inline constexpr bool @\libglobal{is_default_constructible_v}@ = is_default_constructible::value; - template - inline constexpr bool @\libglobal{is_copy_constructible_v}@ = is_copy_constructible::value; - template - inline constexpr bool @\libglobal{is_move_constructible_v}@ = is_move_constructible::value; - template - inline constexpr bool @\libglobal{is_assignable_v}@ = is_assignable::value; - template - inline constexpr bool @\libglobal{is_copy_assignable_v}@ = is_copy_assignable::value; - template - inline constexpr bool @\libglobal{is_move_assignable_v}@ = is_move_assignable::value; - template - inline constexpr bool @\libglobal{is_swappable_with_v}@ = is_swappable_with::value; - template - inline constexpr bool @\libglobal{is_swappable_v}@ = is_swappable::value; - template - inline constexpr bool @\libglobal{is_destructible_v}@ = is_destructible::value; - template - inline constexpr bool is_trivially_constructible_v - = is_trivially_constructible::value; - template - inline constexpr bool is_trivially_default_constructible_v - = is_trivially_default_constructible::value; - template - inline constexpr bool is_trivially_copy_constructible_v - = is_trivially_copy_constructible::value; - template - inline constexpr bool is_trivially_move_constructible_v - = is_trivially_move_constructible::value; - template - inline constexpr bool @\libglobal{is_trivially_assignable_v}@ = is_trivially_assignable::value; - template - inline constexpr bool is_trivially_copy_assignable_v - = is_trivially_copy_assignable::value; - template - inline constexpr bool is_trivially_move_assignable_v - = is_trivially_move_assignable::value; - template - inline constexpr bool @\libglobal{is_trivially_destructible_v}@ = is_trivially_destructible::value; - template - inline constexpr bool is_nothrow_constructible_v - = is_nothrow_constructible::value; - template - inline constexpr bool is_nothrow_default_constructible_v - = is_nothrow_default_constructible::value; - template - inline constexpr bool is_nothrow_copy_constructible_v - = is_nothrow_copy_constructible::value; - template - inline constexpr bool is_nothrow_move_constructible_v - = is_nothrow_move_constructible::value; - template - inline constexpr bool @\libglobal{is_nothrow_assignable_v}@ = is_nothrow_assignable::value; - template - inline constexpr bool @\libglobal{is_nothrow_copy_assignable_v}@ = is_nothrow_copy_assignable::value; - template - inline constexpr bool @\libglobal{is_nothrow_move_assignable_v}@ = is_nothrow_move_assignable::value; - template - inline constexpr bool @\libglobal{is_nothrow_swappable_with_v}@ = is_nothrow_swappable_with::value; - template - inline constexpr bool @\libglobal{is_nothrow_swappable_v}@ = is_nothrow_swappable::value; - template - inline constexpr bool @\libglobal{is_nothrow_destructible_v}@ = is_nothrow_destructible::value; - template - inline constexpr bool @\libglobal{has_virtual_destructor_v}@ = has_virtual_destructor::value; - template - inline constexpr bool has_unique_object_representations_v - = has_unique_object_representations::value; - - // \ref{meta.unary.prop.query}, type property queries - template - inline constexpr size_t @\libglobal{alignment_of_v}@ = alignment_of::value; - template - inline constexpr size_t @\libglobal{rank_v}@ = rank::value; - template - inline constexpr size_t @\libglobal{extent_v}@ = extent::value; - - // \ref{meta.rel}, type relations - template - inline constexpr bool @\libglobal{is_same_v}@ = is_same::value; - template - inline constexpr bool @\libglobal{is_base_of_v}@ = is_base_of::value; - template - inline constexpr bool @\libglobal{is_convertible_v}@ = is_convertible::value; - template - inline constexpr bool @\libglobal{is_nothrow_convertible_v}@ = is_nothrow_convertible::value; - template - inline constexpr bool @\libglobal{is_layout_compatible_v}@ = is_layout_compatible::value; - template - inline constexpr bool is_pointer_interconvertible_base_of_v - = is_pointer_interconvertible_base_of::value; - template - inline constexpr bool @\libglobal{is_invocable_v}@ = is_invocable::value; - template - inline constexpr bool @\libglobal{is_invocable_r_v}@ = is_invocable_r::value; - template - inline constexpr bool @\libglobal{is_nothrow_invocable_v}@ = is_nothrow_invocable::value; - template - inline constexpr bool is_nothrow_invocable_r_v - = is_nothrow_invocable_r::value; - - // \ref{meta.logical}, logical operator traits - template - inline constexpr bool @\libglobal{conjunction_v}@ = conjunction::value; - template - inline constexpr bool @\libglobal{disjunction_v}@ = disjunction::value; - template - inline constexpr bool @\libglobal{negation_v}@ = negation::value; - - // \ref{meta.member}, member relationships - template - constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept; - template - constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept; - - // \ref{meta.const.eval}, constant evaluation context - constexpr bool is_constant_evaluated() noexcept; -} -\end{codeblock} - -\rSec2[meta.help]{Helper classes} - -\indexlibrarymember{value_type}{integral_constant}% -\begin{codeblock} -namespace std { - template struct integral_constant { - static constexpr T value = v; - - using value_type = T; - using type = integral_constant; - - constexpr operator value_type() const noexcept { return value; } - constexpr value_type operator()() const noexcept { return value; } - }; -} -\end{codeblock} - -\indexlibraryglobal{integral_constant}% -\indexlibraryglobal{bool_constant}% -\indexlibraryglobal{true_type}% -\indexlibraryglobal{false_type}% -\pnum -The class template \tcode{integral_constant}, -alias template \tcode{bool_constant}, and -its associated \grammarterm{typedef-name}{s} -\tcode{true_type} and \tcode{false_type} -are used as base classes to define -the interface for various type traits. - -\rSec2[meta.unary]{Unary type traits} - -\rSec3[meta.unary.general]{General} - -\pnum -Subclause \ref{meta.unary} contains templates that may be used to query the -properties of a type at compile time. - -\pnum -Each of these templates shall be a -\oldconcept{UnaryTypeTrait}\iref{meta.rqmts} -with a base characteristic of -\tcode{true_type} if the corresponding condition is \tcode{true}, otherwise -\tcode{false_type}. - -\rSec3[meta.unary.cat]{Primary type categories} - -\pnum -The primary type categories correspond to the descriptions given in -subclause~\ref{basic.types} of the \Cpp{} standard. - -\pnum -For any given type \tcode{T}, the result of applying one of these templates to -\tcode{T} and to \cv{}~\tcode{T} shall yield the same result. - -\pnum -\begin{note} -For any given type \tcode{T}, exactly one of the primary type categories -has a \tcode{value} member that evaluates to \tcode{true}. -\end{note} - -\begin{libreqtab3e}{Primary type category predicates}{meta.unary.cat} -\\ \topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\\capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep -\endhead -\indexlibraryglobal{is_void}% -\tcode{template}\br - \tcode{struct is_void;} & -\tcode{T} is \keyword{void} & \\ \rowsep -\indexlibraryglobal{is_null_pointer}% -\tcode{template}\br - \tcode{struct is_null_pointer;} & -\tcode{T} is \tcode{nullptr_t}\iref{basic.fundamental} & \\ \rowsep -\indexlibraryglobal{is_integral}% -\tcode{template}\br - \tcode{struct is_integral;} & -\tcode{T} is an integral type\iref{basic.fundamental} & \\ \rowsep -\indexlibraryglobal{is_floating_point}% -\tcode{template}\br - \tcode{struct is_floating_point;} & -\tcode{T} is a floating-point type\iref{basic.fundamental} & \\ \rowsep -\indexlibraryglobal{is_array}% -\tcode{template}\br - \tcode{struct is_array;} & -\tcode{T} is an array type\iref{basic.compound} of known or unknown extent & -Class template \tcode{array}\iref{array} -is not an array type. \\ \rowsep -\indexlibraryglobal{is_pointer}% -\tcode{template}\br - \tcode{struct is_pointer;} & -\tcode{T} is a pointer type\iref{basic.compound} & -Includes pointers to functions -but not pointers to non-static members. \\ \rowsep -\indexlibraryglobal{is_lvalue_reference}% -\tcode{template}\br - \tcode{struct is_lvalue_reference;} & - \tcode{T} is an lvalue reference type\iref{dcl.ref} & \\ \rowsep -\indexlibraryglobal{is_rvalue_reference}% -\tcode{template}\br - \tcode{struct is_rvalue_reference;} & - \tcode{T} is an rvalue reference type\iref{dcl.ref} & \\ \rowsep -\indexlibraryglobal{is_member_object_pointer}% -\tcode{template}\br - \tcode{struct is_member_object_pointer;}& - \tcode{T} is a pointer to data member & \\ \rowsep -\indexlibraryglobal{is_member_function_pointer}% -\tcode{template}\br - \tcode{struct is_member_function_pointer;}& -\tcode{T} is a pointer to member function & \\ \rowsep -\indexlibraryglobal{is_enum}% -\tcode{template}\br - \tcode{struct is_enum;} & -\tcode{T} is an enumeration type\iref{basic.compound} & \\ \rowsep -\indexlibraryglobal{is_union}% -\tcode{template}\br - \tcode{struct is_union;} & -\tcode{T} is a union type\iref{basic.compound} & \\ \rowsep -\indexlibraryglobal{is_class}% -\tcode{template}\br - \tcode{struct is_class;} & -\tcode{T} is a non-union class type\iref{basic.compound} & \\ \rowsep -\indexlibraryglobal{is_function}% -\tcode{template}\br - \tcode{struct is_function;} & -\tcode{T} is a function type\iref{basic.compound} & \\ -\end{libreqtab3e} - -\rSec3[meta.unary.comp]{Composite type traits} - -\pnum -These templates provide convenient compositions of the primary type -categories, corresponding to the descriptions given in subclause~\ref{basic.types}. - -\pnum -For any given type \tcode{T}, the result of applying one of these templates to -\tcode{T} and to \cv{}~\tcode{T} shall yield the same result. - -\begin{libreqtab3b}{Composite type category predicates}{meta.unary.comp} -\\ \topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep -\endhead -\indexlibraryglobal{is_reference}% -\tcode{template}\br - \tcode{struct is_reference;} & - \tcode{T} is an lvalue reference or an rvalue reference & \\ \rowsep -\indexlibraryglobal{is_arithmetic}% -\tcode{template}\br - \tcode{struct is_arithmetic;} & - \tcode{T} is an arithmetic type\iref{basic.fundamental} & \\ \rowsep -\indexlibraryglobal{is_fundamental}% -\tcode{template}\br - \tcode{struct is_fundamental;} & - \tcode{T} is a fundamental type\iref{basic.fundamental} & \\ \rowsep -\indexlibraryglobal{is_object}% -\tcode{template}\br - \tcode{struct is_object;} & - \tcode{T} is an object type\iref{basic.types} & \\ \rowsep -\indexlibraryglobal{is_scalar}% -\tcode{template}\br - \tcode{struct is_scalar;} & - \tcode{T} is a scalar type\iref{basic.types} & \\ \rowsep -\indexlibraryglobal{is_compound}% -\tcode{template}\br - \tcode{struct is_compound;} & - \tcode{T} is a compound type\iref{basic.compound} & \\ \rowsep -\indexlibraryglobal{is_member_pointer}% -\tcode{template}\br - \tcode{struct is_member_pointer;} & - \tcode{T} is a pointer-to-member type\iref{basic.compound} & \\ -\end{libreqtab3b} - -\rSec3[meta.unary.prop]{Type properties} - -\pnum -These templates provide access to some of the more important -properties of types. - -\pnum -It is unspecified whether the library defines any full or partial -specializations of any of these templates. - -\pnum -For all of the class templates \tcode{X} declared in this subclause, -instantiating that template with a template-argument that is a class -template specialization may result in the implicit instantiation of -the template argument if and only if the semantics of \tcode{X} require that -the argument is a complete type. - -\pnum -For the purpose of defining the templates in this subclause, -a function call expression \tcode{declval()} for any type \tcode{T} -is considered to be a trivial~(\ref{basic.types}, \ref{special}) function call -that is not an odr-use\iref{term.odr.use} of \tcode{declval} -in the context of the corresponding definition -notwithstanding the restrictions of~\ref{declval}. - -\begin{libreqtab3b}{Type property predicates}{meta.unary.prop} -\\ \topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Preconditions} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Preconditions} \\ \capsep -\endhead - -\indexlibraryglobal{is_const}% -\tcode{template}\br - \tcode{struct is_const;} & - \tcode{T} is const-qualified\iref{basic.type.qualifier} & \\ \rowsep - -\indexlibraryglobal{is_volatile}% -\tcode{template}\br - \tcode{struct is_volatile;} & - \tcode{T} is volatile-qualified\iref{basic.type.qualifier} & \\ \rowsep - - -\indexlibraryglobal{is_trivial}% -\tcode{template}\br - \tcode{struct is_trivial;} & - \tcode{T} is a trivial type\iref{basic.types} & - \tcode{remove_all_extents_t} shall be a complete - type or \cv{}~\keyword{void}. \\ \rowsep - -\indexlibraryglobal{is_trivially_copyable}% -\tcode{template}\br - \tcode{struct is_trivially_copyable;} & - \tcode{T} is a trivially copyable type\iref{basic.types} & - \tcode{remove_all_extents_t} shall be a complete type or - \cv{}~\keyword{void}. \\ \rowsep - -\indexlibraryglobal{is_standard_layout}% -\tcode{template}\br - \tcode{struct is_standard_layout;} & - \tcode{T} is a standard-layout type\iref{basic.types} & - \tcode{remove_all_extents_t} shall be a complete - type or \cv{}~\keyword{void}. \\ \rowsep - -\indexlibrary{\idxcode{is_empty}!class}% -\tcode{template}\br - \tcode{struct is_empty;} & - \tcode{T} is a class type, but not a union type, with no non-static data - members other than subobjects of zero size, no virtual member functions, - no virtual base classes, and no base class \tcode{B} for - which \tcode{is_empty_v} is \tcode{false}. & - If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{is_polymorphic}% -\tcode{template}\br - \tcode{struct is_polymorphic;} & - \tcode{T} is a polymorphic class\iref{class.virtual} & - If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{is_abstract}% -\tcode{template}\br - \tcode{struct is_abstract;} & - \tcode{T} is an abstract class\iref{class.abstract} & - If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{is_final}% -\tcode{template}\br - \tcode{struct is_final;} & - \tcode{T} is a class type marked with the \grammarterm{class-virt-specifier} - \tcode{final}\iref{class.pre}. -\begin{tailnote} -A union is a class type that - can be marked with \tcode{final}. -\end{tailnote} -& - If \tcode{T} is a class type, \tcode{T} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{is_aggregate}% -\tcode{template}\br - \tcode{struct is_aggregate;} & - \tcode{T} is an aggregate type\iref{dcl.init.aggr} & - \tcode{remove_all_extents_t} shall be a complete type or \cv~\keyword{void}. \\ \rowsep - -\indexlibrary{\idxcode{is_signed}!class}% -\tcode{template}\br - \tcode{struct is_signed;} & - If \tcode{is_arithmetic_v} is \tcode{true}, the same result as - \tcode{T(-1) < T(0)}; - otherwise, \tcode{false} & \\ \rowsep - -\indexlibraryglobal{is_unsigned}% -\tcode{template}\br - \tcode{struct is_unsigned;} & - If \tcode{is_arithmetic_v} is \tcode{true}, the same result as - \tcode{T(0) < T(-1)}; - otherwise, \tcode{false} & \\ \rowsep - -\indexlibraryglobal{is_bounded_array}% -\tcode{template}\br - \tcode{struct is_bounded_array;} & - \tcode{T} is an array type of known bound\iref{dcl.array} - & \\ \rowsep - -\indexlibraryglobal{is_unbounded_array}% -\tcode{template}\br - \tcode{struct is_unbounded_array;} & - \tcode{T} is an array type of unknown bound\iref{dcl.array} - & \\ \rowsep - -\indexlibraryglobal{is_scoped_enum}% -\tcode{template}\br - \tcode{struct is_scoped_enum;} & - \tcode{T} is a scoped enumeration\iref{dcl.enum} - & \\ \rowsep - -\indexlibraryglobal{is_constructible}% -\tcode{template}\br - \tcode{struct is_constructible;} & - For a function type \tcode{T} or - for a \cv{}~\keyword{void} type \tcode{T}, - \tcode{is_constructible_v} is \tcode{false}, - otherwise \seebelow & - \tcode{T} and all types in the template parameter pack \tcode{Args} - shall be complete types, \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_default_constructible}% -\tcode{template}\br - \tcode{struct is_default_constructible;} & - \tcode{is_constructible_v} is \tcode{true}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_copy_constructible}% -\tcode{template}\br - \tcode{struct is_copy_constructible;} & - For a referenceable type \tcode{T}\iref{defns.referenceable}, the same result as - \tcode{is_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_move_constructible}% -\tcode{template}\br - \tcode{struct is_move_constructible;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_assignable}% -\tcode{template}\br - \tcode{struct is_assignable;} & - The expression \tcode{declval() =} \tcode{declval()} is well-formed - when treated as an unevaluated - operand\iref{term.unevaluated.operand}. Access checking is performed as if in a context - unrelated to \tcode{T} and \tcode{U}. Only the validity of the immediate context - of the assignment expression is considered. -\begin{tailnote} -The compilation of the - expression can result in side effects such as the instantiation of class template - specializations and function template specializations, the generation of - implicitly-defined functions, and so on. Such side effects are not in the ``immediate - context'' and can result in the program being ill-formed. -\end{tailnote} -& - \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_copy_assignable}% -\tcode{template}\br - \tcode{struct is_copy_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_move_assignable}% -\tcode{template}\br - \tcode{struct is_move_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_swappable_with}% -\tcode{template}\br - \tcode{struct is_swappable_with;} & - The expressions \tcode{swap(declval(), declval())} and - \tcode{swap(declval(), declval())} are each well-formed - when treated as an unevaluated operand\iref{term.unevaluated.operand} - in an overload-resolution context - for swappable values\iref{swappable.requirements}. - Access checking is performed as if in a context - unrelated to \tcode{T} and \tcode{U}. - Only the validity of the immediate context - of the \tcode{swap} expressions is considered. - \begin{tailnote} - The compilation of the expressions can result in side effects - such as the instantiation of class template specializations and - function template specializations, - the generation of implicitly-defined functions, and so on. - Such side effects are not in the ``immediate context'' and - can result in the program being ill-formed. - \end{tailnote} -& - \tcode{T} and \tcode{U} shall be complete types, - \cv{}~\keyword{void}, or - arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_swappable}% -\tcode{template}\br - \tcode{struct is_swappable;} & - For a referenceable type \tcode{T}, - the same result as \tcode{is_swappable_with_v}, - otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or - an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_destructible}% -\tcode{template}\br - \tcode{struct is_destructible;} & - Either \tcode{T} is a reference type, - or \tcode{T} is a complete object type - for which the expression - \tcode{declval().\~U()} - is well-formed - when treated as an unevaluated operand\iref{term.unevaluated.operand}, - where \tcode{U} is - \tcode{remove_all_extents_t}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_constructible}% -\tcode{template}\br - \keyword{struct}\br - \tcode{is_trivially_constructible;} & - \tcode{is_constructible_v} is \tcode{true} and the variable - definition for \tcode{is_constructible}, as defined below, is known to call - no operation that is not trivial~(\ref{basic.types}, \ref{special}). & - \tcode{T} and all types in the template parameter pack \tcode{Args} shall be complete types, - \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_default_constructible}% -\tcode{template}\br - \tcode{struct is_trivially_default_constructible;} & - \tcode{is_trivially_constructible_v} is \tcode{true}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_copy_constructible}% -\tcode{template}\br - \tcode{struct is_trivially_copy_constructible;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_trivially_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_move_constructible}% -\tcode{template}\br - \tcode{struct is_trivially_move_constructible;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_trivially_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_assignable}% -\tcode{template}\br - \tcode{struct is_trivially_assignable;} & - \tcode{is_assignable_v} is \tcode{true} and the assignment, as defined by - \tcode{is_assignable}, is known to call no operation that is not trivial - ~(\ref{basic.types}, \ref{special}). & - \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_copy_assignable}% -\tcode{template}\br - \tcode{struct is_trivially_copy_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_trivially_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_move_assignable}% -\tcode{template}\br - \tcode{struct is_trivially_move_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_trivially_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_destructible}% -\tcode{template}\br - \tcode{struct is_trivially_destructible;} & - \tcode{is_destructible_v} is \tcode{true} and - \tcode{remove_all_extents_t} is either a non-class type or - a class type with a trivial destructor. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_constructible}% -\tcode{template}\br - \tcode{struct is_nothrow_constructible;} & - \tcode{is_constructible_v} is \tcode{true} - and the - variable definition for \tcode{is_constructible}, as defined below, is known not to - throw any exceptions\iref{expr.unary.noexcept}. - & - \tcode{T} and all types in the template parameter pack \tcode{Args} - shall be complete types, \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_default_constructible}% -\tcode{template}\br - \tcode{struct is_nothrow_default_constructible;} & - \tcode{is_nothrow_constructible_v} is \tcode{true}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_copy_constructible}% -\tcode{template}\br - \tcode{struct is_nothrow_copy_constructible;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_nothrow_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_move_constructible}% -\tcode{template}\br - \tcode{struct is_nothrow_move_constructible;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_nothrow_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_assignable}% -\tcode{template}\br - \tcode{struct is_nothrow_assignable;} & - \tcode{is_assignable_v} is \tcode{true} and the assignment is known not to - throw any exceptions\iref{expr.unary.noexcept}. & - \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_copy_assignable}% -\tcode{template}\br - \tcode{struct is_nothrow_copy_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_nothrow_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_move_assignable}% -\tcode{template}\br - \tcode{struct is_nothrow_move_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_nothrow_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_swappable_with}% -\tcode{template}\br - \tcode{struct is_nothrow_swappable_with;} & - \tcode{is_swappable_with_v} is \tcode{true} and - each \tcode{swap} expression of the definition of - \tcode{is_swappable_with} is known not to throw - any exceptions\iref{expr.unary.noexcept}. & - \tcode{T} and \tcode{U} shall be complete types, - \cv{}~\keyword{void}, or - arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_swappable}% -\tcode{template}\br - \tcode{struct is_nothrow_swappable;} & - For a referenceable type \tcode{T}, - the same result as \tcode{is_nothrow_swappable_with_v}, - otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or - an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_destructible}% -\tcode{template}\br - \tcode{struct is_nothrow_destructible;} & - \tcode{is_destructible_v} is \tcode{true} and the indicated destructor is known - not to throw any exceptions\iref{expr.unary.noexcept}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{has_virtual_destructor}% -\tcode{template}\br - \tcode{struct has_virtual_destructor;} & - \tcode{T} has a virtual destructor\iref{class.dtor} & - If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{has_unique_object_representations}% -\tcode{template}\br - \tcode{struct has_unique_object_representations;} & - For an array type \tcode{T}, the same result as - \tcode{has_unique_object_representations_v>}, - otherwise \seebelow. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, or - an array of unknown bound. \\ \rowsep - -\end{libreqtab3b} - -\pnum -\begin{example} -\begin{codeblock} -is_const_v // \tcode{true} -is_const_v // \tcode{false} -is_const_v // \tcode{false} -is_const_v // \tcode{false} -is_const_v // \tcode{true} -\end{codeblock} -\end{example} - -\pnum -\begin{example} -\begin{codeblock} -remove_const_t // \tcode{volatile int} -remove_const_t // \tcode{const int*} -remove_const_t // \tcode{const int\&} -remove_const_t // \tcode{int[3]} -\end{codeblock} -\end{example} +\ensures +\tcode{*this} has no target object. +\end{itemdescr} -\pnum -\begin{example} -\begin{codeblock} -// Given: -struct P final { }; -union U1 { }; -union U2 final { }; - -// the following assertions hold: -static_assert(!is_final_v); -static_assert(is_final_v

); -static_assert(!is_final_v); -static_assert(is_final_v); -\end{codeblock} -\end{example} +\indexlibraryctor{move_only_function}% +\begin{itemdecl} +move_only_function(move_only_function&& f) noexcept; +\end{itemdecl} -\indexlibraryglobal{is_constructible}% +\begin{itemdescr} \pnum -The predicate condition for a template specialization -\tcode{is_constructible} shall be satisfied if and only if the -following variable definition would be well-formed for some invented variable \tcode{t}: +\ensures +The target object of \tcode{*this} is +the target object \tcode{f} had before construction, and +\tcode{f} is in a valid state with an unspecified value. +\end{itemdescr} -\begin{codeblock} -T t(declval()...); -\end{codeblock} +\indexlibraryctor{move_only_function}% +\begin{itemdecl} +template move_only_function(F&& f); +\end{itemdecl} -\begin{note} -These tokens are never interpreted as a function declaration. -\end{note} -Access checking is performed as if in a context unrelated to \tcode{T} -and any of the \tcode{Args}. Only the validity of the immediate context of the -variable initialization is considered. -\begin{note} -The evaluation of the -initialization can result in side effects such as the instantiation of class -template specializations and function template specializations, the generation -of implicitly-defined functions, and so on. Such side effects are not in the -``immediate context'' and can result in the program being ill-formed. -\end{note} +\begin{itemdescr} +\pnum +Let \tcode{VT} be \tcode{decay_t}. -\indexlibraryglobal{has_unique_object_representations}% \pnum -The predicate condition for a template specialization -\tcode{has_unique_object_representations} -shall be satisfied if and only if: +\constraints \begin{itemize} -\item \tcode{T} is trivially copyable, and -\item any two objects of type \tcode{T} with the same value -have the same object representation, where -two objects of array or non-union class type are considered to have the same value -if their respective sequences of direct subobjects have the same values, and -two objects of union type are considered to have the same value -if they have the same active member and the corresponding members have the same value. +\item +\tcode{remove_cvref_t} is not the same type as \tcode{move_only_function}, and +\item +\tcode{remove_cvref_t} is not a specialization of \tcode{in_place_type_t}, and +\item +\tcode{\exposid{is-callable-from}} is \tcode{true}. \end{itemize} -The set of scalar types for which this condition holds is -\impldef{which scalar types have unique object representations}. -\begin{note} -If a type has padding bits, the condition does not hold; -otherwise, the condition holds true for integral types. -\end{note} - -\rSec2[meta.unary.prop.query]{Type property queries} \pnum -This subclause contains templates that may be used to query -properties of types at compile time. +\mandates +\tcode{is_constructible_v} is \tcode{true}. -\begin{libreqtab2a}{Type property queries}{meta.unary.prop.query} -\\ \topline -\lhdr{Template} & \rhdr{Value} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Value} \\ \capsep -\endhead - -\indexlibraryglobal{alignment_of}% -\tcode{template\br - struct alignment_of;} & - \tcode{alignof(T)}.\br - \mandates - \tcode{alignof(T)} is a valid expression\iref{expr.alignof} \\ \rowsep - -\indexlibraryglobal{rank}% -\tcode{template\br - struct rank;} & - If \tcode{T} names an array type, an integer value representing - the number of dimensions of \tcode{T}; otherwise, 0. \\ \rowsep - -\indexlibraryglobal{extent}% -\tcode{template\br - struct extent;} & - If \tcode{T} is not an array type, or if it has rank less - than or equal to \tcode{I}, or if \tcode{I} is 0 and \tcode{T} - has type ``array of unknown bound of \tcode{U}'', then - 0; otherwise, the bound\iref{dcl.array} of the $\tcode{I}^\text{th}$ dimension of -\tcode{T}, where indexing of \tcode{I} is zero-based \\ -\end{libreqtab2a} - -\pnum -Each of these templates shall be a \oldconcept{UnaryTypeTrait}\iref{meta.rqmts} with a -base characteristic of \tcode{integral_constant}. +\pnum +\expects +\tcode{VT} meets the \oldconcept{Destructible} requirements, and +if \tcode{is_move_constructible_v} is \tcode{true}, +\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. \pnum -\begin{example} -\begin{codeblock} -// the following assertions hold: -assert(rank_v == 0); -assert(rank_v == 1); -assert(rank_v == 2); -\end{codeblock} -\end{example} +\ensures +\tcode{*this} has no target object if any of the following hold: +\begin{itemize} +\item +\tcode{f} is a null function pointer value, or +\item +\tcode{f} is a null member pointer value, or +\item +\tcode{remove_cvref_t} is a specialization of +the \tcode{move_only_function} class template, +and \tcode{f} has no target object. +\end{itemize} +Otherwise, \tcode{*this} has a target object of type \tcode{VT} +direct-non-list-initialized with \tcode{std::forward(f)}. \pnum -\begin{example} -\begin{codeblock} -// the following assertions hold: -assert(extent_v == 0); -assert(extent_v == 2); -assert(extent_v == 2); -assert(extent_v == 0); -assert((extent_v) == 0); -assert((extent_v) == 0); -assert((extent_v) == 4); -assert((extent_v) == 4); -\end{codeblock} -\end{example} +\throws +Any exception thrown by the initialization of the target object. +May throw \tcode{bad_alloc} unless \tcode{VT} is +a function pointer or a specialization of \tcode{reference_wrapper}. +\end{itemdescr} -\rSec2[meta.rel]{Relationships between types} +\indexlibraryctor{move_only_function}% +\begin{itemdecl} +template + explicit move_only_function(in_place_type_t, Args&&... args); +\end{itemdecl} +\begin{itemdescr} \pnum -This subclause contains templates that may be used to query -relationships between types at compile time. +Let \tcode{VT} be \tcode{decay_t}. \pnum -Each of these templates shall be a -\oldconcept{BinaryTypeTrait}\iref{meta.rqmts} -with a base characteristic of -\tcode{true_type} if the corresponding condition is true, otherwise -\tcode{false_type}. - -\begin{libreqtab3f}{Type relationship predicates}{meta.rel} -\\ \topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep -\endhead -\tcode{template}\br - \tcode{struct is_same;} & - \tcode{T} and \tcode{U} name the same type with the same cv-qualifications & \\ \rowsep - -\indexlibraryglobal{is_base_of}% -\tcode{template}\br - \tcode{struct is_base_of;} & - \tcode{Base} is a base class of \tcode{Derived}\iref{class.derived} - without regard to cv-qualifiers - or \tcode{Base} and \tcode{Derived} are not unions and - name the same class type - without regard to cv-qualifiers & - If \tcode{Base} and - \tcode{Derived} are non-union class types and are -not possibly cv-qualified versions of the same type, - \tcode{Derived} shall be a complete - type. - \begin{tailnote} -Base classes that are private, protected, or ambiguous - are, nonetheless, base classes. -\end{tailnote} -\\ \rowsep +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v} is \tcode{true}, and +\item +\tcode{\exposid{is-callable-from}} is \tcode{true}. +\end{itemize} -\indexlibraryglobal{is_convertible}% -\tcode{template}\br - \tcode{struct is_convertible;} & - \seebelow & - \tcode{From} and \tcode{To} shall be complete types, - \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_convertible}% -\tcode{template}\br - \tcode{struct is_nothrow_convertible;} & - \tcode{is_convertible_v} is \tcode{true} and - the conversion, as defined by \tcode{is_convertible}, - is known not to throw any exceptions\iref{expr.unary.noexcept} & - \tcode{From} and \tcode{To} shall be complete types, - \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_layout_compatible}% -\tcode{template}\br - \tcode{struct is_layout_compatible;} & - \tcode{T} and \tcode{U} are layout-compatible\iref{basic.types} & - \tcode{T} and \tcode{U} shall be complete types, - \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_pointer_interconvertible_base_of}% -\tcode{template}\br - \tcode{struct is_pointer_interconvertible_base_of;} & - \tcode{Derived} is unambiguously derived from \tcode{Base} - without regard to cv-qualifiers, - and each object of type \tcode{Derived} - is pointer-interconvertible\iref{basic.compound} with - its \tcode{Base} subobject, - or \tcode{Base} and \tcode{Derived} are not unions - and name the same class type - without regard to cv-qualifiers. & - If \tcode{Base} and \tcode{Derived} are non-union class types - and are not (possibly cv-qualified versions of) the same type, - \tcode{Derived} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{is_invocable}% -\tcode{template}\br - \tcode{struct is_invocable;} & - The expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} - is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand} & - \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} - shall be complete types, \cv{}~\keyword{void}, or - arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_invocable_r}% -\tcode{template}\br - \tcode{struct is_invocable_r;} & - The expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} - is well-formed when treated as an unevaluated operand & - \tcode{Fn}, \tcode{R}, and all types in the template parameter pack \tcode{ArgTypes} - shall be complete types, \cv{}~\keyword{void}, or - arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_invocable}% -\tcode{template}\br - \tcode{struct is_nothrow_invocable;} & - \tcode{is_invocable_v<}\br\tcode{Fn, ArgTypes...>} is \tcode{true} and - the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} - is known not to throw any exceptions\iref{expr.unary.noexcept} & - \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} - shall be complete types, \cv{}~\keyword{void}, or - arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_invocable_r}% -\tcode{template}\br - \tcode{struct is_nothrow_invocable_r;} & - \tcode{is_invocable_r_v<}\br\tcode{R, Fn, ArgTypes...>} is \tcode{true} and - the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} - is known not to throw any exceptions\iref{expr.unary.noexcept} & - \tcode{Fn}, \tcode{R}, and all types in the template parameter pack \tcode{ArgTypes} - shall be complete types, \cv{}~\keyword{void}, or - arrays of unknown bound. \\ -\end{libreqtab3f} - -\pnum -For the purpose of defining the templates in this subclause, -a function call expression \tcode{declval()} for any type \tcode{T} -is considered to be a trivial~(\ref{basic.types}, \ref{special}) function call -that is not an odr-use\iref{term.odr.use} of \tcode{declval} -in the context of the corresponding definition -notwithstanding the restrictions of~\ref{declval}. +\pnum +\mandates +\tcode{VT} is the same type as \tcode{T}. \pnum -\begin{example} -\begin{codeblock} -struct B {}; -struct B1 : B {}; -struct B2 : B {}; -struct D : private B1, private B2 {}; - -is_base_of_v // \tcode{true} -is_base_of_v // \tcode{true} -is_base_of_v // \tcode{true} -is_base_of_v // \tcode{true} -is_base_of_v // \tcode{false} -is_base_of_v // \tcode{false} -is_base_of_v // \tcode{false} -is_base_of_v // \tcode{false} -\end{codeblock} -\end{example} +\expects +\tcode{VT} meets the \oldconcept{Destructible} requirements, and +if \tcode{is_move_constructible_v} is \tcode{true}, +\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. -\indexlibraryglobal{is_convertible}% \pnum -The predicate condition for a template specialization \tcode{is_convertible} -shall be satisfied if and only if the return expression in the following code would be -well-formed, including any implicit conversions to the return type of the function: +\ensures +\tcode{*this} has a target object of type \tcode{VT} +direct-non-list-initialized with \tcode{std::forward\brk{}(args)...}. -\begin{codeblock} -To test() { - return declval(); -} -\end{codeblock} +\pnum +\throws +Any exception thrown by the initialization of the target object. +May throw \tcode{bad_alloc} unless \tcode{VT} is +a function pointer or a specialization of \tcode{reference_wrapper}. +\end{itemdescr} -\begin{note} -This requirement gives well-defined results for reference types, void -types, array types, and function types. -\end{note} -Access checking is performed -in a context unrelated to \tcode{To} and \tcode{From}. Only the validity of -the immediate context of the \grammarterm{expression} of the \tcode{return} statement\iref{stmt.return} -(including initialization of the returned object or reference) is considered. -\begin{note} -The -initialization can result in side effects such as the -instantiation of class template specializations and function template -specializations, the generation of implicitly-defined functions, and so on. Such -side effects are not in the ``immediate context'' and can result in the program -being ill-formed. -\end{note} +\indexlibraryctor{move_only_function}% +\begin{itemdecl} +template + explicit move_only_function(in_place_type_t, initializer_list ilist, Args&&... args); +\end{itemdecl} -\rSec2[meta.trans]{Transformations between types} +\begin{itemdescr} +\pnum +Let \tcode{VT} be \tcode{decay_t}. -\rSec3[meta.trans.general]{General} \pnum -Subclause \ref{meta.trans} contains templates that may be used to transform one -type to another following some predefined rule. +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v\&, ArgTypes...>} is +\tcode{true}, and +\item +\tcode{\exposid{is-callable-from}} is \tcode{true}. +\end{itemize} \pnum -Each of the templates in \ref{meta.trans} shall be a -\oldconcept{TransformationTrait}\iref{meta.rqmts}. +\mandates +\tcode{VT} is the same type as \tcode{T}. -\rSec3[meta.trans.cv]{Const-volatile modifications} +\pnum +\expects +\tcode{VT} meets the \oldconcept{Destructible} requirements, and +if \tcode{is_move_constructible_v} is \tcode{true}, +\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. -\begin{libreqtab2a}{Const-volatile modifications}{meta.trans.cv} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{remove_const}% -\tcode{template\br - struct remove_const;} & - The member typedef \tcode{type} names - the same type as \tcode{T} - except that any top-level const-qualifier has been removed. - \begin{tailexample} -\tcode{remove_const_t} evaluates - to \tcode{volatile int}, whereas \tcode{remove_const_t} evaluates to - \tcode{const int*}. -\end{tailexample} -\\ \rowsep - -\indexlibraryglobal{remove_volatile}% -\tcode{template\br - struct remove_volatile;} & - The member typedef \tcode{type} names - the same type as \tcode{T} - except that any top-level volatile-qualifier has been removed. - \begin{tailexample} -\tcode{remove_volatile_t} - evaluates to \tcode{const int}, - whereas \tcode{remove_volatile_t} evaluates to \tcode{volatile int*}. - \end{tailexample} -\\ \rowsep - -\indexlibraryglobal{remove_cv}% -\tcode{template\br - struct remove_cv;} & - The member typedef \tcode{type} shall be the same as \tcode{T} - except that any top-level cv-qualifier has been removed. - \begin{tailexample} -\tcode{remove_cv_t} - evaluates to \tcode{int}, whereas \tcode{remove_cv_t} - evaluates to \tcode{const volatile int*}. -\end{tailexample} -\\ \rowsep - -\indexlibraryglobal{add_const}% -\tcode{template\br - struct add_const;} & - If \tcode{T} is a reference, function, or top-level const-qualified - type, then \tcode{type} names - the same type as \tcode{T}, otherwise - \tcode{T const}. \\ \rowsep - -\indexlibraryglobal{add_volatile}% -\tcode{template\br - struct add_volatile;} & - If \tcode{T} is a reference, function, or top-level volatile-qualified - type, then \tcode{type} names - the same type as \tcode{T}, otherwise - \tcode{T volatile}. \\ \rowsep - -\indexlibraryglobal{add_cv}% -\tcode{template\br - struct add_cv;} & - The member typedef \tcode{type} names - the same type as - \tcode{add_const_t>}. \\ -\end{libreqtab2a} - -\rSec3[meta.trans.ref]{Reference modifications} - -\begin{libreqtab2a}{Reference modifications}{meta.trans.ref} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{remove_reference}% -\tcode{template\br - struct remove_reference;} & - If \tcode{T} has type ``reference to \tcode{T1}'' then the - member typedef \tcode{type} names \tcode{T1}; - otherwise, \tcode{type} names \tcode{T}.\\ \rowsep - -\indexlibraryglobal{add_lvalue_reference}% -\tcode{template\br - struct add_lvalue_reference;} & - If \tcode{T} names a referenceable type\iref{defns.referenceable} then - the member typedef \tcode{type} names \tcode{T\&}; - otherwise, \tcode{type} names \tcode{T}. - \begin{tailnote} - This rule reflects the semantics of reference collapsing\iref{dcl.ref}. - \end{tailnote} -\\ \rowsep +\pnum +\ensures +\tcode{*this} has a target object of type \tcode{VT} +direct-non-list-initialized with +\tcode{ilist, std::for\-ward(args)...}. -\indexlibraryglobal{add_rvalue_reference}% -\tcode{template}\br - \tcode{struct add_rvalue_reference;} & - If \tcode{T} names a referenceable type then - the member typedef \tcode{type} names \tcode{T\&\&}; - otherwise, \tcode{type} names \tcode{T}. - \begin{tailnote} -This rule reflects the semantics of reference collapsing\iref{dcl.ref}. - For example, when a type \tcode{T} names a type \tcode{T1\&}, the type - \tcode{add_rvalue_reference_t} is not an rvalue reference. - \end{tailnote} -\\ -\end{libreqtab2a} - -\rSec3[meta.trans.sign]{Sign modifications} -\begin{libreqtab2a}{Sign modifications}{meta.trans.sign} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{make_signed}% -\tcode{template}\br - \tcode{struct make_signed;} & - If \tcode{T} names a (possibly cv-qualified) signed integer - type\iref{basic.fundamental} then the member typedef - \tcode{type} names the type \tcode{T}; otherwise, - if \tcode{T} names a (possibly cv-qualified) unsigned integer - type then \tcode{type} names the corresponding - signed integer type, with the same cv-qualifiers as \tcode{T}; - otherwise, \tcode{type} names the signed integer type with smallest - rank\iref{conv.rank} for which - \tcode{sizeof(T) == sizeof(type)}, with the same - cv-qualifiers as \tcode{T}.\br - \mandates \tcode{T} is an integral or enumeration type - other than \cv~\tcode{bool}.\\ \rowsep - -\indexlibraryglobal{make_unsigned}% -\tcode{template}\br - \tcode{struct make_unsigned;} & - If \tcode{T} names a (possibly cv-qualified) unsigned integer - type\iref{basic.fundamental} then the member typedef - \tcode{type} names the type \tcode{T}; otherwise, - if \tcode{T} names a (possibly cv-qualified) signed integer - type then \tcode{type} names the corresponding - unsigned integer type, with the same cv-qualifiers as \tcode{T}; - otherwise, \tcode{type} names the unsigned integer type with smallest - rank\iref{conv.rank} for which - \tcode{sizeof(T) == sizeof(type)}, with the same - cv-qualifiers as \tcode{T}.\br - \mandates \tcode{T} is an integral or enumeration type - other than \cv~\tcode{bool}.\\ -\end{libreqtab2a} - -\rSec3[meta.trans.arr]{Array modifications} -\begin{libreqtab2a}{Array modifications}{meta.trans.arr} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{remove_extent}% -\tcode{template\br - struct remove_extent;} & - If \tcode{T} names a type ``array of \tcode{U}'', - the member typedef \tcode{type} shall - be \tcode{U}, otherwise \tcode{T}. - \begin{tailnote} -For multidimensional arrays, only the first array dimension is - removed. For a type ``array of \tcode{const U}'', the resulting type is - \tcode{const U}. -\end{tailnote} -\\ \rowsep +\pnum +\throws +Any exception thrown by the initialization of the target object. +May throw \tcode{bad_alloc} unless \tcode{VT} is +a function pointer or a specialization of \tcode{reference_wrapper}. +\end{itemdescr} -\indexlibraryglobal{remove_all_extents}% -\tcode{template\br - struct remove_all_extents;} & - If \tcode{T} is ``multi-dimensional array of \tcode{U}'', the resulting member - typedef \tcode{type} is \tcode{U}, otherwise \tcode{T}. \\ -\end{libreqtab2a} +\indexlibrarymember{operator=}{move_only_function}% +\begin{itemdecl} +move_only_function& operator=(move_only_function&& f); +\end{itemdecl} +\begin{itemdescr} \pnum -\begin{example} -\begin{codeblock} -// the following assertions hold: -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int[3]>)); -assert((is_same_v, int[3]>)); -\end{codeblock} -\end{example} +\effects +Equivalent to: \tcode{move_only_function(std::move(f)).swap(*this);} \pnum -\begin{example} -\begin{codeblock} -// the following assertions hold: -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int>)); -\end{codeblock} -\end{example} +\returns +\tcode{*this}. +\end{itemdescr} -\rSec3[meta.trans.ptr]{Pointer modifications} -\begin{libreqtab2a}{Pointer modifications}{meta.trans.ptr} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{remove_pointer}% -\tcode{template\br - struct remove_pointer;} & - If \tcode{T} has type ``(possibly cv-qualified) pointer - to \tcode{T1}'' then the member typedef \tcode{type} - names \tcode{T1}; otherwise, it names \tcode{T}.\\ \rowsep - -\indexlibraryglobal{add_pointer}% -\tcode{template\br - struct add_pointer;} & - If \tcode{T} names a referenceable type\iref{defns.referenceable} or a - \cv{}~\keyword{void} type then - the member typedef \tcode{type} names the same type as - \tcode{remove_reference_t*}; - otherwise, \tcode{type} names \tcode{T}. \\ -\end{libreqtab2a} - -\rSec3[meta.trans.other]{Other transformations} - -\begin{libreqtab2a}{Other transformations}{meta.trans.other} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{type_identity}% -\tcode{template\br - struct type_identity;} - & - The member typedef \tcode{type} names the type \tcode{T}. \\ \rowsep - -\indexlibraryglobal{aligned_storage}% -\tcode{template\br - struct aligned_storage;} - & - The value of \textit{default-alignment} shall be the most - stringent alignment requirement for any object type whose size - is no greater than \tcode{Len}\iref{basic.types}. - The member typedef \tcode{type} shall be 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}.\br - \mandates \tcode{Len} is not zero. \tcode{Align} is equal to - \tcode{alignof(T)} for some type \tcode{T} or to \textit{default-alignment}.\\ \rowsep - -\indexlibraryglobal{aligned_union}% -\tcode{template\br - struct aligned_union;} - & - The member typedef \tcode{type} shall be 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} - shall be an integral constant of type \tcode{size_t} whose value is the - strictest alignment of all types listed in \tcode{Types}.\br - \mandates At least one type is provided. - Each type in the template parameter pack \tcode{Types} - is a complete object type. - \\ \rowsep - -\indexlibraryglobal{remove_cvref}% -\tcode{template\br struct remove_cvref;} - & - The member typedef \tcode{type} names the same type as - \tcode{remove_cv_t>}. - \\ \rowsep - -\indexlibraryglobal{decay}% -\tcode{template\br struct decay;} - & - Let \tcode{U} be \tcode{remove_reference_t}. If \tcode{is_array_v} is - \tcode{true}, the member typedef \tcode{type} equals - \tcode{remove_extent_t*}. If \tcode{is_function_v} is \tcode{true}, - the member typedef \tcode{type} equals \tcode{add_pointer_t}. Otherwise - the member typedef \tcode{type} equals \tcode{remove_cv_t}. -\begin{tailnote} -This behavior is similar to the lvalue-to-rvalue\iref{conv.lval}, -array-to-pointer\iref{conv.array}, and function-to-pointer\iref{conv.func} -conversions applied when an lvalue is used as an rvalue, but also -strips cv-qualifiers from class types in order to more closely model by-value -argument passing. -\end{tailnote} - \\ \rowsep - -\indexlibraryglobal{enable_if}% -\tcode{template} \tcode{struct enable_if;} - & - If \tcode{B} is \tcode{true}, the member typedef \tcode{type} - shall equal \tcode{T}; otherwise, there shall be no member - \tcode{type}. \\ \rowsep - -\tcode{template}\br - \tcode{struct conditional;} - & - If \tcode{B} is \tcode{true}, the member typedef \tcode{type} shall equal \tcode{T}. - If \tcode{B} is \tcode{false}, the member typedef \tcode{type} shall equal \tcode{F}. \\ \rowsep - - \tcode{template} \tcode{struct common_type;} - & - Unless this trait is specialized (as specified in Note B, below), - the member \tcode{type} is defined or omitted as specified in Note A, below. - If it is omitted, there shall be no member \tcode{type}. - Each type in the template parameter pack \tcode{T} shall be - complete, \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{basic_common_reference}% -\tcode{template class,} - \hspace*{2ex}\tcode{template class>} - \keyword{struct} - \hspace*{2ex}\tcode{basic_common_reference;} - & - Unless this trait is specialized (as specified in Note D, below), - there shall be no member \tcode{type}. \\ \rowsep - -\indexlibraryglobal{common_reference}% -\tcode{template} \tcode{struct common_reference;} - & - The member \grammarterm{typedef-name} \tcode{type} is defined or omitted - as specified in Note C, below. Each type in the parameter pack \tcode{T} shall - be complete or \cv{} \keyword{void}. \\ \rowsep - -\indexlibraryglobal{underlying_type}% -\tcode{template}\br - \tcode{struct underlying_type;} - & - If \tcode{T} is an enumeration type, the member typedef \tcode{type} names - the underlying type of \tcode{T}\iref{dcl.enum}; - otherwise, there is no member \tcode{type}.\br - \mandates \tcode{T} is not an incomplete enumeration type. \\ \rowsep - -\tcode{template}\br - \tcode{struct invoke_result;} - & - If the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} - is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand}, - the member typedef \tcode{type} names the type - \tcode{decltype(\placeholdernc{INVOKE}(declval(), declval()...))}; - otherwise, there shall be no member \tcode{type}. Access checking is - performed as if in a context unrelated to \tcode{Fn} and - \tcode{ArgTypes}. Only the validity of the immediate context of the - expression is considered. - \begin{note} - The compilation of the expression can result in side effects such as - the instantiation of class template specializations and function - template specializations, the generation of implicitly-defined - functions, and so on. Such side effects are not in the ``immediate - context'' and can result in the program being ill-formed. - \end{note} - \expects \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} - are complete types, \cv{}~\keyword{void}, or arrays of - unknown bound.\\ \rowsep - -\indexlibraryglobal{unwrap_reference}% -\tcode{template} \tcode{struct unwrap_reference;} - & - If \tcode{T} is - a specialization \tcode{reference_wrapper} for some type \tcode{X}, - the member typedef \tcode{type} of \tcode{unwrap_reference} is \tcode{X\&}, - otherwise it is \tcode{T}. \\ \rowsep +\indexlibrarymember{operator=}{move_only_function}% +\begin{itemdecl} +move_only_function& operator=(nullptr_t) noexcept; +\end{itemdecl} -\indexlibraryglobal{unwrap_ref_decay}% -\tcode{template} \tcode{unwrap_ref_decay;} - & - The member typedef \tcode{type} of \tcode{unwrap_ref_decay} - denotes the type \tcode{unwrap_reference_t>}.\\ -\end{libreqtab2a} +\begin{itemdescr} +\pnum +\effects +Destroys the target object of \tcode{*this}, if any. -\indexlibraryglobal{aligned_storage}% \pnum -\begin{note} -A typical implementation would define \tcode{aligned_storage} as: +\returns +\tcode{*this}. +\end{itemdescr} -\begin{codeblock} -template -struct aligned_storage { - typedef struct { - alignas(Alignment) unsigned char __data[Len]; - } type; -}; -\end{codeblock} -\end{note} +\indexlibrarymember{operator=}{move_only_function}% +\begin{itemdecl} +template move_only_function& operator=(F&& f); +\end{itemdecl} +\begin{itemdescr} \pnum -In addition to being available via inclusion -of the \tcode{} header, the templates -\tcode{unwrap_reference}, -\tcode{unwrap_ref_decay}, -\tcode{unwrap_reference_t}, and -\tcode{unwrap_ref_decay_t} -are available -when the header \tcode{}\iref{functional.syn} is included. +\effects +Equivalent to: \tcode{move_only_function(std::forward(f)).swap(*this);} -\indexlibraryglobal{common_type}% \pnum -Let: -\begin{itemize} -\item \tcode{\placeholdernc{CREF}(A)} be - \tcode{add_lvalue_reference_t{}>}, -\item \tcode{\placeholdernc{XREF}(A)} denote a unary alias template \tcode{T} - such that \tcode{T} denotes the same type as \tcode{U} with the addition - of \tcode{A}'s cv and reference qualifiers, for a non-reference cv-unqualified - type \tcode{U}, -\item \tcode{\placeholdernc{COPYCV}(FROM, TO)} be an alias for type \tcode{TO} - with the addition of \tcode{FROM}'s top-level cv-qualifiers, - \begin{example} - \tcode{\placeholdernc{COPYCV}(const int, volatile short)} is an alias for - \tcode{const volatile short}. - \end{example} -\item \tcode{\placeholdernc{COND-RES}(X, Y)} be - \tcode{decltype(false ?\ declval()() :\ declval()())}. -\end{itemize} -Given types \tcode{A} and \tcode{B}, -let \tcode{X} be \tcode{remove_reference_t}, -let \tcode{Y} be \tcode{remove_reference_t}, and -let \tcode{\placeholdernc{COMMON-\brk{}REF}(A, B)} be: -\begin{itemize} -\item If \tcode{A} and \tcode{B} are both lvalue reference types, - \tcode{\placeholdernc{COMMON-REF}(A, B)} is - \tcode{\placeholdernc{COND-RES}(\placeholdernc{COPYCV}(X, Y) \&, - \placeholdernc{COPYCV}(\brk{}Y, X) \&)} if that type exists - and is a reference type. -\item Otherwise, let \tcode{C} be - \tcode{remove_reference_t<\placeholdernc{COMMON-REF}(X\&, Y\&)>\&\&}. - If \tcode{A} and \tcode{B} are both rvalue reference types, - \tcode{C} is well-formed, and - \tcode{is_convertible_v \&\& is_convertible_v} is \tcode{true}, - then \tcode{\placeholdernc{COMMON-REF}(A, B)} is \tcode{C}. -\item Otherwise, let \tcode{D} be - \tcode{\placeholdernc{COMMON-REF}(const X\&, Y\&)}. If \tcode{A} is an rvalue - reference and \tcode{B} is an lvalue reference and \tcode{D} is - well-formed and \tcode{is_convertible_v} is - \tcode{true}, then \tcode{\placeholdernc{COMMON-REF}(A, B)} is \tcode{D}. -\item Otherwise, if \tcode{A} is an lvalue reference and \tcode{B} - is an rvalue reference, then \tcode{\placeholdernc{COMMON-REF}(A, B)} is - \tcode{\placeholdernc{COMMON-REF}(B, A)}. -\item Otherwise, \tcode{\placeholdernc{COMMON-REF}(A, B)} is ill-formed. -\end{itemize} +\returns +\tcode{*this}. +\end{itemdescr} -If any of the types computed above is ill-formed, then -\tcode{\placeholdernc{COMMON-REF}(A, B)} is ill-formed. +\indexlibrarydtor{move_only_function}% +\begin{itemdecl} +~move_only_function(); +\end{itemdecl} +\begin{itemdescr} \pnum -Note A: -For the \tcode{common_type} trait applied to a template parameter pack \tcode{T} of types, -the member \tcode{type} shall be either defined or not present as follows: +\effects +Destroys the target object of \tcode{*this}, if any. +\end{itemdescr} -\begin{itemize} -\item If \tcode{sizeof...(T)} is zero, there shall be no member \tcode{type}. - -\item If \tcode{sizeof...(T)} is one, let \tcode{T0} denote the sole type -constituting the pack \tcode{T}. -The member \grammarterm{typedef-name} \tcode{type} shall denote the same -type, if any, as \tcode{common_type_t}; -otherwise there shall be no member \tcode{type}. - -\item If \tcode{sizeof...(T)} is two, -let the first and second types constituting \tcode{T} be denoted -by \tcode{T1} and \tcode{T2}, respectively, and -let \tcode{D1} and \tcode{D2} denote -the same types as \tcode{decay_t} and \tcode{decay_t}, respectively. - \begin{itemize} - \item If \tcode{is_same_v} is \tcode{false} or - \tcode{is_same_v} is \tcode{false}, - let \tcode{C} denote the same type, if any, - as \tcode{common_type_t}. - \item - \begin{note} - None of the following will apply if there is a specialization - \tcode{common_type}. - \end{note} - \item Otherwise, if -\begin{codeblock} -decay_t() : declval())> -\end{codeblock} - denotes a valid type, let \tcode{C} denote that type. - \item Otherwise, if - \tcode{\placeholdernc{COND-RES}(\placeholdernc{CREF}(D1), - \placeholdernc{CREF}(D2))} - denotes a type, let \tcode{C} denote the type - \tcode{decay_t<\placeholdernc{COND-RES}(\placeholdernc{CREF}(D1), - \placeholdernc{CREF}(D2))>}. - \end{itemize} -In either case, the member \grammarterm{typedef-name} \tcode{type} shall denote -the same type, if any, as \tcode{C}. -Otherwise, there shall be no member \tcode{type}. - -\item If \tcode{sizeof...(T)} is greater than two, -let \tcode{T1}, \tcode{T2}, and \tcode{R}, respectively, -denote the first, second, and (pack of) remaining types constituting \tcode{T}. -Let \tcode{C} denote the same type, if any, as \tcode{common_type_t}. -If there is such a type \tcode{C}, the member \grammarterm{typedef-name} \tcode{type} -shall denote the same type, if any, as \tcode{common_type_t}. -Otherwise, there shall be no member \tcode{type}. -\end{itemize} +\rSec4[func.wrap.move.inv]{Invocation} -\pnum -Note B: Notwithstanding the provisions of \ref{meta.type.synop}, and -pursuant to \ref{namespace.std}, -a program may specialize \tcode{common_type} -for types \tcode{T1} and \tcode{T2} such that -\tcode{is_same_v>} and -\tcode{is_same_v>} are each \tcode{true}. -\begin{note} -Such specializations are needed when only explicit conversions -are desired between the template arguments. -\end{note} -Such a specialization need not have a member named \tcode{type}, -but if it does, -the \grammarterm{qualified-id} \tcode{common_type::type} shall denote -a cv-unqualified non-reference type -to which each of the types \tcode{T1} and \tcode{T2} is explicitly convertible. -Moreover, \tcode{common_type_t} shall denote -the same type, if any, as does \tcode{common_type_t}. -No diagnostic is required for a violation of this Note's rules. - -\pnum -Note C: For the \tcode{common_reference} trait applied to a parameter pack -\tcode{T} of types, the member \tcode{type} shall be either defined or not -present as follows: -\begin{itemize} -\item If \tcode{sizeof...(T)} is zero, there shall be no member \tcode{type}. - -\item Otherwise, if \tcode{sizeof...(T)} is one, let \tcode{T0} denote the sole - type in the pack \tcode{T}. The member typedef \tcode{type} shall denote the - same type as \tcode{T0}. - -\item Otherwise, if \tcode{sizeof...(T)} is two, let \tcode{T1} and \tcode{T2} - denote the two types in the pack \tcode{T}. Then - \begin{itemize} - \item If \tcode{T1} and \tcode{T2} are reference types and - \tcode{\placeholdernc{COMMON-REF}(T1, T2)} is well-formed, then the member - typedef \tcode{type} denotes that type. - - \item Otherwise, if - \tcode{basic_common_reference, remove_cvref_t, - \brk{}\placeholdernc{XREF}(\brk{}T1), \placeholdernc{XREF}(T2)>::type} - is well-formed, then the member typedef \tcode{type} denotes that type. - - \item Otherwise, if \tcode{\placeholdernc{COND-RES}(T1, T2)} is well-formed, - then the member typedef \tcode{type} denotes that type. - - \item Otherwise, if \tcode{common_type_t} is well-formed, then the - member typedef \tcode{type} denotes that type. - - \item Otherwise, there shall be no member \tcode{type}. - \end{itemize} - -\item Otherwise, if \tcode{sizeof...(T)} is greater than two, let \tcode{T1}, - \tcode{T2}, and \tcode{Rest}, respectively, denote the first, second, and - (pack of) remaining types comprising \tcode{T}. Let \tcode{C} be the type - \tcode{common_reference_t}. Then: - \begin{itemize} - \item If there is such a type \tcode{C}, the member typedef \tcode{type} shall - denote the same type, if any, as \tcode{common_reference_t}. - - \item Otherwise, there shall be no member \tcode{type}. - \end{itemize} -\end{itemize} +\indexlibrarymember{operator bool}{move_only_function}% +\begin{itemdecl} +explicit operator bool() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -Note D: Notwithstanding the provisions of \ref{meta.type.synop}, and -pursuant to \ref{namespace.std}, a program may partially specialize -\tcode{basic_common_reference} -for types \tcode{T} and \tcode{U} such that -\tcode{is_same_v>} and -\tcode{is_same_v>} are each \tcode{true}. -\begin{note} -Such specializations -can be used to influence the result of \tcode{common_reference}, and -are needed when only explicit conversions are desired -between the template arguments. -\end{note} -Such a specialization need not have a member named \tcode{type}, but if it does, -the \grammarterm{qualified-id} -\tcode{basic_common_reference::type} -shall denote a type -to which each of the types \tcode{TQual} and -\tcode{UQual} is convertible. -Moreover, \tcode{basic_common_reference::type} shall denote -the same type, if any, as does -\tcode{basic_common_reference::type}. -No diagnostic is required for a violation of these rules. +\returns +\tcode{true} if \tcode{*this} has a target object, otherwise \tcode{false}. +\end{itemdescr} + +\indexlibrarymember{operator()}{move_only_function}% +\begin{itemdecl} +R operator()(ArgTypes... args) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); +\end{itemdecl} +\begin{itemdescr} \pnum -\begin{example} -Given these definitions: -\begin{codeblock} -using PF1 = bool (&)(); -using PF2 = short (*)(long); - -struct S { - operator PF2() const; - double operator()(char, int&); - void fn(long) const; - char data; -}; +\expects +\tcode{*this} has a target object. -using PMF = void (S::*)(long) const; -using PMD = char S::*; -\end{codeblock} -the following assertions will hold: +\pnum +\effects +Equivalent to: \begin{codeblock} -static_assert(is_same_v, short>); -static_assert(is_same_v, double>); -static_assert(is_same_v, bool>); -static_assert(is_same_v, int>, void>); -static_assert(is_same_v, char&&>); -static_assert(is_same_v, const char&>); +return @\placeholder{INVOKE}@(static_cast(f), std::forward(args)...); \end{codeblock} -\end{example} - -\rSec2[meta.logical]{Logical operator traits} +where \tcode{f} is an lvalue designating the target object of \tcode{*this} and +\tcode{F} is the type of \tcode{f}. +\end{itemdescr} -\pnum -This subclause describes type traits for applying logical operators -to other type traits. +\rSec4[func.wrap.move.util]{Utility} -\indexlibraryglobal{conjunction}% +\indexlibrarymember{swap}{move_only_function}% \begin{itemdecl} -template struct conjunction : @\seebelow@ { }; +void swap(move_only_function& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -The class template \tcode{conjunction} -forms the logical conjunction of its template type arguments. - -\pnum -For a specialization \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>}, -if there is a template type argument $\tcode{B}_{i}$ -for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{false}, -then instantiating \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>::value} -does not require the instantiation of \tcode{$\tcode{B}_{j}$::value} for $j > i$. -\begin{note} -This is analogous to the short-circuiting behavior of -the built-in operator \tcode{\&\&}. -\end{note} - -\pnum -Every template type argument -for which \tcode{$\tcode{B}_{i}$::value} is instantiated -shall be usable as a base class and -shall have a member \tcode{value} which -is convertible to \tcode{bool}, -is not hidden, and -is unambiguously available in the type. +\effects +Exchanges the target objects of \tcode{*this} and \tcode{other}. +\end{itemdescr} -\pnum -The specialization \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} -has a public and unambiguous base that is either -\begin{itemize} -\item -the first type $\tcode{B}_{i}$ in the list \tcode{true_type, $\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} -for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{false}, or -\item -if there is no such $\tcode{B}_{i}$, the last type in the list. -\end{itemize} -\begin{note} -This means a specialization of \tcode{conjunction} -does not necessarily inherit from -either \tcode{true_type} or \tcode{false_type}. -\end{note} +\indexlibrarymember{swap}{move_only_function}% +\begin{itemdecl} +friend void swap(move_only_function& f1, move_only_function& f2) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -The member names of the base class, other than \tcode{conjunction} and -\tcode{operator=}, shall not be hidden and shall be unambiguously available -in \tcode{conjunction}. +\effects +Equivalent to \tcode{f1.swap(f2)}. \end{itemdescr} -\indexlibraryglobal{disjunction}% +\indexlibrarymember{operator==}{move_only_function}% \begin{itemdecl} -template struct disjunction : @\seebelow@ { }; +friend bool operator==(const move_only_function& f, nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -The class template \tcode{disjunction} -forms the logical disjunction of its template type arguments. +\returns +\tcode{true} if \tcode{f} has no target object, otherwise \tcode{false}. +\end{itemdescr} +\indextext{function object!wrapper|)} -\pnum -For a specialization \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>}, -if there is a template type argument $\tcode{B}_{i}$ -for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{true}, -then instantiating \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>::value} -does not require the instantiation of \tcode{$\tcode{B}_{j}$::value} for $j > i$. -\begin{note} -This is analogous to the short-circuiting behavior of -the built-in operator \tcode{||}. -\end{note} +\rSec2[func.search]{Searchers} + +\rSec3[func.search.general]{General} \pnum -Every template type argument -for which \tcode{$\tcode{B}_{i}$::value} is instantiated -shall be usable as a base class and -shall have a member \tcode{value} which -is convertible to \tcode{bool}, -is not hidden, and -is unambiguously available in the type. +Subclause \ref{func.search} provides function object types\iref{function.objects} for +operations that search for a sequence \range{pat\textunderscore\nobreak first}{pat_last} in another +sequence \range{first}{last} that is provided to the object's function call +operator. The first sequence (the pattern to be searched for) is provided to +the object's constructor, and the second (the sequence to be searched) is +provided to the function call operator. \pnum -The specialization \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} -has a public and unambiguous base that is either +Each specialization of a class template specified in \ref{func.search} +shall meet the \oldconcept{CopyConst\-ruct\-ible} and \oldconcept{CopyAssignable} requirements. +Template parameters named \begin{itemize} -\item the first type $\tcode{B}_{i}$ in the list \tcode{false_type, $\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} -for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{true}, or -\item if there is no such $\tcode{B}_{i}$, the last type in the list. +\item \tcode{ForwardIterator}, +\item \tcode{ForwardIterator1}, +\item \tcode{ForwardIterator2}, +\item \tcode{RandomAccessIterator}, +\item \tcode{RandomAccessIterator1}, +\item \tcode{RandomAccessIterator2}, and +\item \tcode{BinaryPredicate} \end{itemize} -\begin{note} -This means a specialization of \tcode{disjunction} -does not necessarily inherit from -either \tcode{true_type} or \tcode{false_type}. -\end{note} +of templates specified in +\ref{func.search} shall meet the same requirements and semantics as +specified in \ref{algorithms.general}. +Template parameters named \tcode{Hash} shall meet the \oldconcept{Hash} +requirements (\tref{cpp17.hash}). \pnum -The member names of the base class, -other than \tcode{disjunction} and \tcode{operator=}, -shall not be hidden and shall be unambiguously available in \tcode{disjunction}. -\end{itemdescr} +The Boyer-Moore searcher implements the Boyer-Moore search algorithm. +The Boyer-Moore-Horspool searcher implements the Boyer-Moore-Horspool search algorithm. +In general, the Boyer-Moore searcher will use more memory and give better runtime performance than Boyer-Moore-Horspool. -\indexlibraryglobal{negation}% -\begin{itemdecl} -template struct negation : @\seebelow@ { }; -\end{itemdecl} +\rSec3[func.search.default]{Class template \tcode{default_searcher}} -\begin{itemdescr} -\pnum -The class template \tcode{negation} -forms the logical negation of its template type argument. -The type \tcode{negation} -is a \oldconcept{UnaryTypeTrait} with a base characteristic of \tcode{bool_constant}. -\end{itemdescr} +\indexlibraryglobal{default_searcher}% +\begin{codeblock} +namespace std { + template> + class default_searcher { + public: + constexpr default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last, + BinaryPredicate pred = BinaryPredicate()); + + template + constexpr pair + operator()(ForwardIterator2 first, ForwardIterator2 last) const; -\rSec2[meta.member]{Member relationships} + private: + ForwardIterator1 pat_first_; // \expos + ForwardIterator1 pat_last_; // \expos + BinaryPredicate pred_; // \expos + }; +} +\end{codeblock} -\indexlibraryglobal{is_pointer_interconvertible_with_class} +\indexlibraryctor{default_searcher}% \begin{itemdecl} -template - constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept; +constexpr default_searcher(ForwardIterator pat_first, ForwardIterator pat_last, + BinaryPredicate pred = BinaryPredicate()); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{S} is a complete type. +\effects +% FIXME: The mbox prevents TeX from adding a bizarre hyphen after pat_last_. +Constructs a \tcode{default_searcher} object, initializing \tcode{pat_first_} +with \tcode{pat_first}, \mbox{\tcode{pat_last_}} with \tcode{pat_last}, and +\tcode{pred_} with \tcode{pred}. \pnum -\returns -\tcode{true} if and only if - \tcode{S} is a standard-layout type, - \tcode{M} is an object type, - \tcode{m} is not null, - and each object \tcode{s} of type \tcode{S} - is pointer-interconvertible\iref{basic.compound} - with its subobject \tcode{s.*m}. +\throws +Any exception thrown by the copy constructor of \tcode{BinaryPredicate} or +\tcode{ForwardIterator1}. \end{itemdescr} -\indexlibraryglobal{is_corresponding_member} +\indexlibrarymember{operator()}{default_searcher}% \begin{itemdecl} -template - constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept; +template + constexpr pair + operator()(ForwardIterator2 first, ForwardIterator2 last) const; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{S1} and \tcode{S2} are complete types. - -\pnum -\returns -\tcode{true} if and only if - \tcode{S1} and \tcode{S2} are standard-layout struct\iref{class.prop} types, - \tcode{M1} and \tcode{M2} are object types, - \tcode{m1} and \tcode{m2} are not null, - and \tcode{m1} and \tcode{m2} point to corresponding members of - the common initial sequence\iref{class.mem} of \tcode{S1} and \tcode{S2}. +\effects +Returns a pair of iterators \tcode{i} and \tcode{j} such that +\begin{itemize} +\item \tcode{i == search(first, last, pat_first_, pat_last_, pred_)}, and +\item if \tcode{i == last}, then \tcode{j == last}, +otherwise \tcode{j == next(i, distance(pat_first_, pat_last_))}. +\end{itemize} \end{itemdescr} -\pnum -\begin{note} -The type of a pointer-to-member expression \tcode{\&C::b} -is not always a pointer to member of \tcode{C}, -leading to potentially surprising results -when using these functions in conjunction with inheritance. -\begin{example} +\rSec3[func.search.bm]{Class template \tcode{boyer_moore_searcher}} + +\indexlibraryglobal{boyer_moore_searcher}% \begin{codeblock} -struct A { int a; }; // a standard-layout class -struct B { int b; }; // a standard-layout class -struct C: public A, public B { }; // not a standard-layout class - -static_assert( is_pointer_interconvertible_with_class( &C::b ) ); - // Succeeds because, despite its appearance, \tcode{\&C::b} has type - // ``pointer to member of \tcode{B} of type \tcode{int}''. -static_assert( is_pointer_interconvertible_with_class( &C::b ) ); - // Forces the use of class \tcode{C}, and fails. - -static_assert( is_corresponding_member( &C::a, &C::b ) ); - // Succeeds because, despite its appearance, \tcode{\&C::a} and \tcode{\&C::b} have types - // ``pointer to member of \tcode{A} of type \tcode{int}'' and - // ``pointer to member of \tcode{B} of type \tcode{int}'', respectively. -static_assert( is_corresponding_member( &C::a, &C::b ) ); - // Forces the use of class \tcode{C}, and fails. +namespace std { + template::value_type>, + class BinaryPredicate = equal_to<>> + class boyer_moore_searcher { + public: + boyer_moore_searcher(RandomAccessIterator1 pat_first, + RandomAccessIterator1 pat_last, + Hash hf = Hash(), + BinaryPredicate pred = BinaryPredicate()); + + template + pair + operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; + + private: + RandomAccessIterator1 pat_first_; // \expos + RandomAccessIterator1 pat_last_; // \expos + Hash hash_; // \expos + BinaryPredicate pred_; // \expos + }; +} \end{codeblock} -\end{example} -\end{note} -\rSec2[meta.const.eval]{Constant evaluation context} +\indexlibraryctor{boyer_moore_searcher}% \begin{itemdecl} -constexpr bool is_constant_evaluated() noexcept; +boyer_moore_searcher(RandomAccessIterator1 pat_first, + RandomAccessIterator1 pat_last, + Hash hf = Hash(), + BinaryPredicate pred = BinaryPredicate()); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +The value type of \tcode{RandomAccessIterator1} meets +the \oldconcept{DefaultConstructible}, +the \oldconcept{Copy\-Constructible}, and +the \oldconcept{CopyAssignable} requirements. + +\pnum +Let \tcode{V} be \tcode{iterator_traits::val\-ue_type}. +For any two values \tcode{A} and \tcode{B} of type \tcode{V}, +if \tcode{pred(A, B) == true}, then \tcode{hf(A) == hf(B)} is \tcode{true}. + \pnum \effects -Equivalent to: -\begin{codeblock} -if consteval { - return true; -} else { - return false; -} -\end{codeblock} +Initializes +\tcode{pat_first_} with \tcode{pat_first}, +\tcode{pat_last_} with \tcode{pat_last}, +\tcode{hash_} with \tcode{hf}, and +\tcode{pred_} with \tcode{pred}. \pnum -\begin{example} -\begin{codeblock} -constexpr void f(unsigned char *p, int n) { - if (std::is_constant_evaluated()) { // should not be a constexpr if statement - for (int k = 0; k + pair + operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; +\end{itemdecl} +\begin{itemdescr} \pnum -\indexlibraryglobal{ratio}% -Subclause~\ref{ratio} describes the ratio library. It provides a class template -\tcode{ratio} which exactly represents any finite rational number with a -numerator and denominator representable by compile-time constants of type -\tcode{intmax_t}. +\mandates +\tcode{RandomAccessIterator1} and \tcode{RandomAccessIterator2} +have the same value type. \pnum -Throughout subclause~\ref{ratio}, the names of template parameters are used to express -type requirements. If a template parameter is named \tcode{R1} or \tcode{R2}, -and the template argument is not a specialization of the \tcode{ratio} template, -the program is ill-formed. +\effects +Finds a subsequence of equal values in a sequence. -\rSec2[ratio.syn]{Header \tcode{} synopsis} +\pnum +\returns +A pair of iterators \tcode{i} and \tcode{j} such that +\begin{itemize} +\item \tcode{i} is the first iterator +in the range \range{first}{last - (pat_last_ - pat_first_)} such that +for every non-negative integer \tcode{n} less than \tcode{pat_last_ - pat_first_} +the following condition holds: +\tcode{pred(*(i + n), *(pat_first_ + n)) != false}, and +\item \tcode{j == next(i, distance(pat_first_, pat_last_))}. +\end{itemize} +Returns \tcode{make_pair(first, first)} if \range{pat_first_}{pat_last_} is empty, +otherwise returns \tcode{make_pair(last, last)} if no such iterator is found. -\indexheader{ratio}% -\begin{codeblockdigitsep} -namespace std { - // \ref{ratio.ratio}, class template \tcode{ratio} - template class ratio; - - // \ref{ratio.arithmetic}, ratio arithmetic - template using ratio_add = @\seebelow@; - template using ratio_subtract = @\seebelow@; - template using ratio_multiply = @\seebelow@; - template using ratio_divide = @\seebelow@; - - // \ref{ratio.comparison}, ratio comparison - template struct ratio_equal; - template struct ratio_not_equal; - template struct ratio_less; - template struct ratio_less_equal; - template struct ratio_greater; - template struct ratio_greater_equal; - - template - inline constexpr bool @\libglobal{ratio_equal_v}@ = ratio_equal::value; - template - inline constexpr bool @\libglobal{ratio_not_equal_v}@ = ratio_not_equal::value; - template - inline constexpr bool @\libglobal{ratio_less_v}@ = ratio_less::value; - template - inline constexpr bool @\libglobal{ratio_less_equal_v}@ = ratio_less_equal::value; - template - inline constexpr bool @\libglobal{ratio_greater_v}@ = ratio_greater::value; - template - inline constexpr bool @\libglobal{ratio_greater_equal_v}@ = ratio_greater_equal::value; - - // \ref{ratio.si}, convenience SI typedefs - using yocto = ratio<1, 1'000'000'000'000'000'000'000'000>; // see below - using zepto = ratio<1, 1'000'000'000'000'000'000'000>; // see below - using atto = ratio<1, 1'000'000'000'000'000'000>; - using femto = ratio<1, 1'000'000'000'000'000>; - using pico = ratio<1, 1'000'000'000'000>; - using nano = ratio<1, 1'000'000'000>; - using micro = ratio<1, 1'000'000>; - using milli = ratio<1, 1'000>; - using centi = ratio<1, 100>; - using deci = ratio<1, 10>; - using deca = ratio< 10, 1>; - using hecto = ratio< 100, 1>; - using kilo = ratio< 1'000, 1>; - using mega = ratio< 1'000'000, 1>; - using giga = ratio< 1'000'000'000, 1>; - using tera = ratio< 1'000'000'000'000, 1>; - using peta = ratio< 1'000'000'000'000'000, 1>; - using exa = ratio< 1'000'000'000'000'000'000, 1>; - using zetta = ratio< 1'000'000'000'000'000'000'000, 1>; // see below - using yotta = ratio<1'000'000'000'000'000'000'000'000, 1>; // see below -} -\end{codeblockdigitsep} +\pnum +\complexity +At most \tcode{(last - first) * (pat_last_ - pat_first_)} applications of the predicate. +\end{itemdescr} -\rSec2[ratio.ratio]{Class template \tcode{ratio}} +\rSec3[func.search.bmh]{Class template \tcode{boyer_moore_horspool_searcher}} -\indexlibraryglobal{ratio}% +\indexlibraryglobal{boyer_moore_horspool_searcher}% \begin{codeblock} namespace std { - template class ratio { + template::value_type>, + class BinaryPredicate = equal_to<>> + class boyer_moore_horspool_searcher { public: - static constexpr intmax_t num; - static constexpr intmax_t den; - using type = ratio; + boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, + RandomAccessIterator1 pat_last, + Hash hf = Hash(), + BinaryPredicate pred = BinaryPredicate()); + + template + pair + operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; + + private: + RandomAccessIterator1 pat_first_; // \expos + RandomAccessIterator1 pat_last_; // \expos + Hash hash_; // \expos + BinaryPredicate pred_; // \expos }; } \end{codeblock} -\pnum -\indextext{signed integer representation!two's complement}% -If the template argument \tcode{D} is zero or the absolute values of either of the -template arguments \tcode{N} and \tcode{D} is not representable by type -\tcode{intmax_t}, the program is ill-formed. -\begin{note} -These rules ensure that infinite -ratios are avoided and that for any negative input, there exists a representable value -of its absolute value which is positive. -This excludes the most negative value. -\end{note} - -\pnum -The static data members \tcode{num} and \tcode{den} shall have the following values, -where \tcode{gcd} represents the greatest common divisor of the absolute values of -\tcode{N} and \tcode{D}: - -\begin{itemize} -\item \tcode{num} shall have the value \tcode{sign(N) * sign(D) * abs(N) / gcd}. -\item \tcode{den} shall have the value \tcode{abs(D) / gcd}. -\end{itemize} - -\rSec2[ratio.arithmetic]{Arithmetic on \tcode{ratio}{s}} +\indexlibraryctor{boyer_moore_horspool_searcher}% +\begin{itemdecl} +boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, + RandomAccessIterator1 pat_last, + Hash hf = Hash(), + BinaryPredicate pred = BinaryPredicate()); +\end{itemdecl} +\begin{itemdescr} \pnum -Each of the alias templates \tcode{ratio_add}, \tcode{ratio_subtract}, \tcode{ratio_multiply}, -and \tcode{ratio_divide} denotes the result of an arithmetic computation on two -\tcode{ratio}{s} \tcode{R1} and \tcode{R2}. With \tcode{X} and \tcode{Y} computed (in the -absence of arithmetic overflow) as specified by \tref{ratio.arithmetic}, each alias -denotes a \tcode{ratio} such that \tcode{U} is the same as \tcode{ratio::num} and -\tcode{V} is the same as \tcode{ratio::den}. +\expects +The value type of \tcode{RandomAccessIterator1} meets the \oldconcept{DefaultConstructible}, +\oldconcept{Copy\-Constructible}, and \oldconcept{CopyAssignable} requirements. \pnum -If it is not possible to represent \tcode{U} or \tcode{V} with \tcode{intmax_t}, the program is -ill-formed. Otherwise, an implementation should yield correct values of \tcode{U} and -\tcode{V}. If it is not possible to represent \tcode{X} or \tcode{Y} with \tcode{intmax_t}, the -program is ill-formed unless the implementation yields correct values of \tcode{U} and -\tcode{V}. - -\begin{floattable}{Expressions used to perform ratio arithmetic}{ratio.arithmetic} -{lll} -\topline -\lhdr{Type} & - \chdr{Value of \tcode{X}} & - \rhdr{Value of \tcode{Y}} \\ \rowsep - -\tcode{ratio_add} & - \tcode{R1::num * R2::den +} & - \tcode{R1::den * R2::den} \\ - & - \tcode{R2::num * R1::den} & - \\ \rowsep - -\tcode{ratio_subtract} & - \tcode{R1::num * R2::den -} & - \tcode{R1::den * R2::den} \\ - & - \tcode{R2::num * R1::den} & - \\ \rowsep - -\tcode{ratio_multiply} & - \tcode{R1::num * R2::num} & - \tcode{R1::den * R2::den} \\ \rowsep - -\tcode{ratio_divide} & - \tcode{R1::num * R2::den} & - \tcode{R1::den * R2::num} \\ -\end{floattable} +Let \tcode{V} be \tcode{iterator_traits::val\-ue_type}. +For any two values \tcode{A} and \tcode{B} of type \tcode{V}, +if \tcode{pred(A, B) == true}, then \tcode{hf(A) == hf(B)} is \tcode{true}. \pnum -\begin{example} -\begin{codeblock} -static_assert(ratio_add, ratio<1, 6>>::num == 1, "1/3+1/6 == 1/2"); -static_assert(ratio_add, ratio<1, 6>>::den == 2, "1/3+1/6 == 1/2"); -static_assert(ratio_multiply, ratio<3, 2>>::num == 1, "1/3*3/2 == 1/2"); -static_assert(ratio_multiply, ratio<3, 2>>::den == 2, "1/3*3/2 == 1/2"); - -// The following cases may cause the program to be ill-formed under some implementations -static_assert(ratio_add, ratio<1, INT_MAX>>::num == 2, - "1/MAX+1/MAX == 2/MAX"); -static_assert(ratio_add, ratio<1, INT_MAX>>::den == INT_MAX, - "1/MAX+1/MAX == 2/MAX"); -static_assert(ratio_multiply, ratio>::num == 1, - "1/MAX * MAX/2 == 1/2"); -static_assert(ratio_multiply, ratio>::den == 2, - "1/MAX * MAX/2 == 1/2"); -\end{codeblock} - -\end{example} +\effects +Initializes +\tcode{pat_first_} with \tcode{pat_first}, +\tcode{pat_last_} with \tcode{pat_last}, +\tcode{hash_} with \tcode{hf}, and +\tcode{pred_} with \tcode{pred}. -\rSec2[ratio.comparison]{Comparison of \tcode{ratio}{s}} +\pnum +\throws +Any exception thrown by the copy constructor of \tcode{RandomAccessIterator1}, +or by the default constructor, copy constructor, or the copy assignment operator of the value type of \tcode{RandomAccess\-Iterator1}, +or the copy constructor or \tcode{operator()} of \tcode{BinaryPredicate} or \tcode{Hash}. +May throw \tcode{bad_alloc} if additional memory needed for internal data structures cannot be allocated. +\end{itemdescr} -\indexlibraryglobal{ratio_equal}% +\indexlibrarymember{operator()}{boyer_moore_horspool_searcher}% \begin{itemdecl} -template - struct ratio_equal : bool_constant { }; +template + pair + operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; \end{itemdecl} -\indexlibraryglobal{ratio_not_equal}% -\begin{itemdecl} -template - struct ratio_not_equal : bool_constant> { }; -\end{itemdecl} +\begin{itemdescr} +\pnum +\mandates +\tcode{RandomAccessIterator1} and \tcode{RandomAccessIterator2} +have the same value type. -\indexlibraryglobal{ratio_less}% -\begin{itemdecl} -template - struct ratio_less : bool_constant<@\seebelow@> { }; -\end{itemdecl} +\pnum +\effects +Finds a subsequence of equal values in a sequence. -\begin{itemdescr} \pnum -If \tcode{R1::num} $\times$ \tcode{R2::den} is less than \tcode{R2::num} $\times$ \tcode{R1::den}, -\tcode{ratio_less} shall be -derived from \tcode{bool_constant}; otherwise it shall be derived from -\tcode{bool_constant}. Implementations may use other algorithms to -compute this relationship to avoid overflow. If overflow occurs, the program is ill-formed. +\returns +A pair of iterators \tcode{i} and \tcode{j} such that +\begin{itemize} +\item \tcode{i} is the first iterator in the range +\range{first}{last - (pat_last_ - pat_first_)} such that +for every non-negative integer \tcode{n} less than \tcode{pat_last_ - pat_first_} +the following condition holds: +\tcode{pred(*(i + n), *(pat_first_ + n)) != false}, and +\item \tcode{j == next(i, distance(pat_first_, pat_last_))}. +\end{itemize} +Returns \tcode{make_pair(first, first)} if \range{pat_first_}{pat_last_} is empty, +otherwise returns \tcode{make_pair(last, last)} if no such iterator is found. + +\pnum +\complexity +At most \tcode{(last - first) * (pat_last_ - pat_first_)} applications of the predicate. \end{itemdescr} -\indexlibraryglobal{ratio_less_equal}% -\begin{itemdecl} -template - struct ratio_less_equal : bool_constant> { }; -\end{itemdecl} +\rSec2[unord.hash]{Class template \tcode{hash}} -\indexlibraryglobal{ratio_greater}% -\begin{itemdecl} -template - struct ratio_greater : bool_constant> { }; -\end{itemdecl} +\pnum +\indexlibraryglobal{hash}% +\indextext{\idxcode{hash}!instantiation restrictions}% +The unordered associative containers defined in \ref{unord} use +specializations of the class template \tcode{hash}\iref{functional.syn} +as the default hash function. -\indexlibraryglobal{ratio_greater_equal}% -\begin{itemdecl} -template - struct ratio_greater_equal : bool_constant> { }; -\end{itemdecl} +\pnum +Each specialization of \tcode{hash} is either enabled or disabled, +as described below. +\begin{note} +Enabled specializations meet the \oldconcept{Hash} requirements, and +disabled specializations do not. +\end{note} +Each header that declares the template \tcode{hash} +provides enabled specializations of \tcode{hash} for \tcode{nullptr_t} and +all cv-unqualified arithmetic, enumeration, and pointer types. +For any type \tcode{Key} for which neither the library nor the user provides +an explicit or partial specialization of the class template \tcode{hash}, +\tcode{hash} is disabled. + +\pnum +If the library provides an explicit or partial specialization of \tcode{hash}, +that specialization is enabled except as noted otherwise, +and its member functions are \keyword{noexcept} except as noted otherwise. -\rSec2[ratio.si]{SI types for \tcode{ratio}} +\pnum +If \tcode{H} is a disabled specialization of \tcode{hash}, +these values are \tcode{false}: +\tcode{is_default_constructible_v}, +\tcode{is_copy_constructible_v}, +\tcode{is_move_constructible_v}, +\tcode{is_copy_assignable_v}, and +\tcode{is_move_assignable_v}. +Disabled specializations of \tcode{hash} +are not function object types\iref{function.objects}. +\begin{note} +This means that the specialization of \tcode{hash} exists, but +any attempts to use it as a \oldconcept{Hash} will be ill-formed. +\end{note} \pnum -For each of the \grammarterm{typedef-name}{s} \tcode{yocto}, \tcode{zepto}, -\tcode{zetta}, and \tcode{yotta}, if both of the constants used in its -specification are representable by \tcode{intmax_t}, the typedef is -defined; if either of the constants is not representable by \tcode{intmax_t}, -the typedef is not defined. +An enabled specialization \tcode{hash} will: +\begin{itemize} +\item meet the \oldconcept{Hash} requirements (\tref{cpp17.hash}), +with \tcode{Key} as the function +call argument type, the \oldconcept{Default\-Constructible} requirements (\tref{cpp17.defaultconstructible}), +the \oldconcept{CopyAssignable} requirements (\tref{cpp17.copyassignable}), +\item be swappable\iref{swappable.requirements} for lvalues, +\item meet the requirement that if \tcode{k1 == k2} is \tcode{true}, \tcode{h(k1) == h(k2)} is +also \tcode{true}, where \tcode{h} is an object of type \tcode{hash} and \tcode{k1} and \tcode{k2} +are objects of type \tcode{Key}; +\item meet the requirement that the expression \tcode{h(k)}, where \tcode{h} +is an object of type \tcode{hash} and \tcode{k} is an object of type +\tcode{Key}, shall not throw an exception unless \tcode{hash} is a +program-defined specialization. +\end{itemize} \rSec1[type.index]{Class \tcode{type_index}} @@ -20901,14 +13745,15 @@ \tcode{<} & Forces the field to be aligned to the start of the available space. This is the default for -non-arithmetic types, \tcode{charT}, and \tcode{bool}, +non-arithmetic non-pointer types, \tcode{charT}, and \tcode{bool}, unless an integer presentation type is specified. \\ \rowsep % \tcode{>} & Forces the field to be aligned to the end of the available space. This is the default for -arithmetic types other than \tcode{charT} and \tcode{bool} +arithmetic types other than \tcode{charT} and \tcode{bool}, +pointer types, or when an integer presentation type is specified. \\ \rowsep % @@ -21047,20 +13892,20 @@ The extended grapheme clusters of a string are defined by UAX \#29. The estimated width of the following code points is 2: \begin{itemize} -\item \tcode{U+1100-U+115F} -\item \tcode{U+2329-U+232A} -\item \tcode{U+2E80-U+303E} -\item \tcode{U+3040-U+A4CF} -\item \tcode{U+AC00-U+D7A3} -\item \tcode{U+F900-U+FAFF} -\item \tcode{U+FE10-U+FE19} -\item \tcode{U+FE30-U+FE6F} -\item \tcode{U+FF00-U+FF60} -\item \tcode{U+FFE0-U+FFE6} -\item \tcode{U+1F300-U+1F64F} -\item \tcode{U+1F900-U+1F9FF} -\item \tcode{U+20000-U+2FFFD} -\item \tcode{U+30000-U+3FFFD} +\item \ucode{1100} -- \ucode{115f} +\item \ucode{2329} -- \ucode{232a} +\item \ucode{2e80} -- \ucode{303e} +\item \ucode{3040} -- \ucode{a4cf} +\item \ucode{ac00} -- \ucode{d7a3} +\item \ucode{f900} -- \ucode{faff} +\item \ucode{fe10} -- \ucode{fe19} +\item \ucode{fe30} -- \ucode{fe6f} +\item \ucode{ff00} -- \ucode{ff60} +\item \ucode{ffe0} -- \ucode{ffe6} +\item \ucode{1f300} -- \ucode{1f64f} +\item \ucode{1f900} -- \ucode{1f9ff} +\item \ucode{20000} -- \ucode{2fffd} +\item \ucode{30000} -- \ucode{3fffd} \end{itemize} The estimated width of other code points is 1. @@ -21248,7 +14093,7 @@ Copies textual representation, either \tcode{true} or \tcode{false}, to the output. \\ \rowsep % -\tcode{b}, \tcode{B}, \tcode{c}, \tcode{d}, \tcode{o}, \tcode{x}, \tcode{X} & +\tcode{b}, \tcode{B}, \tcode{d}, \tcode{o}, \tcode{x}, \tcode{X} & As specified in \tref{format.type.int} for the value \tcode{static_cast(value)}. @@ -21503,7 +14348,7 @@ \effects Equivalent to: \begin{codeblock} -return vformat_to(out, fmt.@\exposid{str}@, make_format_args(args...)); +return vformat_to(std::move(out), fmt.@\exposid{str}@, make_format_args(args...)); \end{codeblock} \end{itemdescr} @@ -21533,7 +14378,7 @@ \effects Equivalent to: \begin{codeblock} -return vformat_to(out, loc, fmt.@\exposid{str}@, make_format_args(args...)); +return vformat_to(std::move(out), loc, fmt.@\exposid{str}@, make_format_args(args...)); \end{codeblock} \end{itemdescr} @@ -21582,9 +14427,7 @@ the arguments provided by \tcode{args}, formatted according to the specifications given in \tcode{fmt}, into the range \range{out}{out + N}, -where \tcode{N} is -\tcode{formatted_size(fmt, args...)} for the functions without a \tcode{loc} parameter and -\tcode{formatted_size(loc, fmt, args...)} for the functions with a \tcode{loc} parameter. +where \tcode{N} is the number of characters in that character representation. If present, \tcode{loc} is used for locale-specific formatting. \pnum @@ -22082,7 +14925,7 @@ using char_type = charT; template using formatter_type = formatter; - basic_format_arg arg(size_t id) const; + basic_format_arg arg(size_t id) const noexcept; std::locale locale(); iterator out(); @@ -22125,7 +14968,7 @@ \indexlibrarymember{arg}{basic_format_context}% \begin{itemdecl} -basic_format_arg arg(size_t id) const; +basic_format_arg arg(size_t id) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -22576,813 +15419,507 @@ template basic_format_args(const @\exposid{format-arg-store}@& store) noexcept; - basic_format_arg get(size_t i) const noexcept; - }; -} -\end{codeblock} - -\pnum -An instance of \tcode{basic_format_args} provides access to formatting -arguments. -Implementations should -optimize the representation of \tcode{basic_format_args} -for a small number of formatting arguments. -\begin{note} -For example, by storing indices of type alternatives separately from values -and packing the former. -\end{note} - -\indexlibraryctor{basic_format_args}% -\begin{itemdecl} -basic_format_args() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{size_} with \tcode{0}. -\end{itemdescr} - -\indexlibraryctor{basic_format_args}% -\begin{itemdecl} -template - basic_format_args(const @\exposid{format-arg-store}@& store) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes -\tcode{size_} with \tcode{sizeof...(Args)} and -\tcode{data_} with \tcode{store.args.data()}. -\end{itemdescr} - -\indexlibrarymember{get}{basic_format_args}% -\begin{itemdecl} -basic_format_arg get(size_t i) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{i < size_ ?\ data_[i] :\ basic_format_arg()}. -\end{itemdescr} - -\rSec2[format.error]{Class \tcode{format_error}} - -\indexlibraryglobal{format_error}% -\begin{codeblock} -namespace std { - class format_error : public runtime_error { - public: - explicit format_error(const string& what_arg); - explicit format_error(const char* what_arg); - }; -} -\end{codeblock} - -\pnum -The class \tcode{format_error} defines the type of objects thrown as -exceptions to report errors from the formatting library. - -\indexlibraryctor{format_error}% -\begin{itemdecl} -format_error(const string& what_arg); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{strcmp(what(), what_arg.c_str()) == 0}. - -\indexlibraryctor{format_error}% -\end{itemdescr} -\begin{itemdecl} -format_error(const char* what_arg); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{strcmp(what(), what_arg) == 0}. -\end{itemdescr} - -\rSec1[stacktrace]{Stacktrace} - -\rSec2[stacktrace.general]{General} - -\pnum -Subclause \ref{stacktrace} describes components -that \Cpp{} programs may use to store -the stacktrace of the current thread of execution and -query information about the stored stacktrace at runtime. - -\pnum -The \defn{invocation sequence} of the current evaluation $x_0$ -in the current thread of execution -is a sequence $(x_0, \ldots, x_n)$ of evaluations such that, for $i \geq 0$, -$x_i$ is within the function invocation $x_{i+1}$\iref{intro.execution}. - -\pnum -A \defn{stacktrace} is an approximate representation of -an invocation sequence and consists of stacktrace entries. -A \defn{stacktrace entry} represents an evaluation in a stacktrace. - -\rSec2[stacktrace.syn]{Header \tcode{} synopsis} - -\indexheader{stacktrace}% -\begin{codeblock} -namespace std { - // \ref{stacktrace.entry}, class \tcode{stacktrace_entry} - class stacktrace_entry; - - // \ref{stacktrace.basic}, class template \tcode{basic_stacktrace} - template - class basic_stacktrace; - - // \tcode{basic_stacktrace} \grammarterm{typedef-name}s - using stacktrace = basic_stacktrace>; - - // \ref{stacktrace.basic.nonmem}, non-member functions - template - void swap(basic_stacktrace& a, basic_stacktrace& b) - noexcept(noexcept(a.swap(b))); - - string to_string(const stacktrace_entry& f); - - template - string to_string(const basic_stacktrace& st); - - template - basic_ostream& - operator<<(basic_ostream& os, const stacktrace_entry& f); - - template - basic_ostream& - operator<<(basic_ostream& os, const basic_stacktrace& st); - - namespace pmr { - using stacktrace = basic_stacktrace>; - } - - // \ref{stacktrace.basic.hash}, hash support - template struct hash; - template<> struct hash; - template struct hash>; -} -\end{codeblock} - -\rSec2[stacktrace.entry]{Class \tcode{stacktrace_entry}} - -\rSec3[stacktrace.entry.overview]{Overview} - -\begin{codeblock} -namespace std { - class @\libglobal{stacktrace_entry}@ { - public: - using native_handle_type = @\impdefx{\tcode{stacktrace_entry::native_handle_type}}@; - - // \ref{stacktrace.entry.ctor}, constructors - constexpr stacktrace_entry() noexcept; - constexpr stacktrace_entry(const stacktrace_entry& other) noexcept; - constexpr stacktrace_entry& operator=(const stacktrace_entry& other) noexcept; - - ~stacktrace_entry(); - - // \ref{stacktrace.entry.obs}, observers - constexpr native_handle_type native_handle() const noexcept; - constexpr explicit operator bool() const noexcept; - - // \ref{stacktrace.entry.query}, query - string description() const; - string source_file() const; - uint_least32_t source_line() const; - - // \ref{stacktrace.entry.cmp}, comparison - friend constexpr bool operator==(const stacktrace_entry& x, - const stacktrace_entry& y) noexcept; - friend constexpr strong_ordering operator<=>(const stacktrace_entry& x, - const stacktrace_entry& y) noexcept; + basic_format_arg get(size_t i) const noexcept; }; } \end{codeblock} \pnum -An object of type \tcode{stacktrace_entry} is either empty, -or represents a stacktrace entry and -provides operations for querying information about it. -The class \tcode{stacktrace_entry} models -\libconcept{regular}\iref{concepts.object} and -\tcode{\libconcept{three_way_comparable}}\iref{cmp.concept}. - -\rSec3[stacktrace.entry.ctor]{Constructors} +An instance of \tcode{basic_format_args} provides access to formatting +arguments. +Implementations should +optimize the representation of \tcode{basic_format_args} +for a small number of formatting arguments. +\begin{note} +For example, by storing indices of type alternatives separately from values +and packing the former. +\end{note} -\indexlibraryctor{stacktrace_entry}% +\indexlibraryctor{basic_format_args}% \begin{itemdecl} -constexpr stacktrace_entry() noexcept; +basic_format_args() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{*this} is empty. +\effects +Initializes \tcode{size_} with \tcode{0}. \end{itemdescr} -\rSec3[stacktrace.entry.obs]{Observers} - -\indexlibrarymember{native_handle}{stacktrace_entry}% +\indexlibraryctor{basic_format_args}% \begin{itemdecl} -constexpr native_handle_type native_handle() const noexcept; +template + basic_format_args(const @\exposid{format-arg-store}@& store) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -The semantics of this function are -\impldef{semantics of \tcode{stacktrace_entry::native_handle}}. - -\pnum -\remarks -Successive invocations of the \tcode{native_handle} function -for an unchanged \tcode{stacktrace_entry} object return identical values. +\effects +Initializes +\tcode{size_} with \tcode{sizeof...(Args)} and +\tcode{data_} with \tcode{store.args.data()}. \end{itemdescr} -\indexlibrarymember{operator bool}{stacktrace_entry}% +\indexlibrarymember{get}{basic_format_args}% \begin{itemdecl} -constexpr explicit operator bool() const noexcept; +basic_format_arg get(size_t i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{false} if and only if \tcode{*this} is empty. +\tcode{i < size_ ?\ data_[i] :\ basic_format_arg()}. \end{itemdescr} -\rSec3[stacktrace.entry.query]{Query} +\rSec2[format.error]{Class \tcode{format_error}} + +\indexlibraryglobal{format_error}% +\begin{codeblock} +namespace std { + class format_error : public runtime_error { + public: + explicit format_error(const string& what_arg); + explicit format_error(const char* what_arg); + }; +} +\end{codeblock} \pnum -\begin{note} -All the \tcode{stacktrace_entry} query functions treat -errors other than memory allocation errors -as ``no information available'' and do not throw in that case. -\end{note} +The class \tcode{format_error} defines the type of objects thrown as +exceptions to report errors from the formatting library. -\indexlibrarymember{description}{stacktrace_entry}% +\indexlibraryctor{format_error}% \begin{itemdecl} -string description() const; +format_error(const string& what_arg); \end{itemdecl} \begin{itemdescr} \pnum -\returns -A description of the evaluation represented by \tcode{*this}, -or an empty string. +\ensures +\tcode{strcmp(what(), what_arg.c_str()) == 0}. -\pnum -\throws -\tcode{bad_alloc} if memory for -the internal data structures or the resulting string cannot be allocated. +\indexlibraryctor{format_error}% \end{itemdescr} - -\indexlibrarymember{source_file}{stacktrace_entry}% \begin{itemdecl} -string source_file() const; +format_error(const char* what_arg); \end{itemdecl} \begin{itemdescr} \pnum -\returns -The presumed or actual name of the source file\iref{cpp.predefined} -that lexically contains the expression or statement -whose evaluation is represented by \tcode{*this}, or an empty string. - -\pnum -\throws -\tcode{bad_alloc} if memory for -the internal data structures or the resulting string cannot be allocated. +\ensures +\tcode{strcmp(what(), what_arg) == 0}. \end{itemdescr} -\indexlibrarymember{source_line}{stacktrace_entry}% -\begin{itemdecl} -uint_least32_t source_line() const; -\end{itemdecl} +\rSec1[bit]{Bit manipulation} -\begin{itemdescr} -\pnum -\returns -\tcode{0}, or a 1-based line number that lexically relates to the evaluation -represented by \tcode{*this}. -If \tcode{source_file} returns the presumed name of the source file, -returns the presumed line number; -if \tcode{source_file} returns the actual name of the source file, -returns the actual line number. +\rSec2[bit.general]{General} \pnum -\throws -\tcode{bad_alloc} if memory for -the internal data structures cannot be allocated. -\end{itemdescr} +The header \libheaderdef{bit} provides components to access, +manipulate and process both individual bits and bit sequences. -\rSec3[stacktrace.entry.cmp]{Comparison} +\rSec2[bit.syn]{Header \tcode{} synopsis} -\indexlibrarymember{operator==}{stacktrace_entry}% -\begin{itemdecl} -friend constexpr bool operator==(const stacktrace_entry& x, const stacktrace_entry& y) noexcept; -\end{itemdecl} +\begin{codeblock} +namespace std { + // \ref{bit.cast}, \tcode{bit_cast} + template + constexpr To bit_cast(const From& from) noexcept; -\begin{itemdescr} -\pnum -\returns -\tcode{true} if and only if \tcode{x} and \tcode{y} represent -the same stacktrace entry or both \tcode{x} and \tcode{y} are empty. -\end{itemdescr} + // \ref{bit.byteswap}, \tcode{byteswap} + template + constexpr T byteswap(T value) noexcept; -\rSec2[stacktrace.basic]{Class template \tcode{basic_stacktrace}} + // \ref{bit.pow.two}, integral powers of 2 + template + constexpr bool has_single_bit(T x) noexcept; + template + constexpr T bit_ceil(T x); + template + constexpr T bit_floor(T x) noexcept; + template + constexpr T bit_width(T x) noexcept; -\rSec3[stacktrace.basic.overview]{Overview} + // \ref{bit.rotate}, rotating + template + [[nodiscard]] constexpr T rotl(T x, int s) noexcept; + template + [[nodiscard]] constexpr T rotr(T x, int s) noexcept; -\begin{codeblock} -namespace std { - template - class @\libglobal{basic_stacktrace}@ { - public: - using value_type = stacktrace_entry; - using const_reference = const value_type&; - using reference = value_type&; - using const_iterator = @\impdefx{type of \tcode{basic_stacktrace::const_iterator}}@; // see \ref{stacktrace.basic.obs} - using iterator = const_iterator; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using difference_type = @\impdefx{type of \tcode{basic_stacktrace::difference_type}}@; - using size_type = @\impdefx{type of \tcode{basic_stacktrace::size_type}}@; - using allocator_type = Allocator; - - // \ref{stacktrace.basic.ctor}, creation and assignment - static basic_stacktrace current(const allocator_type& alloc = allocator_type()) noexcept; - static basic_stacktrace current(size_type skip, - const allocator_type& alloc = allocator_type()) noexcept; - static basic_stacktrace current(size_type skip, size_type max_depth, - const allocator_type& alloc = allocator_type()) noexcept; - - basic_stacktrace() noexcept(is_nothrow_default_constructible_v); - explicit basic_stacktrace(const allocator_type& alloc) noexcept; - - basic_stacktrace(const basic_stacktrace& other); - basic_stacktrace(basic_stacktrace&& other) noexcept; - basic_stacktrace(const basic_stacktrace& other, const allocator_type& alloc); - basic_stacktrace(basic_stacktrace&& other, const allocator_type& alloc); - basic_stacktrace& operator=(const basic_stacktrace& other); - basic_stacktrace& operator=(basic_stacktrace&& other) - noexcept(allocator_traits::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); - - ~basic_stacktrace(); - - // \ref{stacktrace.basic.obs}, observers - allocator_type get_allocator() const noexcept; - - const_iterator begin() const noexcept; - const_iterator end() const noexcept; - const_reverse_iterator rbegin() const noexcept; - const_reverse_iterator rend() const noexcept; - - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; - - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; - - const_reference operator[](size_type) const; - const_reference at(size_type) const; - - // \ref{stacktrace.basic.cmp}, comparisons - template - friend bool operator==(const basic_stacktrace& x, - const basic_stacktrace& y) noexcept; - template - friend strong_ordering operator<=>(const basic_stacktrace& x, - const basic_stacktrace& y) noexcept; - - // \ref{stacktrace.basic.mod}, modifiers - void swap(basic_stacktrace& other) - noexcept(allocator_traits::propagate_on_container_swap::value || - allocator_traits::is_always_equal::value); + // \ref{bit.count}, counting + template + constexpr int countl_zero(T x) noexcept; + template + constexpr int countl_one(T x) noexcept; + template + constexpr int countr_zero(T x) noexcept; + template + constexpr int countr_one(T x) noexcept; + template + constexpr int popcount(T x) noexcept; - private: - vector frames_; // \expos + // \ref{bit.endian}, endian + enum class endian { + little = @\seebelow@, + big = @\seebelow@, + native = @\seebelow@ }; } \end{codeblock} -\pnum -The class template \tcode{basic_stacktrace} satisfies -the requirements of -an allocator-aware container (\tref{container.alloc.req}), -a sequence container\iref{sequence.reqmts}, and -a reversible container\iref{container.requirements.general} -except that -\begin{itemize} -\item -only move, assignment, swap, and -operations defined for const-qualified sequence containers are supported and, -\item -the semantics of comparison functions -are different from those required for a container. -\end{itemize} - -\rSec3[stacktrace.basic.ctor]{Creation and assignment} +\rSec2[bit.cast]{Function template \tcode{bit_cast}} -\indexlibrarymember{current}{basic_stacktrace}% +\indexlibraryglobal{bit_cast}% \begin{itemdecl} -static basic_stacktrace current(const allocator_type& alloc = allocator_type()) noexcept; +template + constexpr To bit_cast(const From& from) noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{sizeof(To) == sizeof(From)} is \tcode{true}; +\item \tcode{is_trivially_copyable_v} is \tcode{true}; and +\item \tcode{is_trivially_copyable_v} is \tcode{true}. +\end{itemize} + \pnum \returns -A \tcode{basic_stacktrace} object -with \tcode{frames_} storing -the stacktrace of the current evaluation in the current thread of execution, or -an empty \tcode{basic_stacktrace} object -if the initialization of \tcode{frames_} failed. -\tcode{alloc} is passed to the constructor of the \tcode{frames_} object. +An object of type \tcode{To}. +Implicitly creates objects nested within the result\iref{intro.object}. +Each bit of the value representation of the result +is equal to the corresponding bit in the object representation +of \tcode{from}. Padding bits of the result are unspecified. +For the result and each object created within it, +if there is no value of the object's type corresponding to the +value representation produced, the behavior is undefined. +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 +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. -\begin{note} -If the stacktrace was successfully obtained, -then \tcode{frames_.front()} is the \tcode{stacktrace_entry} -representing approximately the current evaluation, and -\tcode{frames_.back()} is the \tcode{stacktrace_entry} -representing approximately the initial function of -the current thread of execution. -\end{note} +\pnum +\remarks +This function is \keyword{constexpr} if and only if +\tcode{To}, \tcode{From}, and the types of all subobjects +of \tcode{To} and \tcode{From} are types \tcode{T} such that: +\begin{itemize} +\item \tcode{is_union_v} is \tcode{false}; +\item \tcode{is_pointer_v} is \tcode{false}; +\item \tcode{is_member_pointer_v} is \tcode{false}; +\item \tcode{is_volatile_v} is \tcode{false}; and +\item \tcode{T} has no non-static data members of reference type. +\end{itemize} \end{itemdescr} -\indexlibrarymember{current}{basic_stacktrace}% +\rSec2[bit.byteswap]{\tcode{byteswap}} + +\indexlibraryglobal{byteswap}% \begin{itemdecl} -static basic_stacktrace current(size_type skip, - const allocator_type& alloc = allocator_type()) noexcept; +template + constexpr T byteswap(T value) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{t} be a stacktrace -as-if obtained via \tcode{basic_stacktrace::current(alloc)}. -Let \tcode{n} be \tcode{t.size()}. +\constraints +\tcode{T} models \libconcept{integral}. + +\pnum +\mandates +\tcode{T} does not have padding bits\iref{basic.types.general}. + +\pnum +Let the sequence $R$ comprise +the bytes of the object representation of \tcode{value} in reverse order. \pnum \returns -A \tcode{basic_stacktrace} object -where \tcode{frames_} is direct-non-list-initialized from arguments -\tcode{t.begin() + min(n, skip)}, \tcode{t.end()}, and \tcode{alloc}, -or an empty \tcode{basic_stacktrace} object -if the initialization of \tcode{frames_} failed. +An object \tcode{v} of type \tcode{T} +such that each byte in the object representation of \tcode{v} is equal to +the byte in the corresponding position in $R$. \end{itemdescr} -\indexlibrarymember{current}{basic_stacktrace}% +\rSec2[bit.pow.two]{Integral powers of 2} + +\indexlibraryglobal{has_single_bit}% \begin{itemdecl} -static basic_stacktrace current(size_type skip, size_type max_depth, - const allocator_type& alloc = allocator_type()) noexcept; +template + constexpr bool has_single_bit(T x) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{t} be a stacktrace -as-if obtained via \tcode{basic_stacktrace::current(alloc)}. -Let \tcode{n} be \tcode{t.size()}. - -\pnum -\expects -\tcode{skip <= skip + max_depth} is \tcode{true}. +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. \pnum \returns -A \tcode{basic_stacktrace} object -where \tcode{frames_} is direct-non-list-initialized from arguments -\tcode{t.begin() + min(n, skip)}, \tcode{t.begin() + min(n, skip + max_depth)}, -and \tcode{alloc}, -or an empty \tcode{basic_stacktrace} object -if the initialization of \tcode{frames_} failed. +\tcode{true} if \tcode{x} is an integral power of two; +\tcode{false} otherwise. + \end{itemdescr} -\indexlibraryctor{basic_stacktrace}% +\indexlibraryglobal{bit_ceil}% \begin{itemdecl} -basic_stacktrace() noexcept(is_nothrow_default_constructible_v); +template + constexpr T bit_ceil(T x); \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{empty()} is \tcode{true}. -\end{itemdescr} +Let $N$ be the smallest power of 2 greater than or equal to \tcode{x}. -\indexlibraryctor{basic_stacktrace}% -\begin{itemdecl} -explicit basic_stacktrace(const allocator_type& alloc) noexcept; -\end{itemdecl} +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. -\begin{itemdescr} \pnum -\effects -\tcode{alloc} is passed to the \tcode{frames_} constructor. +\expects +$N$ is representable as a value of type \tcode{T}. \pnum -\ensures -\tcode{empty()} is \tcode{true}. -\end{itemdescr} +\returns +$N$. -\indexlibraryctor{basic_stacktrace}% -\indexlibrarymember{operator=}{basic_stacktrace}% -\begin{itemdecl} -basic_stacktrace(const basic_stacktrace& other); -basic_stacktrace(const basic_stacktrace& other, const allocator_type& alloc); -basic_stacktrace(basic_stacktrace&& other, const allocator_type& alloc); -basic_stacktrace& operator=(const basic_stacktrace& other); -basic_stacktrace& operator=(basic_stacktrace&& other) - noexcept(allocator_traits::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); -\end{itemdecl} +\pnum +\throws +Nothing. -\begin{itemdescr} \pnum \remarks -Implementations may strengthen the exception specification -for these functions\iref{res.on.exception.handling} -by ensuring that \tcode{empty()} is \tcode{true} on failed allocation. +A function call expression +that violates the precondition in the \expects element +is not a core constant expression\iref{expr.const}. \end{itemdescr} -\rSec3[stacktrace.basic.obs]{Observers} - -\indexlibrarymember{const_iterator}{basic_stacktrace}% +\indexlibraryglobal{bit_floor}% \begin{itemdecl} -using const_iterator = @\impdef@; +template + constexpr T bit_floor(T x) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -The type models -\libconcept{random_access_iterator}\iref{iterator.concept.random.access} and -meets the -\oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators}. -\end{itemdescr} - -\indexlibrarymember{get_allocator}{basic_stacktrace}% -\begin{itemdecl} -allocator_type get_allocator() const noexcept; -\end{itemdecl} +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. -\begin{itemdescr} \pnum \returns -\tcode{frames_.get_allocator()}. -\end{itemdescr} - -\indexlibrarymember{begin}{basic_stacktrace}% -\indexlibrarymember{cbegin}{basic_stacktrace}% -\begin{itemdecl} -const_iterator begin() const noexcept; -const_iterator cbegin() const noexcept; -\end{itemdecl} +If \tcode{x == 0}, \tcode{0}; +otherwise the maximal value \tcode{y} +such that \tcode{has_single_bit(y)} is \tcode{true} and \tcode{y <= x}. -\begin{itemdescr} -\pnum -\returns -An iterator referring to the first element in \tcode{frames_}. -If \tcode{empty()} is \tcode{true}, -then it returns the same value as \tcode{end()}. \end{itemdescr} -\indexlibrarymember{end}{basic_stacktrace}% -\indexlibrarymember{cend}{basic_stacktrace}% +\indexlibraryglobal{bit_width}% \begin{itemdecl} -const_iterator end() const noexcept; -const_iterator cend() const noexcept; +template + constexpr T bit_width(T x) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -The end iterator. -\end{itemdescr} - -\indexlibrarymember{rbegin}{basic_stacktrace}% -\indexlibrarymember{crbegin}{basic_stacktrace}% -\begin{itemdecl} -const_reverse_iterator rbegin() const noexcept; -const_reverse_iterator crbegin() const noexcept; -\end{itemdecl} +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. -\begin{itemdescr} \pnum \returns -\tcode{reverse_iterator(cend())}. +If \tcode{x == 0}, \tcode{0}; +otherwise one plus the base-2 logarithm of \tcode{x}, +with any fractional part discarded. + \end{itemdescr} -\indexlibrarymember{rend}{basic_stacktrace}% -\indexlibrarymember{crend}{basic_stacktrace}% -\begin{itemdecl} -const_reverse_iterator rend() const noexcept; -const_reverse_iterator crend() const noexcept; -\end{itemdecl} +\rSec2[bit.rotate]{Rotating} -\begin{itemdescr} \pnum -\returns -\tcode{reverse_iterator(cbegin())}. -\end{itemdescr} +In the following descriptions, +let \tcode{N} denote \tcode{numeric_limits::digits}. -\indexlibrarymember{empty}{basic_stacktrace}% \begin{itemdecl} -[[nodiscard]] bool empty() const noexcept; +template + [[nodiscard]] constexpr T rotl(T x, int s) noexcept; \end{itemdecl} +\indexlibraryglobal{rotl}% \begin{itemdescr} \pnum -\returns -\tcode{frames_.empty()}. -\end{itemdescr} +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. -\indexlibrarymember{size}{basic_stacktrace}% -\begin{itemdecl} -size_type size() const noexcept; -\end{itemdecl} +\pnum +Let \tcode{r} be \tcode{s \% N}. -\begin{itemdescr} \pnum \returns -\tcode{frames_.size()}. +If \tcode{r} is \tcode{0}, \tcode{x}; +if \tcode{r} is positive, \tcode{(x << r) | (x >> (N - r))}; +if \tcode{r} is negative, \tcode{rotr(x, -r)}. \end{itemdescr} -\indexlibrarymember{max_size}{basic_stacktrace}% \begin{itemdecl} -size_type max_size() const noexcept; +template + [[nodiscard]] constexpr T rotr(T x, int s) noexcept; \end{itemdecl} +\indexlibraryglobal{rotr}% \begin{itemdescr} \pnum -\returns -\tcode{frames_.max_size()}. -\end{itemdescr} - -\indexlibrarymember{operator[]}{basic_stacktrace}% -\begin{itemdecl} -const_reference operator[](size_type frame_no) const; -\end{itemdecl} +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. -\begin{itemdescr} \pnum -\expects -\tcode{frame_no < size()} is \tcode{true}. +Let \tcode{r} be \tcode{s \% N}. \pnum \returns -\tcode{frames_[frame_no]}. +If \tcode{r} is \tcode{0}, \tcode{x}; +if \tcode{r} is positive, \tcode{(x >> r) | (x << (N - r))}; +if \tcode{r} is negative, \tcode{rotl(x, -r)}. +\end{itemdescr} + +\rSec2[bit.count]{Counting} \pnum -\throws -Nothing. -\end{itemdescr} +In the following descriptions, +let \tcode{N} denote \tcode{numeric_limits::digits}. -\indexlibrarymember{at}{basic_stacktrace}% \begin{itemdecl} -const_reference at(size_type frame_no) const; +template + constexpr int countl_zero(T x) noexcept; \end{itemdecl} +\indexlibraryglobal{countl_zero}% \begin{itemdescr} \pnum -\returns -\tcode{frames_[frame_no]}. +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. \pnum -\throws -\tcode{out_of_range} if \tcode{frame_no >= size()}. +\returns +The number of consecutive \tcode{0} bits in the value of \tcode{x}, +starting from the most significant bit. +\begin{note} +Returns \tcode{N} if \tcode{x == 0}. +\end{note} \end{itemdescr} -\rSec3[stacktrace.basic.cmp]{Comparisons} - -\indexlibrarymember{operator==}{basic_stacktrace}% \begin{itemdecl} -template -friend bool operator==(const basic_stacktrace& x, const basic_stacktrace& y) noexcept; +template + constexpr int countl_one(T x) noexcept; \end{itemdecl} +\indexlibraryglobal{countl_one}% \begin{itemdescr} \pnum -\returns -\tcode{equal(x.begin(), x.end(), y.begin(), y.end())}. -\end{itemdescr} - -\indexlibrarymember{operator<=>}{basic_stacktrace}% -\begin{itemdecl} -template -friend strong_ordering - operator<=>(const basic_stacktrace& x, const basic_stacktrace& y) noexcept; -\end{itemdecl} +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. -\begin{itemdescr} \pnum \returns -\tcode{x.size() <=> y.size()} if \tcode{x.size() != y.size()}; -\tcode{lexicographical_compare_three_way(x.begin(), x.end(), y.begin(), y.end())} -otherwise. +The number of consecutive \tcode{1} bits in the value of \tcode{x}, +starting from the most significant bit. +\begin{note} +Returns \tcode{N} if \tcode{x == numeric_limits::max()}. +\end{note} \end{itemdescr} -\rSec3[stacktrace.basic.mod]{Modifiers} - -\indexlibrarymember{swap}{basic_stacktrace}% \begin{itemdecl} -void swap(basic_stacktrace& other) - noexcept(allocator_traits::propagate_on_container_swap::value || - allocator_traits::is_always_equal::value); +template + constexpr int countr_zero(T x) noexcept; \end{itemdecl} +\indexlibraryglobal{countr_zero}% \begin{itemdescr} \pnum -\effects -Exchanges the contents of \tcode{*this} and \tcode{other}. -\end{itemdescr} - -\rSec3[stacktrace.basic.nonmem]{Non-member functions} - -\indexlibrarymember{swap}{basic_stacktrace}% -\begin{itemdecl} -template -void swap(basic_stacktrace& a, basic_stacktrace& b) - noexcept(noexcept(a.swap(b))); -\end{itemdecl} +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. -\begin{itemdescr} \pnum -\effects -Equivalent to \tcode{a.swap(b)}. +\returns +The number of consecutive \tcode{0} bits in the value of \tcode{x}, +starting from the least significant bit. +\begin{note} +Returns \tcode{N} if \tcode{x == 0}. +\end{note} \end{itemdescr} -\indexlibrarymember{to_string}{basic_stacktrace}% \begin{itemdecl} -string to_string(const stacktrace_entry& f); +template + constexpr int countr_one(T x) noexcept; \end{itemdecl} +\indexlibraryglobal{countr_one}% \begin{itemdescr} \pnum -\returns -A string with a description of \tcode{f}. - -\recommended -The description should provide information about the contained evaluation, -including information from -\tcode{f.source_file()} and \tcode{f.source_line()}. -\end{itemdescr} - -\indexlibrarymember{to_string}{basic_stacktrace}% -\begin{itemdecl} -template -string to_string(const basic_stacktrace& st); -\end{itemdecl} +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. -\begin{itemdescr} \pnum \returns -A string with a description of \tcode{st}. +The number of consecutive \tcode{1} bits in the value of \tcode{x}, +starting from the least significant bit. \begin{note} -The number of lines is not guaranteed to be equal to \tcode{st.size()}. +Returns \tcode{N} if \tcode{x == numeric_limits::max()}. \end{note} \end{itemdescr} -\indexlibrarymember{operator<<}{stacktrace_entry}% \begin{itemdecl} -template -basic_ostream& - operator<<(basic_ostream& os, const stacktrace_entry& f); +template + constexpr int popcount(T x) noexcept; \end{itemdecl} +\indexlibraryglobal{popcount}% \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return os << to_string(f);} -\end{itemdescr} - -\indexlibrarymember{operator<<}{basic_stacktrace}% -\begin{itemdecl} -template -basic_ostream& - operator<<(basic_ostream& os, const basic_stacktrace& st); -\end{itemdecl} +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return os << to_string(st);} +\returns +The number of \tcode{1} bits in the value of \tcode{x}. \end{itemdescr} -\rSec3[stacktrace.basic.hash]{Hash support} +\rSec2[bit.endian]{Endian} + +\pnum +Two common methods of byte ordering in multibyte scalar types are big-endian +and little-endian in the execution environment. Big-endian is a format for +storage of binary data in which the most significant byte is placed first, +with the rest in descending order. Little-endian is a format for storage of +binary data in which the least significant byte is placed first, with the rest +in ascending order. This subclause describes the endianness of the scalar types +of the execution environment. +\indexlibraryglobal{endian}% +\indexlibrarymember{little}{endian}% +\indexlibrarymember{big}{endian}% +\indexlibrarymember{native}{endian}% \begin{itemdecl} -template<> struct hash; -template struct hash>; +enum class endian { + little = @\seebelow@, + big = @\seebelow@, + native = @\seebelow@ +}; \end{itemdecl} \begin{itemdescr} \pnum -The specializations are enabled\iref{unord.hash}. +If all scalar types have size 1 byte, then all of \tcode{endian::little}, +\tcode{endian::big}, and \tcode{endian::native} have the same value. +Otherwise, \tcode{endian::little} is not equal to \tcode{endian::big}. +If all scalar types are big-endian, \tcode{endian::native} is +equal to \tcode{endian::big}. +If all scalar types are little-endian, \tcode{endian::native} is +equal to \tcode{endian::little}. +Otherwise, \tcode{endian::native} is not equal +to either \tcode{endian::big} or \tcode{endian::little}. \end{itemdescr} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index aa5fc326ea..719ca93f9c 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -30,7 +30,7 @@ \movedxref{basic.lookup.classref}{basic.lookup.qual} \movedxref{namespace.memdef}{namespace.def} \movedxref{class.this}{expr.prim.this} -\movedxref{class.mfct.non-static.general}{class.mfct.non-static} +\movedxref{class.mfct.non-static.general}{class.mfct.non.static} \movedxref{class.nested.type}{diff.basic} \movedxref{over.load}{basic.scope.scope} \movedxref{over.dcl}{basic.link} @@ -82,5 +82,19 @@ \movedxref{depr.stdbool.h.syn}{stdbool.h.syn} \movedxref{depr.tgmath.h.syn}{tgmath.h.syn} +\movedxref{istringstream.assign}{istringstream.swap} +\movedxref{ostringstream.assign}{ostringstream.swap} +\movedxref{stringstream.assign}{stringstream.swap} +\movedxref{ifstream.assign}{ifstream.swap} +\movedxref{ofstream.assign}{ofstream.swap} +\movedxref{fstream.assign}{fstream.swap} + +% P2387R3 Pipe support for user-defined range adaptors +\movedxref{func.bind.front}{func.bind.partial} + +\movedxref{class.mfct.non-static}{class.mfct.non.static} +\movedxref{defns.direct-non-list-init}{defns.direct.non.list.init} +\movedxref{defns.expression-equivalent}{defns.expression.equivalent} + % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) diff --git a/tools/check-output.sh b/tools/check-output.sh index e6b8acab41..257ec2fd63 100755 --- a/tools/check-output.sh +++ b/tools/check-output.sh @@ -17,6 +17,36 @@ sed -n '/\.tex/{s/^.*\/\([-a-z0-9]\+\.tex\).*$/\1/;h}; /Overfull [\\][hv]box\|LaTeX Warning..Reference/{x;p;x;p}' std.log | sed '/^.\+\.tex$/{N;s/\n/:/}' | fail || failed=1 +# Check for dangling "see" in general index (does not work with formatting) +grep item < std-generalindex.ind | sed 's/,.*$//;s/\\[sub]*item //' | + awk '/^ [^ ]/ { item=$0; print $0 } /^ [^ ]/ { subitem=$0; print item ", " $0 } /^ [^ ]/ { print item ", " subitem ", " $0 }' | + sed 's/^ *//;s/ */ /g' | sort > tmp.txt + +grep -o '\\see{[^}]*}' < std-generalindex.ind | + sed 's/^\\see{//;s/}$//;s/\\-//' | + grep -v "leavevmode\|texttt\|textsc\|kern" | + while read see; do + if grep -q "$see" tmp.txt; then + : + else + grep -n "see{$see}" *.tex | sed 's/$/ is dangling/' + fi + done | fail || failed=1 +rm -f tmp.txt + +# Find bad labels +grep newlabel `ls *.aux | grep -v std.aux` | awk -F '{' '{ print $2 }' | + sed 's/}//g' | sed 's/^tab://;s/fig://;s/idx.*\..//' | + grep -v '^[a-z.0-9]*$' | + sed 's/^\(.*\)$/bad label \1/' | + fail || failed=1 + +# Find grammar index entries missing a definition +cat std-grammarindex.ind | + awk 'BEGIN { def=1 } /^ .item/ { if (def==0) { gsub("[{},]", "", item); print item } item=$NF; def=0; next } /hyperindexformat/ { def=1 }' | + grep -v -- '-keyword$' | # xxx-keyword is special + sed 's/^\(.*\)$/grammar non-terminal \1 has no definition/' | + fail || failed=1 # Cross references since the previous standard. function indexentries() { sed 's,\\glossaryentry{\(.*\)@.*,\1,' "$1" | LANG=C sort; } diff --git a/tools/check-source.sh b/tools/check-source.sh index 37bd96f9e4..6d53272b64 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -6,7 +6,7 @@ failed=0 # Ignore files where rules may be violated within macro definitions. texfiles=$(ls *.tex | grep -v macros.tex | grep -v layout.tex | grep -v tables.tex) -texlibdesc="support.tex concepts.tex diagnostics.tex utilities.tex strings.tex containers.tex iterators.tex ranges.tex algorithms.tex numerics.tex time.tex locales.tex iostreams.tex regex.tex atomics.tex threads.tex" +texlibdesc="support.tex concepts.tex diagnostics.tex memory.tex meta.tex utilities.tex strings.tex containers.tex iterators.tex ranges.tex algorithms.tex numerics.tex time.tex locales.tex iostreams.tex regex.tex threads.tex" texlib="lib-intro.tex $texlibdesc" # Filter that reformats the error message as a "workflow command", @@ -63,10 +63,36 @@ grep -n '\\opt[^{]' $texfiles | grep -n 'opt{}' *.tex | fail '\\opt used incorrectly' || failed=1 +# Use \expos insted of "exposition only" +grep -n "// exposition only" $texfiles | + fail 'use \\expos instead' || failed=1 + # Use \notdef instead of "not defined". grep -n "// not defined" $texfiles | fail "use \\notdef instead" || failed=1 +# Use \Cpp{} instead of C++ +grep -n '^[^%]*[^{"]C++[^"}]' $texfiles | + fail 'use \Cpp{} instead' || failed=1 + +# Use \unicode instead of U+nnnn +grep -n 'U+' $texfiles | + fail 'use \\unicode or \\ucode or \\uname instead' || failed=1 + +# Hex digits inside \ucode and \unicode must be lowercase so that \textsc works +grep -n 'ucode{[^}]*[^0-9a-f}][^}]*}' $texfiles | + fail 'use lowercase hex digits inside \\ucode' || failed=1 +grep -n 'unicode{[^}]*[^0-9a-f}][^}]*}' $texfiles | + fail 'use lowercase hex digits inside \\unicode' || failed=1 + +# Use \iref instead of "(\ref", except for subclause ranges +grep -n '.(\\ref' $texfiles | grep -v -- "--" | + fail 'use \\iref instead of (\\ref' || failed=1 + +# Use \xrefc instead of "ISO C x.y.z" +grep -n "^ISO C [0-9]*\." $texfiles | + fail 'use \\xrefc instead' || failed=1 + # Library element introducer followed by stuff. grep -ne '^\\\(constraints\|mandates\|expects\|effects\|sync\|ensures\|returns\|throws\|complexity\|remarks\|errors\).\+$' $texlibdesc | fail 'stuff after library element' || failed=1 @@ -86,6 +112,18 @@ grep -Hne '^\\\(change\|rationale\|effect\|difficulty\|howwide\)\s.\+$' compatib grep -ne 'template\s]*>//;/\(class\|struct\)[A-Za-z0-9_: ]*{/{=;p;};};}' $f | + # prefix output with filename and line + sed '/^[0-9]\+$/{N;s/\n/:/;}' | sed "s/.*/$f:&/" +done | + fail 'No namespace around class definition' || failed=1 + +# ref-qualifier on member functions with no space, e.g. "const&" +fgrep -ne ') const&' $texlib | + fail 'no space between cv-qualifier and ref-qualifier' || failed=1 + # \begin{example/note} with non-whitespace in front on the same line. grep -ne '^.*[^ ]\s*\\\(begin\|end\){\(example\|note\)}' $texfiles | fail "non-whitespace before note/example begins" || failed=1 @@ -123,8 +161,8 @@ grep -n "&[ 0-9a-z_]\+) = delete" $texfiles | fail 'named parameter in deleted special member' || failed=1 # to fix: sed '/= delete/s/&[ 0-9a-z_]\+)/\&)/' -# Bad characters in label. "-" is allowed due to a single remaining offender. -grep -n '^\\rSec.\[[^]]*[^-a-z.0-9][^]]*\]{' $texfiles | +# Bad characters in label. +grep -n '^\\rSec.\[[^]]*[^a-z.0-9][^]]*\]{' $texfiles | fail 'bad character in label' || failed=1 # Use of parenthesized \ref @@ -168,9 +206,7 @@ done | fail 'subclause without siblings' || failed=1 # Library descriptive macros not immediately preceded by \pnum. for f in $texlibdesc; do - sed -n '/^\\pnum/{h;:x;n;/^\\index/b x;/^\\\(constraints\|mandates\|expects\|effects\|sync\|ensures\|returns\|throws\|complexity\|remarks\|errors\)/{x;/\n/{x;=;p;};d;};/^\\pnum/D;H;b x;}' $f | - # prefix output with filename and line - sed '/^[0-9]\+$/{N;s/\n/:/;}' | sed "s/.*/$f:&/" + awk '/^\\pnum/ { seenpnum=1; next } /^\\index/ { next } /^\\(constraints|mandates|expects|effects|sync|ensures|returns|throws|complexity|remarks|errors)/ { if(seenpnum == 0) { print FILENAME ":" FNR ":" $0 } } { seenpnum=0 }' $f done | fail '\\pnum missing' || failed=1